Parcourir la source

Fix test script error and related wamrc and GC issues (#2975)

The wamrc execution errors were skipped in the runtest.py due to `sys.exit(1)`
was caught by upper try-catch sentence and ignored with ret_code 0 returned.

This PR fixed this script issue and fixed the related wamrc/GC issues found.
Wenyong Huang il y a 2 ans
Parent
commit
cc23a09d5e

+ 4 - 0
.github/workflows/spec_test_on_nuttx.yml

@@ -159,6 +159,10 @@ jobs:
           echo "config INTERPRETERS_WAMR_AOT_STACK_FRAME" >> apps/interpreters/wamr/Kconfig
           echo "\tbool \"Enable AOT stack frame\"" >> apps/interpreters/wamr/Kconfig
           echo "\tdefault n" >> apps/interpreters/wamr/Kconfig
+          echo "\n" >> apps/interpreters/wamr/Kconfig
+          echo "config INTERPRETERS_WAMR_TAIL_CALL" >> apps/interpreters/wamr/Kconfig
+          echo "\tbool \"Enable Tail Call\"" >> apps/interpreters/wamr/Kconfig
+          echo "\tdefault y" >> apps/interpreters/wamr/Kconfig
 
       - name: Enable WAMR for NuttX
         run: |

+ 23 - 30
core/iwasm/aot/aot_loader.c

@@ -1211,6 +1211,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
                 return false;
             }
             free_if_fail = true;
+            init_values->count = field_count;
             expr->u.data = init_values;
 
             if (type_idx >= module->type_count) {
@@ -1255,26 +1256,21 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
         case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
         case INIT_EXPR_TYPE_ARRAY_NEW_FIXED:
         {
+            uint32 array_elem_type;
             uint32 type_idx, length;
-            AOTArrayType *array_type = NULL;
             WASMArrayNewInitValues *init_values = NULL;
 
+            /* Note: at this time the aot types haven't been loaded */
+            read_uint32(buf, buf_end, array_elem_type);
             read_uint32(buf, buf_end, type_idx);
             read_uint32(buf, buf_end, length);
 
-            if (type_idx >= module->type_count) {
-                set_error_buf(error_buf, error_buf_size, "unknown array type.");
-                goto fail;
-            }
-
-            array_type = (AOTArrayType *)module->types[type_idx];
-
             if (init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
                 expr->u.array_new_default.type_index = type_idx;
-                expr->u.array_new_default.N = length;
+                expr->u.array_new_default.length = length;
             }
             else {
-
+                uint32 i, elem_size, elem_data_count;
                 uint64 size = offsetof(WASMArrayNewInitValues, elem_data)
                               + sizeof(WASMValue) * (uint64)length;
                 if (!(init_values =
@@ -1287,26 +1283,23 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
                 init_values->type_idx = type_idx;
                 init_values->length = length;
 
-                if (length > 0) {
-                    uint32 i;
-                    uint32 elem_size =
-                        wasm_value_type_size(array_type->elem_type);
-
-                    for (i = 0; i < length; i++) {
-
-                        if (elem_size <= sizeof(uint32))
-                            read_uint32(buf, buf_end,
-                                        init_values->elem_data[i].u32);
-                        else if (elem_size == sizeof(uint64))
-                            read_uint64(buf, buf_end,
-                                        init_values->elem_data[i].u64);
-                        else if (elem_size == sizeof(uint64) * 2)
-                            read_byte_array(buf, buf_end,
-                                            &init_values->elem_data[i],
-                                            elem_size);
-                        else {
-                            bh_assert(0);
-                        }
+                elem_data_count =
+                    (init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) ? length
+                                                                       : 1;
+                elem_size = wasm_value_type_size((uint8)array_elem_type);
+
+                for (i = 0; i < elem_data_count; i++) {
+                    if (elem_size <= sizeof(uint32))
+                        read_uint32(buf, buf_end,
+                                    init_values->elem_data[i].u32);
+                    else if (elem_size == sizeof(uint64))
+                        read_uint64(buf, buf_end,
+                                    init_values->elem_data[i].u64);
+                    else if (elem_size == sizeof(uint64) * 2)
+                        read_byte_array(buf, buf_end,
+                                        &init_values->elem_data[i], elem_size);
+                    else {
+                        bh_assert(0);
                     }
                 }
             }

+ 15 - 9
core/iwasm/aot/aot_runtime.c

@@ -313,7 +313,7 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
 
             if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
                 type_idx = init_expr->u.array_new_default.type_index;
-                len = init_expr->u.array_new_default.N;
+                len = init_expr->u.array_new_default.length;
                 arr_init_val = &empty_val;
             }
             else {
@@ -337,8 +337,9 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
             }
 
             if (!(array_obj = wasm_array_obj_new_internal(
-                      module_inst->e->common.gc_heap_handle, rtt_type, len,
-                      arr_init_val))) {
+                      ((AOTModuleInstanceExtra *)module_inst->e)
+                          ->common.gc_heap_handle,
+                      rtt_type, len, arr_init_val))) {
                 set_error_buf(error_buf, error_buf_size,
                               "create array object failed");
                 return false;
@@ -523,7 +524,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 
                 if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
                     type_idx = init_expr->u.array_new_default.type_index;
-                    len = init_expr->u.array_new_default.N;
+                    len = init_expr->u.array_new_default.length;
                     arr_init_val = &empty_val;
                 }
                 else {
@@ -547,8 +548,9 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
                 }
 
                 if (!(array_obj = wasm_array_obj_new_internal(
-                          module_inst->e->common.gc_heap_handle, rtt_type, len,
-                          arr_init_val))) {
+                          ((AOTModuleInstanceExtra *)module_inst->e)
+                              ->common.gc_heap_handle,
+                          rtt_type, len, arr_init_val))) {
                     set_error_buf(error_buf, error_buf_size,
                                   "create array object failed");
                     return false;
@@ -1684,8 +1686,14 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     if (stack_size == 0)
         stack_size = DEFAULT_WASM_STACK_SIZE;
 #if WASM_ENABLE_SPEC_TEST != 0
+#if WASM_ENABLE_TAIL_CALL == 0
     if (stack_size < 128 * 1024)
         stack_size = 128 * 1024;
+#else
+    /* Some tail-call cases require large operand stack */
+    if (stack_size < 10 * 1024 * 1024)
+        stack_size = 10 * 1024 * 1024;
+#endif
 #endif
     module_inst->default_wasm_stack_size = stack_size;
 
@@ -3512,8 +3520,7 @@ aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index)
     frame = wasm_exec_env_alloc_wasm_frame(exec_env, frame_size);
 
     if (!frame) {
-        aot_set_exception((AOTModuleInstance *)exec_env->module_inst,
-                          "wasm operand stack overflow");
+        aot_set_exception(module_inst, "wasm operand stack overflow");
         return false;
     }
 
@@ -3669,7 +3676,6 @@ aot_create_call_stack(struct WASMExecEnv *exec_env)
             }
             bh_memcpy_s(frame.lp, lp_size, cur_frame->lp, lp_size);
 
-            /* Only save frame sp when fast-interpr isn't enabled */
             frame.sp = frame.lp + (cur_frame->sp - cur_frame->lp);
 #if WASM_ENABLE_GC != 0
             frame.frame_ref = (uint8 *)frame.lp

+ 3 - 3
core/iwasm/common/gc/gc_type.h

@@ -225,21 +225,21 @@ wasm_is_reftype_arrayref(uint8 type)
     return type == (uint8)REF_TYPE_ARRAYREF ? true : false;
 }
 
-/* Whether a reference type is an nullref type */
+/* Whether a reference type is a nullref type */
 inline static bool
 wasm_is_reftype_nullref(uint8 type)
 {
     return type == (uint8)REF_TYPE_NULLREF ? true : false;
 }
 
-/* Whether a reference type is an nullfuncref type */
+/* Whether a reference type is a nullfuncref type */
 inline static bool
 wasm_is_reftype_nullfuncref(uint8 type)
 {
     return type == (uint8)REF_TYPE_NULLFUNCREF ? true : false;
 }
 
-/* Whether a reference type is an nullexternref type */
+/* Whether a reference type is a nullexternref type */
 inline static bool
 wasm_is_reftype_nullexternref(uint8 type)
 {

+ 0 - 2
core/iwasm/compilation/aot_compiler.c

@@ -684,7 +684,6 @@ init_comp_frame(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 uint32 func_idx)
 {
     AOTCompFrame *aot_frame;
-    WASMModule *wasm_module = comp_ctx->comp_data->wasm_module;
     AOTFunc *aot_func = func_ctx->aot_func;
     AOTFuncType *func_type = aot_func->func_type;
     AOTBlock *block = func_ctx->block_stack.block_list_end;
@@ -719,7 +718,6 @@ init_comp_frame(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     }
     memset(aot_frame, 0, (uint32)total_size);
 
-    aot_frame->cur_wasm_module = wasm_module;
     aot_frame->comp_ctx = comp_ctx;
     aot_frame->func_ctx = func_ctx;
 

+ 61 - 33
core/iwasm/compilation/aot_emit_aot_file.c

@@ -278,7 +278,9 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
 {
     /* init_expr_type */
     uint32 size = sizeof(uint32);
+#if WASM_ENABLE_GC != 0
     WASMModule *module = comp_data->wasm_module;
+#endif
 
     /* + init value size */
     switch (expr->init_expr_type) {
@@ -322,12 +324,17 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
                 WASMStructType *struct_type =
                     (WASMStructType *)
                         module->types[struct_new_init_values->type_idx];
+                uint32 field_size;
+
                 bh_assert(struct_type);
                 bh_assert(struct_type->field_count
                           == struct_new_init_values->count);
 
-                size += wasm_value_type_size_internal(
+                field_size = wasm_value_type_size_internal(
                     struct_type->fields[i].field_type, comp_ctx->pointer_size);
+                if (field_size < sizeof(uint32))
+                    field_size = sizeof(uint32);
+                size += field_size;
             }
             break;
         }
@@ -335,31 +342,34 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
             /* type_index */
             size += sizeof(uint32);
             break;
-        case INIT_EXPR_TYPE_ARRAY_NEW:
-            /* type_index + len + elem */
-            size += sizeof(uint32) * 2 + sizeof(WASMValue);
-            break;
         case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
-            /* type_index + len */
-            size += sizeof(uint32) * 2;
+            /* array_elem_type + type_index + len */
+            size += sizeof(uint32) * 3;
             break;
+        case INIT_EXPR_TYPE_ARRAY_NEW:
         case INIT_EXPR_TYPE_ARRAY_NEW_FIXED:
         {
             WASMArrayNewInitValues *array_new_init_values =
                 (WASMArrayNewInitValues *)expr->u.data;
             WASMArrayType *array_type = NULL;
+            uint32 value_count;
+
+            array_type =
+                (WASMArrayType *)module->types[array_new_init_values->type_idx];
 
             bh_assert(array_type);
             bh_assert(array_new_init_values->type_idx < module->type_count);
 
-            array_type =
-                (WASMArrayType *)module->types[array_new_init_values->type_idx];
+            value_count =
+                (expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED)
+                    ? array_new_init_values->length
+                    : 1;
 
-            /* type_index + len + elems */
-            size += sizeof(uint32) * 2
-                    + array_new_init_values->length
-                          * wasm_value_type_size_internal(
-                              array_type->elem_type, comp_ctx->pointer_size);
+            /* array_elem_type + type_index + len + elems */
+            size += sizeof(uint32) * 3
+                    + wasm_value_type_size_internal(array_type->elem_type,
+                                                    comp_ctx->pointer_size)
+                          * value_count;
             break;
         }
 #endif /* end of WASM_ENABLE_GC != 0 */
@@ -1790,7 +1800,9 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
                    AOTCompContext *comp_ctx, InitializerExpression *expr)
 {
     uint32 offset = *p_offset;
+#if WASM_ENABLE_GC != 0
     WASMModule *module = comp_ctx->comp_data->wasm_module;
+#endif
 
     *p_offset = offset = align_uint(offset, 4);
 
@@ -1857,37 +1869,53 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
         case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
             EMIT_U32(expr->u.type_index);
             break;
-        case INIT_EXPR_TYPE_ARRAY_NEW:
         case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
+        {
+            WASMArrayType *array_type = NULL;
+
+            bh_assert(expr->u.array_new_default.type_index
+                      < module->type_count);
+            array_type =
+                (WASMArrayType *)
+                    module->types[expr->u.array_new_default.type_index];
+
+            EMIT_U32(array_type->elem_type);
+            EMIT_U32(expr->u.array_new_default.type_index);
+            EMIT_U32(expr->u.array_new_default.length);
+            break;
+        }
+        case INIT_EXPR_TYPE_ARRAY_NEW:
         case INIT_EXPR_TYPE_ARRAY_NEW_FIXED:
         {
-            uint32 i;
+            uint32 value_count, i, field_size;
             WASMArrayNewInitValues *init_values =
                 (WASMArrayNewInitValues *)expr->u.data;
             WASMArrayType *array_type = NULL;
 
+            bh_assert(init_values->type_idx < module->type_count);
+            array_type = (WASMArrayType *)module->types[init_values->type_idx];
+
+            EMIT_U32(array_type->elem_type);
             EMIT_U32(init_values->type_idx);
             EMIT_U32(init_values->length);
 
-            bh_assert(init_values->type_idx < module->type_count);
+            value_count =
+                (expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED)
+                    ? init_values->length
+                    : 1;
 
-            array_type = (WASMArrayType *)module->types[init_values->type_idx];
+            field_size = wasm_value_type_size_internal(array_type->elem_type,
+                                                       comp_ctx->pointer_size);
 
-            bh_assert(array_type);
-
-            if (expr->init_expr_type != INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
-                uint32 field_size = wasm_value_type_size_internal(
-                    array_type->elem_type, comp_ctx->pointer_size);
-                for (i = 0; i < init_values->length; i++) {
-                    if (field_size <= sizeof(uint32))
-                        EMIT_U32(init_values->elem_data[i].u32);
-                    else if (field_size == sizeof(uint64))
-                        EMIT_U64(init_values->elem_data[i].u64);
-                    else if (field_size == sizeof(uint64) * 2)
-                        EMIT_V128(init_values->elem_data[i].v128);
-                    else {
-                        bh_assert(0);
-                    }
+            for (i = 0; i < value_count; i++) {
+                if (field_size <= sizeof(uint32))
+                    EMIT_U32(init_values->elem_data[i].u32);
+                else if (field_size == sizeof(uint64))
+                    EMIT_U64(init_values->elem_data[i].u64);
+                else if (field_size == sizeof(uint64) * 2)
+                    EMIT_V128(init_values->elem_data[i].v128);
+                else {
+                    bh_assert(0);
                 }
             }
             break;

+ 2 - 0
core/iwasm/compilation/aot_emit_parametric.c

@@ -65,6 +65,8 @@ pop_value_from_wasm_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         if (!(type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64
 #if WASM_ENABLE_GC != 0
               || (comp_ctx->enable_gc && type == VALUE_TYPE_GC_REF)
+              /* may be i32 which denotes funcref/externref */
+              || (!comp_ctx->enable_gc && type == VALUE_TYPE_I32)
 #endif
                   )) {
             aot_set_last_error("invalid WASM stack data type.");

+ 1 - 3
core/iwasm/compilation/aot_llvm.c

@@ -2582,10 +2582,8 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
     if (option->builtin_intrinsics)
         comp_ctx->builtin_intrinsics = option->builtin_intrinsics;
 
-    if (option->enable_gc) {
+    if (option->enable_gc)
         comp_ctx->enable_gc = true;
-        comp_ctx->enable_aux_stack_frame = true;
-    }
 
     comp_ctx->opt_level = option->opt_level;
     comp_ctx->size_level = option->size_level;

+ 0 - 2
core/iwasm/compilation/aot_llvm.h

@@ -113,8 +113,6 @@ typedef struct AOTValueSlot {
 
 /* Frame information for translation */
 typedef struct AOTCompFrame {
-    /* The current wasm module */
-    WASMModule *cur_wasm_module;
     /* The current compilation context */
     struct AOTCompContext *comp_ctx;
     /* The current function context */

+ 1 - 1
core/iwasm/include/gc_export.h

@@ -85,7 +85,7 @@ typedef union WASMValue {
     uint32_t type_index;
     struct {
         uint32_t type_index;
-        uint32_t N;
+        uint32_t length;
     } array_new_default;
     /* pointer to a memory space holding more data, current usage:
      *  struct.new init value: WASMStructNewInitValues *

+ 5 - 1
core/iwasm/interpreter/wasm.h

@@ -206,7 +206,7 @@ typedef union WASMValue {
     uint32 type_index;
     struct {
         uint32 type_index;
-        uint32 N;
+        uint32 length;
     } array_new_default;
     /* pointer to a memory space holding more data, current usage:
      *  struct.new init value: WASMStructNewInitValues *
@@ -1096,6 +1096,10 @@ wasm_value_type_size_internal(uint8 value_type, uint8 pointer_size)
 #endif
     )
         return pointer_size;
+    else if (value_type == PACKED_TYPE_I8)
+        return sizeof(int8);
+    else if (value_type == PACKED_TYPE_I16)
+        return sizeof(int16);
 #endif
     else {
         bh_assert(0);

+ 2 - 0
core/iwasm/interpreter/wasm_interp.h

@@ -59,6 +59,8 @@ typedef struct WASMInterpFrame {
      *  lp: parameters and local variables
      *  sp_bottom to sp_boundary: wasm operand stack
      *  csp_bottom to csp_boundary: wasm label stack
+     *  frame ref flags: only available for GC
+     *    whether each cell in local and stack area is a GC obj
      *  jit spill cache: only available for fast jit
      */
     uint32 lp[1];

+ 1 - 1
core/iwasm/interpreter/wasm_interp_classic.c

@@ -5160,7 +5160,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         SYNC_ALL_TO_FRAME();
 #endif
                         for (i = 0; i < n; i++) {
-                            /* UINT32_MAX indicates that it is an null ref */
+                            /* UINT32_MAX indicates that it is a null ref */
                             bh_assert(init_values[i].init_expr_type
                                           == INIT_EXPR_TYPE_REFNULL_CONST
                                       || init_values[i].init_expr_type

+ 1 - 1
core/iwasm/interpreter/wasm_interp_fast.c

@@ -5095,7 +5095,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         SYNC_ALL_TO_FRAME();
 #endif
                         for (i = 0; i < n; i++) {
-                            /* UINT32_MAX indicates that it is an null ref */
+                            /* UINT32_MAX indicates that it is a null ref */
                             bh_assert(init_values[i].init_expr_type
                                           == INIT_EXPR_TYPE_REFNULL_CONST
                                       || init_values[i].init_expr_type

+ 18 - 13
core/iwasm/interpreter/wasm_loader.c

@@ -794,8 +794,7 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
                 uint64 high, low;
 
                 CHECK_BUF(p, p_end, 1);
-                flag = read_uint8(p);
-                (void)flag;
+                (void)read_uint8(p);
 
                 CHECK_BUF(p, p_end, 16);
                 wasm_runtime_read_v128(p, &high, &low);
@@ -1204,7 +1203,7 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
                             len = len_val.i32;
 
                             cur_value.array_new_default.type_index = type_idx;
-                            cur_value.array_new_default.N = len;
+                            cur_value.array_new_default.length = len;
                         }
 
                         wasm_set_refheaptype_typeidx(
@@ -4163,16 +4162,22 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
                 case 4:
                 {
 #if WASM_ENABLE_GC != 0
-                    WASMRefType elem_ref_type = { 0 };
-                    /* TODO: for mode 4, we may need to decide elem_type
-                     * according to init expr result */
-                    table_segment->elem_type = REF_TYPE_HT_NON_NULLABLE;
-                    wasm_set_refheaptype_common(&elem_ref_type.ref_ht_common,
-                                                false, HEAP_TYPE_FUNC);
-                    if (!(table_segment->elem_ref_type = reftype_set_insert(
-                              module->ref_type_set, &elem_ref_type, error_buf,
-                              error_buf_size)))
-                        return false;
+                    if (table_segment->mode == 0) {
+                        /* vec(funcidx), set elem type to (ref func) */
+                        WASMRefType elem_ref_type = { 0 };
+                        table_segment->elem_type = REF_TYPE_HT_NON_NULLABLE;
+                        wasm_set_refheaptype_common(
+                            &elem_ref_type.ref_ht_common, false,
+                            HEAP_TYPE_FUNC);
+                        if (!(table_segment->elem_ref_type = reftype_set_insert(
+                                  module->ref_type_set, &elem_ref_type,
+                                  error_buf, error_buf_size)))
+                            return false;
+                    }
+                    else {
+                        /* vec(expr), set elem type to funcref */
+                        table_segment->elem_type = VALUE_TYPE_FUNCREF;
+                    }
 #else
                     table_segment->elem_type = VALUE_TYPE_FUNCREF;
 #endif

+ 13 - 7
core/iwasm/interpreter/wasm_runtime.c

@@ -968,7 +968,7 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
 
                 if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
                     type_idx = init_expr->u.array_new_default.type_index;
-                    len = init_expr->u.array_new_default.N;
+                    len = init_expr->u.array_new_default.length;
                     arr_init_val = &empty_val;
                 }
                 else {
@@ -2106,8 +2106,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
 #endif
 #if WASM_ENABLE_GC != 0
                 case VALUE_TYPE_EXTERNREF:
-                    /* UINT32_MAX indicates that it is an null reference */
-                    bh_assert((uint32)global->initial_value.i32 == UINT32_MAX);
+                    /* the initial value should be a null reference */
+                    bh_assert(global->initial_value.gc_obj == NULL_REF);
                     STORE_PTR((void **)global_data, NULL_REF);
                     global_data += sizeof(void *);
                     break;
@@ -2143,7 +2143,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                             NULL, module_inst->module->types,
                             module_inst->module->type_count)) {
                         WASMFuncObjectRef func_obj = NULL;
-                        /* UINT32_MAX indicates that it is an null reference */
+                        /* UINT32_MAX indicates that it is a null reference */
                         if ((uint32)global->initial_value.i32 != UINT32_MAX) {
                             if (!(func_obj = wasm_create_func_obj(
                                       module_inst, global->initial_value.i32,
@@ -2474,7 +2474,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
 #else
                     WASMFuncObjectRef func_obj;
                     uint32 func_idx = init_expr->u.ref_index;
-                    /* UINT32_MAX indicates that it is an null reference */
+                    /* UINT32_MAX indicates that it is a null reference */
                     if (func_idx != UINT32_MAX) {
                         if (!(func_obj = wasm_create_func_obj(
                                   module_inst, func_idx, false, error_buf,
@@ -2569,7 +2569,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
 
                     if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
                         type_idx = init_expr->u.array_new_default.type_index;
-                        len = init_expr->u.array_new_default.N;
+                        len = init_expr->u.array_new_default.length;
                         arr_init_val = &empty_val;
                     }
                     else {
@@ -2578,7 +2578,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
                         type_idx = init_values->type_idx;
                         len = init_values->length;
 
-                        if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
+                        if (flag == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) {
                             arr_init_val = init_values->elem_data;
                         }
                     }
@@ -2635,8 +2635,14 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
     if (stack_size == 0)
         stack_size = DEFAULT_WASM_STACK_SIZE;
 #if WASM_ENABLE_SPEC_TEST != 0
+#if WASM_ENABLE_TAIL_CALL == 0
     if (stack_size < 128 * 1024)
         stack_size = 128 * 1024;
+#else
+    /* Some tail-call cases require large operand stack */
+    if (stack_size < 10 * 1024 * 1024)
+        stack_size = 10 * 1024 * 1024;
+#endif
 #endif
     module_inst->default_wasm_stack_size = stack_size;
 

+ 6 - 0
product-mini/platforms/nuttx/wamr.mk

@@ -383,6 +383,12 @@ else
 CFLAGS += -DWASM_ENABLE_REF_TYPES=0
 endif
 
+ifeq ($(CONFIG_INTERPRETERS_WAMR_TAIL_CALL),y)
+CFLAGS += -DWASM_ENABLE_TAIL_CALL=1
+else
+CFLAGS += -DWASM_ENABLE_TAIL_CALL=0
+endif
+
 CFLAGS += -Wno-strict-prototypes -Wno-shadow -Wno-unused-variable
 CFLAGS += -Wno-int-conversion -Wno-implicit-function-declaration
 

+ 15 - 33
tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch

@@ -1,33 +1,3 @@
-From 6ba21a1b8aeaa74ddf9697411ae58b7022dbc83f Mon Sep 17 00:00:00 2001
-From: Xu Jun <jun1.xu@intel.com>
-Date: Mon, 11 Dec 2023 02:13:25 +0800
-Subject: [PATCH] ignore cases
-
----
- test/core/binary-leb128.wast     |   2 +-
- test/core/binary.wast            |   3 +-
- test/core/data.wast              |  12 +-
- test/core/elem.wast              |  23 ++--
- test/core/gc/array.wast          |   8 +-
- test/core/gc/extern.wast         |   2 +-
- test/core/gc/initializer.wast    |  34 ++++++
- test/core/gc/ref_test.wast       |  13 ++-
- test/core/gc/type-subtyping.wast |  65 ++++++-----
- test/core/global.wast            |   4 +-
- test/core/imports.wast           |   2 +
- test/core/linking.wast           |  20 ++++
- test/core/ref_func.wast          |   3 +-
- test/core/ref_null.wast          |  30 ++---
- test/core/return_call.wast       |  10 +-
- test/core/return_call_ref.wast   |  10 +-
- test/core/select.wast            |   2 +-
- test/core/table.wast             |   6 +-
- test/core/table_copy.wast        | 181 ++++++++++++++++---------------
- test/core/table_init.wast        |  66 ++++++-----
- test/core/unreached-valid.wast   |   4 +-
- 21 files changed, 297 insertions(+), 203 deletions(-)
- create mode 100644 test/core/gc/initializer.wast
-
 diff --git a/test/core/binary-leb128.wast b/test/core/binary-leb128.wast
 index 335496f0..5b975028 100644
 --- a/test/core/binary-leb128.wast
@@ -792,6 +762,21 @@ index 2f91f4de..ad66acca 100644
  
  
  ;; Invalid typing
+diff --git a/test/core/return_call_indirect.wast b/test/core/return_call_indirect.wast
+index acf0a72e..6b95c24b 100644
+--- a/test/core/return_call_indirect.wast
++++ b/test/core/return_call_indirect.wast
+@@ -263,8 +263,8 @@
+ (assert_return (invoke "odd" (i32.const 1)) (i32.const 44))
+ (assert_return (invoke "odd" (i32.const 200)) (i32.const 99))
+ (assert_return (invoke "odd" (i32.const 77)) (i32.const 44))
+-(assert_return (invoke "odd" (i32.const 200_002)) (i32.const 99))
+-(assert_return (invoke "odd" (i32.const 300_003)) (i32.const 44))
++(assert_return (invoke "odd" (i32.const 100_002)) (i32.const 99))
++(assert_return (invoke "odd" (i32.const 100_003)) (i32.const 44))
+ 
+ 
+ ;; Invalid syntax
 diff --git a/test/core/return_call_ref.wast b/test/core/return_call_ref.wast
 index 353811f0..f79975b4 100644
 --- a/test/core/return_call_ref.wast
@@ -1303,6 +1288,3 @@ index f3feb0f3..d8ef8743 100644
    )
  )
 +;)
--- 
-2.25.1
-

+ 53 - 0
tests/wamr-test-suites/spec-test-script/gc_nuttx_tail_call.patch

@@ -0,0 +1,53 @@
+diff --git a/test/core/return_call.wast b/test/core/return_call.wast
+index ad66acca..b27af19b 100644
+--- a/test/core/return_call.wast
++++ b/test/core/return_call.wast
+@@ -102,20 +102,20 @@
+ 
+ (assert_return (invoke "count" (i64.const 0)) (i64.const 0))
+ (assert_return (invoke "count" (i64.const 1000)) (i64.const 0))
+-(assert_return (invoke "count" (i64.const 100_000)) (i64.const 0))
++(assert_return (invoke "count" (i64.const 1001)) (i64.const 0))
+ 
+ (assert_return (invoke "even" (i64.const 0)) (i32.const 44))
+ (assert_return (invoke "even" (i64.const 1)) (i32.const 99))
+ (assert_return (invoke "even" (i64.const 100)) (i32.const 44))
+ (assert_return (invoke "even" (i64.const 77)) (i32.const 99))
+-(assert_return (invoke "even" (i64.const 100_000)) (i32.const 44))
+-(assert_return (invoke "even" (i64.const 100_001)) (i32.const 99))
++(assert_return (invoke "even" (i64.const 1000)) (i32.const 44))
++(assert_return (invoke "even" (i64.const 1001)) (i32.const 99))
+ (assert_return (invoke "odd" (i64.const 0)) (i32.const 99))
+ (assert_return (invoke "odd" (i64.const 1)) (i32.const 44))
+ (assert_return (invoke "odd" (i64.const 200)) (i32.const 99))
+ (assert_return (invoke "odd" (i64.const 77)) (i32.const 44))
+-(assert_return (invoke "odd" (i64.const 100_000)) (i32.const 99))
+-(assert_return (invoke "odd" (i64.const 99_999)) (i32.const 44))
++(assert_return (invoke "odd" (i64.const 1000)) (i32.const 99))
++(assert_return (invoke "odd" (i64.const 999)) (i32.const 44))
+ 
+ 
+ ;; Invalid typing
+diff --git a/test/core/return_call_indirect.wast b/test/core/return_call_indirect.wast
+index 6b95c24b..a9e86d42 100644
+--- a/test/core/return_call_indirect.wast
++++ b/test/core/return_call_indirect.wast
+@@ -257,14 +257,14 @@
+ (assert_return (invoke "even" (i32.const 1)) (i32.const 99))
+ (assert_return (invoke "even" (i32.const 100)) (i32.const 44))
+ (assert_return (invoke "even" (i32.const 77)) (i32.const 99))
+-(assert_return (invoke "even" (i32.const 100_000)) (i32.const 44))
+-(assert_return (invoke "even" (i32.const 111_111)) (i32.const 99))
++(assert_return (invoke "even" (i32.const 1000)) (i32.const 44))
++(assert_return (invoke "even" (i32.const 1111)) (i32.const 99))
+ (assert_return (invoke "odd" (i32.const 0)) (i32.const 99))
+ (assert_return (invoke "odd" (i32.const 1)) (i32.const 44))
+ (assert_return (invoke "odd" (i32.const 200)) (i32.const 99))
+ (assert_return (invoke "odd" (i32.const 77)) (i32.const 44))
+-(assert_return (invoke "odd" (i32.const 100_002)) (i32.const 99))
+-(assert_return (invoke "odd" (i32.const 100_003)) (i32.const 44))
++(assert_return (invoke "odd" (i32.const 1002)) (i32.const 99))
++(assert_return (invoke "odd" (i32.const 1003)) (i32.const 44))
+ 
+ 
+ ;; Invalid syntax

+ 44 - 18
tests/wamr-test-suites/spec-test-script/runtest.py

@@ -623,7 +623,7 @@ def vector_value_comparison(out, expected):
         int(expected_val[1]) if not "0x" in expected_val[1] else int(expected_val[1], 16))
 
     if lane_type in ["i8x16", "i16x8", "i32x4", "i64x2"]:
-        return out_packed == expected_packed;
+        return out_packed == expected_packed
     else:
         assert(lane_type in ["f32x4", "f64x2"]), "unexpected lane_type"
 
@@ -807,7 +807,7 @@ def test_assert_return(r, opts, form):
             n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"*()()\)\s*\)\s*$', form, re.S)
     if not m and not n:
         if re.search('^\(assert_return\s+\(get.*\).*\)$', form, re.S):
-            log("ignoring assert_return get");
+            log("ignoring assert_return get")
             return
         else:
             raise Exception("unparsed assert_return: '%s'" % form)
@@ -888,6 +888,7 @@ def test_assert_return(r, opts, form):
             except:
                 _, exc, _ = sys.exc_info()
                 log("Run wamrc failed:\n  got: '%s'" % r.buf)
+                ret_code = 1
                 sys.exit(1)
         r = run_wasm_with_repl(module+".wasm", module+".aot" if test_aot else module, opts, r)
         # Wait for the initial prompt
@@ -953,6 +954,7 @@ def test_assert_trap(r, opts, form):
             except:
                 _, exc, _ = sys.exc_info()
                 log("Run wamrc failed:\n  got: '%s'" % r.buf)
+                ret_code = 1
                 sys.exit(1)
         r = run_wasm_with_repl(module+".wasm", module+".aot" if test_aot else module, opts, r)
         # Wait for the initial prompt
@@ -1043,7 +1045,7 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts):
     return True
 
 def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = 'default'):
-    log("Compiling AOT to '%s'" % aot_tempfile)
+    log("Compiling '%s' to '%s'" % (wasm_tempfile, aot_tempfile))
     cmd = [opts.aot_compiler]
 
     if test_target in aot_target_options_map:
@@ -1064,6 +1066,7 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = '
 
     if opts.gc:
         cmd.append("--enable-gc")
+        cmd.append("--enable-tail-call")
 
     if output == 'object':
         cmd.append("--format=object")
@@ -1178,6 +1181,7 @@ def test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile,
             else:
                 log("Run wamrc failed:\n  expected: '%s'\n  got: '%s'" % \
                     (expected, r.buf))
+                ret_code = 1
                 sys.exit(1)
 
     r = run_wasm_with_repl(wasm_tempfile, aot_tempfile if test_aot else None, opts, r)
@@ -1272,26 +1276,47 @@ if __name__ == "__main__":
                                 log("Out exception includes expected one, pass:")
                                 log("  Expected: %s" % error_msg)
                                 log("  Got: %s" % r.buf)
+                                continue
+                            # one case in binary.wast
+                            elif (error_msg == "unexpected end of section or function"
+                                  and r.buf.find("unexpected end")):
+                                continue
+                            # one case in binary.wast
+                            elif (error_msg == "invalid value type"
+                                  and r.buf.find("unexpected end")):
+                                continue
+                            # one case in binary.wast
+                            elif (error_msg == "integer too large"
+                                  and r.buf.find("tables cannot be shared")):
+                                continue
+                            # one case in binary.wast
+                            elif (error_msg == "zero byte expected"
+                                  and r.buf.find("unknown table")):
+                                continue
+                            # one case in binary.wast
+                            elif (error_msg == "invalid section id"
+                                  and r.buf.find("unexpected end of section or function")):
+                                continue
+                            # one case in binary.wast
+                            elif (error_msg == "illegal opcode"
+                                  and r.buf.find("unexpected end of section or function")):
+                                continue
+                            # one case in custom.wast
+                            elif (error_msg == "length out of bounds"
+                                  and r.buf.find("unexpected end")):
+                                continue
+                            # several cases in binary-leb128.wast
+                            elif (error_msg == "integer representation too long"
+                                  and r.buf.find("invalid section id")):
+                                continue
                             else:
                                 log("Run wamrc failed:\n  expected: '%s'\n  got: '%s'" % \
                                     (error_msg, r.buf))
-                            continue
+                                ret_code = 1
+                                sys.exit(1)
 
                     r = run_wasm_with_repl(wasm_tempfile, aot_tempfile if test_aot else None, opts, r)
 
-                    if (error_msg == "unexpected end of section or function"):
-                        # one case in binary.wast
-                        assert_prompt(r, ["unexpected end", error_msg], opts.start_timeout, True)
-                    elif (error_msg == "invalid value type"):
-                        # one case in binary.wast
-                        assert_prompt(r, ["unexpected end", error_msg], opts.start_timeout, True)
-                    elif (error_msg == "length out of bounds"):
-                        # one case in custom.wast
-                        assert_prompt(r, ["unexpected end", error_msg], opts.start_timeout, True)
-                    elif (error_msg == "integer representation too long"):
-                        # several cases in binary-leb128.wast
-                        assert_prompt(r, ["invalid section id", error_msg], opts.start_timeout, True)
-
                 elif re.match("^\(assert_malformed\s*\(module quote", form):
                     log("ignoring assert_malformed module quote")
                 else:
@@ -1324,6 +1349,7 @@ if __name__ == "__main__":
                             except:
                                 _, exc, _ = sys.exc_info()
                                 log("Run wamrc failed:\n  got: '%s'" % r.buf)
+                                ret_code = 1
                                 sys.exit(1)
                         temp_module_table[module_name] = temp_files[1]
                         r = run_wasm_with_repl(temp_files[1], temp_files[2] if test_aot else None, opts, r)
@@ -1338,6 +1364,7 @@ if __name__ == "__main__":
                         except:
                             _, exc, _ = sys.exc_info()
                             log("Run wamrc failed:\n  got: '%s'" % r.buf)
+                            ret_code = 1
                             sys.exit(1)
 
                     r = run_wasm_with_repl(wasm_tempfile, aot_tempfile if test_aot else None, opts, r)
@@ -1421,4 +1448,3 @@ if __name__ == "__main__":
             log("Leaving tempfiles: %s" % ([wast_tempfile, wasm_tempfile]))
 
         sys.exit(ret_code)
-        

+ 0 - 202
tests/wamr-test-suites/spec-test-script/tail-call/return_call.wast

@@ -1,202 +0,0 @@
-;; Test `return_call` operator
-
-(module
-  ;; Auxiliary definitions
-  (func $const-i32 (result i32) (i32.const 0x132))
-  (func $const-i64 (result i64) (i64.const 0x164))
-  (func $const-f32 (result f32) (f32.const 0xf32))
-  (func $const-f64 (result f64) (f64.const 0xf64))
-
-  (func $id-i32 (param i32) (result i32) (get_local 0))
-  (func $id-i64 (param i64) (result i64) (get_local 0))
-  (func $id-f32 (param f32) (result f32) (get_local 0))
-  (func $id-f64 (param f64) (result f64) (get_local 0))
-
-  (func $f32-i32 (param f32 i32) (result i32) (get_local 1))
-  (func $i32-i64 (param i32 i64) (result i64) (get_local 1))
-  (func $f64-f32 (param f64 f32) (result f32) (get_local 1))
-  (func $i64-f64 (param i64 f64) (result f64) (get_local 1))
-
-  ;; Typing
-
-  (func (export "type-i32") (result i32) (return_call $const-i32))
-  (func (export "type-i64") (result i64) (return_call $const-i64))
-  (func (export "type-f32") (result f32) (return_call $const-f32))
-  (func (export "type-f64") (result f64) (return_call $const-f64))
-
-  (func (export "type-first-i32") (result i32) (return_call $id-i32 (i32.const 32)))
-  (func (export "type-first-i64") (result i64) (return_call $id-i64 (i64.const 64)))
-  (func (export "type-first-f32") (result f32) (return_call $id-f32 (f32.const 1.32)))
-  (func (export "type-first-f64") (result f64) (return_call $id-f64 (f64.const 1.64)))
-
-  (func (export "type-second-i32") (result i32)
-    (return_call $f32-i32 (f32.const 32.1) (i32.const 32))
-  )
-  (func (export "type-second-i64") (result i64)
-    (return_call $i32-i64 (i32.const 32) (i64.const 64))
-  )
-  (func (export "type-second-f32") (result f32)
-    (return_call $f64-f32 (f64.const 64) (f32.const 32))
-  )
-  (func (export "type-second-f64") (result f64)
-    (return_call $i64-f64 (i64.const 64) (f64.const 64.1))
-  )
-
-  ;; Recursion
-
-  (func $fac-acc (export "fac-acc") (param i64 i64) (result i64)
-    (if (result i64) (i64.eqz (get_local 0))
-      (then (get_local 1))
-      (else
-        (return_call $fac-acc
-          (i64.sub (get_local 0) (i64.const 1))
-          (i64.mul (get_local 0) (get_local 1))
-        )
-      )
-    )
-  )
-
-  (func $count (export "count") (param i64) (result i64)
-    (if (result i64) (i64.eqz (get_local 0))
-      (then (get_local 0))
-      (else (return_call $count (i64.sub (get_local 0) (i64.const 1))))
-    )
-  )
-
-  (func $even (export "even") (param i64) (result i32)
-    (if (result i32) (i64.eqz (get_local 0))
-      (then (i32.const 44))
-      (else (return_call $odd (i64.sub (get_local 0) (i64.const 1))))
-    )
-  )
-  (func $odd (export "odd") (param i64) (result i32)
-    (if (result i32) (i64.eqz (get_local 0))
-      (then (i32.const 99))
-      (else (return_call $even (i64.sub (get_local 0) (i64.const 1))))
-    )
-  )
-)
-
-(assert_return (invoke "type-i32") (i32.const 0x132))
-(assert_return (invoke "type-i64") (i64.const 0x164))
-(assert_return (invoke "type-f32") (f32.const 0xf32))
-(assert_return (invoke "type-f64") (f64.const 0xf64))
-
-(assert_return (invoke "type-first-i32") (i32.const 32))
-(assert_return (invoke "type-first-i64") (i64.const 64))
-(assert_return (invoke "type-first-f32") (f32.const 1.32))
-(assert_return (invoke "type-first-f64") (f64.const 1.64))
-
-(assert_return (invoke "type-second-i32") (i32.const 32))
-(assert_return (invoke "type-second-i64") (i64.const 64))
-(assert_return (invoke "type-second-f32") (f32.const 32))
-(assert_return (invoke "type-second-f64") (f64.const 64.1))
-
-(assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1))
-(assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1))
-(assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120))
-(assert_return
-  (invoke "fac-acc" (i64.const 25) (i64.const 1))
-  (i64.const 7034535277573963776)
-)
-
-(assert_return (invoke "count" (i64.const 0)) (i64.const 0))
-(assert_return (invoke "count" (i64.const 1000)) (i64.const 0))
-(assert_return (invoke "count" (i64.const 1_000_000)) (i64.const 0))
-
-(assert_return (invoke "even" (i64.const 0)) (i32.const 44))
-(assert_return (invoke "even" (i64.const 1)) (i32.const 99))
-(assert_return (invoke "even" (i64.const 100)) (i32.const 44))
-(assert_return (invoke "even" (i64.const 77)) (i32.const 99))
-(assert_return (invoke "even" (i64.const 1_000_000)) (i32.const 44))
-(assert_return (invoke "even" (i64.const 1_000_001)) (i32.const 99))
-(assert_return (invoke "odd" (i64.const 0)) (i32.const 99))
-(assert_return (invoke "odd" (i64.const 1)) (i32.const 44))
-(assert_return (invoke "odd" (i64.const 200)) (i32.const 99))
-(assert_return (invoke "odd" (i64.const 77)) (i32.const 44))
-(assert_return (invoke "odd" (i64.const 1_000_000)) (i32.const 99))
-(assert_return (invoke "odd" (i64.const 999_999)) (i32.const 44))
-
-
-;; Invalid typing
-
-(assert_invalid
-  (module
-    (func $type-void-vs-num (result i32) (return_call 1) (i32.const 0))
-    (func)
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (func $type-num-vs-num (result i32) (return_call 1) (i32.const 0))
-    (func (result i64) (i64.const 1))
-  )
-  "type mismatch"
-)
-
-(assert_invalid
-  (module
-    (func $arity-0-vs-1 (return_call 1))
-    (func (param i32))
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (func $arity-0-vs-2 (return_call 1))
-    (func (param f64 i32))
-  )
-  "type mismatch"
-)
-
-(module
-  (func $arity-1-vs-0 (i32.const 1) (return_call 1))
-  (func)
-)
-
-(module
-  (func $arity-2-vs-0 (f64.const 2) (i32.const 1) (return_call 1))
-  (func)
-)
-
-(assert_invalid
-  (module
-    (func $type-first-void-vs-num (return_call 1 (nop) (i32.const 1)))
-    (func (param i32 i32))
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (func $type-second-void-vs-num (return_call 1 (i32.const 1) (nop)))
-    (func (param i32 i32))
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (func $type-first-num-vs-num (return_call 1 (f64.const 1) (i32.const 1)))
-    (func (param i32 f64))
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (func $type-second-num-vs-num (return_call 1 (i32.const 1) (f64.const 1)))
-    (func (param f64 i32))
-  )
-  "type mismatch"
-)
-
-
-;; Unbound function
-
-(assert_invalid
-  (module (func $unbound-func (return_call 1)))
-  "unknown function"
-)
-(assert_invalid
-  (module (func $large-func (return_call 1012321300)))
-  "unknown function"
-)

+ 0 - 511
tests/wamr-test-suites/spec-test-script/tail-call/return_call_indirect.wast

@@ -1,511 +0,0 @@
-;; Test `return_call_indirect` operator
-
-(module
-  ;; Auxiliary definitions
-  (type $proc (func))
-  (type $out-i32 (func (result i32)))
-  (type $out-i64 (func (result i64)))
-  (type $out-f32 (func (result f32)))
-  (type $out-f64 (func (result f64)))
-  (type $over-i32 (func (param i32) (result i32)))
-  (type $over-i64 (func (param i64) (result i64)))
-  (type $over-f32 (func (param f32) (result f32)))
-  (type $over-f64 (func (param f64) (result f64)))
-  (type $f32-i32 (func (param f32 i32) (result i32)))
-  (type $i32-i64 (func (param i32 i64) (result i64)))
-  (type $f64-f32 (func (param f64 f32) (result f32)))
-  (type $i64-f64 (func (param i64 f64) (result f64)))
-  (type $over-i32-duplicate (func (param i32) (result i32)))
-  (type $over-i64-duplicate (func (param i64) (result i64)))
-  (type $over-f32-duplicate (func (param f32) (result f32)))
-  (type $over-f64-duplicate (func (param f64) (result f64)))
-
-  (func $const-i32 (type $out-i32) (i32.const 0x132))
-  (func $const-i64 (type $out-i64) (i64.const 0x164))
-  (func $const-f32 (type $out-f32) (f32.const 0xf32))
-  (func $const-f64 (type $out-f64) (f64.const 0xf64))
-
-  (func $id-i32 (type $over-i32) (get_local 0))
-  (func $id-i64 (type $over-i64) (get_local 0))
-  (func $id-f32 (type $over-f32) (get_local 0))
-  (func $id-f64 (type $over-f64) (get_local 0))
-
-  (func $i32-i64 (type $i32-i64) (get_local 1))
-  (func $i64-f64 (type $i64-f64) (get_local 1))
-  (func $f32-i32 (type $f32-i32) (get_local 1))
-  (func $f64-f32 (type $f64-f32) (get_local 1))
-
-  (func $over-i32-duplicate (type $over-i32-duplicate) (get_local 0))
-  (func $over-i64-duplicate (type $over-i64-duplicate) (get_local 0))
-  (func $over-f32-duplicate (type $over-f32-duplicate) (get_local 0))
-  (func $over-f64-duplicate (type $over-f64-duplicate) (get_local 0))
-
-  (table anyfunc
-    (elem
-      $const-i32 $const-i64 $const-f32 $const-f64
-      $id-i32 $id-i64 $id-f32 $id-f64
-      $f32-i32 $i32-i64 $f64-f32 $i64-f64
-      $fac $fac-acc $even $odd
-      $over-i32-duplicate $over-i64-duplicate
-      $over-f32-duplicate $over-f64-duplicate
-    )
-  )
-
-  ;; Syntax
-
-  (func
-    (return_call_indirect (i32.const 0))
-    (return_call_indirect (param i64) (i64.const 0) (i32.const 0))
-    (return_call_indirect (param i64) (param) (param f64 i32 i64)
-      (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0)
-    )
-    (return_call_indirect (result) (i32.const 0))
-  )
-
-  (func (result i32)
-    (return_call_indirect (result i32) (i32.const 0))
-    (return_call_indirect (result i32) (result) (i32.const 0))
-    (return_call_indirect (param i64) (result i32) (i64.const 0) (i32.const 0))
-    (return_call_indirect
-      (param) (param i64) (param) (param f64 i32 i64) (param) (param)
-      (result) (result i32) (result) (result)
-      (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0)
-    )
-  )
-
-  (func (result i64)
-    (return_call_indirect (type $over-i64) (param i64) (result i64)
-      (i64.const 0) (i32.const 0)
-    )
-  )
-
-  ;; Typing
-
-  (func (export "type-i32") (result i32)
-    (return_call_indirect (type $out-i32) (i32.const 0))
-  )
-  (func (export "type-i64") (result i64)
-    (return_call_indirect (type $out-i64) (i32.const 1))
-  )
-  (func (export "type-f32") (result f32)
-    (return_call_indirect (type $out-f32) (i32.const 2))
-  )
-  (func (export "type-f64") (result f64)
-    (return_call_indirect (type $out-f64) (i32.const 3))
-  )
-
-  (func (export "type-index") (result i64)
-    (return_call_indirect (type $over-i64) (i64.const 100) (i32.const 5))
-  )
-
-  (func (export "type-first-i32") (result i32)
-    (return_call_indirect (type $over-i32) (i32.const 32) (i32.const 4))
-  )
-  (func (export "type-first-i64") (result i64)
-    (return_call_indirect (type $over-i64) (i64.const 64) (i32.const 5))
-  )
-  (func (export "type-first-f32") (result f32)
-    (return_call_indirect (type $over-f32) (f32.const 1.32) (i32.const 6))
-  )
-  (func (export "type-first-f64") (result f64)
-    (return_call_indirect (type $over-f64) (f64.const 1.64) (i32.const 7))
-  )
-
-  (func (export "type-second-i32") (result i32)
-    (return_call_indirect (type $f32-i32)
-      (f32.const 32.1) (i32.const 32) (i32.const 8)
-    )
-  )
-  (func (export "type-second-i64") (result i64)
-    (return_call_indirect (type $i32-i64)
-      (i32.const 32) (i64.const 64) (i32.const 9)
-    )
-  )
-  (func (export "type-second-f32") (result f32)
-    (return_call_indirect (type $f64-f32)
-      (f64.const 64) (f32.const 32) (i32.const 10)
-    )
-  )
-  (func (export "type-second-f64") (result f64)
-    (return_call_indirect (type $i64-f64)
-      (i64.const 64) (f64.const 64.1) (i32.const 11)
-    )
-  )
-
-  ;; Dispatch
-
-  (func (export "dispatch") (param i32 i64) (result i64)
-    (return_call_indirect (type $over-i64) (get_local 1) (get_local 0))
-  )
-
-  (func (export "dispatch-structural") (param i32) (result i64)
-    (return_call_indirect (type $over-i64-duplicate)
-      (i64.const 9) (get_local 0)
-    )
-  )
-
-  ;; Recursion
-
-  (func $fac (export "fac") (type $over-i64)
-    (return_call_indirect (param i64 i64) (result i64)
-      (get_local 0) (i64.const 1) (i32.const 13)
-    )
-  )
-
-  (func $fac-acc (param i64 i64) (result i64)
-    (if (result i64) (i64.eqz (get_local 0))
-      (then (get_local 1))
-      (else
-        (return_call_indirect (param i64 i64) (result i64)
-          (i64.sub (get_local 0) (i64.const 1))
-          (i64.mul (get_local 0) (get_local 1))
-          (i32.const 13)
-        )
-      )
-    )
-  )
-
-  (func $even (export "even") (param i32) (result i32)
-    (if (result i32) (i32.eqz (get_local 0))
-      (then (i32.const 44))
-      (else
-        (return_call_indirect (type $over-i32)
-          (i32.sub (get_local 0) (i32.const 1))
-          (i32.const 15)
-        )
-      )
-    )
-  )
-  (func $odd (export "odd") (param i32) (result i32)
-    (if (result i32) (i32.eqz (get_local 0))
-      (then (i32.const 99))
-      (else
-        (return_call_indirect (type $over-i32)
-          (i32.sub (get_local 0) (i32.const 1))
-          (i32.const 14)
-        )
-      )
-    )
-  )
-)
-
-(assert_return (invoke "type-i32") (i32.const 0x132))
-(assert_return (invoke "type-i64") (i64.const 0x164))
-(assert_return (invoke "type-f32") (f32.const 0xf32))
-(assert_return (invoke "type-f64") (f64.const 0xf64))
-
-(assert_return (invoke "type-index") (i64.const 100))
-
-(assert_return (invoke "type-first-i32") (i32.const 32))
-(assert_return (invoke "type-first-i64") (i64.const 64))
-(assert_return (invoke "type-first-f32") (f32.const 1.32))
-(assert_return (invoke "type-first-f64") (f64.const 1.64))
-
-(assert_return (invoke "type-second-i32") (i32.const 32))
-(assert_return (invoke "type-second-i64") (i64.const 64))
-(assert_return (invoke "type-second-f32") (f32.const 32))
-(assert_return (invoke "type-second-f64") (f64.const 64.1))
-
-(assert_return (invoke "dispatch" (i32.const 5) (i64.const 2)) (i64.const 2))
-(assert_return (invoke "dispatch" (i32.const 5) (i64.const 5)) (i64.const 5))
-(assert_return (invoke "dispatch" (i32.const 12) (i64.const 5)) (i64.const 120))
-(assert_return (invoke "dispatch" (i32.const 17) (i64.const 2)) (i64.const 2))
-(assert_trap (invoke "dispatch" (i32.const 0) (i64.const 2)) "indirect call type mismatch")
-(assert_trap (invoke "dispatch" (i32.const 15) (i64.const 2)) "indirect call type mismatch")
-(assert_trap (invoke "dispatch" (i32.const 20) (i64.const 2)) "undefined element")
-(assert_trap (invoke "dispatch" (i32.const -1) (i64.const 2)) "undefined element")
-(assert_trap (invoke "dispatch" (i32.const 1213432423) (i64.const 2)) "undefined element")
-
-(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9))
-(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9))
-(assert_return (invoke "dispatch-structural" (i32.const 12)) (i64.const 362880))
-(assert_return (invoke "dispatch-structural" (i32.const 17)) (i64.const 9))
-(assert_trap (invoke "dispatch-structural" (i32.const 11)) "indirect call type mismatch")
-(assert_trap (invoke "dispatch-structural" (i32.const 16)) "indirect call type mismatch")
-
-(assert_return (invoke "fac" (i64.const 0)) (i64.const 1))
-(assert_return (invoke "fac" (i64.const 1)) (i64.const 1))
-(assert_return (invoke "fac" (i64.const 5)) (i64.const 120))
-(assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776))
-
-(assert_return (invoke "even" (i32.const 0)) (i32.const 44))
-(assert_return (invoke "even" (i32.const 1)) (i32.const 99))
-(assert_return (invoke "even" (i32.const 100)) (i32.const 44))
-(assert_return (invoke "even" (i32.const 77)) (i32.const 99))
-(assert_return (invoke "even" (i32.const 100_000)) (i32.const 44))
-(assert_return (invoke "even" (i32.const 111_111)) (i32.const 99))
-(assert_return (invoke "odd" (i32.const 0)) (i32.const 99))
-(assert_return (invoke "odd" (i32.const 1)) (i32.const 44))
-(assert_return (invoke "odd" (i32.const 200)) (i32.const 99))
-(assert_return (invoke "odd" (i32.const 77)) (i32.const 44))
-(assert_return (invoke "odd" (i32.const 200_002)) (i32.const 99))
-(assert_return (invoke "odd" (i32.const 300_003)) (i32.const 44))
-
-
-;; Invalid syntax
-
-(assert_malformed
-  (module quote
-    "(type $sig (func (param i32) (result i32)))"
-    "(table 0 anyfunc)"
-    "(func (result i32)"
-    "  (return_call_indirect (type $sig) (result i32) (param i32)"
-    "    (i32.const 0) (i32.const 0)"
-    "  )"
-    ")"
-  )
-  "unexpected token"
-)
-(assert_malformed
-  (module quote
-    "(type $sig (func (param i32) (result i32)))"
-    "(table 0 anyfunc)"
-    "(func (result i32)"
-    "  (return_call_indirect (param i32) (type $sig) (result i32)"
-    "    (i32.const 0) (i32.const 0)"
-    "  )"
-    ")"
-  )
-  "unexpected token"
-)
-(assert_malformed
-  (module quote
-    "(type $sig (func (param i32) (result i32)))"
-    "(table 0 anyfunc)"
-    "(func (result i32)"
-    "  (return_call_indirect (param i32) (result i32) (type $sig)"
-    "    (i32.const 0) (i32.const 0)"
-    "  )"
-    ")"
-  )
-  "unexpected token"
-)
-(assert_malformed
-  (module quote
-    "(type $sig (func (param i32) (result i32)))"
-    "(table 0 anyfunc)"
-    "(func (result i32)"
-    "  (return_call_indirect (result i32) (type $sig) (param i32)"
-    "    (i32.const 0) (i32.const 0)"
-    "  )"
-    ")"
-  )
-  "unexpected token"
-)
-(assert_malformed
-  (module quote
-    "(type $sig (func (param i32) (result i32)))"
-    "(table 0 anyfunc)"
-    "(func (result i32)"
-    "  (return_call_indirect (result i32) (param i32) (type $sig)"
-    "    (i32.const 0) (i32.const 0)"
-    "  )"
-    ")"
-  )
-  "unexpected token"
-)
-(assert_malformed
-  (module quote
-    "(table 0 anyfunc)"
-    "(func (result i32)"
-    "  (return_call_indirect (result i32) (param i32)"
-    "    (i32.const 0) (i32.const 0)"
-    "  )"
-    ")"
-  )
-  "unexpected token"
-)
-
-(assert_malformed
-  (module quote
-    "(table 0 anyfunc)"
-    "(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0)))"
-  )
-  "unexpected token"
-)
-(assert_malformed
-  (module quote
-    "(type $sig (func))"
-    "(table 0 anyfunc)"
-    "(func (result i32)"
-    "  (return_call_indirect (type $sig) (result i32) (i32.const 0))"
-    ")"
-  )
-  "inline function type"
-)
-(assert_malformed
-  (module quote
-    "(type $sig (func (param i32) (result i32)))"
-    "(table 0 anyfunc)"
-    "(func (result i32)"
-    "  (return_call_indirect (type $sig) (result i32) (i32.const 0))"
-    ")"
-  )
-  "inline function type"
-)
-(assert_malformed
-  (module quote
-    "(type $sig (func (param i32) (result i32)))"
-    "(table 0 anyfunc)"
-    "(func"
-    "  (return_call_indirect (type $sig) (param i32)"
-    "    (i32.const 0) (i32.const 0)"
-    "  )"
-    ")"
-  )
-  "inline function type"
-)
-(assert_malformed
-  (module quote
-    "(type $sig (func (param i32 i32) (result i32)))"
-    "(table 0 anyfunc)"
-    "(func (result i32)"
-    "  (return_call_indirect (type $sig) (param i32) (result i32)"
-    "    (i32.const 0) (i32.const 0)"
-    "  )"
-    ")"
-  )
-  "inline function type"
-)
-
-;; Invalid typing
-
-(assert_invalid
-  (module
-    (type (func))
-    (func $no-table (return_call_indirect (type 0) (i32.const 0)))
-  )
-  "unknown table"
-)
-
-(assert_invalid
-  (module
-    (type (func))
-    (table 0 anyfunc)
-    (func $type-void-vs-num (i32.eqz (return_call_indirect (type 0) (i32.const 0))))
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (type (func (result i64)))
-    (table 0 anyfunc)
-    (func $type-num-vs-num (i32.eqz (return_call_indirect (type 0) (i32.const 0))))
-  )
-  "type mismatch"
-)
-
-(assert_invalid
-  (module
-    (type (func (param i32)))
-    (table 0 anyfunc)
-    (func $arity-0-vs-1 (return_call_indirect (type 0) (i32.const 0)))
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (type (func (param f64 i32)))
-    (table 0 anyfunc)
-    (func $arity-0-vs-2 (return_call_indirect (type 0) (i32.const 0)))
-  )
-  "type mismatch"
-)
-
-(module
-  (type (func))
-  (table 0 anyfunc)
-  (func $arity-1-vs-0 (return_call_indirect (type 0) (i32.const 1) (i32.const 0)))
-)
-
-(module
-  (type (func))
-  (table 0 anyfunc)
-  (func $arity-2-vs-0
-    (return_call_indirect (type 0) (f64.const 2) (i32.const 1) (i32.const 0))
-  )
-)
-
-(assert_invalid
-  (module
-    (type (func (param i32)))
-    (table 0 anyfunc)
-    (func $type-func-void-vs-i32 (return_call_indirect (type 0) (i32.const 1) (nop)))
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (type (func (param i32)))
-    (table 0 anyfunc)
-    (func $type-func-num-vs-i32 (return_call_indirect (type 0) (i32.const 0) (i64.const 1)))
-  )
-  "type mismatch"
-)
-
-(assert_invalid
-  (module
-    (type (func (param i32 i32)))
-    (table 0 anyfunc)
-    (func $type-first-void-vs-num
-      (return_call_indirect (type 0) (nop) (i32.const 1) (i32.const 0))
-    )
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (type (func (param i32 i32)))
-    (table 0 anyfunc)
-    (func $type-second-void-vs-num
-      (return_call_indirect (type 0) (i32.const 1) (nop) (i32.const 0))
-    )
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (type (func (param i32 f64)))
-    (table 0 anyfunc)
-    (func $type-first-num-vs-num
-      (return_call_indirect (type 0) (f64.const 1) (i32.const 1) (i32.const 0))
-    )
-  )
-  "type mismatch"
-)
-(assert_invalid
-  (module
-    (type (func (param f64 i32)))
-    (table 0 anyfunc)
-    (func $type-second-num-vs-num
-      (return_call_indirect (type 0) (i32.const 1) (f64.const 1) (i32.const 0))
-    )
-  )
-  "type mismatch"
-)
-
-
-;; Unbound type
-
-(assert_invalid
-  (module
-    (table 0 anyfunc)
-    (func $unbound-type (return_call_indirect (type 1) (i32.const 0)))
-  )
-  "unknown type"
-)
-(assert_invalid
-  (module
-    (table 0 anyfunc)
-    (func $large-type (return_call_indirect (type 1012321300) (i32.const 0)))
-  )
-  "unknown type"
-)
-
-
-;; Unbound function in table
-
-(assert_invalid
-  (module (table anyfunc (elem 0 0)))
-  "unknown function"
-)

+ 6 - 0
tests/wamr-test-suites/test_wamr.sh

@@ -440,6 +440,12 @@ function spec_test()
         git reset --hard 0caaadc65b5e1910512d8ae228502edcf9d60390
         git apply ../../spec-test-script/gc_ignore_cases.patch
 
+        if [[ ${ENABLE_QEMU} == 1 ]]; then
+            # Decrease the recursive count for tail call cases as nuttx qemu's
+            # native stack size is much smaller
+            git apply ../../spec-test-script/gc_nuttx_tail_call.patch
+        fi
+
         echo "compile the reference intepreter"
         pushd interpreter
         make

+ 5 - 3
wamr-compiler/main.c

@@ -441,7 +441,6 @@ main(int argc, char *argv[])
         else if (!strcmp(argv[0], "--enable-multi-thread")) {
             option.enable_bulk_memory = true;
             option.enable_thread_mgr = true;
-            option.enable_ref_types = false;
         }
         else if (!strcmp(argv[0], "--enable-tail-call")) {
             option.enable_tail_call = true;
@@ -478,6 +477,7 @@ main(int argc, char *argv[])
             option.is_indirect_mode = true;
         }
         else if (!strcmp(argv[0], "--enable-gc")) {
+            option.enable_aux_stack_frame = true;
             option.enable_gc = true;
         }
         else if (!strcmp(argv[0], "--disable-llvm-intrinsics")) {
@@ -634,8 +634,10 @@ main(int argc, char *argv[])
             goto fail1;
     }
 
-    if (get_package_type(wasm_file, wasm_file_size) != Wasm_Module_Bytecode) {
-        printf("Invalid file type: expected wasm file but got other\n");
+    if (wasm_file_size >= 4 /* length of MAGIC NUMBER */
+        && get_package_type(wasm_file, wasm_file_size)
+               != Wasm_Module_Bytecode) {
+        printf("Invalid wasm file: magic header not detected\n");
         goto fail2;
     }