Przeglądaj źródła

Implement post-MVP features and native stack overflow check (#243)

Implement native thread stack overflow check
Implement post-MVP: Non-trapping float-to-int conversions
Implement post-MVP: Sign-extension operators
Enhance WASM loader checks
wenyongh 5 lat temu
rodzic
commit
d381b0fdec
36 zmienionych plików z 1248 dodań i 234 usunięć
  1. 4 0
      build-scripts/config_common.cmake
  2. 4 0
      core/config.h
  3. 8 5
      core/iwasm/aot/aot_loader.c
  4. 25 4
      core/iwasm/aot/aot_runtime.c
  5. 1 0
      core/iwasm/aot/aot_runtime.h
  6. 9 0
      core/iwasm/common/wasm_exec_env.c
  7. 16 10
      core/iwasm/common/wasm_exec_env.h
  8. 5 1
      core/iwasm/common/wasm_native.c
  9. 36 31
      core/iwasm/common/wasm_runtime_common.c
  10. 65 4
      core/iwasm/compilation/aot_compiler.c
  11. 265 16
      core/iwasm/compilation/aot_emit_conversion.c
  12. 12 4
      core/iwasm/compilation/aot_emit_conversion.h
  13. 2 1
      core/iwasm/compilation/aot_emit_exception.c
  14. 36 0
      core/iwasm/compilation/aot_emit_function.c
  15. 1 1
      core/iwasm/compilation/aot_emit_numberic.c
  16. 35 0
      core/iwasm/compilation/aot_llvm.c
  17. 2 0
      core/iwasm/compilation/aot_llvm.h
  18. 214 29
      core/iwasm/interpreter/wasm_interp_classic.c
  19. 208 30
      core/iwasm/interpreter/wasm_interp_fast.c
  20. 105 22
      core/iwasm/interpreter/wasm_loader.c
  21. 51 23
      core/iwasm/interpreter/wasm_opcode.h
  22. 26 39
      core/iwasm/interpreter/wasm_runtime.c
  23. 0 1
      core/iwasm/interpreter/wasm_runtime.h
  24. 46 4
      core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c
  25. 17 4
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h
  26. 6 0
      core/shared/platform/alios/alios_thread.c
  27. 1 1
      core/shared/platform/android/platform_internal.h
  28. 20 0
      core/shared/platform/common/posix/posix_thread.c
  29. 1 1
      core/shared/platform/darwin/platform_internal.h
  30. 7 0
      core/shared/platform/include/platform_api_vmcore.h
  31. 6 0
      core/shared/platform/linux-sgx/sgx_thread.c
  32. 1 1
      core/shared/platform/linux/platform_internal.h
  33. 1 1
      core/shared/platform/vxworks/platform_internal.h
  34. 10 0
      core/shared/platform/zephyr/zephyr_thread.c
  35. 1 0
      samples/littlevgl/vgl-native-ui-app/CMakeLists.txt
  36. 1 1
      wamr-compiler/CMakeLists.txt

+ 4 - 0
build-scripts/config_common.cmake

@@ -124,3 +124,7 @@ else ()
   message ("     Fast interpreter disabled")
 endif ()
 
+if (WAMR_BUILD_SPEC_TEST EQUAL 1)
+  add_definitions (-DWASM_ENABLE_SPEC_TEST=1)
+  message ("     spec test compatible mode is on")
+endif()

+ 4 - 0
core/config.h

@@ -179,6 +179,10 @@ enum {
 #define APP_THREAD_STACK_SIZE_MAX (256 * 1024)
 #endif
 
+/* Reserved bytes to the native thread stack boundary, throw native
+   stack overflow exception if the guard boudary is reached */
+#define RESERVED_BYTES_TO_NATIVE_STACK_BOUNDARY (512)
+
 /* Default wasm block address cache size and conflict list size */
 #define BLOCK_ADDR_CACHE_SIZE 64
 #define BLOCK_ADDR_CONFLICT_SIZE 2

+ 8 - 5
core/iwasm/aot/aot_loader.c

@@ -942,8 +942,7 @@ load_init_data_section(const uint8 *buf, const uint8 *buf_end,
 
     /* check start function index */
     if (module->start_func_index != (uint32)-1
-        && (module->start_func_index < module->import_func_count
-            || module->start_func_index >= module->import_func_count
+        && (module->start_func_index >= module->import_func_count
                                            + module->func_count)) {
         set_error_buf(error_buf, error_buf_size,
                       "AOT module load failed: "
@@ -1044,9 +1043,13 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
 
     /* Set start function when function pointers are resolved */
     if (module->start_func_index != (uint32)-1) {
-        module->start_function =
-            module->func_ptrs[module->start_func_index
-                              - module->import_func_count];
+        if (module->start_func_index >= module->import_func_count)
+            module->start_function =
+                module->func_ptrs[module->start_func_index
+                            - module->import_func_count];
+        else
+            /* TODO: fix start function can be import function issue */
+            module->start_function = NULL;
     }
     else {
         module->start_function = NULL;

+ 25 - 4
core/iwasm/aot/aot_runtime.c

@@ -39,7 +39,11 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
         init_expr = &global->init_expr;
         switch (init_expr->init_expr_type) {
             case INIT_EXPR_TYPE_GET_GLOBAL:
-                bh_assert(init_expr->u.global_index < module->import_global_count);
+                if (init_expr->u.global_index >= module->import_global_count + i) {
+                    set_error_buf(error_buf, error_buf_size,
+                                  "Instantiate global failed: unknown global.");
+                    return false;
+                }
                 memcpy(p,
                        &module->import_globals[init_expr->u.global_index].global_data_linked,
                        global->size);
@@ -501,6 +505,9 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
         return false;
     }
 
+    /* set thread handle and stack boundary */
+    wasm_exec_env_set_thread_info(exec_env);
+
     ret = aot_call_function(exec_env, func, argc, argv);
     wasm_exec_env_destroy(exec_env);
     return ret;
@@ -556,6 +563,9 @@ aot_set_exception_with_id(AOTModuleInstance *module_inst,
         case EXCE_CALL_UNLINKED_IMPORT_FUNC:
             aot_set_exception(module_inst, "fail to call unlinked import function");
             break;
+        case EXCE_NATIVE_STACK_OVERFLOW:
+            aot_set_exception(module_inst, "native stack overflow");
+            break;
         default:
             break;
     }
@@ -662,10 +672,12 @@ void *
 aot_addr_app_to_native(AOTModuleInstance *module_inst, int32 app_offset)
 {
     int32 memory_data_size = (int32)module_inst->memory_data_size;
+    uint8 *addr = (uint8 *)module_inst->memory_data.ptr + app_offset;
 
-    if (module_inst->heap_base_offset < app_offset
-        && app_offset < memory_data_size)
-        return (uint8*)module_inst->memory_data.ptr + app_offset;
+    if ((uint8*)module_inst->heap_data.ptr < addr
+        && addr < (uint8*)module_inst->memory_data.ptr
+                  + memory_data_size)
+        return addr;
     return NULL;
 }
 
@@ -929,6 +941,15 @@ aot_call_indirect(WASMExecEnv *exec_env,
         }
     }
 
+    /* this function is called from native code, so exec_env->handle and
+       exec_env->native_stack_boundary must have been set, we don't set
+       it again */
+
+    if ((uint8*)&module_inst < exec_env->native_stack_boundary) {
+        aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
+        return false;
+    }
+
     return wasm_runtime_invoke_native(exec_env, func_ptr,
                                       func_type, signature, attachment,
                                       argv, argc, argv);

+ 1 - 0
core/iwasm/aot/aot_runtime.h

@@ -30,6 +30,7 @@ typedef enum AOTExceptionID {
     EXCE_UNDEFINED_ELEMENT,
     EXCE_UNINITIALIZED_ELEMENT,
     EXCE_CALL_UNLINKED_IMPORT_FUNC,
+    EXCE_NATIVE_STACK_OVERFLOW,
     EXCE_NUM,
 } AOTExceptionID;
 

+ 9 - 0
core/iwasm/common/wasm_exec_env.c

@@ -50,3 +50,12 @@ wasm_exec_env_get_module_inst(WASMExecEnv *exec_env)
     return exec_env->module_inst;
 }
 
+void
+wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
+{
+    exec_env->handle = os_self_thread();
+    exec_env->native_stack_boundary = os_thread_get_stack_boundary()
+                                      + RESERVED_BYTES_TO_NATIVE_STACK_BOUNDARY;
+
+}
+

+ 16 - 10
core/iwasm/common/wasm_exec_env.h

@@ -20,12 +20,15 @@ struct WASMInterpFrame;
 
 /* Execution environment */
 typedef struct WASMExecEnv {
-    /* Next thread's exec env of a WASM module instance.  */
+    /* Next thread's exec env of a WASM module instance. */
     struct WASMExecEnv *next;
 
-    /* Previous thread's exec env of a WASM module instance.  */
+    /* Previous thread's exec env of a WASM module instance. */
     struct WASMExecEnv *prev;
 
+    /* Note: field module_inst, argv_buf and native_stack_boundary
+             are used by AOTed code, don't change the places of them */
+
     /* The WASM module instance of current thread */
     struct WASMModuleInstanceCommon *module_inst;
 
@@ -33,6 +36,11 @@ typedef struct WASMExecEnv {
     uint32 *argv_buf;
 #endif
 
+    /* The boundary of native stack. When runtime detects that native
+       frame may overrun this boundary, it throws stack overflow
+       exception. */
+    uint8 *native_stack_boundary;
+
     /* attachment for native function */
     void *attachment;
 
@@ -48,11 +56,6 @@ typedef struct WASMExecEnv {
     BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
 #endif
 
-    /* The boundary of native stack. When interpreter detects that native
-       frame may overrun this boundary, it throws a stack overflow
-       exception. */
-    void *native_stack_boundary;
-
     /* The WASM stack size */
     uint32 wasm_stack_size;
 
@@ -61,13 +64,13 @@ typedef struct WASMExecEnv {
         uint64 __make_it_8_byte_aligned_;
 
         struct {
-            /* The top boundary of the stack.  */
+            /* The top boundary of the stack. */
             uint8 *top_boundary;
 
-            /* Top cell index which is free.  */
+            /* Top cell index which is free. */
             uint8 *top;
 
-            /* The Java stack.  */
+            /* The WASM stack. */
             uint8 bottom[1];
         } s;
     } wasm_stack;
@@ -159,6 +162,9 @@ wasm_exec_env_get_cur_frame(WASMExecEnv *exec_env)
 struct WASMModuleInstanceCommon *
 wasm_exec_env_get_module_inst(WASMExecEnv *exec_env);
 
+void
+wasm_exec_env_set_thread_info(WASMExecEnv *exec_env);
+
 #ifdef __cplusplus
 }
 #endif

+ 5 - 1
core/iwasm/common/wasm_native.c

@@ -14,8 +14,10 @@ static NativeSymbolsList g_native_symbols_list_end = NULL;
 uint32
 get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
 
+#if WASM_ENABLE_SPEC_TEST != 0
 uint32
 get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis);
+#endif
 
 uint32
 get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis);
@@ -242,11 +244,13 @@ wasm_native_init()
                                        native_symbols, n_native_symbols))
         return false;
 
+#if WASM_ENABLE_SPEC_TEST
     n_native_symbols = get_spectest_export_apis(&native_symbols);
     if (!wasm_native_register_natives("spectest",
                                        native_symbols, n_native_symbols))
         return false;
-#endif
+#endif /* WASM_ENABLE_SPEC_TEST */
+#endif /* WASM_ENABLE_LIBC_BUILTIN */
 
 #if WASM_ENABLE_LIBC_WASI != 0
     n_native_symbols = get_libc_wasi_export_apis(&native_symbols);

+ 36 - 31
core/iwasm/common/wasm_runtime_common.c

@@ -292,7 +292,8 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
         return false;
     }
 
-    exec_env->handle = os_self_thread();
+    /* set thread handle and stack boundary */
+    wasm_exec_env_set_thread_info(exec_env);
 
 #if WASM_ENABLE_INTERP != 0
     if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
@@ -1410,37 +1411,39 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
     }
 
     /* print return value */
-    switch (type->types[type->param_count]) {
-        case VALUE_TYPE_I32:
-            os_printf("0x%x:i32", argv1[0]);
-            break;
-        case VALUE_TYPE_I64:
-        {
-            union { uint64 val; uint32 parts[2]; } u;
-            u.parts[0] = argv1[0];
-            u.parts[1] = argv1[1];
+    if (type->result_count > 0) {
+        switch (type->types[type->param_count]) {
+            case VALUE_TYPE_I32:
+                os_printf("0x%x:i32", argv1[0]);
+                break;
+            case VALUE_TYPE_I64:
+            {
+                union { uint64 val; uint32 parts[2]; } u;
+                u.parts[0] = argv1[0];
+                u.parts[1] = argv1[1];
 #ifdef PRIx64
-            os_printf("0x%"PRIx64":i64", u.val);
+                os_printf("0x%"PRIx64":i64", u.val);
 #else
-            char buf[16];
-            if (sizeof(long) == 4)
-                snprintf(buf, sizeof(buf), "%s", "0x%llx:i64");
-            else
-                snprintf(buf, sizeof(buf), "%s", "0x%lx:i64");
-            os_printf(buf, u.val);
-#endif
-            break;
-        }
-        case VALUE_TYPE_F32:
-            os_printf("%.7g:f32", *(float32*)argv1);
-        break;
-        case VALUE_TYPE_F64:
-        {
-            union { float64 val; uint32 parts[2]; } u;
-            u.parts[0] = argv1[0];
-            u.parts[1] = argv1[1];
-            os_printf("%.7g:f64", u.val);
-            break;
+                char buf[16];
+                if (sizeof(long) == 4)
+                    snprintf(buf, sizeof(buf), "%s", "0x%llx:i64");
+                else
+                    snprintf(buf, sizeof(buf), "%s", "0x%lx:i64");
+                os_printf(buf, u.val);
+#endif
+                break;
+            }
+            case VALUE_TYPE_F32:
+                os_printf("%.7g:f32", *(float32*)argv1);
+                break;
+            case VALUE_TYPE_F64:
+            {
+                union { float64 val; uint32 parts[2]; } u;
+                u.parts[0] = argv1[0];
+                u.parts[1] = argv1[1];
+                os_printf("%.7g:f64", u.val);
+                break;
+            }
         }
     }
     os_printf("\n");
@@ -2148,7 +2151,9 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env,
         return false;
     }
 
-    exec_env->handle = os_self_thread();
+    /* this function is called from native code, so exec_env->handle and
+       exec_env->native_stack_boundary must have been set, we don't set
+       it again */
 
 #if WASM_ENABLE_INTERP != 0
     if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)

+ 65 - 4
core/iwasm/compilation/aot_compiler.c

@@ -595,14 +595,14 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
       case WASM_OP_I32_TRUNC_S_F32:
       case WASM_OP_I32_TRUNC_U_F32:
         sign = (opcode == WASM_OP_I32_TRUNC_S_F32) ? true : false;
-        if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign))
+        if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign, false))
           return false;
         break;
 
       case WASM_OP_I32_TRUNC_S_F64:
       case WASM_OP_I32_TRUNC_U_F64:
         sign = (opcode == WASM_OP_I32_TRUNC_S_F64) ? true : false;
-        if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign))
+        if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign, false))
           return false;
         break;
 
@@ -616,14 +616,14 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
       case WASM_OP_I64_TRUNC_S_F32:
       case WASM_OP_I64_TRUNC_U_F32:
         sign = (opcode == WASM_OP_I64_TRUNC_S_F32) ? true : false;
-        if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign))
+        if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign, false))
           return false;
         break;
 
       case WASM_OP_I64_TRUNC_S_F64:
       case WASM_OP_I64_TRUNC_U_F64:
         sign = (opcode == WASM_OP_I64_TRUNC_S_F64) ? true : false;
-        if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign))
+        if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign, false))
           return false;
         break;
 
@@ -685,6 +685,67 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
             return false;
         break;
 
+      case WASM_OP_I32_EXTEND8_S:
+        if (!aot_compile_op_i32_extend_i32(comp_ctx, func_ctx, 8))
+          return false;
+        break;
+
+      case WASM_OP_I32_EXTEND16_S:
+        if (!aot_compile_op_i32_extend_i32(comp_ctx, func_ctx, 16))
+          return false;
+        break;
+
+      case WASM_OP_I64_EXTEND8_S:
+        if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 8))
+          return false;
+        break;
+
+      case WASM_OP_I64_EXTEND16_S:
+        if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 16))
+          return false;
+        break;
+
+      case WASM_OP_I64_EXTEND32_S:
+        if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 32))
+          return false;
+        break;
+
+      case WASM_OP_MISC_PREFIX:
+      {
+        if (frame_ip < frame_ip_end) {
+          opcode = *frame_ip++;
+        }
+
+        switch (opcode) {
+          case WASM_OP_I32_TRUNC_SAT_S_F32:
+          case WASM_OP_I32_TRUNC_SAT_U_F32:
+            sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F32) ? true : false;
+            if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign, true))
+              return false;
+            break;
+          case WASM_OP_I32_TRUNC_SAT_S_F64:
+          case WASM_OP_I32_TRUNC_SAT_U_F64:
+            sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F64) ? true : false;
+            if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign, true))
+              return false;
+            break;
+          case WASM_OP_I64_TRUNC_SAT_S_F32:
+          case WASM_OP_I64_TRUNC_SAT_U_F32:
+            sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F32) ? true : false;
+            if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign, true))
+              return false;
+            break;
+          case WASM_OP_I64_TRUNC_SAT_S_F64:
+          case WASM_OP_I64_TRUNC_SAT_U_F64:
+            sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F64) ? true : false;
+            if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign, true))
+              return false;
+            break;
+          default:
+            break;
+        }
+      }
+
       default:
         break;
     }

+ 265 - 16
core/iwasm/compilation/aot_emit_conversion.c

@@ -89,6 +89,156 @@ fail:
     return false;
 }
 
+#define ADD_BASIC_BLOCK(block, name) do {                                  \
+    if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context,         \
+                                                func_ctx->func,            \
+                                                name))) {                  \
+        aot_set_last_error("llvm add basic block failed.");                \
+        goto fail;                                                         \
+    }                                                                      \
+                                                                           \
+    LLVMMoveBasicBlockAfter(block, LLVMGetInsertBlock(comp_ctx->builder)); \
+} while (0)
+
+static bool
+trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                       LLVMValueRef operand, LLVMTypeRef dest_type,
+                       LLVMValueRef min_value, LLVMValueRef max_value,
+                       char *name, bool sign)
+{
+    LLVMBasicBlockRef check_nan_succ, check_less_succ, check_greater_succ;
+    LLVMBasicBlockRef is_nan_block, is_less_block, is_greater_block, res_block;
+    LLVMValueRef is_less, is_greater, res, phi;
+    LLVMValueRef zero = (dest_type == I32_TYPE) ? I32_ZERO : I64_ZERO;
+    LLVMValueRef vmin, vmax;
+
+    if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO,
+                              operand, operand, "fcmp_is_nan"))) {
+        aot_set_last_error("llvm build fcmp failed.");
+        goto fail;
+    }
+
+    ADD_BASIC_BLOCK(check_nan_succ, "check_nan_succ");
+    ADD_BASIC_BLOCK(is_nan_block, "is_nan_block");
+    ADD_BASIC_BLOCK(check_less_succ, "check_less_succ");
+    ADD_BASIC_BLOCK(is_less_block, "is_less_block");
+    ADD_BASIC_BLOCK(check_greater_succ, "check_greater_succ");
+    ADD_BASIC_BLOCK(is_greater_block, "is_greater_block");
+    ADD_BASIC_BLOCK(res_block, "res_block");
+
+    if (!LLVMBuildCondBr(comp_ctx->builder, res,
+                         is_nan_block, check_nan_succ)) {
+        aot_set_last_error("llvm build cond br failed.");
+        goto fail;
+    }
+
+    /* Start to translate is_nan block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, is_nan_block);
+    if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+        aot_set_last_error("llvm build br failed.");
+        goto fail;
+    }
+
+    /* Start to translate check_nan_succ block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, check_nan_succ);
+    if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand,
+                                  min_value, "fcmp_min_value"))) {
+        aot_set_last_error("llvm build fcmp failed.");
+        goto fail;
+    }
+    if (!LLVMBuildCondBr(comp_ctx->builder, is_less,
+                         is_less_block, check_less_succ)) {
+        aot_set_last_error("llvm build cond br failed.");
+        goto fail;
+    }
+
+    /* Start to translate is_less block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, is_less_block);
+    if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+        aot_set_last_error("llvm build br failed.");
+        goto fail;
+    }
+
+    /* Start to translate check_less_succ block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, check_less_succ);
+    if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand,
+                                     max_value, "fcmp_max_value"))) {
+        aot_set_last_error("llvm build fcmp failed.");
+        goto fail;
+    }
+    if (!LLVMBuildCondBr(comp_ctx->builder, is_greater,
+                         is_greater_block, check_greater_succ)) {
+        aot_set_last_error("llvm build cond br failed.");
+        goto fail;
+    }
+
+    /* Start to translate is_greater block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, is_greater_block);
+    if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+        aot_set_last_error("llvm build br failed.");
+        goto fail;
+    }
+
+    /* Start to translate check_greater_succ block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, check_greater_succ);
+    if (sign)
+        res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name);
+    else
+        res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name);
+    if (!res) {
+        aot_set_last_error("llvm build conversion failed.");
+        return false;
+    }
+    if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+        aot_set_last_error("llvm build br failed.");
+        goto fail;
+    }
+
+    /* Start to translate res_block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, res_block);
+    /* Create result phi */
+    if (!(phi = LLVMBuildPhi(comp_ctx->builder,
+                             dest_type,
+                             "trunc_sat_result_phi"))) {
+        aot_set_last_error("llvm build phi failed.");
+        return false;
+    }
+
+    /* Add phi incoming values */
+    if (dest_type == I32_TYPE) {
+        if (sign) {
+            vmin = I32_CONST(INT32_MIN);
+            vmax = I32_CONST(INT32_MAX);
+        }
+        else {
+            vmin = I32_CONST(0);
+            vmax = I32_CONST(UINT32_MAX);
+        }
+    }
+    else if (dest_type == I64_TYPE) {
+        if (sign) {
+            vmin = I64_CONST(INT64_MIN);
+            vmax = I64_CONST(INT64_MAX);
+        }
+        else {
+            vmin = I64_CONST(0);
+            vmax = I64_CONST(UINT64_MAX);
+        }
+    }
+    LLVMAddIncoming(phi, &zero, &is_nan_block, 1);
+    LLVMAddIncoming(phi, &vmin, &is_less_block, 1);
+    LLVMAddIncoming(phi, &vmax, &is_greater_block, 1);
+    LLVMAddIncoming(phi, &res, &check_greater_succ, 1);
+
+    if (dest_type == I32_TYPE)
+        PUSH_I32(phi);
+    else if (dest_type == I64_TYPE)
+        PUSH_I64(phi);
+    return true;
+fail:
+    return false;
+}
+
 bool
 aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 {
@@ -109,7 +259,7 @@ fail:
 
 bool
 aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign)
+                             bool sign, bool saturating)
 {
     LLVMValueRef value;
     LLVMValueRef min_value, max_value;
@@ -125,16 +275,22 @@ aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         max_value = F32_CONST(4294967296.0f);
     }
 
-    return trunc_float_to_int(comp_ctx, func_ctx, value,
-                              I32_TYPE, min_value, max_value,
-                              sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
+    if (!saturating)
+        return trunc_float_to_int(comp_ctx, func_ctx, value,
+                                  I32_TYPE, min_value, max_value,
+                                  sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
+    else
+        return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
+                                      I32_TYPE, min_value, max_value,
+                                      sign ? "i32_trunc_sat_f32_s" :
+                                      "i32_trunc_sat_f32_u", sign);
 fail:
     return false;
 }
 
 bool
 aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign)
+                             bool sign, bool saturating)
 {
     LLVMValueRef value;
     LLVMValueRef min_value, max_value;
@@ -150,9 +306,15 @@ aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         max_value = F64_CONST(4294967296.0);
     }
 
-    return trunc_float_to_int(comp_ctx, func_ctx, value,
-                              I32_TYPE, min_value, max_value,
-                              sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
+    if (!saturating)
+        return trunc_float_to_int(comp_ctx, func_ctx, value,
+                                  I32_TYPE, min_value, max_value,
+                                  sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
+    else
+        return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
+                                      I32_TYPE, min_value, max_value,
+                                      sign ? "i32_trunc_sat_f64_s" :
+                                      "i32_trunc_sat_f64_u", sign);
 fail:
     return false;
 }
@@ -180,9 +342,83 @@ fail:
     return false;
 }
 
+bool
+aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                              int8 bitwidth)
+{
+    LLVMValueRef value, res, cast_value = NULL;
+
+    POP_I64(value);
+
+    if (bitwidth == 8) {
+        cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
+                                       INT8_TYPE, true, "i8_intcast_i64");
+    }
+    else if (bitwidth == 16) {
+        cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
+                                       INT16_TYPE, true, "i16_intcast_i64");
+    }
+    else if (bitwidth == 32) {
+        cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
+                                       I32_TYPE, true, "i32_intcast_i64");
+    }
+
+    if (!cast_value) {
+        aot_set_last_error("llvm build conversion failed.");
+        return false;
+    }
+
+    res = LLVMBuildSExt(comp_ctx->builder, cast_value, I64_TYPE, "i64_extend_i64_s");
+
+    if (!res) {
+        aot_set_last_error("llvm build conversion failed.");
+        return false;
+    }
+
+    PUSH_I64(res);
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                              int8 bitwidth)
+{
+    LLVMValueRef value, res, cast_value = NULL;
+
+    POP_I32(value);
+
+    if (bitwidth == 8) {
+        cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
+                                       INT8_TYPE, true, "i8_intcast_i32");
+    }
+    else if (bitwidth == 16) {
+        cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
+                                       INT16_TYPE, true, "i16_intcast_i32");
+    }
+
+    if (!cast_value) {
+        aot_set_last_error("llvm build conversion failed.");
+        return false;
+    }
+
+    res = LLVMBuildSExt(comp_ctx->builder, cast_value, I32_TYPE, "i32_extend_i32_s");
+
+    if (!res) {
+        aot_set_last_error("llvm build conversion failed.");
+        return false;
+    }
+
+    PUSH_I32(res);
+    return true;
+fail:
+    return false;
+}
+
 bool
 aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign)
+                             bool sign, bool saturating)
 {
     LLVMValueRef value;
     LLVMValueRef min_value, max_value;
@@ -198,16 +434,22 @@ aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         max_value = F32_CONST(18446744073709551616.0f);
     }
 
-    return trunc_float_to_int(comp_ctx, func_ctx, value,
-                              I64_TYPE, min_value, max_value,
-                              sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
+    if (!saturating)
+        return trunc_float_to_int(comp_ctx, func_ctx, value,
+                                  I64_TYPE, min_value, max_value,
+                                  sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
+    else
+        return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
+                                      I64_TYPE, min_value, max_value,
+                                      sign ? "i64_trunc_sat_f32_s" :
+                                      "i64_trunc_sat_f32_u", sign);
 fail:
     return false;
 }
 
 bool
 aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign)
+                             bool sign, bool saturating)
 {
     LLVMValueRef value;
     LLVMValueRef min_value, max_value;
@@ -223,9 +465,16 @@ aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         max_value = F64_CONST(18446744073709551616.0);
     }
 
-    return trunc_float_to_int(comp_ctx, func_ctx, value,
-                              I64_TYPE, min_value, max_value,
-                              sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
+    if (!saturating)
+        return trunc_float_to_int(comp_ctx, func_ctx, value,
+                                  I64_TYPE, min_value, max_value,
+                                  sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
+    else
+        return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
+                                      I64_TYPE, min_value, max_value,
+                                      sign ? "i64_trunc_sat_f64_s" :
+                                      "i64_trunc_sat_f64_u", sign);
+
 fail:
     return false;
 }

+ 12 - 4
core/iwasm/compilation/aot_emit_conversion.h

@@ -17,23 +17,31 @@ aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
 
 bool
 aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign);
+                             bool sign, bool saturating);
 
 bool
 aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign);
+                             bool sign, bool saturating);
 
 bool
 aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                               bool sign);
 
+bool
+aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                              int8 bitwidth);
+
+bool
+aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                              int8 bitwidth);
+
 bool
 aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign);
+                             bool sign, bool saturating);
 
 bool
 aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign);
+                             bool sign, bool saturating);
 
 bool
 aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,

+ 2 - 1
core/iwasm/compilation/aot_emit_exception.c

@@ -17,7 +17,8 @@ static char *exce_block_names[] = {
     "exce_invalid_func_idx",        /* EXCE_INVALID_FUNCTION_INDEX */
     "exce_undefined_element",       /* EXCE_UNDEFINED_ELEMENT */
     "exce_uninit_element",          /* EXCE_UNINITIALIZED_ELEMENT */
-    "exce_call_unlinked"            /* EXCE_CALL_UNLINKED_IMPORT_FUNC */
+    "exce_call_unlinked",           /* EXCE_CALL_UNLINKED_IMPORT_FUNC */
+    "exce_native_stack_overflow"    /* EXCE_NATIVE_STACK_OVERFLOW */
 };
 
 bool

+ 36 - 0
core/iwasm/compilation/aot_emit_function.c

@@ -255,6 +255,39 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     return true;
 }
 
+static bool
+check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+    LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+    LLVMBasicBlockRef check_stack;
+    LLVMValueRef cmp;
+
+    if (!(check_stack = LLVMAppendBasicBlockInContext(comp_ctx->context,
+                                                      func_ctx->func,
+                                                      "check_stack"))) {
+        aot_set_last_error("llvm add basic block failed.");
+        return false;
+    }
+
+    LLVMMoveBasicBlockAfter(check_stack, block_curr);
+
+    if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT,
+                              func_ctx->last_alloca, func_ctx->native_stack_bound,
+                              "cmp"))) {
+        aot_set_last_error("llvm build icmp failed.");
+        return false;
+    }
+
+    if (!aot_emit_exception(comp_ctx, func_ctx,
+                            EXCE_NATIVE_STACK_OVERFLOW,
+                            true, cmp, check_stack)) {
+        return false;
+    }
+
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, check_stack);
+    return true;
+}
+
 bool
 aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                     uint32 func_idx, uint8 **p_frame_ip)
@@ -347,6 +380,9 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     else {
         func = func_ctxes[func_idx - import_func_count]->func;
 
+        if (!check_stack_boundary(comp_ctx, func_ctx))
+            goto fail;
+
         /* Call the function */
         if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
                                         param_values, (uint32)param_count + 1,

+ 1 - 1
core/iwasm/compilation/aot_emit_numberic.c

@@ -27,7 +27,7 @@
 #define ADD_BASIC_BLOCK(block, name) do {                                  \
     if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context,         \
                                                 func_ctx->func,            \
-                                                name))) { \
+                                                name))) {                  \
         aot_set_last_error("llvm add basic block failed.");                \
         goto fail;                                                         \
     }                                                                      \

+ 35 - 0
core/iwasm/compilation/aot_llvm.c

@@ -5,6 +5,7 @@
 
 #include "aot_llvm.h"
 #include "aot_compiler.h"
+#include "aot_emit_exception.h"
 #include "../aot/aot_runtime.h"
 
 
@@ -451,6 +452,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
     LLVMTypeRef int8_ptr_type, int32_ptr_type;
     LLVMValueRef aot_inst_offset = I32_TWO, aot_inst_addr;
     LLVMValueRef argv_buf_offset = I32_THREE, argv_buf_addr;
+    LLVMValueRef stack_bound_offset = I32_FOUR, stack_bound_addr;
     char local_name[32];
     uint64 size;
     uint32 i, j = 0;
@@ -526,6 +528,21 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
         goto fail;
     }
 
+    /* Get native stack boundary address */
+    if (!(stack_bound_addr =
+            LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
+                                 &stack_bound_offset, 1, "stack_bound_addr"))) {
+        aot_set_last_error("llvm build in bounds gep failed");
+        goto fail;
+    }
+
+    if (!(func_ctx->native_stack_bound =
+            LLVMBuildLoad(comp_ctx->builder,
+                          stack_bound_addr, "native_stack_bound"))) {
+        aot_set_last_error("llvm build load failed");
+        goto fail;
+    }
+
     for (i = 0; i < aot_func_type->param_count; i++, j++) {
         snprintf(local_name, sizeof(local_name), "l%d", i);
         func_ctx->locals[i] =
@@ -580,6 +597,24 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
         }
     }
 
+    if (aot_func_type->param_count + func->local_count > 0) {
+        func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count
+                                                 + func->local_count - 1];
+        if (!(func_ctx->last_alloca =
+                    LLVMBuildBitCast(comp_ctx->builder, func_ctx->last_alloca,
+                                     INT8_PTR_TYPE, "stack_ptr"))) {
+            aot_set_last_error("llvm build bit cast failed.");
+            goto fail;
+        }
+    }
+    else {
+        if (!(func_ctx->last_alloca = LLVMBuildAlloca(comp_ctx->builder, INT8_TYPE,
+                                          "stack_ptr"))) {
+            aot_set_last_error("llvm build alloca failed.");
+            goto fail;
+        }
+    }
+
     if (!(int8_ptr_type = LLVMPointerType(INT8_PTR_TYPE, 0))) {
         aot_set_last_error("llvm add pointer type failed.");
         goto fail;

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

@@ -102,6 +102,8 @@ typedef struct AOTFuncContext {
   LLVMValueRef aot_inst;
   LLVMValueRef table_base;
   LLVMValueRef argv_buf;
+  LLVMValueRef native_stack_bound;
+  LLVMValueRef last_alloca;
 
   LLVMValueRef heap_base_offset;
   LLVMValueRef mem_base_addr;

+ 214 - 29
core/iwasm/interpreter/wasm_interp_classic.c

@@ -606,18 +606,128 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
     PUSH_##src_op_type(method(val));                                \
   } while (0)
 
-#define DEF_OP_TRUNC(dst_type, dst_op_type, src_type, src_op_type,  \
-                     min_cond, max_cond) do {                       \
-    src_type value = POP_##src_op_type();                           \
-    if (isnan(value)) {                                             \
-      wasm_set_exception(module, "invalid conversion to integer");  \
-      goto got_exception;                                           \
-    }                                                               \
-    else if (value min_cond || value max_cond) {                    \
-      wasm_set_exception(module, "integer overflow");               \
-      goto got_exception;                                           \
-    }                                                               \
-    PUSH_##dst_op_type(((dst_type)value));                          \
+#define TRUNC_FUNCTION(func_name, src_type, dst_type, signed_type)  \
+static dst_type                                                     \
+func_name(src_type src_value, src_type src_min, src_type src_max,   \
+          dst_type dst_min, dst_type dst_max, bool is_sign)         \
+{                                                                   \
+  dst_type dst_value = 0;                                           \
+  if (!isnan(src_value)) {                                          \
+      if (src_value <= src_min)                                     \
+          dst_value = dst_min;                                      \
+      else if (src_value >= src_max)                                \
+          dst_value = dst_max;                                      \
+      else {                                                        \
+          if (is_sign)                                              \
+              dst_value = (dst_type)(signed_type)src_value;         \
+          else                                                      \
+              dst_value = (dst_type)src_value;                      \
+      }                                                             \
+  }                                                                 \
+  return dst_value;                                                 \
+}
+
+TRUNC_FUNCTION(trunc_f32_to_i32, float32, uint32, int32)
+TRUNC_FUNCTION(trunc_f32_to_i64, float32, uint64, int64)
+TRUNC_FUNCTION(trunc_f64_to_i32, float64, uint32, int32)
+TRUNC_FUNCTION(trunc_f64_to_i64, float64, uint64, int64)
+
+static bool
+trunc_f32_to_int(WASMModuleInstance *module,
+                 uint32 *frame_sp,
+                 float32 src_min, float32 src_max,
+                 bool saturating, bool is_i32, bool is_sign)
+{
+    float32 src_value = POP_F32();
+    uint64 dst_value_i64;
+    uint32 dst_value_i32;
+
+    if (!saturating) {
+        if (isnan(src_value)) {
+            wasm_set_exception(module, "invalid conversion to integer");
+            return true;
+        }
+        else if (src_value <= src_min || src_value >= src_max) {
+            wasm_set_exception(module, "integer overflow");
+            return true;
+        }
+    }
+
+    if (is_i32) {
+        uint32 dst_min = is_sign ? INT32_MIN : 0;
+        uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
+        dst_value_i32 = trunc_f32_to_i32(src_value, src_min, src_max,
+                                         dst_min, dst_max, is_sign);
+        PUSH_I32(dst_value_i32);
+    }
+    else {
+        uint64 dst_min = is_sign ? INT64_MIN : 0;
+        uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
+        dst_value_i64 = trunc_f32_to_i64(src_value, src_min, src_max,
+                                         dst_min, dst_max, is_sign);
+        PUSH_I64(dst_value_i64);
+    }
+    return false;
+}
+
+static bool
+trunc_f64_to_int(WASMModuleInstance *module,
+                 uint32 *frame_sp,
+                 float64 src_min, float64 src_max,
+                 bool saturating, bool is_i32, bool is_sign)
+{
+    float64 src_value = POP_F64();
+    uint64 dst_value_i64;
+    uint32 dst_value_i32;
+
+    if (!saturating) {
+        if (isnan(src_value)) {
+            wasm_set_exception(module, "invalid conversion to integer");
+            return true;
+        }
+        else if (src_value <= src_min || src_value >= src_max) {
+            wasm_set_exception(module, "integer overflow");
+            return true;
+        }
+    }
+
+    if (is_i32) {
+        uint32 dst_min = is_sign ? INT32_MIN : 0;
+        uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
+        dst_value_i32 = trunc_f64_to_i32(src_value, src_min, src_max,
+                                         dst_min, dst_max, is_sign);
+        PUSH_I32(dst_value_i32);
+    }
+    else {
+        uint64 dst_min = is_sign ? INT64_MIN : 0;
+        uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
+        dst_value_i64 = trunc_f64_to_i64(src_value, src_min, src_max,
+                                         dst_min, dst_max, is_sign);
+        PUSH_I64(dst_value_i64);
+    }
+    return false;
+}
+
+#define DEF_OP_TRUNC_F32(min, max, is_i32, is_sign) do {            \
+    if (trunc_f32_to_int(module, frame_sp, min, max,                \
+                         false, is_i32, is_sign))                   \
+        goto got_exception;                                         \
+  } while (0)
+
+#define DEF_OP_TRUNC_F64(min, max, is_i32, is_sign) do {            \
+    if (trunc_f64_to_int(module, frame_sp, min, max,                \
+                         false, is_i32, is_sign))                   \
+        goto got_exception;                                         \
+  } while (0)
+
+#define DEF_OP_TRUNC_SAT_F32(min, max, is_i32, is_sign) do {        \
+    (void)trunc_f32_to_int(module, frame_sp, min, max,              \
+                           true, is_i32, is_sign);                  \
+  } while (0)
+
+#define DEF_OP_TRUNC_SAT_F64(min, max, is_i32, is_sign) do {        \
+    (void)trunc_f64_to_int(module, frame_sp, min, max,              \
+                           true, is_i32, is_sign);                  \
   } while (0)
 
 #define DEF_OP_CONVERT(dst_type, dst_op_type,                       \
@@ -2088,23 +2198,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
            all int32/uint32/int64/uint64 values, e.g.:
            UINT32_MAX is 4294967295, but (float32)4294967295 is 4294967296.0f,
            but not 4294967295.0f. */
-        DEF_OP_TRUNC(int32, I32, float32, F32, <= -2147483904.0f,
-                                               >= 2147483648.0f);
+        DEF_OP_TRUNC_F32(-2147483904.0f, 2147483648.0f, true, true);
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I32_TRUNC_U_F32):
-        DEF_OP_TRUNC(uint32, I32, float32, F32, <= -1.0f,
-                                                >= 4294967296.0f);
+        DEF_OP_TRUNC_F32(-1.0f, 4294967296.0f, true, false);
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I32_TRUNC_S_F64):
-        DEF_OP_TRUNC(int32, I32, float64, F64, <= -2147483649.0,
-                                               >= 2147483648.0);
+        DEF_OP_TRUNC_F64(-2147483649.0, 2147483648.0, true, true);
+        /* frame_sp can't be moved in trunc function, we need to manually adjust
+          it if src and dst op's cell num is different */
+        frame_sp--;
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I32_TRUNC_U_F64):
-        DEF_OP_TRUNC(uint32, I32, float64, F64, <= -1.0 ,
-                                                >= 4294967296.0);
+        DEF_OP_TRUNC_F64(-1.0, 4294967296.0, true, false);
+        frame_sp--;
         HANDLE_OP_END ();
 
       /* conversions of i64 */
@@ -2117,23 +2227,25 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I64_TRUNC_S_F32):
-        DEF_OP_TRUNC(int64, I64, float32, F32, <= -9223373136366403584.0f,
-                                               >= 9223372036854775808.0f);
+        DEF_OP_TRUNC_F32(-9223373136366403584.0f, 9223372036854775808.0f,
+                         false, true);
+        frame_sp++;
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I64_TRUNC_U_F32):
-        DEF_OP_TRUNC(uint64, I64, float32, F32, <= -1.0f,
-                                                >= 18446744073709551616.0f);
+        DEF_OP_TRUNC_F32(-1.0f, 18446744073709551616.0f,
+                         false, false);
+        frame_sp++;
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I64_TRUNC_S_F64):
-        DEF_OP_TRUNC(int64, I64, float64, F64, <= -9223372036854777856.0,
-                                               >= 9223372036854775808.0);
+        DEF_OP_TRUNC_F64(-9223372036854777856.0, 9223372036854775808.0,
+                         false, true);
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I64_TRUNC_U_F64):
-        DEF_OP_TRUNC(uint64, I64, float64, F64, <= -1.0,
-                                                >= 18446744073709551616.0);
+        DEF_OP_TRUNC_F64(-1.0, 18446744073709551616.0,
+                         false, false);
         HANDLE_OP_END ();
 
       /* conversions of f32 */
@@ -2185,6 +2297,75 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
       HANDLE_OP (WASM_OP_F64_REINTERPRET_I64):
         HANDLE_OP_END ();
 
+      HANDLE_OP (WASM_OP_I32_EXTEND8_S):
+        DEF_OP_CONVERT(int32, I32, int8, I32);
+        HANDLE_OP_END ();
+
+      HANDLE_OP (WASM_OP_I32_EXTEND16_S):
+        DEF_OP_CONVERT(int32, I32, int16, I32);
+        HANDLE_OP_END ();
+
+      HANDLE_OP (WASM_OP_I64_EXTEND8_S):
+        DEF_OP_CONVERT(int64, I64, int8, I64);
+        HANDLE_OP_END ();
+
+      HANDLE_OP (WASM_OP_I64_EXTEND16_S):
+        DEF_OP_CONVERT(int64, I64, int16, I64);
+        HANDLE_OP_END ();
+
+      HANDLE_OP (WASM_OP_I64_EXTEND32_S):
+        DEF_OP_CONVERT(int64, I64, int32, I64);
+        HANDLE_OP_END ();
+
+      HANDLE_OP (WASM_OP_MISC_PREFIX):
+      {
+        opcode = *frame_ip++;
+        switch (opcode)
+        {
+        case WASM_OP_I32_TRUNC_SAT_S_F32:
+          DEF_OP_TRUNC_SAT_F32(-2147483904.0f, 2147483648.0f,
+                               true, true);
+          break;
+        case WASM_OP_I32_TRUNC_SAT_U_F32:
+          DEF_OP_TRUNC_SAT_F32(-1.0f, 4294967296.0f,
+                               true, false);
+          break;
+        case WASM_OP_I32_TRUNC_SAT_S_F64:
+          DEF_OP_TRUNC_SAT_F64(-2147483649.0, 2147483648.0,
+                               true, true);
+          frame_sp--;
+          break;
+        case WASM_OP_I32_TRUNC_SAT_U_F64:
+          DEF_OP_TRUNC_SAT_F64(-1.0, 4294967296.0,
+                               true, false);
+          frame_sp--;
+          break;
+        case WASM_OP_I64_TRUNC_SAT_S_F32:
+          DEF_OP_TRUNC_SAT_F32(-9223373136366403584.0f, 9223372036854775808.0f,
+                               false, true);
+          frame_sp++;
+          break;
+        case WASM_OP_I64_TRUNC_SAT_U_F32:
+          DEF_OP_TRUNC_SAT_F32(-1.0f, 18446744073709551616.0f,
+                               false, false);
+          frame_sp++;
+          break;
+        case WASM_OP_I64_TRUNC_SAT_S_F64:
+          DEF_OP_TRUNC_SAT_F64(-9223372036854777856.0, 9223372036854775808.0,
+                               false, true);
+          break;
+        case WASM_OP_I64_TRUNC_SAT_U_F64:
+          DEF_OP_TRUNC_SAT_F64(-1.0f, 18446744073709551616.0,
+                               false, false);
+          break;
+        default:
+          wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
+            goto got_exception;
+          break;
+        }
+        HANDLE_OP_END ();
+      }
+
       HANDLE_OP (WASM_OP_IMPDEP):
         frame = prev_frame;
         frame_ip = frame->ip;
@@ -2359,7 +2540,11 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
         return;
     }
 
-    /* TODO: check stack overflow. */
+    if ((uint8*)&prev_frame < exec_env->native_stack_boundary) {
+        wasm_set_exception((WASMModuleInstance*)exec_env->module_inst,
+                           "WASM interp failed: native stack overflow.");
+        return;
+    }
 
     if (!(frame = ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame*)prev_frame)))
         return;

+ 208 - 30
core/iwasm/interpreter/wasm_interp_fast.c

@@ -536,18 +536,131 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
       frame_ip += 4;                                                \
   } while (0)
 
-#define DEF_OP_TRUNC(dst_type, dst_op_type, src_type, src_op_type,  \
-                     min_cond, max_cond) do {                       \
-    src_type value = GET_OPERAND(src_type, 0);                      \
-    if (isnan(value)) {                                             \
-      wasm_set_exception(module, "invalid conversion to integer");  \
-      goto got_exception;                                           \
-    }                                                               \
-    else if (value min_cond || value max_cond) {                    \
-      wasm_set_exception(module, "integer overflow");               \
-      goto got_exception;                                           \
-    }                                                               \
-    SET_OPERAND(dst_type, 2, value);                               \
+#define TRUNC_FUNCTION(func_name, src_type, dst_type, signed_type)  \
+static dst_type                                                     \
+func_name(src_type src_value, src_type src_min, src_type src_max,   \
+          dst_type dst_min, dst_type dst_max, bool is_sign)         \
+{                                                                   \
+  dst_type dst_value = 0;                                           \
+  if (!isnan(src_value)) {                                          \
+      if (src_value <= src_min)                                     \
+          dst_value = dst_min;                                      \
+      else if (src_value >= src_max)                                \
+          dst_value = dst_max;                                      \
+      else {                                                        \
+          if (is_sign)                                              \
+              dst_value = (dst_type)(signed_type)src_value;         \
+          else                                                      \
+              dst_value = (dst_type)src_value;                      \
+      }                                                             \
+  }                                                                 \
+  return dst_value;                                                 \
+}
+
+TRUNC_FUNCTION(trunc_f32_to_i32, float32, uint32, int32)
+TRUNC_FUNCTION(trunc_f32_to_i64, float32, uint64, int64)
+TRUNC_FUNCTION(trunc_f64_to_i32, float64, uint32, int32)
+TRUNC_FUNCTION(trunc_f64_to_i64, float64, uint64, int64)
+
+static bool
+trunc_f32_to_int(WASMModuleInstance *module,
+                 uint8 *frame_ip, uint32 *frame_lp,
+                 float32 src_min, float32 src_max,
+                 bool saturating, bool is_i32, bool is_sign)
+{
+    float32 src_value = GET_OPERAND(float32, 0);
+    uint64 dst_value_i64;
+    uint32 dst_value_i32;
+
+    if (!saturating) {
+        if (isnan(src_value)) {
+            wasm_set_exception(module, "invalid conversion to integer");
+            return true;
+        }
+        else if (src_value <= src_min || src_value >= src_max) {
+            wasm_set_exception(module, "integer overflow");
+            return true;
+        }
+    }
+
+    if (is_i32) {
+        uint32 dst_min = is_sign ? INT32_MIN : 0;
+        uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
+        dst_value_i32 = trunc_f32_to_i32(src_value, src_min, src_max,
+                                         dst_min, dst_max, is_sign);
+        SET_OPERAND(uint32, 2, dst_value_i32);
+    }
+    else {
+        uint64 dst_min = is_sign ? INT64_MIN : 0;
+        uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
+        dst_value_i64 = trunc_f32_to_i64(src_value, src_min, src_max,
+                                         dst_min, dst_max, is_sign);
+        SET_OPERAND(uint64, 2, dst_value_i64);
+    }
+    return false;
+}
+
+static bool
+trunc_f64_to_int(WASMModuleInstance *module,
+                 uint8 *frame_ip, uint32 *frame_lp,
+                 float64 src_min, float64 src_max,
+                 bool saturating, bool is_i32, bool is_sign)
+{
+    float64 src_value = GET_OPERAND(float64, 0);
+    uint64 dst_value_i64;
+    uint32 dst_value_i32;
+
+    if (!saturating) {
+        if (isnan(src_value)) {
+            wasm_set_exception(module, "invalid conversion to integer");
+            return true;
+        }
+        else if (src_value <= src_min || src_value >= src_max) {
+            wasm_set_exception(module, "integer overflow");
+            return true;
+        }
+    }
+
+    if (is_i32) {
+        uint32 dst_min = is_sign ? INT32_MIN : 0;
+        uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX;
+        dst_value_i32 = trunc_f64_to_i32(src_value, src_min, src_max,
+                                         dst_min, dst_max, is_sign);
+        SET_OPERAND(uint32, 2, dst_value_i32);
+    }
+    else {
+        uint64 dst_min = is_sign ? INT64_MIN : 0;
+        uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX;
+        dst_value_i64 = trunc_f64_to_i64(src_value, src_min, src_max,
+                                         dst_min, dst_max, is_sign);
+        SET_OPERAND(uint64, 2, dst_value_i64);
+    }
+    return false;
+}
+
+#define DEF_OP_TRUNC_F32(min, max, is_i32, is_sign) do {            \
+    if (trunc_f32_to_int(module, frame_ip, frame_lp, min, max,      \
+                         false, is_i32, is_sign))                   \
+        goto got_exception;                                         \
+    frame_ip += 4;                                                  \
+  } while (0)
+
+#define DEF_OP_TRUNC_F64(min, max, is_i32, is_sign) do {            \
+    if (trunc_f64_to_int(module, frame_ip, frame_lp, min, max,      \
+                         false, is_i32, is_sign))                   \
+        goto got_exception;                                         \
+    frame_ip += 4;                                                  \
+  } while (0)
+
+#define DEF_OP_TRUNC_SAT_F32(min, max, is_i32, is_sign) do {        \
+    (void)trunc_f32_to_int(module, frame_ip, frame_lp, min, max,    \
+                           true, is_i32, is_sign);                  \
+    frame_ip += 4;                                                  \
+  } while (0)
+
+#define DEF_OP_TRUNC_SAT_F64(min, max, is_i32, is_sign) do {        \
+    (void)trunc_f64_to_int(module, frame_ip, frame_lp, min, max,    \
+                           true, is_i32, is_sign);                  \
     frame_ip += 4;                                                  \
   } while (0)
 
@@ -799,7 +912,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
   int32 didx, val;
   uint8 *maddr = NULL;
   uint32 local_idx, local_offset, global_idx;
-  uint8 local_type, *global_addr;
+  uint8 opcode, local_type, *global_addr;
 
 #if WASM_ENABLE_LABELS_AS_VALUES != 0
   #define HANDLE_OPCODE(op) &&HANDLE_##op
@@ -1981,23 +2094,19 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
            all int32/uint32/int64/uint64 values, e.g.:
            UINT32_MAX is 4294967295, but (float32)4294967295 is 4294967296.0f,
            but not 4294967295.0f. */
-        DEF_OP_TRUNC(int32, I32, float32, F32, <= -2147483904.0f,
-                                               >= 2147483648.0f);
+        DEF_OP_TRUNC_F32(-2147483904.0f, 2147483648.0f, true, true);
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I32_TRUNC_U_F32):
-        DEF_OP_TRUNC(uint32, I32, float32, F32, <= -1.0f,
-                                                >= 4294967296.0f);
+        DEF_OP_TRUNC_F32(-1.0f, 4294967296.0f, true, false);
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I32_TRUNC_S_F64):
-        DEF_OP_TRUNC(int32, I32, float64, F64, <= -2147483649.0,
-                                               >= 2147483648.0);
+        DEF_OP_TRUNC_F64(-2147483649.0, 2147483648.0, true, true);
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I32_TRUNC_U_F64):
-        DEF_OP_TRUNC(uint32, I32, float64, F64, <= -1.0 ,
-                                                >= 4294967296.0);
+        DEF_OP_TRUNC_F64(-1.0, 4294967296.0, true, false);
         HANDLE_OP_END ();
 
       /* conversions of i64 */
@@ -2010,23 +2119,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I64_TRUNC_S_F32):
-        DEF_OP_TRUNC(int64, I64, float32, F32, <= -9223373136366403584.0f,
-                                               >= 9223372036854775808.0f);
+        DEF_OP_TRUNC_F32(-9223373136366403584.0f,
+                         9223372036854775808.0f, false, true);
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I64_TRUNC_U_F32):
-        DEF_OP_TRUNC(uint64, I64, float32, F32, <= -1.0f,
-                                                >= 18446744073709551616.0f);
+        DEF_OP_TRUNC_F32(-1.0f, 18446744073709551616.0f,
+                         false, false);
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I64_TRUNC_S_F64):
-        DEF_OP_TRUNC(int64, I64, float64, F64, <= -9223372036854777856.0,
-                                               >= 9223372036854775808.0);
+        DEF_OP_TRUNC_F64(-9223372036854777856.0,
+                         9223372036854775808.0, false, true);
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_I64_TRUNC_U_F64):
-        DEF_OP_TRUNC(uint64, I64, float64, F64, <= -1.0,
-                                                >= 18446744073709551616.0);
+        DEF_OP_TRUNC_F64(-1.0, 18446744073709551616.0,
+                         false, false);
         HANDLE_OP_END ();
 
       /* conversions of f32 */
@@ -2130,6 +2239,71 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
           HANDLE_OP_END ();
         }
 
+      HANDLE_OP (WASM_OP_I32_EXTEND8_S):
+        DEF_OP_CONVERT(int32, I32, int8, I32);
+        HANDLE_OP_END ();
+
+      HANDLE_OP (WASM_OP_I32_EXTEND16_S):
+        DEF_OP_CONVERT(int32, I32, int16, I32);
+        HANDLE_OP_END ();
+
+      HANDLE_OP (WASM_OP_I64_EXTEND8_S):
+        DEF_OP_CONVERT(int64, I64, int8, I64);
+        HANDLE_OP_END ();
+
+      HANDLE_OP (WASM_OP_I64_EXTEND16_S):
+        DEF_OP_CONVERT(int64, I64, int16, I64);
+        HANDLE_OP_END ();
+
+      HANDLE_OP (WASM_OP_I64_EXTEND32_S):
+        DEF_OP_CONVERT(int64, I64, int32, I64);
+        HANDLE_OP_END ();
+
+      HANDLE_OP (WASM_OP_MISC_PREFIX):
+      {
+        GET_OPCODE();
+        switch (opcode)
+        {
+        case WASM_OP_I32_TRUNC_SAT_S_F32:
+          DEF_OP_TRUNC_SAT_F32(-2147483904.0f, 2147483648.0f,
+                               true, true);
+          break;
+        case WASM_OP_I32_TRUNC_SAT_U_F32:
+          DEF_OP_TRUNC_SAT_F32(-1.0f, 4294967296.0f,
+                               true, false);
+          break;
+        case WASM_OP_I32_TRUNC_SAT_S_F64:
+          DEF_OP_TRUNC_SAT_F64(-2147483649.0, 2147483648.0,
+                               true, true);
+          break;
+        case WASM_OP_I32_TRUNC_SAT_U_F64:
+          DEF_OP_TRUNC_SAT_F64(-1.0, 4294967296.0,
+                               true, false);
+          break;
+        case WASM_OP_I64_TRUNC_SAT_S_F32:
+          DEF_OP_TRUNC_SAT_F32(-9223373136366403584.0f, 9223372036854775808.0f,
+                               false, true);
+          break;
+        case WASM_OP_I64_TRUNC_SAT_U_F32:
+          DEF_OP_TRUNC_SAT_F32(-1.0f, 18446744073709551616.0f,
+                               false, false);
+          break;
+        case WASM_OP_I64_TRUNC_SAT_S_F64:
+          DEF_OP_TRUNC_SAT_F64(-9223372036854777856.0, 9223372036854775808.0,
+                               false, true);
+          break;
+        case WASM_OP_I64_TRUNC_SAT_U_F64:
+          DEF_OP_TRUNC_SAT_F64(-1.0, 18446744073709551616.0,
+                               false, false);
+          break;
+        default:
+          wasm_set_exception(module, "WASM interp failed: unsupported opcode.");
+            goto got_exception;
+          break;
+        }
+        HANDLE_OP_END ();
+      }
+
       HANDLE_OP (WASM_OP_IMPDEP):
         frame = prev_frame;
         frame_ip = frame->ip;
@@ -2334,7 +2508,11 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst,
         return;
     }
 
-    /* TODO: check stack overflow. */
+    if ((uint8*)&prev_frame < exec_env->native_stack_boundary) {
+        wasm_set_exception((WASMModuleInstance*)exec_env->module_inst,
+                           "WASM interp failed: native stack overflow.");
+        return;
+    }
 
     if (!(frame = ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame*)prev_frame)))
         return;

+ 105 - 22
core/iwasm/interpreter/wasm_loader.c

@@ -321,7 +321,7 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module,
 
 static bool
 load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
-               InitializerExpression *init_expr,
+               InitializerExpression *init_expr, uint8 type,
                char *error_buf, uint32 error_buf_size)
 {
     const uint8 *p = *p_buf, *p_end = buf_end;
@@ -335,14 +335,20 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
     switch (flag) {
         /* i32.const */
         case INIT_EXPR_TYPE_I32_CONST:
+            if (type != VALUE_TYPE_I32)
+                goto fail;
             read_leb_int32(p, p_end, init_expr->u.i32);
             break;
         /* i64.const */
         case INIT_EXPR_TYPE_I64_CONST:
+            if (type != VALUE_TYPE_I64)
+                goto fail;
             read_leb_int64(p, p_end, init_expr->u.i64);
             break;
         /* f32.const */
         case INIT_EXPR_TYPE_F32_CONST:
+            if (type != VALUE_TYPE_F32)
+                goto fail;
             CHECK_BUF(p, p_end, 4);
             p_float = (uint8*)&init_expr->u.f32;
             for (i = 0; i < sizeof(float32); i++)
@@ -350,6 +356,8 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
             break;
         /* f64.const */
         case INIT_EXPR_TYPE_F64_CONST:
+            if (type != VALUE_TYPE_F64)
+                goto fail;
             CHECK_BUF(p, p_end, 8);
             p_float = (uint8*)&init_expr->u.f64;
             for (i = 0; i < sizeof(float64); i++)
@@ -360,21 +368,20 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end,
             read_leb_uint32(p, p_end, init_expr->u.global_index);
             break;
         default:
-            set_error_buf(error_buf, error_buf_size,
-                          "WASM module load failed: type mismatch");
-            return false;
+            goto fail;
     }
     CHECK_BUF(p, p_end, 1);
     end_byte = read_uint8(p);
-    if (end_byte != 0x0b) {
-        set_error_buf(error_buf, error_buf_size,
-                      "WASM module load failed: "
-                      "unexpected end of section or function");
-        return false;
-    }
+    if (end_byte != 0x0b)
+        goto fail;
     *p_buf = p;
 
     return true;
+fail:
+    set_error_buf(error_buf, error_buf_size,
+                  "WASM module load failed: type mismatch or "
+                  "constant expression required.");
+    return false;
 }
 
 static bool
@@ -1104,7 +1111,6 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
     WASMMemory *memory;
 
     read_leb_uint32(p, p_end, memory_count);
-    bh_assert(memory_count == 1);
 
     if (memory_count) {
         if (memory_count > 1) {
@@ -1180,7 +1186,8 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
             global->is_mutable = mutable ? true : false;
 
             /* initialize expression */
-            if (!load_init_expr(&p, p_end, &(global->init_expr), error_buf, error_buf_size))
+            if (!load_init_expr(&p, p_end, &(global->init_expr),
+                                global->type, error_buf, error_buf_size))
                 return false;
         }
     }
@@ -1327,7 +1334,7 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m
 
             /* initialize expression */
             if (!load_init_expr(&p, p_end, &(table_segment->base_offset),
-                                error_buf, error_buf_size))
+                                VALUE_TYPE_I32, error_buf, error_buf_size))
                 return false;
 
             read_leb_uint32(p, p_end, function_count);
@@ -1387,7 +1394,8 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
         for (i = 0; i < data_seg_count; i++) {
             read_leb_uint32(p, p_end, mem_index);
 
-            if (!load_init_expr(&p, p_end, &init_expr, error_buf, error_buf_size))
+            if (!load_init_expr(&p, p_end, &init_expr, VALUE_TYPE_I32,
+                                error_buf, error_buf_size))
                 return false;
 
             read_leb_uint32(p, p_end, data_seg_len);
@@ -1455,20 +1463,33 @@ load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                    char *error_buf, uint32 error_buf_size)
 {
     const uint8 *p = buf, *p_end = buf_end;
+    WASMType *type;
     uint32 start_function;
 
     read_leb_uint32(p, p_end, start_function);
 
-    if (start_function) {
-        if (start_function >= module->function_count + module->import_function_count) {
-            set_error_buf(error_buf, error_buf_size,
-                          "Load start section failed: "
-                          "unknown function.");
-            return false;
-        }
-        module->start_function = start_function;
+    if (start_function >= module->function_count
+                          + module->import_function_count) {
+        set_error_buf(error_buf, error_buf_size,
+                "Load start section failed: "
+                "unknown function.");
+        return false;
+    }
+
+    if (start_function < module->import_function_count)
+        type = module->import_functions[start_function].u.function.func_type;
+    else
+        type = module->functions
+                [start_function - module->import_function_count]->func_type;
+    if (type->param_count != 0 || type->result_count != 0) {
+        set_error_buf(error_buf, error_buf_size,
+                "Load start section failed: "
+                "invalid start function.");
+        return false;
     }
 
+    module->start_function = start_function;
+
     if (p != p_end) {
         set_error_buf(error_buf, error_buf_size,
                       "Load start section failed: section size mismatch");
@@ -2345,6 +2366,16 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache,
             case WASM_OP_I64_REINTERPRET_F64:
             case WASM_OP_F32_REINTERPRET_I32:
             case WASM_OP_F64_REINTERPRET_I64:
+            case WASM_OP_I32_EXTEND8_S:
+            case WASM_OP_I32_EXTEND16_S:
+            case WASM_OP_I64_EXTEND8_S:
+            case WASM_OP_I64_EXTEND16_S:
+            case WASM_OP_I64_EXTEND32_S:
+                break;
+            case WASM_OP_MISC_PREFIX:
+                /* skip extend op */
+                if (p < code_end_addr)
+                    p++;
                 break;
 
             default:
@@ -4714,6 +4745,58 @@ handle_next_reachable_block:
                 PUSH_F64();
                 break;
 
+            case WASM_OP_I32_EXTEND8_S:
+            case WASM_OP_I32_EXTEND16_S:
+                POP_I32();
+                PUSH_I32();
+                break;
+
+            case WASM_OP_I64_EXTEND8_S:
+            case WASM_OP_I64_EXTEND16_S:
+            case WASM_OP_I64_EXTEND32_S:
+                POP_I64();
+                PUSH_I64();
+                break;
+
+            case WASM_OP_MISC_PREFIX:
+            {
+                opcode = read_uint8(p);
+#if WASM_ENABLE_FAST_INTERP != 0
+                emit_byte(loader_ctx, opcode);
+#endif
+                switch (opcode)
+                {
+                case WASM_OP_I32_TRUNC_SAT_S_F32:
+                case WASM_OP_I32_TRUNC_SAT_U_F32:
+                    POP_F32();
+                    PUSH_I32();
+                    break;
+                case WASM_OP_I32_TRUNC_SAT_S_F64:
+                case WASM_OP_I32_TRUNC_SAT_U_F64:
+                    POP_F64();
+                    PUSH_I32();
+                    break;
+                case WASM_OP_I64_TRUNC_SAT_S_F32:
+                case WASM_OP_I64_TRUNC_SAT_U_F32:
+                    POP_F32();
+                    PUSH_I64();
+                    break;
+                case WASM_OP_I64_TRUNC_SAT_S_F64:
+                case WASM_OP_I64_TRUNC_SAT_U_F64:
+                    POP_F64();
+                    PUSH_I64();
+                    break;
+                default:
+                    if (error_buf != NULL)
+                        snprintf(error_buf, error_buf_size,
+                                 "WASM module load failed: "
+                                 "invalid opcode 0xfc %02x.", opcode);
+                    goto fail;
+                    break;
+                }
+                break;
+            }
+
             default:
                 if (error_buf != NULL)
                     snprintf(error_buf, error_buf_size,

+ 51 - 23
core/iwasm/interpreter/wasm_opcode.h

@@ -237,22 +237,42 @@ typedef enum WASMOpcode {
     WASM_OP_F32_REINTERPRET_I32   = 0xbe, /* f32.reinterpret/i32 */
     WASM_OP_F64_REINTERPRET_I64   = 0xbf, /* f64.reinterpret/i64 */
 
+    WASM_OP_I32_EXTEND8_S         = 0xc0,  /* i32.extend8_s */
+    WASM_OP_I32_EXTEND16_S        = 0xc1,  /* i32.extend16_s */
+    WASM_OP_I64_EXTEND8_S         = 0xc2,  /* i64.extend8_s */
+    WASM_OP_I64_EXTEND16_S        = 0xc3,  /* i64.extend16_s */
+    WASM_OP_I64_EXTEND32_S        = 0xc4,  /* i64.extend32_s */
+
     /* drop/select specified types*/
-    WASM_OP_DROP_64               = 0xc0,
-    WASM_OP_SELECT_64             = 0xc1,
+    WASM_OP_DROP_64               = 0xc5,
+    WASM_OP_SELECT_64             = 0xc6,
 
     /* extend op code */
-    EXT_OP_GET_LOCAL_FAST         = 0xc2,
-    EXT_OP_SET_LOCAL_FAST_I64     = 0xc3,
-    EXT_OP_SET_LOCAL_FAST         = 0xc4,
-    EXT_OP_TEE_LOCAL_FAST         = 0xc5,
-    EXT_OP_TEE_LOCAL_FAST_I64     = 0xc6,
-    EXT_OP_COPY_STACK_TOP         = 0xc7,
-    EXT_OP_COPY_STACK_TOP_I64     = 0xc8,
-
-    WASM_OP_IMPDEP                = 0xc9
+    EXT_OP_GET_LOCAL_FAST         = 0xc7,
+    EXT_OP_SET_LOCAL_FAST_I64     = 0xc8,
+    EXT_OP_SET_LOCAL_FAST         = 0xc9,
+    EXT_OP_TEE_LOCAL_FAST         = 0xca,
+    EXT_OP_TEE_LOCAL_FAST_I64     = 0xcb,
+    EXT_OP_COPY_STACK_TOP         = 0xcc,
+    EXT_OP_COPY_STACK_TOP_I64     = 0xcd,
+
+    WASM_OP_IMPDEP                = 0xce,
+
+    /* Post-MVP extend op prefix */
+    WASM_OP_MISC_PREFIX           = 0xfc,
 } WASMOpcode;
 
+typedef enum WASMEXTOpcode {
+    WASM_OP_I32_TRUNC_SAT_S_F32   = 0x00,
+    WASM_OP_I32_TRUNC_SAT_U_F32   = 0x01,
+    WASM_OP_I32_TRUNC_SAT_S_F64   = 0x02,
+    WASM_OP_I32_TRUNC_SAT_U_F64   = 0x03,
+    WASM_OP_I64_TRUNC_SAT_S_F32   = 0x04,
+    WASM_OP_I64_TRUNC_SAT_U_F32   = 0x05,
+    WASM_OP_I64_TRUNC_SAT_S_F64   = 0x06,
+    WASM_OP_I64_TRUNC_SAT_U_F64   = 0x07,
+} WASMEXTOpcode;
+
 #ifdef __cplusplus
 }
 #endif
@@ -456,16 +476,24 @@ static type _name[WASM_INSTRUCTION_NUM] = {                  \
   HANDLE_OPCODE (WASM_OP_I64_REINTERPRET_F64),   /* 0xbd */  \
   HANDLE_OPCODE (WASM_OP_F32_REINTERPRET_I32),   /* 0xbe */  \
   HANDLE_OPCODE (WASM_OP_F64_REINTERPRET_I64),   /* 0xbf */  \
-  HANDLE_OPCODE (WASM_OP_DROP_64),           /* 0xc0 */      \
-  HANDLE_OPCODE (WASM_OP_SELECT_64),         /* 0xc1 */      \
-  HANDLE_OPCODE (EXT_OP_GET_LOCAL_FAST),     /* 0xc2 */      \
-  HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST_I64), /* 0xc3 */      \
-  HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST),     /* 0xc4 */      \
-  HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST),     /* 0xc5 */      \
-  HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST_I64), /* 0xc6 */      \
-  HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP),     /* 0xc7 */      \
-  HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP_I64), /* 0xc8 */      \
-  HANDLE_OPCODE (WASM_OP_IMPDEP),            /* 0xc9 */      \
-}
-
+  HANDLE_OPCODE (WASM_OP_I32_EXTEND8_S),     /* 0xc0 */      \
+  HANDLE_OPCODE (WASM_OP_I32_EXTEND16_S),    /* 0xc1 */      \
+  HANDLE_OPCODE (WASM_OP_I64_EXTEND8_S),     /* 0xc2 */      \
+  HANDLE_OPCODE (WASM_OP_I64_EXTEND16_S),    /* 0xc3 */      \
+  HANDLE_OPCODE (WASM_OP_I64_EXTEND32_S),    /* 0xc4 */      \
+  HANDLE_OPCODE (WASM_OP_DROP_64),           /* 0xc5 */      \
+  HANDLE_OPCODE (WASM_OP_SELECT_64),         /* 0xc6 */      \
+  HANDLE_OPCODE (EXT_OP_GET_LOCAL_FAST),     /* 0xc7 */      \
+  HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST_I64), /* 0xc8 */      \
+  HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST),     /* 0xc9 */      \
+  HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST),     /* 0xca */      \
+  HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST_I64), /* 0xcb */      \
+  HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP),     /* 0xcc */      \
+  HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP_I64), /* 0xcd */      \
+  HANDLE_OPCODE (WASM_OP_IMPDEP),            /* 0xce */      \
+};                                                           \
+do {                                                         \
+  _name[WASM_OP_MISC_PREFIX] =                               \
+    HANDLE_OPCODE (WASM_OP_MISC_PREFIX);     /* 0xfc */      \
+} while (0)
 #endif /* end of _WASM_OPCODE_H */

+ 26 - 39
core/iwasm/interpreter/wasm_runtime.c

@@ -419,47 +419,24 @@ globals_instantiate(const WASMModule *module,
     return globals;
 }
 
-static void
+static bool
 globals_instantiate_fix(WASMGlobalInstance *globals,
                         const WASMModule *module,
-                        WASMModuleInstance *module_inst)
+                        WASMModuleInstance *module_inst,
+                        char *error_buf, uint32 error_buf_size)
 {
     WASMGlobalInstance *global = globals;
-    WASMImport *import = module->import_globals;
     uint32 i;
 
-    /* Fix globals from import section */
-    for (i = 0; i < module->import_global_count; i++, import++, global++) {
-        if (!strcmp(import->u.names.module_name, "env")) {
-            if (!strcmp(import->u.names.field_name, "memoryBase")
-                || !strcmp(import->u.names.field_name, "__memory_base")) {
-                global->initial_value.addr = 0;
-            }
-            else if (!strcmp(import->u.names.field_name, "tableBase")
-                     || !strcmp(import->u.names.field_name, "__table_base")) {
-                global->initial_value.addr = 0;
-            }
-            else if (!strcmp(import->u.names.field_name, "DYNAMICTOP_PTR")) {
-                global->initial_value.i32 = (int32)
-                    (module_inst->default_memory->num_bytes_per_page
-                     * module_inst->default_memory->cur_page_count);
-                module_inst->DYNAMICTOP_PTR_offset = global->data_offset;
-            }
-            else if (!strcmp(import->u.names.field_name, "STACKTOP")) {
-                global->initial_value.i32 = 0;
-            }
-            else if (!strcmp(import->u.names.field_name, "STACK_MAX")) {
-                /* Unused in emcc wasm bin actually. */
-                global->initial_value.i32 = 0;
-            }
-        }
-    }
-
     for (i = 0; i < module->global_count; i++) {
         InitializerExpression *init_expr = &module->globals[i].init_expr;
 
         if (init_expr->init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
-            bh_assert(init_expr->u.global_index < module->import_global_count);
+            if (init_expr->u.global_index >= module->import_global_count + i) {
+                set_error_buf(error_buf, error_buf_size,
+                              "Instantiate global failed: unknown global.");
+                return false;
+            }
             global->initial_value = globals[init_expr->u.global_index].initial_value;
         }
         else {
@@ -468,6 +445,7 @@ globals_instantiate_fix(WASMGlobalInstance *globals,
         }
         global++;
     }
+    return true;
 }
 
 /**
@@ -658,7 +636,11 @@ wasm_instantiate(WASMModule *module,
         memory_data = module_inst->default_memory->memory_data;
 
         /* fix import memoryBase */
-        globals_instantiate_fix(globals, module, module_inst);
+        if (!globals_instantiate_fix(globals, module, module_inst,
+                                     error_buf, error_buf_size)) {
+            wasm_deinstantiate(module_inst);
+            return NULL;
+        }
 
         /* Initialize the global data */
         global_data = memory->global_data;
@@ -710,7 +692,7 @@ wasm_instantiate(WASMModule *module,
                     && (base_offset >= memory_size
                         || base_offset + length > memory_size)) {
                     set_error_buf(error_buf, error_buf_size,
-                            "Instantiate module failed: data segment out of range.");
+                            "Instantiate module failed: data segment does not fit.");
                     wasm_deinstantiate(module_inst);
                     return NULL;
                 }
@@ -784,9 +766,10 @@ wasm_instantiate(WASMModule *module,
 #endif
 
     if (module->start_function != (uint32)-1) {
-        bh_assert(module->start_function >= module->import_function_count);
-        module_inst->start_function =
-            &module_inst->functions[module->start_function];
+        /* TODO: fix start function can be import function issue */
+        if (module->start_function >= module->import_function_count)
+            module_inst->start_function =
+                &module_inst->functions[module->start_function];
     }
 
     module_inst->module = module;
@@ -881,6 +864,9 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
         return false;
     }
 
+    /* set thread handle and stack boundary */
+    wasm_exec_env_set_thread_info(exec_env);
+
     ret = wasm_call_function(exec_env, func, argc, argv);
     wasm_exec_env_destroy(exec_env);
     return ret;
@@ -998,12 +984,13 @@ wasm_addr_app_to_native(WASMModuleInstance *module_inst,
                         int32 app_offset)
 {
     WASMMemoryInstance *memory = module_inst->default_memory;
+    uint8 *addr = memory->memory_data + app_offset;
     int32 memory_data_size =
         (int32)(memory->num_bytes_per_page * memory->cur_page_count);
 
-    if (memory->heap_base_offset < app_offset
-        && app_offset < memory_data_size)
-        return memory->memory_data + app_offset;
+    if (memory->heap_data < addr
+        && addr < memory->memory_data + memory_data_size)
+        return addr;
     return NULL;
 }
 

+ 0 - 1
core/iwasm/interpreter/wasm_runtime.h

@@ -136,7 +136,6 @@ typedef struct WASMModuleInstance {
     WASIContext *wasi_ctx;
 #endif
 
-    uint32 DYNAMICTOP_PTR_offset;
     uint32 temp_ret;
     uint32 llvm_stack;
 

+ 46 - 4
core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c

@@ -993,11 +993,44 @@ __cxa_throw_wrapper(wasm_exec_env_t exec_env,
     wasm_runtime_set_exception(module_inst, buf);
 }
 
+#if WASM_ENABLE_SPEC_TEST != 0
+static void
+print_wrapper(wasm_exec_env_t exec_env)
+{
+    os_printf("in specttest.print()\n");
+
+}
+
 static void
 print_i32_wrapper(wasm_exec_env_t exec_env, int32 i32)
 {
-    os_printf("%d\n", i32);
+    os_printf("in specttest.print_i32(%d)\n", i32);
+}
+
+static void
+print_i32_f32_wrapper(wasm_exec_env_t exec_env, int32 i32, float f32)
+{
+    os_printf("in specttest.print_i32_f32(%d, %f)\n", i32, f32);
+}
+
+static void
+print_f64_f64_wrapper(wasm_exec_env_t exec_env, double f64_1, double f64_2)
+{
+    os_printf("in specttest.print_f64_f64(%f, %f)\n", f64_1, f64_2);
+}
+
+static void
+print_f32_wrapper(wasm_exec_env_t exec_env, float f32)
+{
+    os_printf("in specttest.print_f32(%f)\n", f32);
+}
+
+static void
+print_f64_wrapper(wasm_exec_env_t exec_env, double f64)
+{
+    os_printf("in specttest.print_f64(%f)\n", f64);
 }
+#endif /* WASM_ENABLE_SPEC_TEST */
 
 #define REG_NATIVE_FUNC(func_name, signature)  \
     { #func_name, func_name##_wrapper, signature, NULL }
@@ -1060,9 +1093,16 @@ static NativeSymbol native_symbols_libc_builtin[] = {
     REG_NATIVE_FUNC(__cxa_throw, "(**i)")
 };
 
+#if WASM_ENABLE_SPEC_TEST != 0
 static NativeSymbol native_symbols_spectest[] = {
-    REG_NATIVE_FUNC(print_i32, "(i)")
+    REG_NATIVE_FUNC(print, "()"),
+    REG_NATIVE_FUNC(print_i32, "(i)"),
+    REG_NATIVE_FUNC(print_i32_f32, "(if)"),
+    REG_NATIVE_FUNC(print_f64_f64, "(fF)"),
+    REG_NATIVE_FUNC(print_f32, "(f)"),
+    REG_NATIVE_FUNC(print_f64, "(F)")
 };
+#endif
 
 uint32
 get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis)
@@ -1071,12 +1111,14 @@ get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis)
     return sizeof(native_symbols_libc_builtin) / sizeof(NativeSymbol);
 }
 
+#if WASM_ENABLE_SPEC_TEST != 0
 uint32
 get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis)
 {
     *p_libc_builtin_apis = native_symbols_spectest;
     return sizeof(native_symbols_spectest) / sizeof(NativeSymbol);
 }
+#endif
 
 /*************************************
  * Global Variables                  *
@@ -1090,8 +1132,8 @@ typedef struct WASMNativeGlobalDef {
 
 static WASMNativeGlobalDef native_global_defs[] = {
     { "spectest", "global_i32", .global_data.i32 = 666 },
-    { "spectest", "global_f32", .global_data.f32 = 0 },
-    { "spectest", "global_f64", .global_data.f64 = 0 },
+    { "spectest", "global_f32", .global_data.f32 = 666.6 },
+    { "spectest", "global_f64", .global_data.f64 = 666.6 },
     { "test", "global-i32", .global_data.i32 = 0 },
     { "test", "global-f32", .global_data.f32 = 0 },
     { "env", "STACKTOP", .global_data.u32 = 0 },

+ 17 - 4
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h

@@ -13,6 +13,22 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#ifdef __cplusplus
+#ifndef _Static_assert
+#define _Static_assert static_assert
+#endif /* _Static_assert */
+
+#ifndef _Alignof
+#define _Alignof alignof
+#endif /* _Alignof */
+
+#ifndef _Noreturn
+#define _Noreturn [[ noreturn ]]
+#endif /* _Noreturn */
+extern "C" {
+#endif
+
+
 _Static_assert(_Alignof(int8_t) == 1, "non-wasi data layout");
 _Static_assert(_Alignof(uint8_t) == 1, "non-wasi data layout");
 _Static_assert(_Alignof(int16_t) == 2, "non-wasi data layout");
@@ -24,10 +40,6 @@ _Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout");
 _Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout");
 #endif
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef uint8_t __wasi_advice_t;
 #define __WASI_ADVICE_NORMAL     (0)
 #define __WASI_ADVICE_SEQUENTIAL (1)
@@ -874,3 +886,4 @@ __wasi_errno_t wasmtime_ssp_sched_yield(void)
 #undef WASMTIME_SSP_SYSCALL_NAME
 
 #endif
+

+ 6 - 0
core/shared/platform/alios/alios_thread.c

@@ -339,3 +339,9 @@ os_cond_signal(korp_cond *cond)
     return BHT_OK;
 }
 
+uint8 *os_thread_get_stack_boundary()
+{
+    /* TODO: get alios stack boundary */
+    return NULL;
+}
+

+ 1 - 1
core/shared/platform/android/platform_internal.h

@@ -40,7 +40,7 @@ extern "C" {
 #define _STACK_SIZE_ADJUSTMENT (32 * 1024)
 
 /* Stack size of applet threads's native part.  */
-#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT)
 
 /* Default thread priority */
 #define BH_THREAD_DEFAULT_PRIORITY 0

+ 20 - 0
core/shared/platform/common/posix/posix_thread.c

@@ -3,6 +3,9 @@
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
 #include "platform_api_vmcore.h"
 #include "platform_api_extension.h"
 
@@ -218,3 +221,20 @@ int os_thread_join(korp_tid thread, void **value_ptr)
     return pthread_join(thread, value_ptr);
 }
 
+uint8 *os_thread_get_stack_boundary()
+{
+    pthread_attr_t attr;
+    void *addr = NULL;
+    size_t size;
+
+    if (pthread_getattr_np(pthread_self(), &attr) == 0) {
+        pthread_attr_getstack(&attr, &addr, &size);
+        pthread_attr_destroy (&attr);
+    }
+
+    if (addr)
+        return (uint8*)addr + _STACK_SIZE_ADJUSTMENT;
+    else
+        return NULL;
+}
+

+ 1 - 1
core/shared/platform/darwin/platform_internal.h

@@ -40,7 +40,7 @@ extern "C" {
 #define _STACK_SIZE_ADJUSTMENT (32 * 1024)
 
 /* Stack size of applet threads's native part.  */
-#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT)
 
 /* Default thread priority */
 #define BH_THREAD_DEFAULT_PRIORITY 0

+ 7 - 0
core/shared/platform/include/platform_api_vmcore.h

@@ -65,6 +65,13 @@ uint64 os_time_get_boot_microsecond(void);
  */
 korp_tid os_self_thread(void);
 
+/**
+ * Get current thread's stack boundary address, used for runtime
+ * to check the native stack overflow. Return NULL if it is not
+ * easy to implement, but may have potential issue.
+ */
+uint8 *os_thread_get_stack_boundary(void);
+
 /**
  ************** mutext APIs ***********
  *  vmcore:  Not required until pthread is supported by runtime

+ 6 - 0
core/shared/platform/linux-sgx/sgx_thread.c

@@ -47,3 +47,9 @@ int os_cond_destroy(korp_cond *cond)
     return BHT_OK;
 }
 
+uint8 *os_thread_get_stack_boundary()
+{
+    /* TODO: get sgx stack boundary */
+    return NULL;
+}
+

+ 1 - 1
core/shared/platform/linux/platform_internal.h

@@ -40,7 +40,7 @@ extern "C" {
 #define _STACK_SIZE_ADJUSTMENT (32 * 1024)
 
 /* Stack size of applet threads's native part.  */
-#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT)
 
 /* Default thread priority */
 #define BH_THREAD_DEFAULT_PRIORITY 0

+ 1 - 1
core/shared/platform/vxworks/platform_internal.h

@@ -39,7 +39,7 @@ extern "C" {
 #define _STACK_SIZE_ADJUSTMENT (32 * 1024)
 
 /* Stack size of applet threads's native part.  */
-#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
+#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024 + _STACK_SIZE_ADJUSTMENT)
 
 /* Default thread priority */
 #define BH_THREAD_DEFAULT_PRIORITY 0

+ 10 - 0
core/shared/platform/zephyr/zephyr_thread.c

@@ -444,3 +444,13 @@ int os_cond_signal(korp_cond *cond)
     return BHT_OK;
 }
 
+uint8 *os_thread_get_stack_boundary()
+{
+#if defined(CONFIG_THREAD_STACK_INFO)
+    korp_tid thread = k_current_get();
+    return (uint8*)thread->stack_info.start;
+#else
+    return NULL;
+#endif
+}
+

+ 1 - 0
samples/littlevgl/vgl-native-ui-app/CMakeLists.txt

@@ -128,6 +128,7 @@ include_directories(
     ${LVGL_DRIVER_DIR}/display
     ${LVGL_DRIVER_DIR}/indev
     ${LVGL_SOURCE_DIR}
+    ${LVGL_SOURCE_DIR}/..
     ${CMAKE_CURRENT_BINARY_DIR}
     ${CMAKE_CURRENT_LIST_DIR}
     ${CMAKE_CURRENT_LIST_DIR}/../lv_config

+ 1 - 1
wamr-compiler/CMakeLists.txt

@@ -59,7 +59,7 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
 endif ()
 
 if (NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE Release)
+  set(CMAKE_BUILD_TYPE Release)
 endif (NOT CMAKE_BUILD_TYPE)
 message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE})