mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 06:55:07 +00:00
Implement Exception Handling for classic interpreter (#3096)
This PR adds the initial support for WASM exception handling: * Inside the classic interpreter only: * Initial handling of Tags * Initial handling of Exceptions based on W3C Exception Proposal * Import and Export of Exceptions and Tags * Add `cmake -DWAMR_BUILD_EXCE_HANDLING=1/0` option to enable/disable the feature, and by default it is disabled * Update the wamr-test-suites scripts to test the feature * Additional CI/CD changes to validate the exception spec proposal cases Refer to: https://github.com/bytecodealliance/wasm-micro-runtime/issues/1884587513f3c6
8bebfe9ad7
59bccdfed8
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>
This commit is contained in:
parent
7e65f9a244
commit
af318bac81
|
@ -335,6 +335,11 @@ if (WAMR_BUILD_REF_TYPES EQUAL 1)
|
||||||
else ()
|
else ()
|
||||||
message (" Reference types disabled")
|
message (" Reference types disabled")
|
||||||
endif ()
|
endif ()
|
||||||
|
if (WAMR_BUILD_EXCE_HANDLING EQUAL 1)
|
||||||
|
add_definitions (-DWASM_ENABLE_EXCE_HANDLING=1)
|
||||||
|
add_definitions (-DWASM_ENABLE_TAGS=1)
|
||||||
|
message (" Exception Handling enabled")
|
||||||
|
endif ()
|
||||||
if (DEFINED WAMR_BH_VPRINTF)
|
if (DEFINED WAMR_BH_VPRINTF)
|
||||||
add_definitions (-DBH_VPRINTF=${WAMR_BH_VPRINTF})
|
add_definitions (-DBH_VPRINTF=${WAMR_BH_VPRINTF})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
|
@ -457,6 +457,14 @@
|
||||||
#define WASM_ENABLE_REF_TYPES 0
|
#define WASM_ENABLE_REF_TYPES 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef WASM_ENABLE_EXCE_HANDLING
|
||||||
|
#define WASM_ENABLE_EXCE_HANDLING 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WASM_ENABLE_TAGS
|
||||||
|
#define WASM_ENABLE_TAGS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef WASM_ENABLE_SGX_IPFS
|
#ifndef WASM_ENABLE_SGX_IPFS
|
||||||
#define WASM_ENABLE_SGX_IPFS 0
|
#define WASM_ENABLE_SGX_IPFS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -65,6 +65,9 @@ extern "C" {
|
||||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
#define SECTION_TYPE_DATACOUNT 12
|
#define SECTION_TYPE_DATACOUNT 12
|
||||||
#endif
|
#endif
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
#define SECTION_TYPE_TAG 13
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SUB_SECTION_TYPE_MODULE 0
|
#define SUB_SECTION_TYPE_MODULE 0
|
||||||
#define SUB_SECTION_TYPE_FUNC 1
|
#define SUB_SECTION_TYPE_FUNC 1
|
||||||
|
@ -74,20 +77,34 @@ extern "C" {
|
||||||
#define IMPORT_KIND_TABLE 1
|
#define IMPORT_KIND_TABLE 1
|
||||||
#define IMPORT_KIND_MEMORY 2
|
#define IMPORT_KIND_MEMORY 2
|
||||||
#define IMPORT_KIND_GLOBAL 3
|
#define IMPORT_KIND_GLOBAL 3
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
#define IMPORT_KIND_TAG 4
|
||||||
|
#endif
|
||||||
|
|
||||||
#define EXPORT_KIND_FUNC 0
|
#define EXPORT_KIND_FUNC 0
|
||||||
#define EXPORT_KIND_TABLE 1
|
#define EXPORT_KIND_TABLE 1
|
||||||
#define EXPORT_KIND_MEMORY 2
|
#define EXPORT_KIND_MEMORY 2
|
||||||
#define EXPORT_KIND_GLOBAL 3
|
#define EXPORT_KIND_GLOBAL 3
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
#define EXPORT_KIND_TAG 4
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LABEL_TYPE_BLOCK 0
|
#define LABEL_TYPE_BLOCK 0
|
||||||
#define LABEL_TYPE_LOOP 1
|
#define LABEL_TYPE_LOOP 1
|
||||||
#define LABEL_TYPE_IF 2
|
#define LABEL_TYPE_IF 2
|
||||||
#define LABEL_TYPE_FUNCTION 3
|
#define LABEL_TYPE_FUNCTION 3
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
#define LABEL_TYPE_TRY 4
|
||||||
|
#define LABEL_TYPE_CATCH 5
|
||||||
|
#define LABEL_TYPE_CATCH_ALL 6
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct WASMModule WASMModule;
|
typedef struct WASMModule WASMModule;
|
||||||
typedef struct WASMFunction WASMFunction;
|
typedef struct WASMFunction WASMFunction;
|
||||||
typedef struct WASMGlobal WASMGlobal;
|
typedef struct WASMGlobal WASMGlobal;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
typedef struct WASMTag WASMTag;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef union V128 {
|
typedef union V128 {
|
||||||
int8 i8x16[16];
|
int8 i8x16[16];
|
||||||
|
@ -201,6 +218,24 @@ typedef struct WASMFunctionImport {
|
||||||
bool call_conv_wasm_c_api;
|
bool call_conv_wasm_c_api;
|
||||||
} WASMFunctionImport;
|
} 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;
|
||||||
|
void *tag_ptr_linked;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
|
/* imported tag pointer after linked */
|
||||||
|
WASMModule *import_module;
|
||||||
|
WASMTag *import_tag_linked;
|
||||||
|
uint32 import_tag_index_linked;
|
||||||
|
#endif
|
||||||
|
} WASMTagImport;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct WASMGlobalImport {
|
typedef struct WASMGlobalImport {
|
||||||
char *module_name;
|
char *module_name;
|
||||||
char *field_name;
|
char *field_name;
|
||||||
|
@ -227,6 +262,9 @@ typedef struct WASMImport {
|
||||||
WASMFunctionImport function;
|
WASMFunctionImport function;
|
||||||
WASMTableImport table;
|
WASMTableImport table;
|
||||||
WASMMemoryImport memory;
|
WASMMemoryImport memory;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
WASMTagImport tag;
|
||||||
|
#endif
|
||||||
WASMGlobalImport global;
|
WASMGlobalImport global;
|
||||||
struct {
|
struct {
|
||||||
char *module_name;
|
char *module_name;
|
||||||
|
@ -265,6 +303,10 @@ struct WASMFunction {
|
||||||
uint32 const_cell_num;
|
uint32 const_cell_num;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
uint32 exception_handler_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
|
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
|
||||||
|| WASM_ENABLE_WAMR_COMPILER != 0
|
|| WASM_ENABLE_WAMR_COMPILER != 0
|
||||||
/* Whether function has opcode memory.grow */
|
/* Whether function has opcode memory.grow */
|
||||||
|
@ -294,6 +336,14 @@ struct WASMFunction {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
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
|
||||||
|
|
||||||
struct WASMGlobal {
|
struct WASMGlobal {
|
||||||
uint8 type;
|
uint8 type;
|
||||||
bool is_mutable;
|
bool is_mutable;
|
||||||
|
@ -420,6 +470,9 @@ struct WASMModule {
|
||||||
uint32 function_count;
|
uint32 function_count;
|
||||||
uint32 table_count;
|
uint32 table_count;
|
||||||
uint32 memory_count;
|
uint32 memory_count;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
uint32 tag_count;
|
||||||
|
#endif
|
||||||
uint32 global_count;
|
uint32 global_count;
|
||||||
uint32 export_count;
|
uint32 export_count;
|
||||||
uint32 table_seg_count;
|
uint32 table_seg_count;
|
||||||
|
@ -433,11 +486,17 @@ struct WASMModule {
|
||||||
uint32 import_function_count;
|
uint32 import_function_count;
|
||||||
uint32 import_table_count;
|
uint32 import_table_count;
|
||||||
uint32 import_memory_count;
|
uint32 import_memory_count;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
uint32 import_tag_count;
|
||||||
|
#endif
|
||||||
uint32 import_global_count;
|
uint32 import_global_count;
|
||||||
|
|
||||||
WASMImport *import_functions;
|
WASMImport *import_functions;
|
||||||
WASMImport *import_tables;
|
WASMImport *import_tables;
|
||||||
WASMImport *import_memories;
|
WASMImport *import_memories;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
WASMImport *import_tags;
|
||||||
|
#endif
|
||||||
WASMImport *import_globals;
|
WASMImport *import_globals;
|
||||||
|
|
||||||
WASMType **types;
|
WASMType **types;
|
||||||
|
@ -445,6 +504,9 @@ struct WASMModule {
|
||||||
WASMFunction **functions;
|
WASMFunction **functions;
|
||||||
WASMTable *tables;
|
WASMTable *tables;
|
||||||
WASMMemory *memories;
|
WASMMemory *memories;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
WASMTag **tags;
|
||||||
|
#endif
|
||||||
WASMGlobal *globals;
|
WASMGlobal *globals;
|
||||||
WASMExport *exports;
|
WASMExport *exports;
|
||||||
WASMTableSeg *table_segments;
|
WASMTableSeg *table_segments;
|
||||||
|
@ -628,6 +690,11 @@ typedef struct WASMBranchBlock {
|
||||||
uint8 *target_addr;
|
uint8 *target_addr;
|
||||||
uint32 *frame_sp;
|
uint32 *frame_sp;
|
||||||
uint32 cell_num;
|
uint32 cell_num;
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
/* in exception handling, label_type needs to be stored to lookup exception
|
||||||
|
* handlers */
|
||||||
|
uint8 label_type;
|
||||||
|
#endif
|
||||||
} WASMBranchBlock;
|
} WASMBranchBlock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -34,6 +34,14 @@ typedef struct WASMInterpFrame {
|
||||||
uint64 time_started;
|
uint64 time_started;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
/* set to true if the callee returns an exception rather than
|
||||||
|
* result values on the stack
|
||||||
|
*/
|
||||||
|
bool exception_raised;
|
||||||
|
uint32 tag_index;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_FAST_INTERP != 0
|
#if WASM_ENABLE_FAST_INTERP != 0
|
||||||
/* Return offset of the first return value of current frame,
|
/* Return offset of the first return value of current frame,
|
||||||
the callee will put return values here continuously */
|
the callee will put return values here continuously */
|
||||||
|
|
|
@ -338,10 +338,19 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
||||||
frame_sp += 2; \
|
frame_sp += 2; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/* in exception handling, label_type needs to be stored to lookup exception
|
||||||
|
* handlers */
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
#define SET_LABEL_TYPE(_label_type) frame_csp->label_type = _label_type
|
||||||
|
#else
|
||||||
|
#define SET_LABEL_TYPE(_label_type) (void)0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \
|
#define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \
|
||||||
do { \
|
do { \
|
||||||
bh_assert(frame_csp < frame->csp_boundary); \
|
bh_assert(frame_csp < frame->csp_boundary); \
|
||||||
/* frame_csp->label_type = _label_type; */ \
|
SET_LABEL_TYPE(_label_type); \
|
||||||
frame_csp->cell_num = cell_num; \
|
frame_csp->cell_num = cell_num; \
|
||||||
frame_csp->begin_addr = frame_ip; \
|
frame_csp->begin_addr = frame_ip; \
|
||||||
frame_csp->target_addr = _target_addr; \
|
frame_csp->target_addr = _target_addr; \
|
||||||
|
@ -392,6 +401,18 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
||||||
frame_sp -= n; \
|
frame_sp -= n; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
/* unwind the CSP to a given label and optionally modify the labeltype */
|
||||||
|
#define UNWIND_CSP(N, T) \
|
||||||
|
do { \
|
||||||
|
/* unwind to function frame */ \
|
||||||
|
frame_csp -= N; \
|
||||||
|
/* drop handlers and values pushd in try block */ \
|
||||||
|
frame_sp = (frame_csp - 1)->frame_sp; \
|
||||||
|
(frame_csp - 1)->label_type = T ? T : (frame_csp - 1)->label_type; \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SYNC_ALL_TO_FRAME() \
|
#define SYNC_ALL_TO_FRAME() \
|
||||||
do { \
|
do { \
|
||||||
frame->sp = frame_sp; \
|
frame->sp = frame_sp; \
|
||||||
|
@ -1188,6 +1209,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
uint32 local_idx, local_offset, global_idx;
|
uint32 local_idx, local_offset, global_idx;
|
||||||
uint8 local_type, *global_addr;
|
uint8 local_type, *global_addr;
|
||||||
uint32 cache_index, type_index, param_cell_num, cell_num;
|
uint32 cache_index, type_index, param_cell_num, cell_num;
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
int32_t exception_tag_index;
|
||||||
|
#endif
|
||||||
uint8 value_type;
|
uint8 value_type;
|
||||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
|
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
|
||||||
|
@ -1230,6 +1254,379 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
|
|
||||||
HANDLE_OP(WASM_OP_NOP) { HANDLE_OP_END(); }
|
HANDLE_OP(WASM_OP_NOP) { HANDLE_OP_END(); }
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
|
||||||
|
HANDLE_OP(WASM_OP_RETHROW)
|
||||||
|
{
|
||||||
|
int32_t relative_depth;
|
||||||
|
read_leb_int32(frame_ip, frame_ip_end, relative_depth);
|
||||||
|
|
||||||
|
/* No frame found with exception handler; validation should
|
||||||
|
* catch it */
|
||||||
|
bh_assert(frame_csp >= frame->csp_bottom + relative_depth);
|
||||||
|
|
||||||
|
/* go up the frame stack */
|
||||||
|
WASMBranchBlock *tgtframe = (frame_csp - 1) - relative_depth;
|
||||||
|
|
||||||
|
bh_assert(tgtframe->label_type == LABEL_TYPE_CATCH
|
||||||
|
|| tgtframe->label_type == LABEL_TYPE_CATCH_ALL);
|
||||||
|
|
||||||
|
/* tgtframe points to the frame containing a thrown
|
||||||
|
* exception */
|
||||||
|
|
||||||
|
uint32 *tgtframe_sp = tgtframe->frame_sp;
|
||||||
|
|
||||||
|
/* frame sp of tgtframe points to catched exception */
|
||||||
|
exception_tag_index = *((uint32 *)tgtframe_sp);
|
||||||
|
tgtframe_sp++;
|
||||||
|
|
||||||
|
/* get tag type */
|
||||||
|
uint8 tag_type_index =
|
||||||
|
module->module->tags[exception_tag_index]->type;
|
||||||
|
uint32 cell_num_to_copy =
|
||||||
|
wasm_types[tag_type_index]->param_cell_num;
|
||||||
|
|
||||||
|
/* move exception parameters (if there are any) onto top
|
||||||
|
* of stack */
|
||||||
|
if (cell_num_to_copy > 0) {
|
||||||
|
word_copy(frame_sp, tgtframe_sp - cell_num_to_copy,
|
||||||
|
cell_num_to_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_sp += cell_num_to_copy;
|
||||||
|
goto find_a_catch_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE_OP(WASM_OP_THROW)
|
||||||
|
{
|
||||||
|
read_leb_int32(frame_ip, frame_ip_end, exception_tag_index);
|
||||||
|
|
||||||
|
/* 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 {
|
||||||
|
POP_CSP_CHECK_OVERFLOW(relative_depth - 1);
|
||||||
|
WASMBranchBlock *tgtframe = frame_csp - relative_depth - 1;
|
||||||
|
|
||||||
|
switch (tgtframe->label_type) {
|
||||||
|
case LABEL_TYPE_BLOCK:
|
||||||
|
case LABEL_TYPE_IF:
|
||||||
|
case LABEL_TYPE_LOOP:
|
||||||
|
case LABEL_TYPE_CATCH:
|
||||||
|
case LABEL_TYPE_CATCH_ALL:
|
||||||
|
/*
|
||||||
|
* skip that blocks in search
|
||||||
|
* BLOCK, IF and LOOP do not contain handlers and
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case LABEL_TYPE_TRY:
|
||||||
|
{
|
||||||
|
uint32 handler_number = 0;
|
||||||
|
uint8 **handlers = (uint8 **)tgtframe->frame_sp;
|
||||||
|
uint8 *handler = NULL;
|
||||||
|
while ((handler = handlers[handler_number]) != 0) {
|
||||||
|
uint8 handler_opcode = *handler;
|
||||||
|
uint8 *target_addr =
|
||||||
|
handler
|
||||||
|
+ 1; /* first instruction or leb-immediate
|
||||||
|
behind the handler opcode */
|
||||||
|
switch (handler_opcode) {
|
||||||
|
case WASM_OP_CATCH:
|
||||||
|
{
|
||||||
|
int32 lookup_index = 0;
|
||||||
|
/* read the tag_index and advance
|
||||||
|
* target_addr to the first instruction
|
||||||
|
* in the block */
|
||||||
|
read_leb_int32(target_addr, 0,
|
||||||
|
lookup_index);
|
||||||
|
|
||||||
|
if (exception_tag_index
|
||||||
|
== lookup_index) {
|
||||||
|
/* set ip */
|
||||||
|
frame_ip = target_addr;
|
||||||
|
/* save frame_sp (points to
|
||||||
|
* exception values) */
|
||||||
|
uint32 *frame_sp_old = frame_sp;
|
||||||
|
|
||||||
|
UNWIND_CSP(relative_depth,
|
||||||
|
LABEL_TYPE_CATCH);
|
||||||
|
|
||||||
|
/* push exception_tag_index and
|
||||||
|
* exception values for rethrow */
|
||||||
|
PUSH_I32(exception_tag_index);
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
word_copy(frame_sp,
|
||||||
|
frame_sp_old
|
||||||
|
- cell_num_to_copy,
|
||||||
|
cell_num_to_copy);
|
||||||
|
frame_sp += cell_num_to_copy;
|
||||||
|
|
||||||
|
/* advance to handler */
|
||||||
|
HANDLE_OP_END();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WASM_OP_DELEGATE:
|
||||||
|
{
|
||||||
|
int32 lookup_depth = 0;
|
||||||
|
/* read the depth */
|
||||||
|
read_leb_int32(target_addr, 0,
|
||||||
|
lookup_depth);
|
||||||
|
|
||||||
|
/* save frame_sp (points to exception
|
||||||
|
* values) */
|
||||||
|
uint32 *frame_sp_old = frame_sp;
|
||||||
|
|
||||||
|
UNWIND_CSP(relative_depth,
|
||||||
|
LABEL_TYPE_CATCH);
|
||||||
|
|
||||||
|
/* leave the block (the delegate is
|
||||||
|
* technically not inside the frame) */
|
||||||
|
frame_csp--;
|
||||||
|
|
||||||
|
/* unwind to delegated frame */
|
||||||
|
frame_csp -= lookup_depth;
|
||||||
|
|
||||||
|
/* push exception values for catch */
|
||||||
|
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
|
||||||
|
* exception_tag_index */
|
||||||
|
goto find_a_catch_handler;
|
||||||
|
}
|
||||||
|
case WASM_OP_CATCH_ALL:
|
||||||
|
{
|
||||||
|
/* no immediate */
|
||||||
|
/* save frame_sp (points to exception
|
||||||
|
* values) */
|
||||||
|
uint32 *frame_sp_old = frame_sp;
|
||||||
|
/* set ip */
|
||||||
|
frame_ip = target_addr;
|
||||||
|
|
||||||
|
UNWIND_CSP(relative_depth,
|
||||||
|
LABEL_TYPE_CATCH_ALL);
|
||||||
|
|
||||||
|
/* push exception_tag_index and
|
||||||
|
* exception values for rethrow */
|
||||||
|
PUSH_I32(exception_tag_index);
|
||||||
|
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 */
|
||||||
|
HANDLE_OP_END();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
wasm_set_exception(
|
||||||
|
module, "WASM_OP_THROW found "
|
||||||
|
"unexpected handler type");
|
||||||
|
goto got_exception;
|
||||||
|
}
|
||||||
|
handler_number++;
|
||||||
|
}
|
||||||
|
/* exception not catched in this frame */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LABEL_TYPE_FUNCTION:
|
||||||
|
{
|
||||||
|
/* save frame_sp (points to exception values) */
|
||||||
|
uint32 *frame_sp_old = frame_sp;
|
||||||
|
|
||||||
|
UNWIND_CSP(relative_depth, LABEL_TYPE_FUNCTION);
|
||||||
|
/* push exception values for catch
|
||||||
|
* The values are copied to the CALLER FRAME
|
||||||
|
* (prev_frame->sp) same behvior ad WASM_OP_RETURN
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
prev_frame->sp++;
|
||||||
|
|
||||||
|
/* mark frame as raised exception */
|
||||||
|
wasm_set_exception(module,
|
||||||
|
"uncaught wasm exception");
|
||||||
|
|
||||||
|
/* end of function, treat as WASM_OP_RETURN */
|
||||||
|
goto return_func;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
wasm_set_exception(
|
||||||
|
module,
|
||||||
|
"unexpected or invalid label in THROW or "
|
||||||
|
"RETHROW when searching a catch handler");
|
||||||
|
goto got_exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
relative_depth++;
|
||||||
|
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* something went wrong. normally, we should always find the
|
||||||
|
* func label. if not, stop the interpreter */
|
||||||
|
wasm_set_exception(
|
||||||
|
module, "WASM_OP_THROW hit the bottom of the frame stack");
|
||||||
|
goto got_exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE_OP(EXT_OP_TRY)
|
||||||
|
{
|
||||||
|
/* read the blocktype */
|
||||||
|
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
||||||
|
param_cell_num = wasm_types[type_index]->param_cell_num;
|
||||||
|
cell_num = wasm_types[type_index]->ret_cell_num;
|
||||||
|
goto handle_op_try;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE_OP(WASM_OP_TRY)
|
||||||
|
{
|
||||||
|
value_type = *frame_ip++;
|
||||||
|
param_cell_num = 0;
|
||||||
|
cell_num = wasm_value_type_cell_num(value_type);
|
||||||
|
|
||||||
|
handle_op_try:
|
||||||
|
|
||||||
|
cache_index = ((uintptr_t)frame_ip)
|
||||||
|
& (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
|
||||||
|
cache_items = exec_env->block_addr_cache[cache_index];
|
||||||
|
if (cache_items[0].start_addr == frame_ip) {
|
||||||
|
cache_items[0].start_addr = 0;
|
||||||
|
}
|
||||||
|
if (cache_items[1].start_addr == frame_ip) {
|
||||||
|
cache_items[1].start_addr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* start at the first opcode following the try and its blocktype
|
||||||
|
*/
|
||||||
|
uint8 *lookup_cursor = frame_ip;
|
||||||
|
uint8 handler_opcode = WASM_OP_UNREACHABLE;
|
||||||
|
|
||||||
|
/* target_addr filled in when END or DELEGATE is found */
|
||||||
|
PUSH_CSP(LABEL_TYPE_TRY, param_cell_num, cell_num, 0);
|
||||||
|
|
||||||
|
/* reset to begin of block */
|
||||||
|
lookup_cursor = frame_ip;
|
||||||
|
do {
|
||||||
|
/* lookup the next CATCH, CATCH_ALL or END for this TRY */
|
||||||
|
if (!wasm_loader_find_block_addr(
|
||||||
|
exec_env, (BlockAddr *)exec_env->block_addr_cache,
|
||||||
|
lookup_cursor, (uint8 *)-1, LABEL_TYPE_TRY,
|
||||||
|
&else_addr, &end_addr)) {
|
||||||
|
/* something went wrong */
|
||||||
|
wasm_set_exception(module, "find block address failed");
|
||||||
|
goto got_exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* place cursor for continuation past opcode */
|
||||||
|
lookup_cursor = end_addr + 1;
|
||||||
|
|
||||||
|
/* end_addr points to CATCH, CATCH_ALL, DELEGATE or END */
|
||||||
|
handler_opcode = *end_addr;
|
||||||
|
switch (handler_opcode) {
|
||||||
|
case WASM_OP_CATCH:
|
||||||
|
skip_leb(lookup_cursor); /* skip tag_index */
|
||||||
|
PUSH_I64(end_addr);
|
||||||
|
break;
|
||||||
|
case WASM_OP_CATCH_ALL:
|
||||||
|
PUSH_I64(end_addr);
|
||||||
|
break;
|
||||||
|
case WASM_OP_DELEGATE:
|
||||||
|
skip_leb(lookup_cursor); /* skip depth */
|
||||||
|
PUSH_I64(end_addr);
|
||||||
|
/* patch target_addr */
|
||||||
|
(frame_csp - 1)->target_addr = lookup_cursor;
|
||||||
|
break;
|
||||||
|
case WASM_OP_END:
|
||||||
|
PUSH_I64(0);
|
||||||
|
/* patch target_addr */
|
||||||
|
(frame_csp - 1)->target_addr = end_addr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* something went wrong */
|
||||||
|
wasm_set_exception(module,
|
||||||
|
"find block address returned an "
|
||||||
|
"unexpected opcode");
|
||||||
|
goto got_exception;
|
||||||
|
}
|
||||||
|
/* ... search until the returned address is the END of the
|
||||||
|
* TRY block */
|
||||||
|
} while (handler_opcode != WASM_OP_END
|
||||||
|
&& handler_opcode != WASM_OP_DELEGATE);
|
||||||
|
/* handler setup on stack complete */
|
||||||
|
|
||||||
|
HANDLE_OP_END();
|
||||||
|
}
|
||||||
|
HANDLE_OP(WASM_OP_CATCH)
|
||||||
|
{
|
||||||
|
/* skip the tag_index */
|
||||||
|
skip_leb(frame_ip);
|
||||||
|
/* leave the frame */
|
||||||
|
POP_CSP_N(0);
|
||||||
|
HANDLE_OP_END();
|
||||||
|
}
|
||||||
|
HANDLE_OP(WASM_OP_CATCH_ALL)
|
||||||
|
{
|
||||||
|
/* leave the frame */
|
||||||
|
POP_CSP_N(0);
|
||||||
|
HANDLE_OP_END();
|
||||||
|
}
|
||||||
|
HANDLE_OP(WASM_OP_DELEGATE)
|
||||||
|
{
|
||||||
|
/* skip the delegate depth */
|
||||||
|
skip_leb(frame_ip);
|
||||||
|
/* leave the frame like WASM_OP_END */
|
||||||
|
POP_CSP();
|
||||||
|
HANDLE_OP_END();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
HANDLE_OP(EXT_OP_BLOCK)
|
HANDLE_OP(EXT_OP_BLOCK)
|
||||||
{
|
{
|
||||||
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
||||||
|
@ -3814,10 +4211,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x06)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x07)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x08)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x09)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x0a)
|
HANDLE_OP(WASM_OP_UNUSED_0x0a)
|
||||||
#if WASM_ENABLE_TAIL_CALL == 0
|
#if WASM_ENABLE_TAIL_CALL == 0
|
||||||
HANDLE_OP(WASM_OP_RETURN_CALL)
|
HANDLE_OP(WASM_OP_RETURN_CALL)
|
||||||
|
@ -3834,6 +4227,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
HANDLE_OP(WASM_OP_REF_IS_NULL)
|
HANDLE_OP(WASM_OP_REF_IS_NULL)
|
||||||
HANDLE_OP(WASM_OP_REF_FUNC)
|
HANDLE_OP(WASM_OP_REF_FUNC)
|
||||||
#endif
|
#endif
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING == 0
|
||||||
|
HANDLE_OP(WASM_OP_TRY)
|
||||||
|
HANDLE_OP(WASM_OP_CATCH)
|
||||||
|
HANDLE_OP(WASM_OP_THROW)
|
||||||
|
HANDLE_OP(WASM_OP_RETHROW)
|
||||||
|
HANDLE_OP(WASM_OP_DELEGATE)
|
||||||
|
HANDLE_OP(WASM_OP_CATCH_ALL)
|
||||||
|
HANDLE_OP(EXT_OP_TRY)
|
||||||
|
#endif
|
||||||
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_SIMD != 0
|
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_SIMD != 0
|
||||||
/* SIMD isn't supported by interpreter, but when JIT is
|
/* SIMD isn't supported by interpreter, but when JIT is
|
||||||
enabled, `iwasm --interp <wasm_file>` may be run to
|
enabled, `iwasm --interp <wasm_file>` may be run to
|
||||||
|
@ -3844,8 +4246,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x15)
|
HANDLE_OP(WASM_OP_UNUSED_0x15)
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x16)
|
HANDLE_OP(WASM_OP_UNUSED_0x16)
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x17)
|
HANDLE_OP(WASM_OP_UNUSED_0x17)
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x18)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x19)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x27)
|
HANDLE_OP(WASM_OP_UNUSED_0x27)
|
||||||
/* Used by fast interpreter */
|
/* Used by fast interpreter */
|
||||||
HANDLE_OP(EXT_OP_SET_LOCAL_FAST_I64)
|
HANDLE_OP(EXT_OP_SET_LOCAL_FAST_I64)
|
||||||
|
@ -3896,6 +4296,50 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
if (cur_func->import_func_inst) {
|
if (cur_func->import_func_inst) {
|
||||||
wasm_interp_call_func_import(module, exec_env, cur_func,
|
wasm_interp_call_func_import(module, exec_env, cur_func,
|
||||||
prev_frame);
|
prev_frame);
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
char uncaught_exception[128] = { 0 };
|
||||||
|
bool has_exception =
|
||||||
|
wasm_copy_exception(module, uncaught_exception);
|
||||||
|
if (has_exception
|
||||||
|
&& strstr(uncaught_exception, "uncaught wasm exception")) {
|
||||||
|
/* fix framesp */
|
||||||
|
UPDATE_ALL_FROM_FRAME();
|
||||||
|
|
||||||
|
uint32 import_exception;
|
||||||
|
/* initialize imported exception index to be invalid */
|
||||||
|
SET_INVALID_TAGINDEX(import_exception);
|
||||||
|
|
||||||
|
/* pull external exception */
|
||||||
|
uint32 ext_exception = POP_I32();
|
||||||
|
|
||||||
|
/* external function came back with an exception or trap */
|
||||||
|
/* lookup exception in import tags */
|
||||||
|
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 ((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 = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
@ -3916,19 +4360,57 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
if (memory)
|
if (memory)
|
||||||
linear_mem_size = get_linear_mem_size();
|
linear_mem_size = get_linear_mem_size();
|
||||||
#endif
|
#endif
|
||||||
if (wasm_copy_exception(module, NULL))
|
if (wasm_copy_exception(module, NULL)) {
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
/* the caller raised an exception */
|
||||||
|
char uncaught_exception[128] = { 0 };
|
||||||
|
bool has_exception =
|
||||||
|
wasm_copy_exception(module, uncaught_exception);
|
||||||
|
|
||||||
|
/* libc_builtin signaled a "exception thrown by stdc++" trap */
|
||||||
|
if (has_exception
|
||||||
|
&& strstr(uncaught_exception,
|
||||||
|
"exception thrown by stdc++")) {
|
||||||
|
wasm_set_exception(module, NULL);
|
||||||
|
|
||||||
|
/* setup internal c++ rethrow */
|
||||||
|
exception_tag_index = 0;
|
||||||
|
goto find_a_catch_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* when throw hits the end of a function it signalles with a
|
||||||
|
* "uncaught wasm exception" trap */
|
||||||
|
if (has_exception
|
||||||
|
&& strstr(uncaught_exception, "uncaught wasm exception")) {
|
||||||
|
wasm_set_exception(module, NULL);
|
||||||
|
exception_tag_index = POP_I32();
|
||||||
|
|
||||||
|
/* rethrow the exception into that frame */
|
||||||
|
goto find_a_catch_handler;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
WASMFunction *cur_wasm_func = cur_func->u.func;
|
WASMFunction *cur_wasm_func = cur_func->u.func;
|
||||||
WASMType *func_type;
|
WASMType *func_type;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
/* account for exception handlers */
|
||||||
|
/* bundle them here */
|
||||||
|
uint32 eh_size =
|
||||||
|
cur_wasm_func->exception_handler_count * sizeof(uint8 *);
|
||||||
|
cur_wasm_func->max_stack_cell_num += eh_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
func_type = cur_wasm_func->func_type;
|
func_type = cur_wasm_func->func_type;
|
||||||
|
|
||||||
all_cell_num = cur_func->param_cell_num + cur_func->local_cell_num
|
all_cell_num = cur_func->param_cell_num + cur_func->local_cell_num
|
||||||
+ cur_wasm_func->max_stack_cell_num
|
+ cur_wasm_func->max_stack_cell_num
|
||||||
+ cur_wasm_func->max_block_num
|
+ cur_wasm_func->max_block_num
|
||||||
* (uint32)sizeof(WASMBranchBlock) / 4;
|
* (uint32)sizeof(WASMBranchBlock) / 4;
|
||||||
|
|
||||||
/* param_cell_num, local_cell_num, max_stack_cell_num and
|
/* param_cell_num, local_cell_num, max_stack_cell_num and
|
||||||
max_block_num are all no larger than UINT16_MAX (checked
|
max_block_num are all no larger than UINT16_MAX (checked
|
||||||
in loader), all_cell_num must be smaller than 1MB */
|
in loader), all_cell_num must be smaller than 1MB */
|
||||||
|
@ -3977,11 +4459,19 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
FREE_FRAME(exec_env, frame);
|
FREE_FRAME(exec_env, frame);
|
||||||
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
|
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
|
||||||
|
|
||||||
if (!prev_frame->ip)
|
if (!prev_frame->ip) {
|
||||||
/* Called from native. */
|
/* Called from native. */
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RECOVER_CONTEXT(prev_frame);
|
RECOVER_CONTEXT(prev_frame);
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
if (wasm_get_exception(module)) {
|
||||||
|
wasm_set_exception(module, NULL);
|
||||||
|
exception_tag_index = POP_I32();
|
||||||
|
goto find_a_catch_handler;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
HANDLE_OP_END();
|
HANDLE_OP_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1437,6 +1437,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
goto call_func_from_interp;
|
goto call_func_from_interp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
HANDLE_OP(WASM_OP_TRY)
|
||||||
|
HANDLE_OP(WASM_OP_CATCH)
|
||||||
|
HANDLE_OP(WASM_OP_THROW)
|
||||||
|
HANDLE_OP(WASM_OP_RETHROW)
|
||||||
|
HANDLE_OP(WASM_OP_DELEGATE)
|
||||||
|
HANDLE_OP(WASM_OP_CATCH_ALL)
|
||||||
|
HANDLE_OP(EXT_OP_TRY)
|
||||||
|
{
|
||||||
|
wasm_set_exception(module, "unsupported opcode");
|
||||||
|
goto got_exception;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* parametric instructions */
|
/* parametric instructions */
|
||||||
HANDLE_OP(WASM_OP_SELECT)
|
HANDLE_OP(WASM_OP_SELECT)
|
||||||
{
|
{
|
||||||
|
@ -3670,10 +3684,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x06)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x07)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x08)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x09)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x0a)
|
HANDLE_OP(WASM_OP_UNUSED_0x0a)
|
||||||
#if WASM_ENABLE_TAIL_CALL == 0
|
#if WASM_ENABLE_TAIL_CALL == 0
|
||||||
HANDLE_OP(WASM_OP_RETURN_CALL)
|
HANDLE_OP(WASM_OP_RETURN_CALL)
|
||||||
|
@ -3688,6 +3698,16 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
HANDLE_OP(WASM_OP_REF_NULL)
|
HANDLE_OP(WASM_OP_REF_NULL)
|
||||||
HANDLE_OP(WASM_OP_REF_IS_NULL)
|
HANDLE_OP(WASM_OP_REF_IS_NULL)
|
||||||
HANDLE_OP(WASM_OP_REF_FUNC)
|
HANDLE_OP(WASM_OP_REF_FUNC)
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING == 0
|
||||||
|
/* if exception handling is disabled, these opcodes issue a trap */
|
||||||
|
HANDLE_OP(WASM_OP_TRY)
|
||||||
|
HANDLE_OP(WASM_OP_CATCH)
|
||||||
|
HANDLE_OP(WASM_OP_THROW)
|
||||||
|
HANDLE_OP(WASM_OP_RETHROW)
|
||||||
|
HANDLE_OP(WASM_OP_DELEGATE)
|
||||||
|
HANDLE_OP(WASM_OP_CATCH_ALL)
|
||||||
|
HANDLE_OP(EXT_OP_TRY)
|
||||||
#endif
|
#endif
|
||||||
/* SELECT_T is converted to SELECT or SELECT_64 */
|
/* SELECT_T is converted to SELECT or SELECT_64 */
|
||||||
HANDLE_OP(WASM_OP_SELECT_T)
|
HANDLE_OP(WASM_OP_SELECT_T)
|
||||||
|
@ -3695,8 +3715,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x15)
|
HANDLE_OP(WASM_OP_UNUSED_0x15)
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x16)
|
HANDLE_OP(WASM_OP_UNUSED_0x16)
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x17)
|
HANDLE_OP(WASM_OP_UNUSED_0x17)
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x18)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x19)
|
|
||||||
HANDLE_OP(WASM_OP_UNUSED_0x27)
|
HANDLE_OP(WASM_OP_UNUSED_0x27)
|
||||||
/* optimized op code */
|
/* optimized op code */
|
||||||
HANDLE_OP(WASM_OP_F32_STORE)
|
HANDLE_OP(WASM_OP_F32_STORE)
|
||||||
|
|
|
@ -707,7 +707,6 @@ wasm_loader_find_export(const WASMModule *module, const char *module_name,
|
||||||
WASMExport *export =
|
WASMExport *export =
|
||||||
loader_find_export((WASMModuleCommon *)module, module_name, field_name,
|
loader_find_export((WASMModuleCommon *)module, module_name, field_name,
|
||||||
export_kind, error_buf, error_buf_size);
|
export_kind, error_buf, error_buf_size);
|
||||||
;
|
|
||||||
return export;
|
return export;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -898,6 +897,58 @@ wasm_loader_resolve_global(const char *module_name, const char *global_name,
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
static WASMTag *
|
||||||
|
wasm_loader_resolve_tag(const char *module_name, const char *tag_name,
|
||||||
|
const WASMType *expected_tag_type,
|
||||||
|
uint32 *linked_tag_index, char *error_buf,
|
||||||
|
uint32 error_buf_size)
|
||||||
|
{
|
||||||
|
WASMModuleCommon *module_reg;
|
||||||
|
WASMTag *tag = NULL;
|
||||||
|
WASMExport *export = NULL;
|
||||||
|
WASMModule *module = NULL;
|
||||||
|
|
||||||
|
module_reg = wasm_runtime_find_module_registered(module_name);
|
||||||
|
if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) {
|
||||||
|
LOG_DEBUG("can not find a module named %s for tag %s", module_name,
|
||||||
|
tag_name);
|
||||||
|
set_error_buf(error_buf, error_buf_size, "unknown import");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
module = (WASMModule *)module_reg;
|
||||||
|
export =
|
||||||
|
wasm_loader_find_export(module, module_name, tag_name, EXPORT_KIND_TAG,
|
||||||
|
error_buf, error_buf_size);
|
||||||
|
if (!export) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* resolve tag type and tag */
|
||||||
|
if (export->index < module->import_tag_count) {
|
||||||
|
/* importing an imported tag from the submodule */
|
||||||
|
tag = module->import_tags[export->index].u.tag.import_tag_linked;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* importing an section tag from the submodule */
|
||||||
|
tag = module->tags[export->index - module->import_tag_count];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check function type */
|
||||||
|
if (!wasm_type_equal(expected_tag_type, tag->tag_type)) {
|
||||||
|
LOG_DEBUG("%s.%s failed the type check", module_name, tag_name);
|
||||||
|
set_error_buf(error_buf, error_buf_size, "incompatible import type");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linked_tag_index != NULL) {
|
||||||
|
*linked_tag_index = export->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif /* end of WASM_ENABLE_MULTI_MODULE */
|
#endif /* end of WASM_ENABLE_MULTI_MODULE */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -1237,6 +1288,89 @@ fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
static bool
|
||||||
|
load_tag_import(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
|
const WASMModule *parent_module, /* this module ! */
|
||||||
|
const char *sub_module_name, const char *tag_name,
|
||||||
|
WASMTagImport *tag, /* structure to fill */
|
||||||
|
char *error_buf, uint32 error_buf_size)
|
||||||
|
{
|
||||||
|
/* attribute and type of the import statement */
|
||||||
|
uint8 declare_tag_attribute;
|
||||||
|
uint32 declare_type_index;
|
||||||
|
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||||
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
|
WASMModule *sub_module = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* get the one byte attribute */
|
||||||
|
CHECK_BUF(p, p_end, 1);
|
||||||
|
declare_tag_attribute = read_uint8(p);
|
||||||
|
if (declare_tag_attribute != 0) {
|
||||||
|
set_error_buf(error_buf, error_buf_size, "unknown tag attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get type */
|
||||||
|
read_leb_uint32(p, p_end, declare_type_index);
|
||||||
|
/* compare against module->types */
|
||||||
|
if (declare_type_index >= parent_module->type_count) {
|
||||||
|
set_error_buf(error_buf, error_buf_size, "unknown tag type");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
WASMType *declare_tag_type = parent_module->types[declare_type_index];
|
||||||
|
|
||||||
|
/* check, that the type of the declared tag returns void */
|
||||||
|
if (declare_tag_type->result_count != 0) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"tag type signature does not return void");
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
|
if (!wasm_runtime_is_built_in_module(sub_module_name)) {
|
||||||
|
sub_module = (WASMModule *)wasm_runtime_load_depended_module(
|
||||||
|
(WASMModuleCommon *)parent_module, sub_module_name, error_buf,
|
||||||
|
error_buf_size);
|
||||||
|
if (!sub_module) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* wasm_loader_resolve_tag checks, that the imported tag
|
||||||
|
* and the declared tag have the same type
|
||||||
|
*/
|
||||||
|
uint32 linked_tag_index = 0;
|
||||||
|
WASMTag *linked_tag = wasm_loader_resolve_tag(
|
||||||
|
sub_module_name, tag_name, declare_tag_type,
|
||||||
|
&linked_tag_index /* out */, error_buf, error_buf_size);
|
||||||
|
if (linked_tag) {
|
||||||
|
tag->import_module = sub_module;
|
||||||
|
tag->import_tag_linked = linked_tag;
|
||||||
|
tag->import_tag_index_linked = linked_tag_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* store to module tag declarations */
|
||||||
|
tag->attribute = declare_tag_attribute;
|
||||||
|
tag->type = declare_type_index;
|
||||||
|
|
||||||
|
tag->module_name = (char *)sub_module_name;
|
||||||
|
tag->field_name = (char *)tag_name;
|
||||||
|
tag->tag_type = declare_tag_type;
|
||||||
|
|
||||||
|
*p_buf = p;
|
||||||
|
(void)parent_module;
|
||||||
|
|
||||||
|
LOG_VERBOSE("Load tag import success\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
load_global_import(const uint8 **p_buf, const uint8 *buf_end,
|
load_global_import(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
const WASMModule *parent_module, char *sub_module_name,
|
const WASMModule *parent_module, char *sub_module_name,
|
||||||
|
@ -1458,6 +1592,9 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
WASMImport *import;
|
WASMImport *import;
|
||||||
WASMImport *import_functions = NULL, *import_tables = NULL;
|
WASMImport *import_functions = NULL, *import_tables = NULL;
|
||||||
WASMImport *import_memories = NULL, *import_globals = NULL;
|
WASMImport *import_memories = NULL, *import_globals = NULL;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
WASMImport *import_tags = NULL;
|
||||||
|
#endif
|
||||||
char *sub_module_name, *field_name;
|
char *sub_module_name, *field_name;
|
||||||
uint8 u8, kind;
|
uint8 u8, kind;
|
||||||
|
|
||||||
|
@ -1486,7 +1623,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
p += name_len;
|
p += name_len;
|
||||||
|
|
||||||
CHECK_BUF(p, p_end, 1);
|
CHECK_BUF(p, p_end, 1);
|
||||||
/* 0x00/0x01/0x02/0x03 */
|
/* 0x00/0x01/0x02/0x03/0x04 */
|
||||||
kind = read_uint8(p);
|
kind = read_uint8(p);
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
@ -1527,6 +1664,16 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
case IMPORT_KIND_TAG: /* import tags */
|
||||||
|
/* it only counts the number of tags to import */
|
||||||
|
module->import_tag_count++;
|
||||||
|
CHECK_BUF(p, p_end, 1);
|
||||||
|
u8 = read_uint8(p);
|
||||||
|
read_leb_uint32(p, p_end, type_index);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case IMPORT_KIND_GLOBAL: /* import global */
|
case IMPORT_KIND_GLOBAL: /* import global */
|
||||||
CHECK_BUF(p, p_end, 2);
|
CHECK_BUF(p, p_end, 2);
|
||||||
p += 2;
|
p += 2;
|
||||||
|
@ -1549,10 +1696,23 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
import_memories = module->import_memories =
|
import_memories = module->import_memories =
|
||||||
module->imports + module->import_function_count
|
module->imports + module->import_function_count
|
||||||
+ module->import_table_count;
|
+ module->import_table_count;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
if (module->import_tag_count)
|
||||||
|
import_tags = module->import_tags =
|
||||||
|
module->imports + module->import_function_count
|
||||||
|
+ module->import_table_count + module->import_memory_count;
|
||||||
|
if (module->import_global_count)
|
||||||
|
import_globals = module->import_globals =
|
||||||
|
module->imports + module->import_function_count
|
||||||
|
+ module->import_table_count + module->import_memory_count
|
||||||
|
+ module->import_tag_count;
|
||||||
|
#else
|
||||||
if (module->import_global_count)
|
if (module->import_global_count)
|
||||||
import_globals = module->import_globals =
|
import_globals = module->import_globals =
|
||||||
module->imports + module->import_function_count
|
module->imports + module->import_function_count
|
||||||
+ module->import_table_count + module->import_memory_count;
|
+ module->import_table_count + module->import_memory_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
p = p_old;
|
p = p_old;
|
||||||
|
|
||||||
|
@ -1579,7 +1739,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
p += name_len;
|
p += name_len;
|
||||||
|
|
||||||
CHECK_BUF(p, p_end, 1);
|
CHECK_BUF(p, p_end, 1);
|
||||||
/* 0x00/0x01/0x02/0x03 */
|
/* 0x00/0x01/0x02/0x03/0x4 */
|
||||||
kind = read_uint8(p);
|
kind = read_uint8(p);
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
@ -1615,6 +1775,18 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
case IMPORT_KIND_TAG:
|
||||||
|
bh_assert(import_tags);
|
||||||
|
import = import_tags++;
|
||||||
|
if (!load_tag_import(&p, p_end, module, sub_module_name,
|
||||||
|
field_name, &import->u.tag, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case IMPORT_KIND_GLOBAL: /* import global */
|
case IMPORT_KIND_GLOBAL: /* import global */
|
||||||
bh_assert(import_globals);
|
bh_assert(import_globals);
|
||||||
import = import_globals++;
|
import = import_globals++;
|
||||||
|
@ -2126,6 +2298,16 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
/* export tag */
|
||||||
|
case EXPORT_KIND_TAG:
|
||||||
|
if (index >= module->tag_count + module->import_tag_count) {
|
||||||
|
set_error_buf(error_buf, error_buf_size, "unknown tag");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* global index */
|
/* global index */
|
||||||
case EXPORT_KIND_GLOBAL:
|
case EXPORT_KIND_GLOBAL:
|
||||||
if (index
|
if (index
|
||||||
|
@ -2135,6 +2317,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
set_error_buf(error_buf, error_buf_size,
|
set_error_buf(error_buf, error_buf_size,
|
||||||
"invalid export kind");
|
"invalid export kind");
|
||||||
|
@ -2541,6 +2724,83 @@ fail:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
static bool
|
||||||
|
load_tag_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_code,
|
||||||
|
const uint8 *buf_code_end, WASMModule *module, char *error_buf,
|
||||||
|
uint32 error_buf_size)
|
||||||
|
{
|
||||||
|
(void)buf_code;
|
||||||
|
(void)buf_code_end;
|
||||||
|
|
||||||
|
const uint8 *p = buf, *p_end = buf_end;
|
||||||
|
size_t total_size = 0;
|
||||||
|
/* number of tags defined in the section */
|
||||||
|
uint32 section_tag_count = 0;
|
||||||
|
uint8 tag_attribute;
|
||||||
|
uint32 tag_type;
|
||||||
|
WASMTag *tag = NULL;
|
||||||
|
|
||||||
|
/* get tag count */
|
||||||
|
read_leb_uint32(p, p_end, section_tag_count);
|
||||||
|
module->tag_count = section_tag_count;
|
||||||
|
|
||||||
|
if (section_tag_count) {
|
||||||
|
total_size = sizeof(WASMTag *) * module->tag_count;
|
||||||
|
if (!(module->tags =
|
||||||
|
loader_malloc(total_size, error_buf, error_buf_size))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* load each tag, imported tags precede the tags */
|
||||||
|
uint32 tag_index;
|
||||||
|
for (tag_index = 0; tag_index < section_tag_count; tag_index++) {
|
||||||
|
|
||||||
|
/* get the one byte attribute */
|
||||||
|
CHECK_BUF(p, p_end, 1);
|
||||||
|
tag_attribute = read_uint8(p);
|
||||||
|
|
||||||
|
/* get type */
|
||||||
|
read_leb_uint32(p, p_end, tag_type);
|
||||||
|
/* compare against module->types */
|
||||||
|
if (tag_type >= module->type_count) {
|
||||||
|
set_error_buf(error_buf, error_buf_size, "unknown type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get return type (must be 0) */
|
||||||
|
/* check, that the type of the referred tag returns void */
|
||||||
|
WASMType *func_type = (WASMType *)module->types[tag_type];
|
||||||
|
if (func_type->result_count != 0) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"non-empty tag result type");
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(tag = module->tags[tag_index] = loader_malloc(
|
||||||
|
sizeof(WASMTag), error_buf, error_buf_size))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store to module tag declarations */
|
||||||
|
tag->attribute = tag_attribute;
|
||||||
|
tag->type = tag_type;
|
||||||
|
tag->tag_type = func_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p != p_end) {
|
||||||
|
set_error_buf(error_buf, error_buf_size, "section size mismatch");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_VERBOSE("Load tag section success.\n");
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
load_code_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_func,
|
load_code_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_func,
|
||||||
const uint8 *buf_func_end, WASMModule *module,
|
const uint8 *buf_func_end, WASMModule *module,
|
||||||
|
@ -3336,6 +3596,14 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
error_buf_size))
|
error_buf_size))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
case SECTION_TYPE_TAG:
|
||||||
|
/* load tag declaration section */
|
||||||
|
if (!load_tag_section(buf, buf_end, buf_code, buf_code_end,
|
||||||
|
module, error_buf, error_buf_size))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case SECTION_TYPE_GLOBAL:
|
case SECTION_TYPE_GLOBAL:
|
||||||
if (!load_global_section(buf, buf_end, module, error_buf,
|
if (!load_global_section(buf, buf_end, module, error_buf,
|
||||||
error_buf_size))
|
error_buf_size))
|
||||||
|
@ -3805,6 +4073,9 @@ static uint8 section_ids[] = {
|
||||||
SECTION_TYPE_FUNC,
|
SECTION_TYPE_FUNC,
|
||||||
SECTION_TYPE_TABLE,
|
SECTION_TYPE_TABLE,
|
||||||
SECTION_TYPE_MEMORY,
|
SECTION_TYPE_MEMORY,
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
SECTION_TYPE_TAG,
|
||||||
|
#endif
|
||||||
SECTION_TYPE_GLOBAL,
|
SECTION_TYPE_GLOBAL,
|
||||||
SECTION_TYPE_EXPORT,
|
SECTION_TYPE_EXPORT,
|
||||||
SECTION_TYPE_START,
|
SECTION_TYPE_START,
|
||||||
|
@ -4210,6 +4481,16 @@ wasm_loader_unload(WASMModule *module)
|
||||||
if (module->memories)
|
if (module->memories)
|
||||||
wasm_runtime_free(module->memories);
|
wasm_runtime_free(module->memories);
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
if (module->tags) {
|
||||||
|
for (i = 0; i < module->tag_count; i++) {
|
||||||
|
if (module->tags[i])
|
||||||
|
wasm_runtime_free(module->tags[i]);
|
||||||
|
}
|
||||||
|
wasm_runtime_free(module->tags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (module->globals)
|
if (module->globals)
|
||||||
wasm_runtime_free(module->globals);
|
wasm_runtime_free(module->globals);
|
||||||
|
|
||||||
|
@ -4350,6 +4631,64 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
|
||||||
case WASM_OP_NOP:
|
case WASM_OP_NOP:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
case WASM_OP_TRY:
|
||||||
|
u8 = read_uint8(p);
|
||||||
|
if (block_nested_depth
|
||||||
|
< sizeof(block_stack) / sizeof(BlockAddr)) {
|
||||||
|
block_stack[block_nested_depth].start_addr = p;
|
||||||
|
block_stack[block_nested_depth].else_addr = NULL;
|
||||||
|
}
|
||||||
|
block_nested_depth++;
|
||||||
|
break;
|
||||||
|
case EXT_OP_TRY:
|
||||||
|
skip_leb_uint32(p, p_end);
|
||||||
|
if (block_nested_depth
|
||||||
|
< sizeof(block_stack) / sizeof(BlockAddr)) {
|
||||||
|
block_stack[block_nested_depth].start_addr = p;
|
||||||
|
block_stack[block_nested_depth].else_addr = NULL;
|
||||||
|
}
|
||||||
|
block_nested_depth++;
|
||||||
|
break;
|
||||||
|
case WASM_OP_CATCH:
|
||||||
|
if (block_nested_depth == 1) {
|
||||||
|
*p_end_addr = (uint8 *)(p - 1);
|
||||||
|
/* stop search and return the address of the catch block */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WASM_OP_CATCH_ALL:
|
||||||
|
if (block_nested_depth == 1) {
|
||||||
|
*p_end_addr = (uint8 *)(p - 1);
|
||||||
|
/* stop search and return the address of the catch_all block
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WASM_OP_THROW:
|
||||||
|
/* skip tag_index */
|
||||||
|
skip_leb(p);
|
||||||
|
break;
|
||||||
|
case WASM_OP_RETHROW:
|
||||||
|
/* skip depth */
|
||||||
|
skip_leb(p);
|
||||||
|
break;
|
||||||
|
case WASM_OP_DELEGATE:
|
||||||
|
if (block_nested_depth == 1) {
|
||||||
|
*p_end_addr = (uint8 *)(p - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* the DELEGATE opcode ends the tryblock, */
|
||||||
|
block_nested_depth--;
|
||||||
|
if (block_nested_depth
|
||||||
|
< sizeof(block_stack) / sizeof(BlockAddr))
|
||||||
|
block_stack[block_nested_depth].end_addr =
|
||||||
|
(uint8 *)(p - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case WASM_OP_BLOCK:
|
case WASM_OP_BLOCK:
|
||||||
case WASM_OP_LOOP:
|
case WASM_OP_LOOP:
|
||||||
case WASM_OP_IF:
|
case WASM_OP_IF:
|
||||||
|
@ -5221,6 +5560,10 @@ wasm_loader_ctx_init(WASMFunction *func, char *error_buf, uint32 error_buf_size)
|
||||||
goto fail;
|
goto fail;
|
||||||
loader_ctx->frame_csp_boundary = loader_ctx->frame_csp_bottom + 8;
|
loader_ctx->frame_csp_boundary = loader_ctx->frame_csp_bottom + 8;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
func->exception_handler_count = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_FAST_INTERP != 0
|
#if WASM_ENABLE_FAST_INTERP != 0
|
||||||
loader_ctx->frame_offset_size = sizeof(int16) * 32;
|
loader_ctx->frame_offset_size = sizeof(int16) * 32;
|
||||||
if (!(loader_ctx->frame_offset_bottom = loader_ctx->frame_offset =
|
if (!(loader_ctx->frame_offset_bottom = loader_ctx->frame_offset =
|
||||||
|
@ -6832,11 +7175,26 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check stack cell num equals return cell num */
|
|
||||||
if (available_stack_cell != return_cell_num) {
|
if (available_stack_cell != return_cell_num) {
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
/* testspec: this error message format is expected by try_catch.wast */
|
||||||
|
snprintf(
|
||||||
|
error_buf, error_buf_size, "type mismatch: %s requires [%s]%s[%s]",
|
||||||
|
block->label_type == LABEL_TYPE_TRY
|
||||||
|
|| (block->label_type == LABEL_TYPE_CATCH
|
||||||
|
&& return_cell_num > 0)
|
||||||
|
? "instruction"
|
||||||
|
: "block",
|
||||||
|
return_cell_num > 0 ? type2str(return_types[0]) : "",
|
||||||
|
" but stack has ",
|
||||||
|
available_stack_cell > 0 ? type2str(*(loader_ctx->frame_ref - 1))
|
||||||
|
: "");
|
||||||
|
goto fail;
|
||||||
|
#else
|
||||||
set_error_buf(error_buf, error_buf_size,
|
set_error_buf(error_buf, error_buf_size,
|
||||||
"type mismatch: stack size does not match block type");
|
"type mismatch: stack size does not match block type");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check stack values match return types */
|
/* Check stack values match return types */
|
||||||
|
@ -7185,6 +7543,24 @@ re_scan:
|
||||||
}
|
}
|
||||||
case WASM_OP_BLOCK:
|
case WASM_OP_BLOCK:
|
||||||
case WASM_OP_LOOP:
|
case WASM_OP_LOOP:
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
case WASM_OP_TRY:
|
||||||
|
if (opcode == WASM_OP_TRY) {
|
||||||
|
/*
|
||||||
|
* keep track of exception handlers to account for
|
||||||
|
* memory allocation
|
||||||
|
*/
|
||||||
|
func->exception_handler_count++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* try is a block
|
||||||
|
* do nothing special, but execution continues to
|
||||||
|
* to handle_op_block_and_loop,
|
||||||
|
* and that be pushes the csp
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
#if WASM_ENABLE_FAST_INTERP != 0
|
#if WASM_ENABLE_FAST_INTERP != 0
|
||||||
PRESERVE_LOCAL_FOR_BLOCK();
|
PRESERVE_LOCAL_FOR_BLOCK();
|
||||||
#endif
|
#endif
|
||||||
|
@ -7258,7 +7634,6 @@ re_scan:
|
||||||
wasm_type->types[wasm_type->param_count - i - 1]);
|
wasm_type->types[wasm_type->param_count - i - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK),
|
PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK),
|
||||||
block_type, p);
|
block_type, p);
|
||||||
|
|
||||||
|
@ -7291,6 +7666,11 @@ re_scan:
|
||||||
loader_ctx->p_code_compiled;
|
loader_ctx->p_code_compiled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
else if (opcode == WASM_OP_TRY) {
|
||||||
|
skip_label();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else if (opcode == WASM_OP_IF) {
|
else if (opcode == WASM_OP_IF) {
|
||||||
BranchBlock *block = loader_ctx->frame_csp - 1;
|
BranchBlock *block = loader_ctx->frame_csp - 1;
|
||||||
/* If block has parameters, we should make sure they are in
|
/* If block has parameters, we should make sure they are in
|
||||||
|
@ -7351,7 +7731,212 @@ re_scan:
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
case WASM_OP_THROW:
|
||||||
|
{
|
||||||
|
SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
|
||||||
|
|
||||||
|
BranchBlock *cur_block = loader_ctx->frame_csp - 1;
|
||||||
|
|
||||||
|
uint8 label_type = cur_block->label_type;
|
||||||
|
uint32 tag_index = 0;
|
||||||
|
read_leb_int32(p, p_end, tag_index);
|
||||||
|
|
||||||
|
/* check validity of tag_index against module->tag_count */
|
||||||
|
/* check tag index is within the tag index space */
|
||||||
|
if (tag_index >= module->import_tag_count + module->tag_count) {
|
||||||
|
snprintf(error_buf, error_buf_size, "unknown tag %d",
|
||||||
|
tag_index);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the tag_type is stored in either the WASMTag (section tags)
|
||||||
|
* or WASMTagImport (import tag) */
|
||||||
|
WASMType *tag_type = NULL;
|
||||||
|
if (tag_index < module->import_tag_count) {
|
||||||
|
tag_type = module->import_tags[tag_index].u.tag.tag_type;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tag_type =
|
||||||
|
module->tags[tag_index - module->import_tag_count]
|
||||||
|
->tag_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag_type->result_count != 0) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"tag type signature does not return void");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 available_stack_cell =
|
||||||
|
(int32)(loader_ctx->stack_cell_num
|
||||||
|
- cur_block->stack_cell_num);
|
||||||
|
|
||||||
|
/* Check stack values match return types by comparing tag param
|
||||||
|
* types with stack cells */
|
||||||
|
uint8 *frame_ref = loader_ctx->frame_ref;
|
||||||
|
for (int tti = (int32)tag_type->param_count - 1; tti >= 0;
|
||||||
|
tti--) {
|
||||||
|
if (!check_stack_top_values(frame_ref, available_stack_cell,
|
||||||
|
tag_type->types[tti], error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
|
snprintf(error_buf, error_buf_size,
|
||||||
|
"type mismatch: instruction requires [%s] but "
|
||||||
|
"stack has [%s]",
|
||||||
|
tag_type->param_count > 0
|
||||||
|
? type2str(tag_type->types[tti])
|
||||||
|
: "",
|
||||||
|
available_stack_cell > 0
|
||||||
|
? type2str(*(loader_ctx->frame_ref - 1))
|
||||||
|
: "");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
frame_ref -= wasm_value_type_cell_num(tag_type->types[tti]);
|
||||||
|
available_stack_cell -=
|
||||||
|
wasm_value_type_cell_num(tag_type->types[tti]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* throw is stack polymorphic */
|
||||||
|
(void)label_type;
|
||||||
|
RESET_STACK();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WASM_OP_RETHROW:
|
||||||
|
{
|
||||||
|
/* must be done before checking branch block */
|
||||||
|
SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true);
|
||||||
|
|
||||||
|
/* check the target catching block: LABEL_TYPE_CATCH */
|
||||||
|
if (!(frame_csp_tmp = check_branch_block(
|
||||||
|
loader_ctx, &p, p_end, error_buf, error_buf_size)))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (frame_csp_tmp->label_type != LABEL_TYPE_CATCH
|
||||||
|
&& frame_csp_tmp->label_type != LABEL_TYPE_CATCH_ALL) {
|
||||||
|
/* trap according to spectest (rethrow.wast) */
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"invalid rethrow label");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
BranchBlock *cur_block = loader_ctx->frame_csp - 1;
|
||||||
|
uint8 label_type = cur_block->label_type;
|
||||||
|
(void)label_type;
|
||||||
|
/* rethrow is stack polymorphic */
|
||||||
|
RESET_STACK();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WASM_OP_DELEGATE:
|
||||||
|
{
|
||||||
|
/* check target block is valid */
|
||||||
|
if (!(frame_csp_tmp = check_branch_block(
|
||||||
|
loader_ctx, &p, p_end, error_buf, error_buf_size)))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* valid types */
|
||||||
|
if (LABEL_TYPE_TRY != frame_csp_tmp->label_type) {
|
||||||
|
snprintf(error_buf, error_buf_size, "unknown label");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
BranchBlock *cur_block = loader_ctx->frame_csp - 1;
|
||||||
|
uint8 label_type = cur_block->label_type;
|
||||||
|
|
||||||
|
(void)label_type;
|
||||||
|
/* DELEGATE ends the block */
|
||||||
|
POP_CSP();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WASM_OP_CATCH:
|
||||||
|
{
|
||||||
|
BranchBlock *cur_block = loader_ctx->frame_csp - 1;
|
||||||
|
|
||||||
|
uint8 label_type = cur_block->label_type;
|
||||||
|
uint32 tag_index = 0;
|
||||||
|
read_leb_int32(p, p_end, tag_index);
|
||||||
|
|
||||||
|
/* check validity of tag_index against module->tag_count */
|
||||||
|
/* check tag index is within the tag index space */
|
||||||
|
if (tag_index >= module->import_tag_count + module->tag_count) {
|
||||||
|
LOG_VERBOSE("In %s, unknown tag at WASM_OP_CATCH\n",
|
||||||
|
__FUNCTION__);
|
||||||
|
set_error_buf(error_buf, error_buf_size, "unknown tag");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the tag_type is stored in either the WASMTag (section tags)
|
||||||
|
* or WASMTagImport (import tag) */
|
||||||
|
WASMType *func_type = NULL;
|
||||||
|
if (tag_index < module->import_tag_count) {
|
||||||
|
func_type = module->import_tags[tag_index].u.tag.tag_type;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
func_type =
|
||||||
|
module->tags[tag_index - module->import_tag_count]
|
||||||
|
->tag_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (func_type->result_count != 0) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"tag type signature does not return void");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check validity of current label (expect LABEL_TYPE_TRY or
|
||||||
|
* LABEL_TYPE_CATCH) */
|
||||||
|
if ((LABEL_TYPE_CATCH != label_type)
|
||||||
|
&& (LABEL_TYPE_TRY != label_type)) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"Unexpected block sequence encountered.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockType new_block_type;
|
||||||
|
new_block_type.is_value_type = false;
|
||||||
|
new_block_type.u.type = func_type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* replace frame_csp by LABEL_TYPE_CATCH
|
||||||
|
*/
|
||||||
|
cur_block->label_type = LABEL_TYPE_CATCH;
|
||||||
|
|
||||||
|
/* RESET_STACK removes the values pushed in TRY or pervious
|
||||||
|
* CATCH Blocks */
|
||||||
|
RESET_STACK();
|
||||||
|
|
||||||
|
/* push types on the stack according to catched type */
|
||||||
|
if (BLOCK_HAS_PARAM(new_block_type)) {
|
||||||
|
for (i = 0; i < new_block_type.u.type->param_count; i++)
|
||||||
|
PUSH_TYPE(new_block_type.u.type->types[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WASM_OP_CATCH_ALL:
|
||||||
|
{
|
||||||
|
BranchBlock *cur_block = loader_ctx->frame_csp - 1;
|
||||||
|
|
||||||
|
/* expecting a TRY or CATCH, anything else will be considered an
|
||||||
|
* error */
|
||||||
|
if ((LABEL_TYPE_CATCH != cur_block->label_type)
|
||||||
|
&& (LABEL_TYPE_TRY != cur_block->label_type)) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"Unexpected block sequence encountered.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no immediates */
|
||||||
|
/* replace frame_csp by LABEL_TYPE_CATCH_ALL */
|
||||||
|
cur_block->label_type = LABEL_TYPE_CATCH_ALL;
|
||||||
|
|
||||||
|
/* RESET_STACK removes the values pushed in TRY or pervious
|
||||||
|
* CATCH Blocks */
|
||||||
|
RESET_STACK();
|
||||||
|
|
||||||
|
/* catch_all has no tagtype and therefore no parameters */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
case WASM_OP_ELSE:
|
case WASM_OP_ELSE:
|
||||||
{
|
{
|
||||||
BranchBlock *block = NULL;
|
BranchBlock *block = NULL;
|
||||||
|
|
|
@ -3259,6 +3259,17 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
|
||||||
u8 = read_uint8(p); /* 0x00 */
|
u8 = read_uint8(p); /* 0x00 */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
case WASM_OP_TRY:
|
||||||
|
case WASM_OP_CATCH:
|
||||||
|
case WASM_OP_THROW:
|
||||||
|
case WASM_OP_RETHROW:
|
||||||
|
case WASM_OP_DELEGATE:
|
||||||
|
case WASM_OP_CATCH_ALL:
|
||||||
|
/* TODO */
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
case WASM_OP_DROP:
|
case WASM_OP_DROP:
|
||||||
case WASM_OP_SELECT:
|
case WASM_OP_SELECT:
|
||||||
case WASM_OP_DROP_64:
|
case WASM_OP_DROP_64:
|
||||||
|
@ -6173,6 +6184,18 @@ re_scan:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
case WASM_OP_TRY:
|
||||||
|
case WASM_OP_CATCH:
|
||||||
|
case WASM_OP_THROW:
|
||||||
|
case WASM_OP_RETHROW:
|
||||||
|
case WASM_OP_DELEGATE:
|
||||||
|
case WASM_OP_CATCH_ALL:
|
||||||
|
/* TODO */
|
||||||
|
set_error_buf(error_buf, error_buf_size, "unsupported opcode");
|
||||||
|
goto fail;
|
||||||
|
#endif
|
||||||
|
|
||||||
case WASM_OP_DROP:
|
case WASM_OP_DROP:
|
||||||
{
|
{
|
||||||
BranchBlock *cur_block = loader_ctx->frame_csp - 1;
|
BranchBlock *cur_block = loader_ctx->frame_csp - 1;
|
||||||
|
|
|
@ -20,11 +20,10 @@ typedef enum WASMOpcode {
|
||||||
WASM_OP_LOOP = 0x03, /* loop */
|
WASM_OP_LOOP = 0x03, /* loop */
|
||||||
WASM_OP_IF = 0x04, /* if */
|
WASM_OP_IF = 0x04, /* if */
|
||||||
WASM_OP_ELSE = 0x05, /* else */
|
WASM_OP_ELSE = 0x05, /* else */
|
||||||
|
WASM_OP_TRY = 0x06, /* try */
|
||||||
WASM_OP_UNUSED_0x06 = 0x06,
|
WASM_OP_CATCH = 0x07, /* catch* */
|
||||||
WASM_OP_UNUSED_0x07 = 0x07,
|
WASM_OP_THROW = 0x08, /* throw of a try catch */
|
||||||
WASM_OP_UNUSED_0x08 = 0x08,
|
WASM_OP_RETHROW = 0x09, /* rethrow of a try catch */
|
||||||
WASM_OP_UNUSED_0x09 = 0x09,
|
|
||||||
WASM_OP_UNUSED_0x0a = 0x0a,
|
WASM_OP_UNUSED_0x0a = 0x0a,
|
||||||
|
|
||||||
WASM_OP_END = 0x0b, /* end */
|
WASM_OP_END = 0x0b, /* end */
|
||||||
|
@ -41,8 +40,9 @@ typedef enum WASMOpcode {
|
||||||
WASM_OP_UNUSED_0x15 = 0x15,
|
WASM_OP_UNUSED_0x15 = 0x15,
|
||||||
WASM_OP_UNUSED_0x16 = 0x16,
|
WASM_OP_UNUSED_0x16 = 0x16,
|
||||||
WASM_OP_UNUSED_0x17 = 0x17,
|
WASM_OP_UNUSED_0x17 = 0x17,
|
||||||
WASM_OP_UNUSED_0x18 = 0x18,
|
|
||||||
WASM_OP_UNUSED_0x19 = 0x19,
|
WASM_OP_DELEGATE = 0x18, /* delegate block of the try catch*/
|
||||||
|
WASM_OP_CATCH_ALL = 0x19, /* a catch_all handler in a try block */
|
||||||
|
|
||||||
/* parametric instructions */
|
/* parametric instructions */
|
||||||
WASM_OP_DROP = 0x1a, /* drop */
|
WASM_OP_DROP = 0x1a, /* drop */
|
||||||
|
@ -268,8 +268,10 @@ typedef enum WASMOpcode {
|
||||||
EXT_OP_IF = 0xd5, /* if with blocktype */
|
EXT_OP_IF = 0xd5, /* if with blocktype */
|
||||||
EXT_OP_BR_TABLE_CACHE = 0xd6, /* br_table from cache */
|
EXT_OP_BR_TABLE_CACHE = 0xd6, /* br_table from cache */
|
||||||
|
|
||||||
|
EXT_OP_TRY = 0xd7, /* try block with blocktype */
|
||||||
|
|
||||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||||
DEBUG_OP_BREAK = 0xd7, /* debug break point */
|
DEBUG_OP_BREAK = 0xd8, /* debug break point */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Post-MVP extend op prefix */
|
/* Post-MVP extend op prefix */
|
||||||
|
@ -703,10 +705,10 @@ typedef enum WASMAtomicEXTOpcode {
|
||||||
HANDLE_OPCODE(WASM_OP_LOOP), /* 0x03 */ \
|
HANDLE_OPCODE(WASM_OP_LOOP), /* 0x03 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_IF), /* 0x04 */ \
|
HANDLE_OPCODE(WASM_OP_IF), /* 0x04 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_ELSE), /* 0x05 */ \
|
HANDLE_OPCODE(WASM_OP_ELSE), /* 0x05 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x06), /* 0x06 */ \
|
HANDLE_OPCODE(WASM_OP_TRY), /* 0x06 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x07), /* 0x07 */ \
|
HANDLE_OPCODE(WASM_OP_CATCH), /* 0x07 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x08), /* 0x08 */ \
|
HANDLE_OPCODE(WASM_OP_THROW), /* 0x08 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x09), /* 0x09 */ \
|
HANDLE_OPCODE(WASM_OP_RETHROW), /* 0x09 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x0a), /* 0x0a */ \
|
HANDLE_OPCODE(WASM_OP_UNUSED_0x0a), /* 0x0a */ \
|
||||||
HANDLE_OPCODE(WASM_OP_END), /* 0x0b */ \
|
HANDLE_OPCODE(WASM_OP_END), /* 0x0b */ \
|
||||||
HANDLE_OPCODE(WASM_OP_BR), /* 0x0c */ \
|
HANDLE_OPCODE(WASM_OP_BR), /* 0x0c */ \
|
||||||
|
@ -721,8 +723,8 @@ typedef enum WASMAtomicEXTOpcode {
|
||||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x15), /* 0x15 */ \
|
HANDLE_OPCODE(WASM_OP_UNUSED_0x15), /* 0x15 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x16), /* 0x16 */ \
|
HANDLE_OPCODE(WASM_OP_UNUSED_0x16), /* 0x16 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x17), /* 0x17 */ \
|
HANDLE_OPCODE(WASM_OP_UNUSED_0x17), /* 0x17 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x18), /* 0x18 */ \
|
HANDLE_OPCODE(WASM_OP_DELEGATE), /* 0x18 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_UNUSED_0x19), /* 0x19 */ \
|
HANDLE_OPCODE(WASM_OP_CATCH_ALL), /* 0x19 */ \
|
||||||
HANDLE_OPCODE(WASM_OP_DROP), /* 0x1a */ \
|
HANDLE_OPCODE(WASM_OP_DROP), /* 0x1a */ \
|
||||||
HANDLE_OPCODE(WASM_OP_SELECT), /* 0x1b */ \
|
HANDLE_OPCODE(WASM_OP_SELECT), /* 0x1b */ \
|
||||||
HANDLE_OPCODE(WASM_OP_SELECT_T), /* 0x1c */ \
|
HANDLE_OPCODE(WASM_OP_SELECT_T), /* 0x1c */ \
|
||||||
|
@ -912,6 +914,7 @@ typedef enum WASMAtomicEXTOpcode {
|
||||||
HANDLE_OPCODE(EXT_OP_LOOP), /* 0xd4 */ \
|
HANDLE_OPCODE(EXT_OP_LOOP), /* 0xd4 */ \
|
||||||
HANDLE_OPCODE(EXT_OP_IF), /* 0xd5 */ \
|
HANDLE_OPCODE(EXT_OP_IF), /* 0xd5 */ \
|
||||||
HANDLE_OPCODE(EXT_OP_BR_TABLE_CACHE), /* 0xd6 */ \
|
HANDLE_OPCODE(EXT_OP_BR_TABLE_CACHE), /* 0xd6 */ \
|
||||||
|
HANDLE_OPCODE(EXT_OP_TRY), /* 0xd7 */ \
|
||||||
SET_GOTO_TABLE_ELEM(WASM_OP_MISC_PREFIX), /* 0xfc */ \
|
SET_GOTO_TABLE_ELEM(WASM_OP_MISC_PREFIX), /* 0xfc */ \
|
||||||
SET_GOTO_TABLE_SIMD_PREFIX_ELEM() /* 0xfd */ \
|
SET_GOTO_TABLE_SIMD_PREFIX_ELEM() /* 0xfd */ \
|
||||||
SET_GOTO_TABLE_ELEM(WASM_OP_ATOMIC_PREFIX), /* 0xfe */ \
|
SET_GOTO_TABLE_ELEM(WASM_OP_ATOMIC_PREFIX), /* 0xfe */ \
|
||||||
|
|
|
@ -732,6 +732,101 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
|
||||||
return functions;
|
return functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
/**
|
||||||
|
* Destroy tags instances.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
tags_deinstantiate(WASMTagInstance *tags, void **import_tag_ptrs)
|
||||||
|
{
|
||||||
|
if (tags) {
|
||||||
|
wasm_runtime_free(tags);
|
||||||
|
}
|
||||||
|
if (import_tag_ptrs) {
|
||||||
|
wasm_runtime_free(import_tag_ptrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate tags in a module.
|
||||||
|
*/
|
||||||
|
static WASMTagInstance *
|
||||||
|
tags_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
|
||||||
|
char *error_buf, uint32 error_buf_size)
|
||||||
|
{
|
||||||
|
WASMImport *import;
|
||||||
|
uint32 i, tag_count = module->import_tag_count + module->tag_count;
|
||||||
|
uint64 total_size = sizeof(WASMTagInstance) * (uint64)tag_count;
|
||||||
|
WASMTagInstance *tags, *tag;
|
||||||
|
|
||||||
|
if (!(tags = runtime_malloc(total_size, error_buf, error_buf_size))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_size = sizeof(void *) * (uint64)module->import_tag_count;
|
||||||
|
if (total_size > 0
|
||||||
|
&& !(module_inst->e->import_tag_ptrs =
|
||||||
|
runtime_malloc(total_size, error_buf, error_buf_size))) {
|
||||||
|
wasm_runtime_free(tags);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* instantiate tags from import section */
|
||||||
|
tag = tags;
|
||||||
|
import = module->import_tags;
|
||||||
|
for (i = 0; i < module->import_tag_count; i++, import++) {
|
||||||
|
tag->is_import_tag = true;
|
||||||
|
tag->u.tag_import = &import->u.tag;
|
||||||
|
tag->type = import->u.tag.type;
|
||||||
|
tag->attribute = import->u.tag.attribute;
|
||||||
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
|
if (import->u.tag.import_module) {
|
||||||
|
if (!(tag->import_module_inst = get_sub_module_inst(
|
||||||
|
module_inst, import->u.tag.import_module))) {
|
||||||
|
set_error_buf(error_buf, error_buf_size, "unknown tag");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(tag->import_tag_inst =
|
||||||
|
wasm_lookup_tag(tag->import_module_inst,
|
||||||
|
import->u.tag.field_name, NULL))) {
|
||||||
|
set_error_buf(error_buf, error_buf_size, "unknown tag");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the imported tag to current instance */
|
||||||
|
module_inst->e->import_tag_ptrs[i] =
|
||||||
|
tag->u.tag_import->import_tag_linked;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
tag++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* instantiate tags from tag section */
|
||||||
|
for (i = 0; i < module->tag_count; i++) {
|
||||||
|
tag->is_import_tag = false;
|
||||||
|
tag->type = module->tags[i]->type;
|
||||||
|
tag->u.tag = module->tags[i];
|
||||||
|
|
||||||
|
#if WASM_ENABLE_FAST_INTERP != 0
|
||||||
|
/* tag->const_cell_num = function->u.func->const_cell_num; */
|
||||||
|
#endif
|
||||||
|
tag++;
|
||||||
|
}
|
||||||
|
bh_assert((uint32)(tag - tags) == tag_count);
|
||||||
|
|
||||||
|
return tags;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
|
fail:
|
||||||
|
tags_deinstantiate(tags, module_inst->e->import_tag_ptrs);
|
||||||
|
/* clean up */
|
||||||
|
module_inst->e->import_tag_ptrs = NULL;
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy global instances.
|
* Destroy global instances.
|
||||||
*/
|
*/
|
||||||
|
@ -931,6 +1026,52 @@ export_functions_instantiate(const WASMModule *module,
|
||||||
return export_funcs;
|
return export_funcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
/**
|
||||||
|
* Destroy export function instances.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
export_tags_deinstantiate(WASMExportTagInstance *tags)
|
||||||
|
{
|
||||||
|
if (tags)
|
||||||
|
wasm_runtime_free(tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate export functions in a module.
|
||||||
|
*/
|
||||||
|
static WASMExportTagInstance *
|
||||||
|
export_tags_instantiate(const WASMModule *module,
|
||||||
|
WASMModuleInstance *module_inst,
|
||||||
|
uint32 export_tag_count, char *error_buf,
|
||||||
|
uint32 error_buf_size)
|
||||||
|
{
|
||||||
|
WASMExportTagInstance *export_tags, *export_tag;
|
||||||
|
WASMExport *export = module->exports;
|
||||||
|
uint32 i;
|
||||||
|
uint64 total_size =
|
||||||
|
sizeof(WASMExportTagInstance) * (uint64)export_tag_count;
|
||||||
|
|
||||||
|
if (!(export_tag = export_tags =
|
||||||
|
runtime_malloc(total_size, error_buf, error_buf_size))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < module->export_count; i++, export ++)
|
||||||
|
if (export->kind == EXPORT_KIND_TAG) {
|
||||||
|
export_tag->name = export->name;
|
||||||
|
|
||||||
|
bh_assert((uint32)(module_inst->export_tags));
|
||||||
|
|
||||||
|
export_tag->tag = &module_inst->e->tags[export->index];
|
||||||
|
export_tag++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bh_assert((uint32)(export_tag - export_tags) == export_tag_count);
|
||||||
|
return export_tags;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
static void
|
static void
|
||||||
export_globals_deinstantiate(WASMExportGlobInstance *globals)
|
export_globals_deinstantiate(WASMExportGlobInstance *globals)
|
||||||
|
@ -1720,6 +1861,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||||
module_inst->table_count = module->import_table_count + module->table_count;
|
module_inst->table_count = module->import_table_count + module->table_count;
|
||||||
module_inst->e->function_count =
|
module_inst->e->function_count =
|
||||||
module->import_function_count + module->function_count;
|
module->import_function_count + module->function_count;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
module_inst->e->tag_count = module->import_tag_count + module->tag_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* export */
|
/* export */
|
||||||
module_inst->export_func_count = get_export_count(module, EXPORT_KIND_FUNC);
|
module_inst->export_func_count = get_export_count(module, EXPORT_KIND_FUNC);
|
||||||
|
@ -1728,11 +1872,15 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||||
get_export_count(module, EXPORT_KIND_TABLE);
|
get_export_count(module, EXPORT_KIND_TABLE);
|
||||||
module_inst->export_memory_count =
|
module_inst->export_memory_count =
|
||||||
get_export_count(module, EXPORT_KIND_MEMORY);
|
get_export_count(module, EXPORT_KIND_MEMORY);
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
module_inst->e->export_tag_count =
|
||||||
|
get_export_count(module, EXPORT_KIND_TAG);
|
||||||
|
#endif
|
||||||
module_inst->export_global_count =
|
module_inst->export_global_count =
|
||||||
get_export_count(module, EXPORT_KIND_GLOBAL);
|
get_export_count(module, EXPORT_KIND_GLOBAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Instantiate memories/tables/functions */
|
/* Instantiate memories/tables/functions/tags */
|
||||||
if ((module_inst->memory_count > 0
|
if ((module_inst->memory_count > 0
|
||||||
&& !(module_inst->memories =
|
&& !(module_inst->memories =
|
||||||
memories_instantiate(module, module_inst, parent, heap_size,
|
memories_instantiate(module, module_inst, parent, heap_size,
|
||||||
|
@ -1748,6 +1896,15 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||||
&& !(module_inst->export_functions = export_functions_instantiate(
|
&& !(module_inst->export_functions = export_functions_instantiate(
|
||||||
module, module_inst, module_inst->export_func_count,
|
module, module_inst, module_inst->export_func_count,
|
||||||
error_buf, error_buf_size)))
|
error_buf, error_buf_size)))
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
|| (module_inst->e->tag_count > 0
|
||||||
|
&& !(module_inst->e->tags = tags_instantiate(
|
||||||
|
module, module_inst, error_buf, error_buf_size)))
|
||||||
|
|| (module_inst->e->export_tag_count > 0
|
||||||
|
&& !(module_inst->e->export_tags = export_tags_instantiate(
|
||||||
|
module, module_inst, module_inst->e->export_tag_count,
|
||||||
|
error_buf, error_buf_size)))
|
||||||
|
#endif
|
||||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
|| (module_inst->export_global_count > 0
|
|| (module_inst->export_global_count > 0
|
||||||
&& !(module_inst->export_globals = export_globals_instantiate(
|
&& !(module_inst->export_globals = export_globals_instantiate(
|
||||||
|
@ -1765,7 +1922,6 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||||
) {
|
) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global_count > 0) {
|
if (global_count > 0) {
|
||||||
/* Initialize the global data */
|
/* Initialize the global data */
|
||||||
global_data = module_inst->global_data;
|
global_data = module_inst->global_data;
|
||||||
|
@ -2188,8 +2344,16 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
||||||
tables_deinstantiate(module_inst);
|
tables_deinstantiate(module_inst);
|
||||||
functions_deinstantiate(module_inst->e->functions,
|
functions_deinstantiate(module_inst->e->functions,
|
||||||
module_inst->e->function_count);
|
module_inst->e->function_count);
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
tags_deinstantiate(module_inst->e->tags, module_inst->e->import_tag_ptrs);
|
||||||
|
#endif
|
||||||
|
|
||||||
globals_deinstantiate(module_inst->e->globals);
|
globals_deinstantiate(module_inst->e->globals);
|
||||||
export_functions_deinstantiate(module_inst->export_functions);
|
export_functions_deinstantiate(module_inst->export_functions);
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
export_tags_deinstantiate(module_inst->e->export_tags);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
export_globals_deinstantiate(module_inst->export_globals);
|
export_globals_deinstantiate(module_inst->export_globals);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2270,6 +2434,21 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name)
|
||||||
(void)module_inst->export_tables;
|
(void)module_inst->export_tables;
|
||||||
return module_inst->tables[0];
|
return module_inst->tables[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
WASMTagInstance *
|
||||||
|
wasm_lookup_tag(const WASMModuleInstance *module_inst, const char *name,
|
||||||
|
const char *signature)
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
for (i = 0; i < module_inst->e->export_tag_count; i++)
|
||||||
|
if (!strcmp(module_inst->e->export_tags[i].name, name))
|
||||||
|
return module_inst->e->export_tags[i].tag;
|
||||||
|
(void)signature;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||||
|
|
|
@ -28,6 +28,9 @@ typedef struct WASMFunctionInstance WASMFunctionInstance;
|
||||||
typedef struct WASMMemoryInstance WASMMemoryInstance;
|
typedef struct WASMMemoryInstance WASMMemoryInstance;
|
||||||
typedef struct WASMTableInstance WASMTableInstance;
|
typedef struct WASMTableInstance WASMTableInstance;
|
||||||
typedef struct WASMGlobalInstance WASMGlobalInstance;
|
typedef struct WASMGlobalInstance WASMGlobalInstance;
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
typedef struct WASMTagInstance WASMTagInstance;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When LLVM JIT, WAMR compiler or AOT is enabled, we should ensure that
|
* When LLVM JIT, WAMR compiler or AOT is enabled, we should ensure that
|
||||||
|
@ -191,6 +194,30 @@ struct WASMFunctionInstance {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
struct WASMTagInstance {
|
||||||
|
bool is_import_tag;
|
||||||
|
/* tag attribute */
|
||||||
|
uint8 attribute;
|
||||||
|
/* tag type index */
|
||||||
|
uint32 type;
|
||||||
|
union {
|
||||||
|
WASMTagImport *tag_import;
|
||||||
|
WASMTag *tag;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
|
WASMModuleInstance *import_module_inst;
|
||||||
|
WASMTagInstance *import_tag_inst;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||||
|
#define INVALID_TAGINDEX ((uint32)0xFFFFFFFF)
|
||||||
|
#define SET_INVALID_TAGINDEX(tag) (tag = INVALID_TAGINDEX)
|
||||||
|
#define IS_INVALID_TAGINDEX(tag) ((tag & INVALID_TAGINDEX) == INVALID_TAGINDEX)
|
||||||
|
#endif
|
||||||
typedef struct WASMExportFuncInstance {
|
typedef struct WASMExportFuncInstance {
|
||||||
char *name;
|
char *name;
|
||||||
WASMFunctionInstance *function;
|
WASMFunctionInstance *function;
|
||||||
|
@ -211,6 +238,13 @@ typedef struct WASMExportMemInstance {
|
||||||
WASMMemoryInstance *memory;
|
WASMMemoryInstance *memory;
|
||||||
} WASMExportMemInstance;
|
} WASMExportMemInstance;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
typedef struct WASMExportTagInstance {
|
||||||
|
char *name;
|
||||||
|
WASMTagInstance *tag;
|
||||||
|
} WASMExportTagInstance;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* wasm-c-api import function info */
|
/* wasm-c-api import function info */
|
||||||
typedef struct CApiFuncImport {
|
typedef struct CApiFuncImport {
|
||||||
/* host func pointer after linked */
|
/* host func pointer after linked */
|
||||||
|
@ -263,6 +297,14 @@ typedef struct WASMModuleInstanceExtra {
|
||||||
WASMTableInstance **table_insts_linked;
|
WASMTableInstance **table_insts_linked;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
uint32 tag_count;
|
||||||
|
uint32 export_tag_count;
|
||||||
|
WASMTagInstance *tags;
|
||||||
|
WASMExportTagInstance *export_tags;
|
||||||
|
void **import_tag_ptrs;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||||
uint32 max_aux_stack_used;
|
uint32 max_aux_stack_used;
|
||||||
#endif
|
#endif
|
||||||
|
@ -461,6 +503,13 @@ wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name);
|
||||||
|
|
||||||
WASMTableInstance *
|
WASMTableInstance *
|
||||||
wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name);
|
wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name);
|
||||||
|
|
||||||
|
#if WASM_ENABLE_TAGS != 0
|
||||||
|
WASMTagInstance *
|
||||||
|
wasm_lookup_tag(const WASMModuleInstance *module_inst, const char *name,
|
||||||
|
const char *signature);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -359,6 +359,14 @@ else
|
||||||
CFLAGS += -DWASM_ENABLE_REF_TYPES=0
|
CFLAGS += -DWASM_ENABLE_REF_TYPES=0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_INTERPRETERS_WAMR_ENABLE_EXCE_HANDLING),y)
|
||||||
|
CFLAGS += -DWASM_ENABLE_EXCE_HANDLING=1
|
||||||
|
CFLAGS += -DWASM_ENABLE_TAGS=1
|
||||||
|
else
|
||||||
|
CFLAGS += -DWASM_ENABLE_EXCE_HANDLING=0
|
||||||
|
CFLAGS += -DWASM_ENABLE_TAGS=0
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += -Wno-strict-prototypes -Wno-shadow -Wno-unused-variable
|
CFLAGS += -Wno-strict-prototypes -Wno-shadow -Wno-unused-variable
|
||||||
CFLAGS += -Wno-int-conversion -Wno-implicit-function-declaration
|
CFLAGS += -Wno-int-conversion -Wno-implicit-function-declaration
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ IWASM_CMD = get_iwasm_cmd(PLATFORM_NAME)
|
||||||
IWASM_SGX_CMD = "../../../product-mini/platforms/linux-sgx/enclave-sample/iwasm"
|
IWASM_SGX_CMD = "../../../product-mini/platforms/linux-sgx/enclave-sample/iwasm"
|
||||||
IWASM_QEMU_CMD = "iwasm"
|
IWASM_QEMU_CMD = "iwasm"
|
||||||
SPEC_TEST_DIR = "spec/test/core"
|
SPEC_TEST_DIR = "spec/test/core"
|
||||||
|
EXCE_HANDLING_DIR = "exception-handling/test/core"
|
||||||
WAST2WASM_CMD = exe_file_path("./wabt/out/gcc/Release/wat2wasm")
|
WAST2WASM_CMD = exe_file_path("./wabt/out/gcc/Release/wat2wasm")
|
||||||
SPEC_INTERPRETER_CMD = "spec/interpreter/wasm"
|
SPEC_INTERPRETER_CMD = "spec/interpreter/wasm"
|
||||||
WAMRC_CMD = "../../../wamr-compiler/build/wamrc"
|
WAMRC_CMD = "../../../wamr-compiler/build/wamrc"
|
||||||
|
@ -78,8 +79,10 @@ def ignore_the_case(
|
||||||
simd_flag=False,
|
simd_flag=False,
|
||||||
gc_flag=False,
|
gc_flag=False,
|
||||||
xip_flag=False,
|
xip_flag=False,
|
||||||
|
eh_flag=False,
|
||||||
qemu_flag=False,
|
qemu_flag=False,
|
||||||
):
|
):
|
||||||
|
|
||||||
if case_name in ["comments", "inline-module", "names"]:
|
if case_name in ["comments", "inline-module", "names"]:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -126,7 +129,7 @@ def ignore_the_case(
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def preflight_check(aot_flag):
|
def preflight_check(aot_flag, eh_flag):
|
||||||
if not pathlib.Path(SPEC_TEST_DIR).resolve().exists():
|
if not pathlib.Path(SPEC_TEST_DIR).resolve().exists():
|
||||||
print(f"Can not find {SPEC_TEST_DIR}")
|
print(f"Can not find {SPEC_TEST_DIR}")
|
||||||
return False
|
return False
|
||||||
|
@ -139,6 +142,10 @@ def preflight_check(aot_flag):
|
||||||
print(f"Can not find {WAMRC_CMD}")
|
print(f"Can not find {WAMRC_CMD}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if eh_flag and not pathlib.Path(EXCE_HANDLING_DIR).resolve().exists():
|
||||||
|
print(f"Can not find {EXCE_HANDLING_DIR}")
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,6 +158,7 @@ def test_case(
|
||||||
multi_thread_flag=False,
|
multi_thread_flag=False,
|
||||||
simd_flag=False,
|
simd_flag=False,
|
||||||
xip_flag=False,
|
xip_flag=False,
|
||||||
|
eh_flag=False,
|
||||||
clean_up_flag=True,
|
clean_up_flag=True,
|
||||||
verbose_flag=True,
|
verbose_flag=True,
|
||||||
gc_flag=False,
|
gc_flag=False,
|
||||||
|
@ -195,6 +203,9 @@ def test_case(
|
||||||
if xip_flag:
|
if xip_flag:
|
||||||
CMD.append("--xip")
|
CMD.append("--xip")
|
||||||
|
|
||||||
|
if eh_flag:
|
||||||
|
CMD.append("--eh")
|
||||||
|
|
||||||
if qemu_flag:
|
if qemu_flag:
|
||||||
CMD.append("--qemu")
|
CMD.append("--qemu")
|
||||||
CMD.append("--qemu-firmware")
|
CMD.append("--qemu-firmware")
|
||||||
|
@ -268,6 +279,7 @@ def test_suite(
|
||||||
multi_thread_flag=False,
|
multi_thread_flag=False,
|
||||||
simd_flag=False,
|
simd_flag=False,
|
||||||
xip_flag=False,
|
xip_flag=False,
|
||||||
|
eh_flag=False,
|
||||||
clean_up_flag=True,
|
clean_up_flag=True,
|
||||||
verbose_flag=True,
|
verbose_flag=True,
|
||||||
gc_flag=False,
|
gc_flag=False,
|
||||||
|
@ -291,6 +303,15 @@ def test_suite(
|
||||||
gc_case_list = sorted(suite_path.glob("gc/*.wast"))
|
gc_case_list = sorted(suite_path.glob("gc/*.wast"))
|
||||||
case_list.extend(gc_case_list)
|
case_list.extend(gc_case_list)
|
||||||
|
|
||||||
|
if eh_flag:
|
||||||
|
eh_path = pathlib.Path(EXCE_HANDLING_DIR).resolve()
|
||||||
|
if not eh_path.exists():
|
||||||
|
print(f"can not find spec test cases at {eh_path}")
|
||||||
|
return False
|
||||||
|
eh_case_list = sorted(eh_path.glob("*.wast"))
|
||||||
|
eh_case_list_include = [test for test in eh_case_list if test.stem in ["throw", "tag", "try_catch", "rethrow", "try_delegate"]]
|
||||||
|
case_list.extend(eh_case_list_include)
|
||||||
|
|
||||||
# ignore based on command line options
|
# ignore based on command line options
|
||||||
filtered_case_list = []
|
filtered_case_list = []
|
||||||
for case_path in case_list:
|
for case_path in case_list:
|
||||||
|
@ -305,6 +326,7 @@ def test_suite(
|
||||||
simd_flag,
|
simd_flag,
|
||||||
gc_flag,
|
gc_flag,
|
||||||
xip_flag,
|
xip_flag,
|
||||||
|
eh_flag,
|
||||||
qemu_flag,
|
qemu_flag,
|
||||||
):
|
):
|
||||||
filtered_case_list.append(case_path)
|
filtered_case_list.append(case_path)
|
||||||
|
@ -331,6 +353,7 @@ def test_suite(
|
||||||
multi_thread_flag,
|
multi_thread_flag,
|
||||||
simd_flag,
|
simd_flag,
|
||||||
xip_flag,
|
xip_flag,
|
||||||
|
eh_flag,
|
||||||
clean_up_flag,
|
clean_up_flag,
|
||||||
verbose_flag,
|
verbose_flag,
|
||||||
gc_flag,
|
gc_flag,
|
||||||
|
@ -369,6 +392,7 @@ def test_suite(
|
||||||
multi_thread_flag,
|
multi_thread_flag,
|
||||||
simd_flag,
|
simd_flag,
|
||||||
xip_flag,
|
xip_flag,
|
||||||
|
eh_flag,
|
||||||
clean_up_flag,
|
clean_up_flag,
|
||||||
verbose_flag,
|
verbose_flag,
|
||||||
gc_flag,
|
gc_flag,
|
||||||
|
@ -428,6 +452,14 @@ def main():
|
||||||
dest="xip_flag",
|
dest="xip_flag",
|
||||||
help="Running with the XIP feature",
|
help="Running with the XIP feature",
|
||||||
)
|
)
|
||||||
|
# added to support WASM_ENABLE_EXCE_HANDLING
|
||||||
|
parser.add_argument(
|
||||||
|
"-e",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
dest="eh_flag",
|
||||||
|
help="Running with the exception-handling feature",
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-t",
|
"-t",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
|
@ -508,7 +540,7 @@ def main():
|
||||||
if options.target == "x86_32":
|
if options.target == "x86_32":
|
||||||
options.target = "i386"
|
options.target = "i386"
|
||||||
|
|
||||||
if not preflight_check(options.aot_flag):
|
if not preflight_check(options.aot_flag, options.eh_flag):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not options.cases:
|
if not options.cases:
|
||||||
|
@ -527,6 +559,7 @@ def main():
|
||||||
options.multi_thread_flag,
|
options.multi_thread_flag,
|
||||||
options.simd_flag,
|
options.simd_flag,
|
||||||
options.xip_flag,
|
options.xip_flag,
|
||||||
|
options.eh_flag,
|
||||||
options.clean_up_flag,
|
options.clean_up_flag,
|
||||||
options.verbose_flag,
|
options.verbose_flag,
|
||||||
options.gc_flag,
|
options.gc_flag,
|
||||||
|
@ -552,6 +585,7 @@ def main():
|
||||||
options.multi_thread_flag,
|
options.multi_thread_flag,
|
||||||
options.simd_flag,
|
options.simd_flag,
|
||||||
options.xip_flag,
|
options.xip_flag,
|
||||||
|
options.eh_flag,
|
||||||
options.clean_up_flag,
|
options.clean_up_flag,
|
||||||
options.verbose_flag,
|
options.verbose_flag,
|
||||||
options.gc_flag,
|
options.gc_flag,
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
diff --git a/test/core/try_catch.wast b/test/core/try_catch.wast
|
||||||
|
index 2a0e9ff6..f243489d 100644
|
||||||
|
--- a/test/core/try_catch.wast
|
||||||
|
+++ b/test/core/try_catch.wast
|
||||||
|
@@ -203,7 +203,6 @@
|
||||||
|
|
||||||
|
(assert_return (invoke "catch-param-i32" (i32.const 5)) (i32.const 5))
|
||||||
|
|
||||||
|
-(assert_return (invoke "catch-imported") (i32.const 2))
|
||||||
|
|
||||||
|
(assert_return (invoke "catchless-try" (i32.const 0)) (i32.const 0))
|
||||||
|
(assert_return (invoke "catchless-try" (i32.const 1)) (i32.const 1))
|
||||||
|
@@ -231,7 +230,6 @@
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
-(assert_return (invoke "imported-mismatch") (i32.const 3))
|
||||||
|
|
||||||
|
(assert_malformed
|
||||||
|
(module quote "(module (func (catch_all)))")
|
|
@ -301,6 +301,9 @@ parser.add_argument('--simd', default=False, action='store_true',
|
||||||
parser.add_argument('--xip', default=False, action='store_true',
|
parser.add_argument('--xip', default=False, action='store_true',
|
||||||
help="Enable XIP")
|
help="Enable XIP")
|
||||||
|
|
||||||
|
parser.add_argument('--eh', default=False, action='store_true',
|
||||||
|
help="Enable Exception Handling")
|
||||||
|
|
||||||
parser.add_argument('--multi-module', default=False, action='store_true',
|
parser.add_argument('--multi-module', default=False, action='store_true',
|
||||||
help="Enable Multi-thread")
|
help="Enable Multi-thread")
|
||||||
|
|
||||||
|
@ -762,6 +765,13 @@ def test_assert(r, opts, mode, cmd, expected):
|
||||||
if o.find(e) >= 0 or e.find(o) >= 0:
|
if o.find(e) >= 0 or e.find(o) >= 0:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# wasm-exception thrown out of function call, not a trap
|
||||||
|
if mode=='wasmexception':
|
||||||
|
o = re.sub('^Exception: ', '', out)
|
||||||
|
e = re.sub('^Exception: ', '', expected)
|
||||||
|
if o.find(e) >= 0 or e.find(o) >= 0:
|
||||||
|
return True
|
||||||
|
|
||||||
## 0x9:i32,-0x1:i32 -> ['0x9:i32', '-0x1:i32']
|
## 0x9:i32,-0x1:i32 -> ['0x9:i32', '-0x1:i32']
|
||||||
expected_list = re.split(',', expected)
|
expected_list = re.split(',', expected)
|
||||||
out_list = re.split(',', out)
|
out_list = re.split(',', out)
|
||||||
|
@ -987,6 +997,42 @@ def test_assert_exhaustion(r,opts,form):
|
||||||
expected = "Exception: %s\n" % m.group(3)
|
expected = "Exception: %s\n" % m.group(3)
|
||||||
test_assert(r, opts, "exhaustion", "%s %s" % (func, " ".join(args)), expected)
|
test_assert(r, opts, "exhaustion", "%s %s" % (func, " ".join(args)), expected)
|
||||||
|
|
||||||
|
|
||||||
|
# added to support WASM_ENABLE_EXCE_HANDLING
|
||||||
|
def test_assert_wasmexception(r,opts,form):
|
||||||
|
# params
|
||||||
|
|
||||||
|
# ^
|
||||||
|
# \(assert_exception\s+
|
||||||
|
# \(invoke\s+"([^"]+)"\s+
|
||||||
|
# (\(.*\))\s*
|
||||||
|
# ()
|
||||||
|
# \)\s*
|
||||||
|
# \)\s*
|
||||||
|
# $
|
||||||
|
m = re.search('^\(assert_exception\s+\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*\)\s*$', form)
|
||||||
|
if not m:
|
||||||
|
# no params
|
||||||
|
|
||||||
|
# ^
|
||||||
|
# \(assert_exception\s+
|
||||||
|
# \(invoke\s+"([^"]+)"\s*
|
||||||
|
# ()
|
||||||
|
# \)\s*
|
||||||
|
# \)\s*
|
||||||
|
# $
|
||||||
|
m = re.search('^\(assert_exception\s+\(invoke\s+"([^"]+)"\s*()\)\s*\)\s*$', form)
|
||||||
|
if not m:
|
||||||
|
raise Exception("unparsed assert_exception: '%s'" % form)
|
||||||
|
func = m.group(1) # function name
|
||||||
|
if m.group(2) == '': # arguments
|
||||||
|
args = []
|
||||||
|
else:
|
||||||
|
args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])]
|
||||||
|
|
||||||
|
expected = "Exception: uncaught wasm exception\n"
|
||||||
|
test_assert(r, opts, "wasmexception", "%s %s" % (func, " ".join(args)), expected)
|
||||||
|
|
||||||
def do_invoke(r, opts, form):
|
def do_invoke(r, opts, form):
|
||||||
# params
|
# params
|
||||||
m = re.search('^\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*$', form)
|
m = re.search('^\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*$', form)
|
||||||
|
@ -1025,6 +1071,8 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts):
|
||||||
# default arguments
|
# default arguments
|
||||||
if opts.gc:
|
if opts.gc:
|
||||||
cmd = [opts.wast2wasm, "-u", "-d", wast_tempfile, "-o", wasm_tempfile]
|
cmd = [opts.wast2wasm, "-u", "-d", wast_tempfile, "-o", wasm_tempfile]
|
||||||
|
elif opts.eh:
|
||||||
|
cmd = [opts.wast2wasm, "--enable-thread", "--no-check", "--enable-exceptions", "--enable-tail-call", wast_tempfile, "-o", wasm_tempfile ]
|
||||||
else:
|
else:
|
||||||
cmd = [opts.wast2wasm, "--enable-thread", "--no-check",
|
cmd = [opts.wast2wasm, "--enable-thread", "--no-check",
|
||||||
wast_tempfile, "-o", wasm_tempfile ]
|
wast_tempfile, "-o", wasm_tempfile ]
|
||||||
|
@ -1236,6 +1284,8 @@ if __name__ == "__main__":
|
||||||
test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r)
|
test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r)
|
||||||
elif re.match("^\(assert_exhaustion\\b.*", form):
|
elif re.match("^\(assert_exhaustion\\b.*", form):
|
||||||
test_assert_exhaustion(r, opts, form)
|
test_assert_exhaustion(r, opts, form)
|
||||||
|
elif re.match("^\(assert_exception\\b.*", form):
|
||||||
|
test_assert_wasmexception(r, opts, form)
|
||||||
elif re.match("^\(assert_unlinkable\\b.*", form):
|
elif re.match("^\(assert_unlinkable\\b.*", form):
|
||||||
test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r, False)
|
test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r, False)
|
||||||
elif re.match("^\(assert_malformed\\b.*", form):
|
elif re.match("^\(assert_malformed\\b.*", form):
|
||||||
|
|
|
@ -24,6 +24,7 @@ function help()
|
||||||
echo "-S enable SIMD feature"
|
echo "-S enable SIMD feature"
|
||||||
echo "-G enable GC feature"
|
echo "-G enable GC feature"
|
||||||
echo "-X enable XIP feature"
|
echo "-X enable XIP feature"
|
||||||
|
echo "-e enable exception handling"
|
||||||
echo "-x test SGX"
|
echo "-x test SGX"
|
||||||
echo "-w enable WASI threads"
|
echo "-w enable WASI threads"
|
||||||
echo "-b use the wabt binary release package instead of compiling from the source code"
|
echo "-b use the wabt binary release package instead of compiling from the source code"
|
||||||
|
@ -50,6 +51,7 @@ COLLECT_CODE_COVERAGE=0
|
||||||
ENABLE_SIMD=0
|
ENABLE_SIMD=0
|
||||||
ENABLE_GC=0
|
ENABLE_GC=0
|
||||||
ENABLE_XIP=0
|
ENABLE_XIP=0
|
||||||
|
ENABLE_EH=0
|
||||||
ENABLE_DEBUG_VERSION=0
|
ENABLE_DEBUG_VERSION=0
|
||||||
ENABLE_GC_HEAP_VERIFY=0
|
ENABLE_GC_HEAP_VERIFY=0
|
||||||
#unit test case arrary
|
#unit test case arrary
|
||||||
|
@ -70,7 +72,7 @@ WASI_TESTSUITE_COMMIT="ee807fc551978490bf1c277059aabfa1e589a6c2"
|
||||||
TARGET_LIST=("AARCH64" "AARCH64_VFP" "ARMV7" "ARMV7_VFP" "THUMBV7" "THUMBV7_VFP" \
|
TARGET_LIST=("AARCH64" "AARCH64_VFP" "ARMV7" "ARMV7_VFP" "THUMBV7" "THUMBV7_VFP" \
|
||||||
"RISCV32" "RISCV32_ILP32F" "RISCV32_ILP32D" "RISCV64" "RISCV64_LP64F" "RISCV64_LP64D")
|
"RISCV32" "RISCV32_ILP32F" "RISCV32_ILP32D" "RISCV64" "RISCV64_LP64F" "RISCV64_LP64D")
|
||||||
|
|
||||||
while getopts ":s:cabgvt:m:MCpSXxwPGQF:j:T:" opt
|
while getopts ":s:cabgvt:m:MCpSXexwPGQF:j:T:" opt
|
||||||
do
|
do
|
||||||
OPT_PARSED="TRUE"
|
OPT_PARSED="TRUE"
|
||||||
case $opt in
|
case $opt in
|
||||||
|
@ -145,6 +147,10 @@ do
|
||||||
echo "enable XIP feature"
|
echo "enable XIP feature"
|
||||||
ENABLE_XIP=1
|
ENABLE_XIP=1
|
||||||
;;
|
;;
|
||||||
|
e)
|
||||||
|
echo "enable exception handling feature"
|
||||||
|
ENABLE_EH=1
|
||||||
|
;;
|
||||||
x)
|
x)
|
||||||
echo "test SGX"
|
echo "test SGX"
|
||||||
SGX_OPT="--sgx"
|
SGX_OPT="--sgx"
|
||||||
|
@ -425,6 +431,26 @@ function spec_test()
|
||||||
git apply ../../spec-test-script/thread_proposal_fix_atomic_case.patch
|
git apply ../../spec-test-script/thread_proposal_fix_atomic_case.patch
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ ${ENABLE_EH} == 1 ]; then
|
||||||
|
echo "checkout exception-handling test cases"
|
||||||
|
popd
|
||||||
|
if [ ! -d "exception-handling" ];then
|
||||||
|
echo "exception-handling not exist, clone it from github"
|
||||||
|
git clone -b master --single-branch https://github.com/WebAssembly/exception-handling
|
||||||
|
fi
|
||||||
|
pushd exception-handling
|
||||||
|
|
||||||
|
# restore and clean everything
|
||||||
|
git reset --hard 51c721661b671bb7dc4b3a3acb9e079b49778d36
|
||||||
|
|
||||||
|
if [[ ${ENABLE_MULTI_MODULE} == 0 ]]; then
|
||||||
|
git apply ../../spec-test-script/exception_handling.patch
|
||||||
|
fi
|
||||||
|
|
||||||
|
popd
|
||||||
|
echo $(pwd)
|
||||||
|
fi
|
||||||
|
|
||||||
# update GC cases
|
# update GC cases
|
||||||
if [[ ${ENABLE_GC} == 1 ]]; then
|
if [[ ${ENABLE_GC} == 1 ]]; then
|
||||||
echo "checkout spec for GC proposal"
|
echo "checkout spec for GC proposal"
|
||||||
|
@ -463,6 +489,10 @@ function spec_test()
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ 1 == ${ENABLE_EH} ]]; then
|
||||||
|
ARGS_FOR_SPEC_TEST+="-e "
|
||||||
|
fi
|
||||||
|
|
||||||
# sgx only enable in interp mode and aot mode
|
# sgx only enable in interp mode and aot mode
|
||||||
if [[ ${SGX_OPT} == "--sgx" ]];then
|
if [[ ${SGX_OPT} == "--sgx" ]];then
|
||||||
if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' || $1 == 'fast-jit' ]]; then
|
if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' || $1 == 'fast-jit' ]]; then
|
||||||
|
@ -827,6 +857,10 @@ function trigger()
|
||||||
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_WASI_THREADS=1"
|
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_WASI_THREADS=1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ ${ENABLE_EH} == 1 ]]; then
|
||||||
|
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_EXCE_HANDLING=1"
|
||||||
|
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_TAIL_CALL=1"
|
||||||
|
fi
|
||||||
echo "SANITIZER IS" $WAMR_BUILD_SANITIZER
|
echo "SANITIZER IS" $WAMR_BUILD_SANITIZER
|
||||||
|
|
||||||
if [[ "$WAMR_BUILD_SANITIZER" == "ubsan" ]]; then
|
if [[ "$WAMR_BUILD_SANITIZER" == "ubsan" ]]; then
|
||||||
|
|
Loading…
Reference in New Issue
Block a user