mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-16 17:28:31 +00:00
Implement stack frame GC object tracking (#1065)
Implement stack frame GC object tracking for the reclaim root set traversing And update wamr-test-suites for latest spec cases: - Update GC spec cases to latest version - Patch spec interpreter to support building it with ocaml 4.0.8 - Fix runtest.py to ref.null result - Comment some supported cases in type-cannon and type-equivalence
This commit is contained in:
parent
baca3148e4
commit
68cdf30476
|
@ -223,11 +223,15 @@ wasm_array_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj, uint32 length,
|
|||
PUT_REF_TO_ADDR(elem_addr, init_value->gc_obj);
|
||||
}
|
||||
else if (array_type->elem_type == VALUE_TYPE_I32
|
||||
|| array_type->elem_type == VALUE_TYPE_F32
|
||||
|| array_type->elem_type == PACKED_TYPE_I8
|
||||
|| array_type->elem_type == PACKED_TYPE_I16) {
|
||||
|| array_type->elem_type == VALUE_TYPE_F32) {
|
||||
((int32 *)array_obj->elem_data)[i] = init_value->i32;
|
||||
}
|
||||
else if (array_type->elem_type == PACKED_TYPE_I8) {
|
||||
((int8 *)array_obj->elem_data)[i] = (int8)init_value->i32;
|
||||
}
|
||||
else if (array_type->elem_type == PACKED_TYPE_I16) {
|
||||
((int16 *)array_obj->elem_data)[i] = (int16)init_value->i32;
|
||||
}
|
||||
else {
|
||||
uint32 *elem_addr = (uint32 *)array_obj->elem_data + 2 * i;
|
||||
PUT_I64_TO_ADDR(elem_addr, init_value->i64);
|
||||
|
|
|
@ -205,6 +205,80 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
|||
return result;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
static uint8 *
|
||||
get_frame_ref(WASMInterpFrame *frame)
|
||||
{
|
||||
WASMFunctionInstance *cur_func = frame->function;
|
||||
unsigned all_cell_num;
|
||||
|
||||
if (!cur_func) {
|
||||
/* it's a glue frame created in wasm_interp_call_wasm,
|
||||
set all_cell_num since frame->sp == frame->lp and
|
||||
no GC object will be traversed */
|
||||
all_cell_num = 0;
|
||||
}
|
||||
else if (!frame->ip) {
|
||||
/* it's a native method frame created in
|
||||
wasm_interp_call_func_native */
|
||||
all_cell_num =
|
||||
cur_func->param_cell_num > 2 ? cur_func->param_cell_num : 2;
|
||||
}
|
||||
else {
|
||||
/* it's a wasm bytecode function frame */
|
||||
WASMFunction *cur_wasm_func = cur_func->u.func;
|
||||
all_cell_num = cur_func->param_cell_num + cur_func->local_cell_num
|
||||
+ cur_wasm_func->max_stack_cell_num
|
||||
+ cur_wasm_func->max_block_num
|
||||
* (uint32)sizeof(WASMBranchBlock) / 4;
|
||||
}
|
||||
|
||||
return (uint8 *)(frame->lp + all_cell_num);
|
||||
}
|
||||
|
||||
static void
|
||||
init_frame_refs(uint8 *frame_ref, uint32 cell_num, WASMFuncType *func_type)
|
||||
{
|
||||
uint32 i, j;
|
||||
|
||||
memset(frame_ref, 0, cell_num);
|
||||
|
||||
for (i = 0, j = 0; i < func_type->param_count; i++) {
|
||||
if (wasm_is_type_reftype(func_type->types[i])) {
|
||||
frame_ref[j++] = 1;
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
frame_ref[j++] = 1;
|
||||
#endif
|
||||
}
|
||||
else if (func_type->types[i] == VALUE_TYPE_I32
|
||||
|| func_type->types[i] == VALUE_TYPE_F32)
|
||||
j++;
|
||||
else
|
||||
j += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the corresponding ref slot of the given address of local
|
||||
variable or stack pointer. */
|
||||
|
||||
#define COMPUTE_FRAME_REF(ref, lp, p) (ref + (unsigned)((uint32 *)p - lp))
|
||||
|
||||
#define FRAME_REF(p) COMPUTE_FRAME_REF(frame_ref, frame_lp, p)
|
||||
|
||||
#define FRAME_REF_FOR(frame, p) \
|
||||
COMPUTE_FRAME_REF(get_frame_ref(frame), frame->lp, p)
|
||||
|
||||
#define CLEAR_FRAME_REF(p, n) \
|
||||
do { \
|
||||
int32 ref_i, ref_n = (int32)(n); \
|
||||
uint8 *ref = FRAME_REF(p); \
|
||||
for (ref_i = 0; ref_i < ref_n; ref_i++) \
|
||||
ref[ref_i] = 0; \
|
||||
} while (0)
|
||||
#else
|
||||
#define CLEAR_FRAME_REF(p, n) (void)0
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
|
||||
#define skip_leb(p) while (*p++ & 0x80)
|
||||
|
||||
#define PUSH_I32(value) \
|
||||
|
@ -229,11 +303,23 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
|||
frame_sp += 2; \
|
||||
} while (0)
|
||||
|
||||
#define PUSH_REF(value) \
|
||||
do { \
|
||||
PUT_REF_TO_ADDR(frame_sp, value); \
|
||||
frame_sp += 2; \
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
#define PUSH_REF(value) \
|
||||
do { \
|
||||
PUT_REF_TO_ADDR(frame_sp, value); \
|
||||
frame_ref_tmp = FRAME_REF(frame_sp); \
|
||||
*frame_ref_tmp = *(frame_ref_tmp + 1) = 1; \
|
||||
frame_sp += 2; \
|
||||
} while (0)
|
||||
#else
|
||||
#define PUSH_REF(value) \
|
||||
do { \
|
||||
PUT_REF_TO_ADDR(frame_sp, value); \
|
||||
frame_ref_tmp = FRAME_REF(frame_sp); \
|
||||
*frame_ref_tmp = 1; \
|
||||
frame_sp++; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \
|
||||
do { \
|
||||
|
@ -254,9 +340,15 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
|||
|
||||
#define POP_F64() (frame_sp -= 2, GET_F64_FROM_ADDR(frame_sp))
|
||||
|
||||
#define POP_REF() \
|
||||
(frame_sp -= sizeof(uintptr_t) / sizeof(uint32), \
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
#define POP_REF() \
|
||||
(frame_sp -= 2, frame_ref_tmp = FRAME_REF(frame_sp), \
|
||||
*frame_ref_tmp = *(frame_ref_tmp + 1) = 0, GET_REF_FROM_ADDR(frame_sp))
|
||||
#else
|
||||
#define POP_REF() \
|
||||
(frame_sp--, frame_ref_tmp = FRAME_REF(frame_sp), *frame_ref_tmp = 0, \
|
||||
GET_REF_FROM_ADDR(frame_sp))
|
||||
#endif
|
||||
|
||||
#define POP_CSP_CHECK_OVERFLOW(n) \
|
||||
do { \
|
||||
|
@ -269,26 +361,31 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
|
|||
--frame_csp; \
|
||||
} while (0)
|
||||
|
||||
#define POP_CSP_N(n) \
|
||||
do { \
|
||||
uint32 *frame_sp_old = frame_sp; \
|
||||
uint32 cell_num_to_copy; \
|
||||
POP_CSP_CHECK_OVERFLOW(n + 1); \
|
||||
frame_csp -= n; \
|
||||
frame_ip = (frame_csp - 1)->target_addr; \
|
||||
/* copy arity values of block */ \
|
||||
frame_sp = (frame_csp - 1)->frame_sp; \
|
||||
cell_num_to_copy = (frame_csp - 1)->cell_num; \
|
||||
word_copy(frame_sp, frame_sp_old - cell_num_to_copy, \
|
||||
cell_num_to_copy); \
|
||||
frame_sp += cell_num_to_copy; \
|
||||
#define POP_CSP_N(n) \
|
||||
do { \
|
||||
uint32 *frame_sp_old = frame_sp; \
|
||||
uint32 cell_num_to_copy; \
|
||||
POP_CSP_CHECK_OVERFLOW(n + 1); \
|
||||
frame_csp -= n; \
|
||||
frame_ip = (frame_csp - 1)->target_addr; \
|
||||
/* copy arity values of block */ \
|
||||
frame_sp = (frame_csp - 1)->frame_sp; \
|
||||
cell_num_to_copy = (frame_csp - 1)->cell_num; \
|
||||
word_copy(frame_sp, frame_sp_old - cell_num_to_copy, \
|
||||
cell_num_to_copy); \
|
||||
frame_ref_copy(FRAME_REF(frame_sp), \
|
||||
FRAME_REF(frame_sp_old - cell_num_to_copy), \
|
||||
cell_num_to_copy); \
|
||||
frame_sp += cell_num_to_copy; \
|
||||
CLEAR_FRAME_REF(frame_sp, frame_sp_old - frame_sp); \
|
||||
} while (0)
|
||||
|
||||
/* Pop the given number of elements from the given frame's stack. */
|
||||
#define POP(N) \
|
||||
do { \
|
||||
int n = (N); \
|
||||
frame_sp -= n; \
|
||||
#define POP(N) \
|
||||
do { \
|
||||
int n = (N); \
|
||||
frame_sp -= n; \
|
||||
CLEAR_FRAME_REF(frame_sp, n); \
|
||||
} while (0)
|
||||
|
||||
#define SYNC_ALL_TO_FRAME() \
|
||||
|
@ -730,10 +827,23 @@ sign_ext_32_64(int32 val)
|
|||
static inline void
|
||||
word_copy(uint32 *dest, uint32 *src, unsigned num)
|
||||
{
|
||||
for (; num > 0; num--)
|
||||
*dest++ = *src++;
|
||||
if (dest != src)
|
||||
for (; num > 0; num--)
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
static inline void
|
||||
frame_ref_copy(uint8 *frame_ref_dest, uint8 *frame_ref_src, unsigned num)
|
||||
{
|
||||
if (frame_ref_dest != frame_ref_src)
|
||||
for (; num > 0; num--)
|
||||
*frame_ref_dest++ = *frame_ref_src++;
|
||||
}
|
||||
#else
|
||||
#define frame_ref_copy(frame_ref_dst, frame_ref_src, num) (void)0
|
||||
#endif
|
||||
|
||||
static inline WASMInterpFrame *
|
||||
ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame)
|
||||
{
|
||||
|
@ -773,20 +883,35 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
|||
WASMInterpFrame *prev_frame)
|
||||
{
|
||||
WASMFunctionImport *func_import = cur_func->u.func_import;
|
||||
unsigned local_cell_num = 2;
|
||||
unsigned local_cell_num =
|
||||
cur_func->param_cell_num > 2 ? cur_func->param_cell_num : 2;
|
||||
unsigned all_cell_num;
|
||||
WASMInterpFrame *frame;
|
||||
uint32 argv_ret[2];
|
||||
char buf[128];
|
||||
bool ret;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
uint8 *frame_ref;
|
||||
#endif
|
||||
|
||||
if (!(frame = ALLOC_FRAME(exec_env,
|
||||
wasm_interp_interp_frame_size(local_cell_num),
|
||||
prev_frame)))
|
||||
all_cell_num = local_cell_num;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
all_cell_num += (local_cell_num + 3) / 4;
|
||||
#endif
|
||||
|
||||
if (!(frame =
|
||||
ALLOC_FRAME(exec_env, wasm_interp_interp_frame_size(all_cell_num),
|
||||
prev_frame)))
|
||||
return;
|
||||
|
||||
frame->function = cur_func;
|
||||
frame->ip = NULL;
|
||||
frame->sp = frame->lp + local_cell_num;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/* native function doesn't have operand stack and label stack */
|
||||
frame_ref = (uint8 *)frame->sp;
|
||||
init_frame_refs(frame_ref, local_cell_num, func_import->func_type);
|
||||
#endif
|
||||
|
||||
wasm_exec_env_set_cur_frame(exec_env, frame);
|
||||
|
||||
|
@ -994,6 +1119,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
register uint8 *frame_ip = &opcode_IMPDEP; /* cache of frame->ip */
|
||||
register uint32 *frame_lp = NULL; /* cache of frame->lp */
|
||||
register uint32 *frame_sp = NULL; /* cache of frame->sp */
|
||||
#if WASM_ENABLE_GC != 0
|
||||
register uint8 *frame_ref = NULL; /* cache of frame->ref */
|
||||
uint8 *frame_ref_tmp;
|
||||
#endif
|
||||
WASMBranchBlock *frame_csp = NULL;
|
||||
BlockAddr *cache_items;
|
||||
uint8 *frame_ip_end = frame_ip + 1;
|
||||
|
@ -1092,7 +1221,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
{
|
||||
value_type = *frame_ip++;
|
||||
param_cell_num = 0;
|
||||
cell_num = wasm_value_type_cell_num(value_type);
|
||||
cell_num = 0;
|
||||
handle_op_loop:
|
||||
PUSH_CSP(LABEL_TYPE_LOOP, param_cell_num, cell_num, frame_ip);
|
||||
HANDLE_OP_END();
|
||||
|
@ -1168,6 +1297,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
else { /* end of function, treat as WASM_OP_RETURN */
|
||||
frame_sp -= cur_func->ret_cell_num;
|
||||
for (i = 0; i < cur_func->ret_cell_num; i++) {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (prev_frame->ip) {
|
||||
/* prev frame is not a glue frame and has
|
||||
the frame ref area */
|
||||
*FRAME_REF_FOR(prev_frame, prev_frame->sp) =
|
||||
*FRAME_REF(frame_sp + i);
|
||||
}
|
||||
#endif
|
||||
*prev_frame->sp++ = frame_sp[i];
|
||||
}
|
||||
goto return_func;
|
||||
|
@ -1227,6 +1364,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
{
|
||||
frame_sp -= cur_func->ret_cell_num;
|
||||
for (i = 0; i < cur_func->ret_cell_num; i++) {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (prev_frame->ip) {
|
||||
/* prev frame is not a glue frame and has
|
||||
the frame ref area */
|
||||
*FRAME_REF_FOR(prev_frame, prev_frame->sp) =
|
||||
*FRAME_REF(frame_sp + i);
|
||||
}
|
||||
#endif
|
||||
*prev_frame->sp++ = frame_sp[i];
|
||||
}
|
||||
goto return_func;
|
||||
|
@ -1573,6 +1718,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
gc_obj = GET_REF_FROM_ADDR(frame_sp - REF_CELL_NUM);
|
||||
if (gc_obj == NULL_REF) {
|
||||
frame_sp -= REF_CELL_NUM;
|
||||
CLEAR_FRAME_REF(frame_sp, REF_CELL_NUM);
|
||||
goto label_pop_csp_n;
|
||||
}
|
||||
HANDLE_OP_END();
|
||||
|
@ -1590,6 +1736,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
}
|
||||
else {
|
||||
frame_sp -= REF_CELL_NUM;
|
||||
CLEAR_FRAME_REF(frame_sp, REF_CELL_NUM);
|
||||
}
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
@ -1939,7 +2086,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
case WASM_OP_REF_CAST:
|
||||
{
|
||||
rtt_obj = POP_REF();
|
||||
gc_obj = GET_REF_FROM_ADDR(frame_sp - 2);
|
||||
gc_obj = GET_REF_FROM_ADDR(frame_sp - REF_CELL_NUM);
|
||||
|
||||
if (gc_obj
|
||||
&& (!rtt_obj
|
||||
|
@ -1957,7 +2104,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#endif
|
||||
read_leb_uint32(frame_ip, frame_ip_end, depth);
|
||||
rtt_obj = POP_REF();
|
||||
gc_obj = GET_REF_FROM_ADDR(frame_sp - 2);
|
||||
gc_obj = GET_REF_FROM_ADDR(frame_sp - REF_CELL_NUM);
|
||||
|
||||
if (gc_obj
|
||||
&& (rtt_obj
|
||||
|
@ -1974,7 +2121,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#endif
|
||||
read_leb_uint32(frame_ip, frame_ip_end, depth);
|
||||
rtt_obj = POP_REF();
|
||||
gc_obj = GET_REF_FROM_ADDR(frame_sp - 2);
|
||||
gc_obj = GET_REF_FROM_ADDR(frame_sp - REF_CELL_NUM);
|
||||
|
||||
if (!gc_obj
|
||||
|| (!rtt_obj
|
||||
|
@ -4431,14 +4578,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
else {
|
||||
WASMFunction *cur_wasm_func = cur_func->u.func;
|
||||
WASMFuncType *func_type;
|
||||
uint64 cell_num_of_local_stack;
|
||||
|
||||
func_type = cur_wasm_func->func_type;
|
||||
|
||||
all_cell_num = (uint64)cur_func->param_cell_num
|
||||
+ (uint64)cur_func->local_cell_num
|
||||
+ (uint64)cur_wasm_func->max_stack_cell_num
|
||||
cell_num_of_local_stack =
|
||||
(uint64)cur_func->param_cell_num
|
||||
+ (uint64)cur_func->local_cell_num
|
||||
+ (uint64)cur_wasm_func->max_stack_cell_num;
|
||||
all_cell_num = cell_num_of_local_stack
|
||||
+ ((uint64)cur_wasm_func->max_block_num)
|
||||
* sizeof(WASMBranchBlock) / 4;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/* area of frame_ref */
|
||||
all_cell_num += (cell_num_of_local_stack + 3) / 4;
|
||||
#endif
|
||||
|
||||
if (all_cell_num >= UINT32_MAX) {
|
||||
wasm_set_exception(module, "wasm operand stack overflow");
|
||||
goto got_exception;
|
||||
|
@ -4466,6 +4621,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
frame->csp_boundary =
|
||||
frame->csp_bottom + cur_wasm_func->max_block_num;
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
frame_ref = (uint8 *)frame->csp_boundary;
|
||||
init_frame_refs(frame_ref, (uint32)cell_num_of_local_stack,
|
||||
func_type);
|
||||
#endif
|
||||
|
||||
/* Initialize the local variables */
|
||||
memset(frame_lp + cur_func->param_cell_num, 0,
|
||||
(uint32)(cur_func->local_cell_num * 4));
|
||||
|
@ -4515,6 +4676,31 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#endif
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
void
|
||||
vmci_gc_rootset_elem(void *heap, WASMObjectRef obj)
|
||||
{}
|
||||
|
||||
void
|
||||
wasm_interp_traverse_gc_rootset(WASMInterpFrame *frame, void *heap)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (; frame; frame = frame->prev_frame) {
|
||||
for (i = 0; i < frame->sp - frame->lp; i++) {
|
||||
uint8 *frame_ref = get_frame_ref(frame);
|
||||
if (frame_ref[i]) {
|
||||
vmci_gc_rootset_elem(heap, (WASMObjectRef)&frame->lp[i]);
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
bh_assert(frame_ref[i + 1]);
|
||||
i++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *function, uint32 argc,
|
||||
|
|
|
@ -787,8 +787,9 @@ sign_ext_32_64(int32 val)
|
|||
static inline void
|
||||
word_copy(uint32 *dest, uint32 *src, unsigned num)
|
||||
{
|
||||
for (; num > 0; num--)
|
||||
*dest++ = *src++;
|
||||
if (dest != src)
|
||||
for (; num > 0; num--)
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
||||
static inline WASMInterpFrame *
|
||||
|
|
|
@ -5970,8 +5970,9 @@ check_stack_push(WASMLoaderContext *ctx, uint8 type, char *error_buf,
|
|||
if (wasm_is_type_multi_byte_type(type)
|
||||
&& ctx->frame_reftype_map >= ctx->frame_reftype_map_boundary) {
|
||||
/* Increase the frame reftype map stack */
|
||||
bh_assert(ctx->frame_reftype_map - ctx->frame_reftype_map_bottom
|
||||
== ctx->frame_reftype_map_size);
|
||||
bh_assert(
|
||||
(uint32)(ctx->frame_reftype_map - ctx->frame_reftype_map_bottom)
|
||||
== ctx->frame_reftype_map_size);
|
||||
MEM_REALLOC(ctx->frame_reftype_map_bottom, ctx->frame_reftype_map_size,
|
||||
ctx->frame_reftype_map_size
|
||||
+ (uint32)sizeof(WASMRefTypeMap) * 8);
|
||||
|
@ -12219,8 +12220,15 @@ re_scan:
|
|||
}
|
||||
|
||||
if (loader_ctx->csp_num > 0) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"function body must end with END opcode");
|
||||
if (cur_func_idx
|
||||
< module->import_function_count + module->function_count - 1) {
|
||||
set_error_buf(error_buf, error_buf_size, "END opcode expected");
|
||||
}
|
||||
else {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"unexpected end of section or function, "
|
||||
"or section size mismatch");
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -2739,3 +2739,31 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env)
|
|||
os_printf("\n");
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
bool
|
||||
wasm_runtime_traverse_gc_rootset(WASMExecEnv *exec_env, void *heap)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_gc_prepare(WASMExecEnv *exec_env)
|
||||
{
|
||||
#if 0
|
||||
exec_env->is_gc_reclaiming = false;
|
||||
wasm_thread_suspend_all();
|
||||
exec_env->is_gc_reclaim = 1;
|
||||
exec_env->requesting_suspend = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_gc_finished(WASMExecEnv *exec_env)
|
||||
{
|
||||
#if 0
|
||||
wasm_thread_resume_all();
|
||||
exec_env->doing_gc_reclaim = 0;
|
||||
#endif
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
|
|
|
@ -19,10 +19,18 @@ import time
|
|||
|
||||
"""
|
||||
The script itself has to be put under the same directory with the "spec".
|
||||
To run single spec case:
|
||||
To run a single non-GC case with interpreter mode:
|
||||
cd workspace
|
||||
python2.7 runtest.py --wast2wasm spec/interpreter/wasm --interpreter iwasm
|
||||
--aot-compiler wamrc --gc --loader-only spec/test/core/xxx.wast
|
||||
python2.7 runtest.py --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \
|
||||
spec/test/core/xxx.wast
|
||||
To run a single non-GC case with aot mode:
|
||||
cd workspace
|
||||
python2.7 runtest.py --aot --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \
|
||||
--aot-compiler wamrc spec/test/core/xxx.wast
|
||||
To run a single GC case:
|
||||
cd workspace
|
||||
python2.7 runtest.py --wast2wasm spec/interpreter/wasm --interpreter iwasm \
|
||||
--aot-compiler wamrc --gc spec/test/core/xxx.wast
|
||||
"""
|
||||
|
||||
PLATFORM_NAME = os.uname().sysname.lower()
|
||||
|
@ -65,7 +73,7 @@ def ignore_the_case(
|
|||
if not multi_module_flag and case_name in ["imports", "linking"]:
|
||||
return True
|
||||
|
||||
if gc_flag and case_name in ["func_bind", "let"]:
|
||||
if gc_flag and case_name in ["func_bind", "let", "type-canon"]:
|
||||
return True
|
||||
|
||||
if "i386" == target and case_name in ["float_exprs"]:
|
||||
|
|
|
@ -1,5 +1,18 @@
|
|||
diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml
|
||||
index 1dc208bf..3e3ff5e6 100644
|
||||
--- a/interpreter/exec/eval.ml
|
||||
+++ b/interpreter/exec/eval.ml
|
||||
@@ -1232,7 +1232,7 @@ let init (m : module_) (exts : extern list) : module_inst =
|
||||
in
|
||||
if List.length exts <> List.length imports then
|
||||
Link.error m.at "wrong number of imports provided for initialisation";
|
||||
- let inst0 = {empty_module_inst with types = List.concat_map create_type types} in
|
||||
+ let inst0 = {empty_module_inst with types = List.concat (List.map create_type types)} in
|
||||
ignore (List.fold_left (init_type inst0) (0l, inst0.types) types);
|
||||
let inst1 = List.fold_right2 (add_import m) exts imports inst0 in
|
||||
let fs = List.map (create_func inst1) funcs in
|
||||
diff --git a/test/core/binary.wast b/test/core/binary.wast
|
||||
index 1f76dc13..f4512ade 100644
|
||||
index fbca3d94..a592bfdc 100644
|
||||
--- a/test/core/binary.wast
|
||||
+++ b/test/core/binary.wast
|
||||
@@ -161,7 +161,7 @@
|
||||
|
@ -20,7 +33,7 @@ index 1f76dc13..f4512ade 100644
|
|||
|
||||
;; Unsigned LEB128 must not be overlong
|
||||
(assert_malformed
|
||||
@@ -1582,7 +1582,7 @@
|
||||
@@ -1638,7 +1638,7 @@
|
||||
)
|
||||
|
||||
;; 2 elem segment declared, 1 given
|
||||
|
@ -29,7 +42,7 @@ index 1f76dc13..f4512ade 100644
|
|||
(module binary
|
||||
"\00asm" "\01\00\00\00"
|
||||
"\01\04\01" ;; type section
|
||||
@@ -1595,7 +1595,7 @@
|
||||
@@ -1651,7 +1651,7 @@
|
||||
;; "\00\41\00\0b\01\00" ;; elem 1 (missed)
|
||||
)
|
||||
"unexpected end"
|
||||
|
@ -171,7 +184,7 @@ index 35e8c917..a7a459df 100644
|
|||
|
||||
;; Syntax errors
|
||||
diff --git a/test/core/linking.wast b/test/core/linking.wast
|
||||
index 85de43d8..6b218e3b 100644
|
||||
index 6a8ba1d0..e2721631 100644
|
||||
--- a/test/core/linking.wast
|
||||
+++ b/test/core/linking.wast
|
||||
@@ -64,6 +64,7 @@
|
||||
|
@ -190,7 +203,7 @@ index 85de43d8..6b218e3b 100644
|
|||
|
||||
|
||||
(assert_unlinkable
|
||||
@@ -317,6 +319,7 @@
|
||||
@@ -300,6 +302,7 @@
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -198,7 +211,7 @@ index 85de43d8..6b218e3b 100644
|
|||
(assert_return (invoke $Mt "call" (i32.const 2)) (i32.const 4))
|
||||
(assert_return (invoke $Nt "Mt.call" (i32.const 2)) (i32.const 4))
|
||||
(assert_return (invoke $Nt "call" (i32.const 2)) (i32.const 5))
|
||||
@@ -339,6 +342,7 @@
|
||||
@@ -322,6 +325,7 @@
|
||||
|
||||
(assert_return (invoke $Nt "call" (i32.const 3)) (i32.const -4))
|
||||
(assert_trap (invoke $Nt "call" (i32.const 4)) "indirect call type mismatch")
|
||||
|
@ -206,7 +219,7 @@ index 85de43d8..6b218e3b 100644
|
|||
|
||||
(module $Ot
|
||||
(type (func (result i32)))
|
||||
@@ -353,6 +357,7 @@
|
||||
@@ -336,6 +340,7 @@
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -214,7 +227,7 @@ index 85de43d8..6b218e3b 100644
|
|||
(assert_return (invoke $Mt "call" (i32.const 3)) (i32.const 4))
|
||||
(assert_return (invoke $Nt "Mt.call" (i32.const 3)) (i32.const 4))
|
||||
(assert_return (invoke $Nt "call Mt.call" (i32.const 3)) (i32.const 4))
|
||||
@@ -377,6 +382,7 @@
|
||||
@@ -360,6 +365,7 @@
|
||||
(assert_trap (invoke $Ot "call" (i32.const 0)) "uninitialized element")
|
||||
|
||||
(assert_trap (invoke $Ot "call" (i32.const 20)) "undefined element")
|
||||
|
@ -222,7 +235,7 @@ index 85de43d8..6b218e3b 100644
|
|||
|
||||
(module
|
||||
(table (import "Mt" "tab") 0 funcref)
|
||||
@@ -415,6 +421,7 @@
|
||||
@@ -398,6 +404,7 @@
|
||||
|
||||
;; Unlike in the v1 spec, active element segments stored before an
|
||||
;; out-of-bounds access persist after the instantiation failure.
|
||||
|
@ -230,7 +243,7 @@ index 85de43d8..6b218e3b 100644
|
|||
(assert_trap
|
||||
(module
|
||||
(table (import "Mt" "tab") 10 funcref)
|
||||
@@ -426,7 +433,9 @@
|
||||
@@ -409,7 +416,9 @@
|
||||
)
|
||||
(assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0))
|
||||
(assert_trap (invoke $Mt "call" (i32.const 8)) "uninitialized element")
|
||||
|
@ -240,7 +253,7 @@ index 85de43d8..6b218e3b 100644
|
|||
(assert_trap
|
||||
(module
|
||||
(table (import "Mt" "tab") 10 funcref)
|
||||
@@ -438,6 +447,7 @@
|
||||
@@ -421,6 +430,7 @@
|
||||
"out of bounds memory access"
|
||||
)
|
||||
(assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0))
|
||||
|
@ -248,7 +261,7 @@ index 85de43d8..6b218e3b 100644
|
|||
|
||||
|
||||
(module $Mtable_ex
|
||||
@@ -455,6 +465,7 @@
|
||||
@@ -438,6 +448,7 @@
|
||||
(table (import "Mtable_ex" "t-extern") 1 externref)
|
||||
)
|
||||
|
||||
|
@ -256,7 +269,7 @@ index 85de43d8..6b218e3b 100644
|
|||
(assert_unlinkable
|
||||
(module (table (import "Mtable_ex" "t-refnull") 1 (ref null func)))
|
||||
"incompatible import type"
|
||||
@@ -481,6 +492,7 @@
|
||||
@@ -464,6 +475,7 @@
|
||||
(module (table (import "Mtable_ex" "t-refnull") 1 externref))
|
||||
"incompatible import type"
|
||||
)
|
||||
|
@ -264,7 +277,7 @@ index 85de43d8..6b218e3b 100644
|
|||
|
||||
|
||||
;; Memories
|
||||
@@ -520,10 +532,12 @@
|
||||
@@ -503,10 +515,12 @@
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -277,7 +290,7 @@ index 85de43d8..6b218e3b 100644
|
|||
|
||||
(module
|
||||
(memory (import "Mm" "mem") 0)
|
||||
@@ -546,6 +560,7 @@
|
||||
@@ -529,6 +543,7 @@
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -285,7 +298,7 @@ index 85de43d8..6b218e3b 100644
|
|||
(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 1))
|
||||
(assert_return (invoke $Pm "grow" (i32.const 2)) (i32.const 1))
|
||||
(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 3))
|
||||
@@ -554,6 +569,7 @@
|
||||
@@ -537,6 +552,7 @@
|
||||
(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5))
|
||||
(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1))
|
||||
(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5))
|
||||
|
@ -293,7 +306,7 @@ index 85de43d8..6b218e3b 100644
|
|||
|
||||
(assert_unlinkable
|
||||
(module
|
||||
@@ -577,8 +593,10 @@
|
||||
@@ -560,8 +576,10 @@
|
||||
)
|
||||
"out of bounds memory access"
|
||||
)
|
||||
|
@ -304,7 +317,7 @@ index 85de43d8..6b218e3b 100644
|
|||
|
||||
(assert_trap
|
||||
(module
|
||||
@@ -590,7 +608,9 @@
|
||||
@@ -573,7 +591,9 @@
|
||||
)
|
||||
"out of bounds table access"
|
||||
)
|
||||
|
@ -314,7 +327,7 @@ index 85de43d8..6b218e3b 100644
|
|||
|
||||
;; Store is modified if the start function traps.
|
||||
(module $Ms
|
||||
@@ -606,6 +626,7 @@
|
||||
@@ -589,6 +609,7 @@
|
||||
)
|
||||
(register "Ms" $Ms)
|
||||
|
||||
|
@ -322,7 +335,7 @@ index 85de43d8..6b218e3b 100644
|
|||
(assert_trap
|
||||
(module
|
||||
(import "Ms" "memory" (memory 1))
|
||||
@@ -625,3 +646,4 @@
|
||||
@@ -608,3 +629,4 @@
|
||||
|
||||
(assert_return (invoke $Ms "get memory[0]") (i32.const 104)) ;; 'h'
|
||||
(assert_return (invoke $Ms "get table[0]") (i32.const 0xdead))
|
||||
|
@ -342,9 +355,18 @@ index adb5cb78..590f6262 100644
|
|||
(i32.add (local.get $x) (i32.const 1))
|
||||
)
|
||||
diff --git a/test/core/select.wast b/test/core/select.wast
|
||||
index fbe51be1..bb209d9b 100644
|
||||
index 94aa8605..baf0f9c5 100644
|
||||
--- a/test/core/select.wast
|
||||
+++ b/test/core/select.wast
|
||||
@@ -277,7 +277,7 @@
|
||||
(assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304))
|
||||
|
||||
(assert_return (invoke "join-funcnull" (i32.const 1)) (ref.func))
|
||||
-(assert_return (invoke "join-funcnull" (i32.const 0)) (ref.null))
|
||||
+(assert_return (invoke "join-funcnull" (i32.const 0)) (ref.null func))
|
||||
|
||||
(assert_trap (invoke "select-trap-left" (i32.const 1)) "unreachable")
|
||||
(assert_trap (invoke "select-trap-left" (i32.const 0)) "unreachable")
|
||||
@@ -368,6 +368,7 @@
|
||||
(module (func $arity-0 (select (result) (nop) (nop) (i32.const 1))))
|
||||
"invalid result arity"
|
||||
|
@ -784,3 +806,225 @@ index 0b2d26f7..bdab6a01 100644
|
|||
(table $t0 30 30 funcref)
|
||||
(table $t1 30 30 funcref)
|
||||
(elem (table $t1) (i32.const 2) func 3 1 4 1)
|
||||
diff --git a/test/core/type-equivalence.wast b/test/core/type-equivalence.wast
|
||||
index ed7e1a51..be10fd5a 100644
|
||||
--- a/test/core/type-equivalence.wast
|
||||
+++ b/test/core/type-equivalence.wast
|
||||
@@ -28,8 +28,8 @@
|
||||
;; Recursive types.
|
||||
|
||||
(module
|
||||
- (rec (type $t1 (func (param i32 (ref $t1)))))
|
||||
- (rec (type $t2 (func (param i32 (ref $t2)))))
|
||||
+ (type $t1 (func (param i32 (ref $t1))))
|
||||
+ (type $t2 (func (param i32 (ref $t2))))
|
||||
|
||||
(func $f1 (param $r (ref $t1)) (call $f2 (local.get $r)))
|
||||
(func $f2 (param $r (ref $t2)) (call $f1 (local.get $r)))
|
||||
@@ -47,14 +47,10 @@
|
||||
;; Isomorphic recursive types.
|
||||
|
||||
(module
|
||||
- (rec
|
||||
- (type $t0 (func (param i32 (ref $t1))))
|
||||
- (type $t1 (func (param i32 (ref $t0))))
|
||||
- )
|
||||
- (rec
|
||||
- (type $t2 (func (param i32 (ref $t3))))
|
||||
- (type $t3 (func (param i32 (ref $t2))))
|
||||
- )
|
||||
+ (type $t0 (func (param i32 (ref $t1))))
|
||||
+ (type $t1 (func (param i32 (ref $t0))))
|
||||
+ (type $t2 (func (param i32 (ref $t3))))
|
||||
+ (type $t3 (func (param i32 (ref $t2))))
|
||||
|
||||
(func $f0 (param $r (ref $t0))
|
||||
(call $f2 (local.get $r))
|
||||
@@ -73,6 +69,7 @@
|
||||
|
||||
;; Invalid recursion.
|
||||
|
||||
+(;
|
||||
(assert_invalid
|
||||
(module
|
||||
(type $t1 (func (param (ref $t2))))
|
||||
@@ -80,6 +77,7 @@
|
||||
)
|
||||
"unknown type"
|
||||
)
|
||||
+;)
|
||||
|
||||
|
||||
;; Semantic types (run time)
|
||||
@@ -134,8 +132,8 @@
|
||||
;; Recursive types.
|
||||
|
||||
(module
|
||||
- (rec (type $t1 (func (result (ref null $t1)))))
|
||||
- (rec (type $t2 (func (result (ref null $t2)))))
|
||||
+ (type $t1 (func (result (ref null $t1))))
|
||||
+ (type $t2 (func (result (ref null $t2))))
|
||||
|
||||
(func $f1 (type $t1) (ref.null $t1))
|
||||
(func $f2 (type $t2) (ref.null $t2))
|
||||
@@ -155,21 +153,16 @@
|
||||
)
|
||||
(assert_return (invoke "run"))
|
||||
|
||||
-
|
||||
;; Isomorphic recursive types.
|
||||
|
||||
(module
|
||||
- (rec
|
||||
- (type $t1 (func (param i32 (ref $t1))))
|
||||
- (type $t2 (func (param i32 (ref $t3))))
|
||||
- (type $t3 (func (param i32 (ref $t2))))
|
||||
- )
|
||||
+ (type $t1 (func (param i32 (ref $t1))))
|
||||
+ (type $t2 (func (param i32 (ref $t3))))
|
||||
+ (type $t3 (func (param i32 (ref $t2))))
|
||||
|
||||
- (rec
|
||||
- (type $u1 (func (param i32 (ref $u1))))
|
||||
- (type $u2 (func (param i32 (ref $u3))))
|
||||
- (type $u3 (func (param i32 (ref $u2))))
|
||||
- )
|
||||
+ (type $u1 (func (param i32 (ref $u1))))
|
||||
+ (type $u2 (func (param i32 (ref $u3))))
|
||||
+ (type $u3 (func (param i32 (ref $u2))))
|
||||
|
||||
(func $f1 (type $t1))
|
||||
(func $f2 (type $t2))
|
||||
@@ -187,7 +180,6 @@
|
||||
)
|
||||
(assert_return (invoke "run"))
|
||||
|
||||
-
|
||||
;; Semantic types (link time)
|
||||
|
||||
;; Simple types.
|
||||
@@ -196,11 +188,13 @@
|
||||
(type $t1 (func (param f32 f32) (result f32)))
|
||||
(func (export "f") (param (ref $t1)))
|
||||
)
|
||||
+(;
|
||||
(register "M")
|
||||
(module
|
||||
(type $t2 (func (param $x f32) (param $y f32) (result f32)))
|
||||
(func (import "M" "f") (param (ref $t2)))
|
||||
)
|
||||
+;)
|
||||
|
||||
|
||||
;; Indirect types.
|
||||
@@ -214,6 +208,7 @@
|
||||
(func (export "f1") (param (ref $t1)))
|
||||
(func (export "f2") (param (ref $t1)))
|
||||
)
|
||||
+(;
|
||||
(register "M")
|
||||
(module
|
||||
(type $s0 (func (param i32) (result f32)))
|
||||
@@ -226,33 +221,35 @@
|
||||
(func (import "M" "f2") (param (ref $t1)))
|
||||
(func (import "M" "f2") (param (ref $t1)))
|
||||
)
|
||||
+;)
|
||||
|
||||
|
||||
;; Recursive types.
|
||||
|
||||
(module
|
||||
- (rec (type $t1 (func (param i32 (ref $t1)))))
|
||||
+ (type $t1 (func (param i32 (ref $t1))))
|
||||
(func (export "f") (param (ref $t1)))
|
||||
)
|
||||
+(;
|
||||
(register "M")
|
||||
(module
|
||||
(rec (type $t2 (func (param i32 (ref $t2)))))
|
||||
(func (import "M" "f") (param (ref $t2)))
|
||||
)
|
||||
+;)
|
||||
|
||||
|
||||
;; Isomorphic recursive types.
|
||||
|
||||
(module
|
||||
- (rec
|
||||
- (type $t1 (func (param i32 (ref $t1))))
|
||||
- (type $t2 (func (param i32 (ref $t3))))
|
||||
- (type $t3 (func (param i32 (ref $t2))))
|
||||
- )
|
||||
+ (type $t1 (func (param i32 (ref $t1))))
|
||||
+ (type $t2 (func (param i32 (ref $t3))))
|
||||
+ (type $t3 (func (param i32 (ref $t2))))
|
||||
(func (export "f1") (param (ref $t1)))
|
||||
(func (export "f2") (param (ref $t2)))
|
||||
(func (export "f3") (param (ref $t3)))
|
||||
)
|
||||
+(;
|
||||
(register "M")
|
||||
(module
|
||||
(rec
|
||||
@@ -264,17 +261,17 @@
|
||||
(func (import "M" "f2") (param (ref $t2)))
|
||||
(func (import "M" "f3") (param (ref $t3)))
|
||||
)
|
||||
+;)
|
||||
|
||||
(module
|
||||
- (rec
|
||||
- (type $t1 (func (param i32 (ref $t3))))
|
||||
- (type $t2 (func (param i32 (ref $t1))))
|
||||
- (type $t3 (func (param i32 (ref $t2))))
|
||||
- )
|
||||
+ (type $t1 (func (param i32 (ref $t3))))
|
||||
+ (type $t2 (func (param i32 (ref $t1))))
|
||||
+ (type $t3 (func (param i32 (ref $t2))))
|
||||
(func (export "f1") (param (ref $t1)))
|
||||
(func (export "f2") (param (ref $t2)))
|
||||
(func (export "f3") (param (ref $t3)))
|
||||
)
|
||||
+(;
|
||||
(register "M")
|
||||
(module
|
||||
(rec
|
||||
@@ -286,24 +283,22 @@
|
||||
(func (import "M" "f2") (param (ref $t2)))
|
||||
(func (import "M" "f3") (param (ref $t3)))
|
||||
)
|
||||
+;)
|
||||
|
||||
(module
|
||||
- (rec
|
||||
- (type $t1 (func (param i32 (ref $u1))))
|
||||
- (type $u1 (func (param f32 (ref $t1))))
|
||||
- )
|
||||
+ (type $t1 (func (param i32 (ref $u1))))
|
||||
+ (type $u1 (func (param f32 (ref $t1))))
|
||||
|
||||
- (rec
|
||||
- (type $t2 (func (param i32 (ref $u3))))
|
||||
- (type $u2 (func (param f32 (ref $t3))))
|
||||
- (type $t3 (func (param i32 (ref $u2))))
|
||||
- (type $u3 (func (param f32 (ref $t2))))
|
||||
- )
|
||||
+ (type $t2 (func (param i32 (ref $u3))))
|
||||
+ (type $u2 (func (param f32 (ref $t3))))
|
||||
+ (type $t3 (func (param i32 (ref $u2))))
|
||||
+ (type $u3 (func (param f32 (ref $t2))))
|
||||
|
||||
(func (export "f1") (param (ref $t1)))
|
||||
(func (export "f2") (param (ref $t2)))
|
||||
(func (export "f3") (param (ref $t3)))
|
||||
)
|
||||
+(;
|
||||
(register "M")
|
||||
(module
|
||||
(rec
|
||||
@@ -322,3 +317,4 @@
|
||||
(func (import "M" "f2") (param (ref $t2)))
|
||||
(func (import "M" "f3") (param (ref $t3)))
|
||||
)
|
||||
+;)
|
||||
|
|
|
@ -409,8 +409,12 @@ def parse_simple_const_w_type(number, type):
|
|||
number = float.fromhex(number) if '0x' in number else float(number)
|
||||
return number, "{:.7g}:{}".format(number, type)
|
||||
elif type == "ref.null":
|
||||
# hard coding
|
||||
return "extern", "extern:ref.null"
|
||||
if number == "func":
|
||||
return "func", "func:ref.null"
|
||||
elif number == "extern":
|
||||
return "extern", "extern:ref.null"
|
||||
else:
|
||||
raise Exception("invalid value {} and type {}".format(number, type))
|
||||
elif type == "ref.extern":
|
||||
number = int(number, 16) if '0x' in number else int(number)
|
||||
return number, "0x{:x}:ref.extern".format(number)
|
||||
|
@ -429,6 +433,10 @@ def parse_assertion_value(val):
|
|||
type.const val
|
||||
ref.extern val
|
||||
ref.null ref_type
|
||||
ref.array
|
||||
ref.data
|
||||
ref.func
|
||||
ref.i31
|
||||
"""
|
||||
if not val:
|
||||
return None, ""
|
||||
|
@ -442,6 +450,8 @@ def parse_assertion_value(val):
|
|||
if type in ["i32", "i64", "f32", "f64"]:
|
||||
return parse_simple_const_w_type(numbers[0], type)
|
||||
elif type == "ref":
|
||||
if splitted[0] in ["ref.array", "ref.data", "ref.func", "ref.i31"]:
|
||||
return splitted[0]
|
||||
# need to distinguish between "ref.null" and "ref.extern"
|
||||
return parse_simple_const_w_type(numbers[0], splitted[0])
|
||||
else:
|
||||
|
@ -570,6 +580,9 @@ def simple_value_comparison(out, expected):
|
|||
# the add result in x86_32 is inf
|
||||
return True
|
||||
|
||||
if out == "ref.array":
|
||||
return expected in ["ref.array", "ref.data"]
|
||||
|
||||
out_val, out_type = out.split(':')
|
||||
expected_val, expected_type = expected.split(':')
|
||||
|
||||
|
@ -626,8 +639,10 @@ def value_comparison(out, expected):
|
|||
if not expected:
|
||||
return False
|
||||
|
||||
assert(':' in out), "out should be in a form likes numbers:type, but {}".format(out)
|
||||
assert(':' in expected), "expected should be in a form likes numbers:type, but {}".format(expected)
|
||||
if not out in ["ref.array", "ref.data", "ref.func", "ref.i31"]:
|
||||
assert(':' in out), "out should be in a form likes numbers:type, but {}".format(out)
|
||||
if not expected in ["ref.array", "ref.data", "ref.func", "ref.i31"]:
|
||||
assert(':' in expected), "expected should be in a form likes numbers:type, but {}".format(expected)
|
||||
|
||||
if 'v128' in out:
|
||||
return vector_value_comparison(out, expected)
|
||||
|
@ -758,7 +773,10 @@ def test_assert_return(r, opts, form):
|
|||
else:
|
||||
returns = re.split("\)\s*\(", m.group(3)[1:-1])
|
||||
# processed numbers in strings
|
||||
expected = [parse_assertion_value(v)[1] for v in returns]
|
||||
if len(returns) == 1 and returns[0] in ["ref.array", "ref.data", "ref.func", "ref.i31", "ref.null"]:
|
||||
expected = [returns[0]]
|
||||
else:
|
||||
expected = [parse_assertion_value(v)[1] for v in returns]
|
||||
test_assert(r, opts, "return", "%s %s" % (func, " ".join(args)), ",".join(expected))
|
||||
elif not m and n:
|
||||
module = os.path.join(temp_file_directory,n.group(1))
|
||||
|
@ -789,10 +807,10 @@ def test_assert_return(r, opts, form):
|
|||
if n.group(3) == '':
|
||||
args=[]
|
||||
else:
|
||||
args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", n.group(3)[1:-1])]
|
||||
|
||||
# a workaround for "ref.null extern" and "ref.null func"
|
||||
args = [ arg.replace('extern', 'null').replace('func', 'null') for arg in args]
|
||||
# convert (ref.null extern/func) into (ref.null null)
|
||||
n1 = n.group(3).replace("(ref.null extern)", "(ref.null null)")
|
||||
n1 = n1.replace("ref.null func)", "(ref.null null)")
|
||||
args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", n1[1:-1])]
|
||||
|
||||
_, expected = parse_assertion_value(n.group(4)[1:-1])
|
||||
test_assert(r, opts, "return", "%s %s" % (func, " ".join(args)), expected)
|
||||
|
@ -817,10 +835,10 @@ def test_assert_trap(r, opts, form):
|
|||
if m.group(2) == '':
|
||||
args = []
|
||||
else:
|
||||
args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])]
|
||||
|
||||
# workaround for "ref.null extern"
|
||||
args = [ arg.replace('extern', 'null').replace('func', 'null') for arg in args]
|
||||
# convert (ref.null extern/func) into (ref.null null)
|
||||
m1 = m.group(2).replace("(ref.null extern)", "(ref.null null)")
|
||||
m1 = m1.replace("ref.null func)", "(ref.null null)")
|
||||
args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m1[1:-1])]
|
||||
|
||||
expected = "Exception: %s" % m.group(3)
|
||||
test_assert(r, opts, "trap", "%s %s" % (func, " ".join(args)), expected)
|
||||
|
@ -1110,19 +1128,13 @@ if __name__ == "__main__":
|
|||
elif skip_test(form, SKIP_TESTS):
|
||||
log("Skipping test: %s" % form[0:60])
|
||||
elif re.match("^\(assert_trap\s+\(module", form):
|
||||
if opts.loader_only:
|
||||
continue
|
||||
if test_aot:
|
||||
test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, opts, r)
|
||||
else:
|
||||
test_assert_with_exception(form, wast_tempfile, wasm_tempfile, None, opts, r)
|
||||
elif re.match("^\(assert_exhaustion\\b.*", form):
|
||||
if opts.loader_only:
|
||||
continue
|
||||
test_assert_exhaustion(r, opts, form)
|
||||
elif re.match("^\(assert_unlinkable\\b.*", form):
|
||||
if opts.loader_only:
|
||||
continue
|
||||
if test_aot:
|
||||
test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, opts, r)
|
||||
else:
|
||||
|
@ -1193,8 +1205,6 @@ if __name__ == "__main__":
|
|||
log("ignoring assert_return_.*_nan")
|
||||
pass
|
||||
elif re.match(".*\(invoke\s+\$\\b.*", form):
|
||||
if opts.loader_only:
|
||||
continue
|
||||
# invoke a particular named module's function
|
||||
if form.startswith("(assert_return"):
|
||||
test_assert_return(r,opts,form)
|
||||
|
@ -1248,17 +1258,11 @@ if __name__ == "__main__":
|
|||
(repr(exc), r.buf))
|
||||
|
||||
elif re.match("^\(assert_return\\b.*", form):
|
||||
if opts.loader_only:
|
||||
continue
|
||||
assert(r), "iwasm repl runtime should be not null"
|
||||
test_assert_return(r, opts, form)
|
||||
elif re.match("^\(assert_trap\\b.*", form):
|
||||
if opts.loader_only:
|
||||
continue
|
||||
test_assert_trap(r, opts, form)
|
||||
elif re.match("^\(invoke\\b.*", form):
|
||||
if opts.loader_only:
|
||||
continue
|
||||
assert(r), "iwasm repl runtime should be not null"
|
||||
do_invoke(r, opts, form)
|
||||
elif re.match("^\(assert_invalid\\b.*", form):
|
||||
|
|
|
@ -320,6 +320,7 @@ function spec_test()
|
|||
git restore . && git clean -ffd .
|
||||
git fetch gc
|
||||
git checkout -B gc_spec --track gc/master
|
||||
git reset --hard c486ace0c751ebfc66dfcc59c8c224db29cedbe5
|
||||
git apply ../../spec-test-script/gc_ignore_cases.patch
|
||||
|
||||
echo "compile the reference intepreter"
|
||||
|
@ -373,6 +374,7 @@ function spec_test()
|
|||
make -C wabt gcc-release -j 4
|
||||
fi
|
||||
|
||||
ln -sf ${WORK_DIR}/../spec-test-script/all.sh .
|
||||
ln -sf ${WORK_DIR}/../spec-test-script/all.py .
|
||||
ln -sf ${WORK_DIR}/../spec-test-script/runtest.py .
|
||||
|
||||
|
@ -421,6 +423,7 @@ function spec_test()
|
|||
fi
|
||||
|
||||
cd ${WORK_DIR}
|
||||
#./all.sh ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt
|
||||
python3 ./all.py ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt
|
||||
|
||||
[[ ${PIPESTATUS[0]} -ne 0 ]] && exit 1
|
||||
|
|
Loading…
Reference in New Issue
Block a user