Skip to content

Commit

Permalink
PR2 Exception Handling Support (#2785)
Browse files Browse the repository at this point in the history
This PR continues the work from #2382 and updates the exception handling support:
* Inside the classic interpreter only:
  * Bug fixes and naming convention improvements
  * Import and Export of Exceptions and Tags
  * Remove the dependency on multi-module
  * Additional CI /CD changes to validate ENABLE_EXCE_HANDLING switch builds
     OK on all platforms

Refer to #1884.

Signed-off-by: Ricardo Aguilar <ricardoaguilar@siemens.com>
Co-authored-by: Chris Woods <chris.woods@siemens.com>
Co-authored-by: Rene Ermler <rene.ermler@siemens.com>
Co-authored-by: Trenner Thomas <trenner.thomas@siemens.com>
  • Loading branch information
4 people committed Nov 21, 2023
1 parent 59f4dd4 commit 59bccdf
Show file tree
Hide file tree
Showing 8 changed files with 540 additions and 291 deletions.
19 changes: 8 additions & 11 deletions core/iwasm/interpreter/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,6 @@
extern "C" {
#endif

#if WASM_ENABLE_EXCE_HANDLING != 0
#define _EXCEWARNING \
LOG_WARNING /* for exception handling misbehavior logging */
#define _EXCEVERBOSE \
LOG_VERBOSE /* more excessive tracing of tagbrowsing and stack pointers */
#endif

/** Value Type */
#define VALUE_TYPE_I32 0x7F
#define VALUE_TYPE_I64 0X7E
Expand Down Expand Up @@ -223,15 +216,18 @@ typedef struct WASMFunctionImport {

#if WASM_ENABLE_TAGS != 0
typedef struct WASMTagImport {
char *module_name;
char *field_name;
uint8 attribute; /* the type of the tag (numerical) */
uint32 type; /* the type of the catch function (numerical)*/
WASMType *tag_type;
uint32 tag_index_linked;
void *tag_ptr_linked;

#if WASM_ENABLE_MULTI_MODULE != 0
/* imported function pointer after linked */
/* TODO: remove if not needed */
/* imported tag pointer after linked */
WASMModule *import_module;
WASMTag *import_tag_linked;
uint32 import_tag_index_linked;
#endif
} WASMTagImport;
#endif
Expand Down Expand Up @@ -340,6 +336,7 @@ struct WASMFunction {
struct WASMTag {
uint8 attribute; /* the attribute property of the tag (expected to be 0) */
uint32 type; /* the type of the tag (expected valid inden in type table) */
WASMType *tag_type;
};
#endif

Expand Down Expand Up @@ -505,7 +502,7 @@ struct WASMModule {
WASMTable *tables;
WASMMemory *memories;
#if WASM_ENABLE_TAGS != 0
WASMTag *tags;
WASMTag **tags;
#endif
WASMGlobal *globals;
WASMExport *exports;
Expand Down
163 changes: 69 additions & 94 deletions core/iwasm/interpreter/wasm_interp_classic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1272,7 +1272,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,

/* get tag type */
uint8 tag_type_index =
module->module->tags[exception_tag_index].type;
module->module->tags[exception_tag_index]->type;
uint32 cell_num_to_copy =
wasm_types[tag_type_index]->param_cell_num;

Expand All @@ -1291,9 +1291,35 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{
read_leb_int32(frame_ip, frame_ip_end, exception_tag_index);

/* landig pad for the rethrow ? */
/* landing pad for the rethrow ? */
find_a_catch_handler:
{
WASMType *tag_type = NULL;
uint32 cell_num_to_copy = 0;
if (IS_INVALID_TAGINDEX(exception_tag_index)) {
/*
* invalid exception index,
* generated if a submodule throws an exception
* that has not been imported here
*
* This should result in a branch to the CATCH_ALL block,
* if there is one
*/
tag_type = NULL;
cell_num_to_copy = 0;
}
else {
if (module->e->tags[exception_tag_index].is_import_tag) {
tag_type = module->e->tags[exception_tag_index]
.u.tag_import->tag_type;
}
else {
tag_type = module->e->tags[exception_tag_index]
.u.tag->tag_type;
}
cell_num_to_copy = tag_type->param_cell_num;
}

/* browse through frame stack */
uint32 relative_depth = 0;
do {
Expand All @@ -1309,7 +1335,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/*
* skip that blocks in search
* BLOCK, IF and LOOP do not contain handlers and
* cannot catch exceptions blocks marked as CATCH or
* cannot catch exceptions.
* blocks marked as CATCH or
* CATCH_ALL did already caugth an exception and can
* only be a target for RETHROW, but cannot catch an
* exception again
Expand Down Expand Up @@ -1347,34 +1374,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
UNWIND_CSP(relative_depth,
LABEL_TYPE_CATCH);

/* transfer exception values */
uint8 tag_type_index =
module->module
->tags[exception_tag_index]
.type;
uint32 cell_num_to_copy =
wasm_types[tag_type_index]
->param_cell_num;
/* push exception_tag_index and
* exception values for rethrow */
PUSH_I32(exception_tag_index);
if (cell_num_to_copy > 0) {
word_copy(
frame_sp,
frame_sp_old
- cell_num_to_copy,
cell_num_to_copy);
}
word_copy(frame_sp,
frame_sp_old
- cell_num_to_copy,
cell_num_to_copy);
frame_sp += cell_num_to_copy;
/* push exception values for catch
*/
if (cell_num_to_copy > 0) {
word_copy(
frame_sp,
frame_sp_old
- cell_num_to_copy,
cell_num_to_copy);
}
word_copy(frame_sp,
frame_sp_old
- cell_num_to_copy,
cell_num_to_copy);
frame_sp += cell_num_to_copy;

/* advance to handler */
Expand Down Expand Up @@ -1403,21 +1416,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/* unwind to delegated frame */
frame_csp -= lookup_depth;

/* transfer exception values */
uint8 tag_type_index =
module->module
->tags[exception_tag_index]
.type;
uint32 cell_num_to_copy =
wasm_types[tag_type_index]
->param_cell_num;
/* push exception values for catch */
if (cell_num_to_copy > 0) {
word_copy(frame_sp,
frame_sp_old
- cell_num_to_copy,
cell_num_to_copy);
}
word_copy(frame_sp,
frame_sp_old
- cell_num_to_copy,
cell_num_to_copy);
frame_sp += cell_num_to_copy;

/* tag_index is already stored in
Expand All @@ -1439,25 +1442,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/* push exception_tag_index and
* exception values for rethrow */
PUSH_I32(exception_tag_index);
if (exception_tag_index
!= (int32_t)0xFFFFFFFF) {
/* transfer exception values */
uint8 tag_type_index =
module->module
->tags[exception_tag_index]
.type;
uint32 cell_num_to_copy =
wasm_types[tag_type_index]
->param_cell_num;
if (cell_num_to_copy > 0) {
word_copy(
frame_sp,
frame_sp_old
- cell_num_to_copy,
cell_num_to_copy);
}
frame_sp += cell_num_to_copy;
}
word_copy(frame_sp,
frame_sp_old
- cell_num_to_copy,
cell_num_to_copy);
frame_sp += cell_num_to_copy;
/* catch_all has no exception values */

/* advance to handler */
Expand All @@ -1469,7 +1458,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
"unexpected handler type");
goto got_exception;
}

handler_number++;
}
/* exception not catched in this frame */
Expand All @@ -1481,29 +1469,16 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 *frame_sp_old = frame_sp;

UNWIND_CSP(relative_depth, LABEL_TYPE_FUNCTION);
if (exception_tag_index
>= (int32_t)module->module->tag_count) {
wasm_set_exception(module, "invalid tag index");
goto got_exception;
}

/* transfer exception values */
uint8 tag_type_index =
module->module->tags[exception_tag_index].type;
uint32 cell_num_to_copy =
wasm_types[tag_type_index]->param_cell_num;
/* push exception values for catch
* The values are copied to the CALLER FRAME
* (prev_frame->sp) same behvior ad WASM_OP_RETURN
*/
if (cell_num_to_copy > 0) {
word_copy(prev_frame->sp,
frame_sp_old - cell_num_to_copy,
cell_num_to_copy);
}
word_copy(prev_frame->sp,
frame_sp_old - cell_num_to_copy,
cell_num_to_copy);
prev_frame->sp += cell_num_to_copy;
*((int32 *)(prev_frame->sp)) = exception_tag_index;
(int32 *)(prev_frame->sp++);
prev_frame->sp++;

/* mark frame as raised exception */
wasm_set_exception(module,
Expand Down Expand Up @@ -4314,37 +4289,37 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/* fix framesp */
UPDATE_ALL_FROM_FRAME();

uint32 import_exception =
0xFFFFFFFF; /* initialize imported exception index to be
invalid */
uint32 import_exception;
/* initialize imported exception index to be invalid */
SET_INVALID_TAGINDEX(import_exception);

/* pull external exception */
uint32 ext_exception = POP_I32();

WASMModule *im_mod = cur_func->u.func_import->import_module;

/* external function came back with an exception or trap */
/* lookup exception in import tags */
uint32 import_tag_index;
for (import_tag_index = 0;
import_tag_index < module->module->import_tag_count;
import_tag_index++) {
WASMTagImport *im_tag =
&(module->module->import_tags[import_tag_index]
.u.tag);
WASMTagInstance *tag = module->e->tags;
for (uint32 t = 0; t < module->module->import_tag_count;
tag++, t++) {

/* compare the module and the external index with the
* imort tag data */
if ((im_mod == im_tag->import_module)
&& (ext_exception == im_tag->tag_index_linked)) {
if ((cur_func->u.func_import->import_module
== tag->u.tag_import->import_module)
&& (ext_exception
== tag->u.tag_import
->import_tag_index_linked)) {
/* set the import_exception to the import tag */
import_exception = import_tag_index;
import_exception = t;
break;
}
}
/*
* push the internal exception index to stack,
* or 0xffffffff in case, the external exception
* is not in the import list
* excange the thrown exception (index valid in submodule)
* with the imported exception index (valid in this module)
* if the module did not import the exception,
* that results in a "INVALID_TAGINDEX", that triggers
* an CATCH_ALL block, if there is one.
*/
PUSH_I32(import_exception);
}
Expand Down
Loading

0 comments on commit 59bccdf

Please sign in to comment.