Selaa lähdekoodia

Fix function type not set issue of aot_call_indirect (#229)

Add registration of libc-wasi to 'wasi_snapshot_preview1' to support cargo-wasi
change zephyr build method from cmake to west
fix problem when preserve space for local vars
fix wasi authority problem
Xu Jun 5 vuotta sitten
vanhempi
sitoutus
5e196253f6

+ 3 - 0
.gitignore

@@ -5,3 +5,6 @@ core/deps/llvm
 core/deps/lvgl
 core/shared/mem-alloc/tlsf
 
+wamr-sdk/out/
+wamr-sdk/runtime/build_runtime_sdk/
+test-tools/host-tool/bin/

+ 129 - 0
_clang-format

@@ -0,0 +1,129 @@
+---
+BasedOnStyle: Mozilla
+IndentWidth: 4
+
+---
+Language: Cpp
+AlignConsecutiveMacros: true
+AllowShortBlocksOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
+BreakBeforeBraces: Custom
+BraceWrapping:
+  AfterCaseLabel: false
+  AfterClass: true
+  AfterControlStatement: false
+  AfterEnum: true
+  AfterFunction: true
+  AfterNamespace: false
+  AfterObjCDeclaration: false
+  AfterStruct: true
+  AfterUnion: false
+  AfterExternBlock: true
+  BeforeCatch: false
+  BeforeElse: false
+  IndentBraces: false
+  SplitEmptyFunction: true
+  SplitEmptyRecord: false
+  SplitEmptyNamespace: true
+ColumnLimit: 79
+DerivePointerAlignment: false
+IncludeBlocks: Regroup
+IncludeCategories:
+  - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+    Priority: 2
+  - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+    Priority: 1
+  - Regex: ".*"
+    Priority: 3
+PointerAlignment: Right
+ReflowComments: false
+Standard: Cpp03
+StatementMacros:
+  - Q_UNUSED
+  - QT_REQUIRE_VERSION
+# AccessModifierOffset: -2
+# AlignAfterOpenBracket: Align
+# AlignConsecutiveAssignments: false
+# AlignConsecutiveDeclarations: false
+# AlignEscapedNewlines: Right
+# AlignOperands:   true
+# AlignTrailingComments: true
+# AllowAllArgumentsOnNextLine: true
+# AllowAllConstructorInitializersOnNextLine: true
+# AllowAllParametersOfDeclarationOnNextLine: false
+# AllowShortCaseLabelsOnASingleLine: false
+# AllowShortFunctionsOnASingleLine: Inline
+# AllowShortLambdasOnASingleLine: All
+# AllowShortIfStatementsOnASingleLine: Never
+# AllowShortLoopsOnASingleLine: false
+# AlwaysBreakAfterDefinitionReturnType: TopLevel
+# AlwaysBreakAfterReturnType: TopLevel
+# AlwaysBreakBeforeMultilineStrings: false
+# AlwaysBreakTemplateDeclarations: Yes
+# BreakBeforeBinaryOperators: None
+# BreakBeforeInheritanceComma: false
+# BreakInheritanceList: BeforeComma
+# BreakBeforeTernaryOperators: true
+# BreakConstructorInitializersBeforeComma: false
+# BreakConstructorInitializers: BeforeComma
+# BreakAfterJavaFieldAnnotations: false
+# BreakStringLiterals: true
+# CommentPragmas:  '^ IWYU pragma:'
+# CompactNamespaces: false
+# ConstructorInitializerAllOnOneLineOrOnePerLine: false
+# ConstructorInitializerIndentWidth: 2
+# ContinuationIndentWidth: 2
+# Cpp11BracedListStyle: false
+# DisableFormat:   false
+# ExperimentalAutoDetectBinPacking: false
+# FixNamespaceComments: false
+# ForEachMacros:
+#   - foreach
+#   - Q_FOREACH
+#   - BOOST_FOREACH
+# IncludeIsMainRegex: '(Test)?$'
+# IndentCaseLabels: true
+# IndentPPDirectives: None
+# IndentWrappedFunctionNames: false
+# JavaScriptQuotes: Leave
+# JavaScriptWrapImports: true
+# KeepEmptyLinesAtTheStartOfBlocks: true
+# MacroBlockBegin: ''
+# MacroBlockEnd:   ''
+# MaxEmptyLinesToKeep: 1
+# NamespaceIndentation: None
+# ObjCBinPackProtocolList: Auto
+# ObjCBlockIndentWidth: 2
+# ObjCSpaceAfterProperty: true
+# ObjCSpaceBeforeProtocolList: false
+# PenaltyBreakAssignment: 2
+# PenaltyBreakBeforeFirstCallParameter: 19
+# PenaltyBreakComment: 300
+# PenaltyBreakFirstLessLess: 120
+# PenaltyBreakString: 1000
+# PenaltyBreakTemplateDeclaration: 10
+# PenaltyExcessCharacter: 1000000
+# PenaltyReturnTypeOnItsOwnLine: 200
+# SortIncludes:    true
+# SortUsingDeclarations: true
+# SpaceAfterCStyleCast: false
+# SpaceAfterLogicalNot: false
+# SpaceAfterTemplateKeyword: false
+# SpaceBeforeAssignmentOperators: true
+# SpaceBeforeCpp11BracedList: false
+# SpaceBeforeCtorInitializerColon: true
+# SpaceBeforeInheritanceColon: true
+# SpaceBeforeParens: ControlStatements
+# SpaceBeforeRangeBasedForLoopColon: true
+# SpaceInEmptyParentheses: false
+# SpacesBeforeTrailingComments: 1
+# SpacesInAngles:  false
+# SpacesInContainerLiterals: true
+# SpacesInCStyleCastParentheses: false
+# SpacesInParentheses: false
+# SpacesInSquareBrackets: false
+# TabWidth:        4
+# UseTab:          Never
+# ...
+

+ 6 - 6
build-scripts/config_common.cmake

@@ -94,33 +94,33 @@ message ("     CMAKE_BUILD_TYPE " ${CMAKE_BUILD_TYPE})
 if (WAMR_BUILD_INTERP EQUAL 1)
   message ("     WAMR Interpreter enabled")
 else ()
-  message ("     WAMR Interpreter disbled")
+  message ("     WAMR Interpreter disabled")
 endif ()
 if (WAMR_BUILD_AOT EQUAL 1)
   message ("     WAMR AOT enabled")
 else ()
-  message ("     WAMR AOT disbled")
+  message ("     WAMR AOT disabled")
 endif ()
 if (WAMR_BUILD_JIT EQUAL 1)
   message ("     WAMR JIT enabled")
 else ()
-  message ("     WAMR JIT disbled")
+  message ("     WAMR JIT disabled")
 endif ()
 if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
   message ("     Libc builtin enabled")
 else ()
-  message ("     Libc builtin disbled")
+  message ("     Libc builtin disabled")
 endif ()
 if (WAMR_BUILD_LIBC_WASI EQUAL 1)
   message ("     Libc WASI enabled")
 else ()
-  message ("     Libc WASI disbled")
+  message ("     Libc WASI disabled")
 endif ()
 if (WAMR_BUILD_FAST_INTERP EQUAL 1)
   add_definitions (-DWASM_ENABLE_FAST_INTERP=1)
   message ("     Fast interpreter enabled")
 else ()
   add_definitions (-DWASM_ENABLE_FAST_INTERP=0)
-  message ("     Fast interpreter disbled")
+  message ("     Fast interpreter disabled")
 endif ()
 

+ 2 - 1
core/iwasm/aot/aot_loader.c

@@ -794,7 +794,8 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end,
         }
 
 #if WASM_ENABLE_LIBC_WASI != 0
-        if (!strcmp(import_funcs[i].module_name, "wasi_unstable"))
+        if (!strcmp(import_funcs[i].module_name, "wasi_unstable")
+            || !strcmp(import_funcs[i].module_name, "wasi_snapshot_preview1"))
             module->is_wasi_module = true;
 #endif
     }

+ 11 - 6
core/iwasm/aot/aot_runtime.c

@@ -855,7 +855,8 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
 
 bool
 aot_call_indirect(WASMExecEnv *exec_env,
-                  uint32 func_type_idx, uint32 table_elem_idx,
+                  bool check_func_type, uint32 func_type_idx,
+                  uint32 table_elem_idx,
                   uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
 {
     AOTModuleInstance *module_inst = (AOTModuleInstance*)
@@ -863,7 +864,7 @@ aot_call_indirect(WASMExecEnv *exec_env,
     AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr;
     uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr;
     uint32 *table_data = (uint32*)module_inst->table_data.ptr;
-    AOTFuncType *func_type = aot_module->func_types[func_type_idx];;
+    AOTFuncType *func_type;
     void **func_ptrs = (void**)module_inst->func_ptrs.ptr, *func_ptr;
     uint32 table_size = module_inst->table_size;
     uint32 func_idx, func_type_idx1;
@@ -884,10 +885,14 @@ aot_call_indirect(WASMExecEnv *exec_env,
     }
 
     func_type_idx1 = func_type_indexes[func_idx];
-    if (!aot_is_wasm_type_equal(module_inst, func_type_idx, func_type_idx1)) {
-        aot_set_exception_with_id(module_inst, EXCE_INVALID_FUNCTION_TYPE_INDEX);
+    if (check_func_type
+        && !aot_is_wasm_type_equal(module_inst, func_type_idx,
+                                   func_type_idx1)) {
+        aot_set_exception_with_id(module_inst,
+                                  EXCE_INVALID_FUNCTION_TYPE_INDEX);
         return false;
     }
+    func_type = aot_module->func_types[func_type_idx1];
 
     if (!(func_ptr = func_ptrs[func_idx])) {
         bh_assert(func_idx < aot_module->import_func_count);
@@ -906,7 +911,8 @@ aot_call_indirect(WASMExecEnv *exec_env,
         if (import_func->call_conv_raw) {
             attachment = import_func->attachment;
             return wasm_runtime_invoke_native_raw(exec_env, func_ptr,
-                                                  func_type, signature, attachment,
+                                                  func_type, signature,
+                                                  attachment,
                                                   frame_lp, argc, argv_ret);
         }
     }
@@ -915,4 +921,3 @@ aot_call_indirect(WASMExecEnv *exec_env,
                                       func_type, signature, attachment,
                                       frame_lp, argc, argv_ret);
 }
-

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

@@ -445,7 +445,8 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
 
 bool
 aot_call_indirect(WASMExecEnv *exec_env,
-                  uint32 func_type_idx, uint32 table_elem_idx,
+                  bool check_func_type, uint32 func_type_idx,
+                  uint32 table_elem_idx,
                   uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
 
 uint32

+ 7 - 7
core/iwasm/aot/iwasm_aot.cmake

@@ -9,19 +9,19 @@ include_directories (${IWASM_AOT_DIR})
 
 file (GLOB c_source_all ${IWASM_AOT_DIR}/*.c)
 
-if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD_64")
+if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
   set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_64.c)
-elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32")
+elseif (WAMR_BUILD_TARGET STREQUAL "X86_32")
   set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_32.c)
-elseif (${WAMR_BUILD_TARGET} MATCHES "AARCH64.*")
+elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
   set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_aarch64.c)
-elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*")
+elseif (WAMR_BUILD_TARGET MATCHES "ARM.*")
   set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arm.c)
-elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*")
+elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
   set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_thumb.c)
-elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS")
+elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
   set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_mips.c)
-elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA")
+elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
   set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_xtensa.c)
 else ()
   message (FATAL_ERROR "Build target isn't set")

+ 10 - 10
core/iwasm/common/iwasm_common.cmake

@@ -10,29 +10,29 @@ add_definitions(-DBH_FREE=wasm_runtime_free)
 
 file (GLOB c_source_all ${IWASM_COMMON_DIR}/*.c)
 
-if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD_64")
+if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
   set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s)
-elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32")
+elseif (WAMR_BUILD_TARGET STREQUAL "X86_32")
   set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s)
-elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*")
-  if (${WAMR_BUILD_TARGET} MATCHES "ARM.*_VFP")
+elseif (WAMR_BUILD_TARGET MATCHES "ARM.*")
+  if (WAMR_BUILD_TARGET MATCHES "ARM.*_VFP")
     set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm_vfp.s)
   else ()
     set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm.s)
   endif ()
-elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*")
-  if (${WAMR_BUILD_TARGET} MATCHES "THUMB.*_VFP")
+elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
+  if (WAMR_BUILD_TARGET MATCHES "THUMB.*_VFP")
     set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb_vfp.s)
   else ()
     set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb.s)
   endif ()
-elseif (${WAMR_BUILD_TARGET} MATCHES "AARCH64.*")
+elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
   set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s)
-elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS")
+elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
   set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s)
-elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA")
+elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
   set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_xtensa.s)
-elseif (${WAMR_BUILD_TARGET} STREQUAL "GENERAL")
+elseif (WAMR_BUILD_TARGET STREQUAL "GENERAL")
   # Use invokeNative_general.c instead of assembly code,
   # but the maximum number of native arguments is limited to 20,
   # and there are possible issues when passing arguments to

+ 3 - 0
core/iwasm/common/wasm_native.c

@@ -251,6 +251,9 @@ wasm_native_init()
     if (!wasm_native_register_natives("wasi_unstable",
                                       native_symbols, n_native_symbols))
         return false;
+    if (!wasm_native_register_natives("wasi_snapshot_preview1",
+                                      native_symbols, n_native_symbols))
+        return false;
 #endif
 
 #if WASM_ENABLE_BASE_LIB != 0

+ 44 - 7
core/iwasm/common/wasm_runtime_common.c

@@ -37,6 +37,17 @@ wasm_runtime_env_init()
     return true;
 }
 
+static bool
+wasm_runtime_env_check(WASMExecEnv *exec_env)
+{
+    return !(!exec_env
+        || !exec_env->module_inst
+        || exec_env->wasm_stack_size == 0
+        || exec_env->wasm_stack.s.top_boundary !=
+                exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size
+        || exec_env->wasm_stack.s.top > exec_env->wasm_stack.s.top_boundary);
+}
+
 bool
 wasm_runtime_init()
 {
@@ -276,12 +287,7 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
                        WASMFunctionInstanceCommon *function,
                        unsigned argc, uint32 argv[])
 {
-    if (!exec_env
-        || !exec_env->module_inst
-        || exec_env->wasm_stack_size == 0
-        || exec_env->wasm_stack.s.top_boundary !=
-                exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size
-        || exec_env->wasm_stack.s.top > exec_env->wasm_stack.s.top_boundary) {
+    if (!wasm_runtime_env_check(exec_env)) {
         LOG_ERROR("Invalid exec env stack info.");
         return false;
     }
@@ -1392,15 +1398,19 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
             break;
         case VALUE_TYPE_I64:
         {
-            char buf[16];
             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);
+#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:
@@ -2110,6 +2120,33 @@ fail:
     return ret;
 }
 
+bool
+wasm_runtime_call_indirect(WASMExecEnv *exec_env,
+                           uint32_t element_indices,
+                           uint32_t argc, uint32_t argv[])
+{
+    if (!wasm_runtime_env_check(exec_env)) {
+        LOG_ERROR("Invalid exec env stack info.");
+        return false;
+    }
+
+    exec_env->handle = os_self_thread();
+
+#if WASM_ENABLE_INTERP != 0
+    if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
+        return wasm_call_indirect(exec_env,
+                                  element_indices,
+                                  argc, argv);
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (exec_env->module_inst->module_type == Wasm_Module_AoT)
+        return aot_call_indirect(exec_env, false, 0,
+                                 element_indices,
+                                 argv, argc, argv);
+#endif
+    return false;
+}
+
 #endif /* end of defined(BUILD_TARGET_X86_64) \
                  || defined(BUILD_TARGET_AMD_64) \
                  || defined(BUILD_TARGET_AARCH64) */

+ 23 - 1
core/iwasm/common/wasm_runtime_common.h

@@ -131,6 +131,28 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
                        WASMFunctionInstanceCommon *function,
                        unsigned argc, uint32 argv[]);
 
+/**
+ * Call a function reference of a given WASM runtime instance with
+ * arguments.
+ *
+ * @param exec_env the execution environment to call the function
+ *   which must be created from wasm_create_exec_env()
+ * @param element_indices the function ference indicies, usually
+ *   prvovided by the caller of a registed native function
+ * @param argc the number of arguments
+ * @param argv the arguments.  If the function method has return value,
+ *   the first (or first two in case 64-bit return value) element of
+ *   argv stores the return value of the called WASM function after this
+ *   function returns.
+ *
+ * @return true if success, false otherwise and exception will be thrown,
+ *   the caller can call wasm_runtime_get_exception to get exception info.
+ */
+bool
+wasm_runtime_call_indirect(WASMExecEnv *exec_env,
+                           uint32_t element_indices,
+                           uint32_t argc, uint32_t argv[]);
+
 bool
 wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst,
                                            WASMFunctionInstanceCommon *function,
@@ -269,6 +291,7 @@ wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst,
 
 WASIContext *
 wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst);
+
 #endif /* end of WASM_ENABLE_LIBC_WASI */
 
 /**
@@ -305,7 +328,6 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
                                void *attachment,
                                uint32 *argv, uint32 argc, uint32 *ret);
 
-
 #ifdef __cplusplus
 }
 #endif

+ 18 - 16
core/iwasm/compilation/aot_emit_function.c

@@ -395,21 +395,22 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                             LLVMTypeRef ret_type, uint8 wasm_ret_type,
                             LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
 {
-    LLVMTypeRef func_type, func_ptr_type, func_param_types[6];
+    LLVMTypeRef func_type, func_ptr_type, func_param_types[7];
     LLVMTypeRef ret_ptr_type, elem_ptr_type;
     LLVMValueRef func, elem_idx, elem_ptr;
-    LLVMValueRef func_param_values[6], value_ret = NULL, value_ret_ptr, res = NULL;
+    LLVMValueRef func_param_values[7], value_ret = NULL, value_ret_ptr, res = NULL;
     char buf[32], *func_name = "aot_call_indirect";
     uint32 i, cell_num = 0;
 
     /* prepare function type of aot_call_indirect */
     func_param_types[0] = comp_ctx->exec_env_type;  /* exec_env */
-    func_param_types[1] = I32_TYPE;                 /* func_type_idx */
-    func_param_types[2] = I32_TYPE;                 /* table_elem_idx */
-    func_param_types[3] = INT32_PTR_TYPE;           /* frame_lp */
-    func_param_types[4] = I32_TYPE;                 /* argc */
-    func_param_types[5] = INT32_PTR_TYPE;           /* argv_ret */
-    if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 6, false))) {
+    func_param_types[1] = INT8_TYPE;                /* check_func_type */
+    func_param_types[2] = I32_TYPE;                 /* func_type_idx */
+    func_param_types[3] = I32_TYPE;                 /* table_elem_idx */
+    func_param_types[4] = INT32_PTR_TYPE;           /* frame_lp */
+    func_param_types[5] = I32_TYPE;                 /* argc */
+    func_param_types[6] = INT32_PTR_TYPE;           /* argv_ret */
+    if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 7, false))) {
         aot_set_last_error("llvm add function type failed.");
         return false;
     }
@@ -493,20 +494,21 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     }
 
     func_param_values[0] = func_ctx->exec_env;
-    func_param_values[1] = func_type_idx;
-    func_param_values[2] = table_elem_idx;
-    func_param_values[3] = func_ctx->argv_buf;
-    func_param_values[4] = I32_CONST(param_cell_num);
-    func_param_values[5] = value_ret_ptr;
-
-    if (!func_param_values[4]) {
+    func_param_values[1] = I8_CONST(true);
+    func_param_values[2] = func_type_idx;
+    func_param_values[3] = table_elem_idx;
+    func_param_values[4] = func_ctx->argv_buf;
+    func_param_values[5] = I32_CONST(param_cell_num);
+    func_param_values[6] = value_ret_ptr;
+
+    if (!func_param_values[1] || !func_param_values[4]) {
         aot_set_last_error("llvm create const failed.");
         return false;
     }
 
     /* call aot_call_indirect() function */
     if (!(res = LLVMBuildCall(comp_ctx->builder, func,
-                              func_param_values, 6, "res"))) {
+                              func_param_values, 7, "res"))) {
         aot_set_last_error("llvm build call failed.");
         return false;
     }

+ 23 - 10
core/iwasm/interpreter/wasm_loader.c

@@ -675,9 +675,11 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 
         p = p_old;
 
-        /* insert "env" and "wasi_unstable" to const str list */
+        /* insert "env", "wasi_unstable" and "wasi_snapshot_preview1" to const str list */
         if (!const_str_list_insert((uint8*)"env", 3, module, error_buf, error_buf_size)
             || !const_str_list_insert((uint8*)"wasi_unstable", 13, module,
+                                     error_buf, error_buf_size)
+            || !const_str_list_insert((uint8*)"wasi_snapshot_preview1", 22, module,
                                      error_buf, error_buf_size)) {
             return false;
         }
@@ -797,7 +799,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 #if WASM_ENABLE_LIBC_WASI != 0
         import = module->import_functions;
         for (i = 0; i < module->import_function_count; i++, import++) {
-            if (!strcmp(import->u.names.module_name, "wasi_unstable")) {
+            if (!strcmp(import->u.names.module_name, "wasi_unstable")
+                || !strcmp(import->u.names.module_name, "wasi_snapshot_preview1")) {
                 module->is_wasi_module = true;
                 break;
             }
@@ -2377,6 +2380,9 @@ typedef struct WASMLoaderContext {
     int16 start_dynamic_offset;
     int16 max_dynamic_offset;
 
+    /* preserved local offset */
+    int16 preserved_local_offset;
+
     /* const buffer */
     uint8 *const_buf;
     uint16 num_const;
@@ -2873,6 +2879,9 @@ wasm_loader_ctx_reinit(WASMLoaderContext *ctx)
     ctx->frame_offset = ctx->frame_offset_bottom;
     ctx->dynamic_offset = ctx->start_dynamic_offset;
 
+    /* init preserved local offsets */
+    ctx->preserved_local_offset = ctx->max_dynamic_offset;
+
     /* const buf is reserved */
     return true;
 }
@@ -2950,19 +2959,21 @@ preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode,
                 skip_label();
                 if (local_type == VALUE_TYPE_I32
                     || local_type == VALUE_TYPE_F32) {
-                    preserved_offset = loader_ctx->dynamic_offset++;
+                    preserved_offset = loader_ctx->preserved_local_offset;
+                    /* Only increase preserve offset in the second traversal */
+                    if (loader_ctx->p_code_compiled)
+                        loader_ctx->preserved_local_offset++;
                     emit_label(EXT_OP_COPY_STACK_TOP);
                 }
                 else {
-                    preserved_offset = loader_ctx->dynamic_offset;
-                    loader_ctx->dynamic_offset += 2;
+                    preserved_offset = loader_ctx->preserved_local_offset;
+                    if (loader_ctx->p_code_compiled)
+                        loader_ctx->preserved_local_offset += 2;
                     emit_label(EXT_OP_COPY_STACK_TOP_I64);
                 }
                 emit_operand(loader_ctx, local_index);
                 emit_operand(loader_ctx, preserved_offset);
                 emit_label(opcode);
-                if (loader_ctx->dynamic_offset > loader_ctx->max_dynamic_offset)
-                    loader_ctx->max_dynamic_offset = loader_ctx->dynamic_offset;
             }
             loader_ctx->frame_offset_bottom[i] = preserved_offset;
         }
@@ -3116,12 +3127,14 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
 
     if (type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32) {
         ctx->frame_offset -= 1;
-        if (*(ctx->frame_offset) > ctx->start_dynamic_offset)
+        if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
+            && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
             ctx->dynamic_offset -= 1;
     }
     else {
         ctx->frame_offset -= 2;
-        if (*(ctx->frame_offset) > ctx->start_dynamic_offset)
+        if ((*(ctx->frame_offset) > ctx->start_dynamic_offset)
+            && (*(ctx->frame_offset) < ctx->max_dynamic_offset))
             ctx->dynamic_offset -= 2;
     }
     emit_operand(ctx, *(ctx->frame_offset));
@@ -4682,7 +4695,7 @@ handle_next_reachable_block:
         }
     }
 
-    func->max_stack_cell_num = loader_ctx->max_dynamic_offset -
+    func->max_stack_cell_num = loader_ctx->preserved_local_offset -
                                     loader_ctx->start_dynamic_offset + 1;
 #else
     func->max_stack_cell_num = loader_ctx->max_stack_cell_num;

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

@@ -1166,3 +1166,42 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
 #endif /* end of WASM_ENABLE_MEMORY_GROW */
 }
 
+
+bool
+wasm_call_indirect(WASMExecEnv *exec_env,
+                   uint32_t element_indices,
+                   uint32_t argc, uint32_t argv[])
+{
+    WASMModuleInstance *module_inst = NULL;
+    WASMTableInstance *table_inst = NULL;
+    uint32_t function_indices = 0;
+    WASMFunctionInstance *function_inst = NULL;
+
+    module_inst =
+        (WASMModuleInstance*)exec_env->module_inst;
+    bh_assert(module_inst);
+
+    table_inst = module_inst->default_table;
+    if (!table_inst) {
+        wasm_set_exception(module_inst, "there is no table");
+        goto got_exception;
+    }
+
+    if (element_indices >= table_inst->cur_size) {
+        wasm_set_exception(module_inst, "undefined element");
+        goto got_exception;
+    }
+
+    function_indices = ((uint32_t*)table_inst->base_addr)[element_indices];
+    if (function_indices == 0xFFFFFFFF) {
+        wasm_set_exception(module_inst, "uninitialized element");
+        goto got_exception;
+    }
+
+    function_inst = module_inst->functions + function_indices;
+    wasm_interp_call_wasm(module_inst, exec_env, function_inst, argc, argv);
+    return !wasm_get_exception(module_inst) ? true : false;
+
+got_exception:
+    return false;
+}

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

@@ -280,6 +280,11 @@ wasm_get_native_addr_range(WASMModuleInstance *module_inst,
 bool
 wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count);
 
+bool
+wasm_call_indirect(WASMExecEnv *exec_env,
+                   uint32_t element_indices,
+                   uint32_t argc, uint32_t argv[]);
+
 #ifdef __cplusplus
 }
 #endif

+ 23 - 2
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c

@@ -1908,6 +1908,21 @@ __wasi_errno_t wasmtime_ssp_path_open(
     close(nfd);
     return error;
   }
+
+  {
+    struct stat sb;
+
+    if (fstat(nfd, &sb) < 0) {
+      close(nfd);
+      return convert_errno(errno);
+    }
+
+    if (S_ISDIR(sb.st_mode))
+      rights_base |= RIGHTS_DIRECTORY_BASE;
+    else if (S_ISREG(sb.st_mode))
+      rights_base |= RIGHTS_REGULAR_FILE_BASE;
+  }
+
   return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base,
                             rights_inheriting & max_inheriting, fd);
 }
@@ -2273,8 +2288,14 @@ __wasi_errno_t wasmtime_ssp_path_filestat_set_times(
     __wasi_timestamp_t st_mtim,
     __wasi_fstflags_t fstflags
 ) {
-  if ((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW |
-                    __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) != 0)
+  if (((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW |
+                     __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) != 0)
+      /* ATIM & ATIM_NOW can't be set at the same time */
+      || ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0
+          && (fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0)
+      /* MTIM & MTIM_NOW can't be set at the same time */
+      || ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0
+          && (fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0))
     return __WASI_EINVAL;
 
   struct path_access pa;

+ 2 - 2
core/shared/platform/zephyr/zephyr_thread.c

@@ -325,7 +325,7 @@ int os_thread_join(korp_tid thread, void **value_ptr)
     k_sem_take(&node->sem, K_FOREVER);
 
     /* Wait some time for the thread to be actually terminated */
-    k_sleep(100);
+    k_sleep(Z_TIMEOUT_MS(100));
 
     /* Destroy resource */
     BH_FREE(node);
@@ -399,7 +399,7 @@ static int os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex,
 
     /* Unlock mutex, wait sem and lock mutex again */
     k_mutex_unlock(mutex);
-    k_sem_take(&node->sem, timed ? mills : K_FOREVER);
+    k_sem_take(&node->sem, timed ? Z_TIMEOUT_MS(mills) : K_FOREVER);
     k_mutex_lock(mutex, K_FOREVER);
 
     /* Remove wait node from wait list */

+ 2 - 13
doc/build_wamr.md

@@ -218,22 +218,11 @@ cp -a <wamr_root_dir>/product-mini/platforms/zephyr/simple .
 cd simple
 ln -s <wamr_root_dir> wamr
 source ../../zephyr-env.sh
+# Execute the ./build_and_run.sh script with board name as parameter. Here take x86 as example:
+./build_and_run.sh x86
 
 ```
 
-1. build for x86 (qemu_x86_nommu)
-``` Bash
-./build.sh x86
-```
-2. build for ARM (nucleo_f767zi)
-``` Bash
-./build.sh stm32
-```
-3. build for AArch64 (qemu_cortex_a53)
-``` Bash
-./build.sh qemu_cortex_a53
-```
-
 Note:
 WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in Zephyr, interpreter, AoT and builtin libc are enabled by default.
 

+ 0 - 62
product-mini/platforms/zephyr/simple/build.sh

@@ -1,62 +0,0 @@
-#!/bin/bash
-
-# Copyright (C) 2019 Intel Corporation.  All rights reserved.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-X86_TARGET="x86"
-STM32_TARGET="stm32"
-QEMU_CORTEX_A53="qemu_cortex_a53"
-XTENSA_QEMU_TARGET="xtensa-qemu"
-ESP32_TARGET="esp32"
-
-if [ $# != 1 ] ; then
-        echo "USAGE:"
-        echo "$0 $X86_TARGET|$STM32_TARGET|$QEMU_CORTEX_A53|$XTENSA_QEMU_TARGET|$ESP32_TARGET"
-        echo "Example:"
-        echo "        $0 $X86_TARGET"
-        echo "        $0 $STM32_TARGET"
-        echo "        $0 $QEMU_CORTEX_A53"
-        echo "        $0 $XTENSA_QEMU_TARGET"
-        echo "        $0 $ESP32_TARGET"
-        exit 1
-fi
-
-TARGET=$1
-
-if [ "$TARGET" = "$X86_TARGET" ] ; then
-        cp prj_qemu_x86_nommu.conf prj.conf
-        rm -fr build && mkdir build && cd build
-        cmake -GNinja -DBOARD=qemu_x86_nommu -DWAMR_BUILD_TARGET=X86_32 ..
-        ninja
-        ninja run
-elif [ "$TARGET" = "$STM32_TARGET" ] ; then
-        cp prj_nucleo767zi.conf prj.conf
-        rm -fr build && mkdir build && cd build
-        cmake -GNinja -DBOARD=nucleo_f767zi -DWAMR_BUILD_TARGET=THUMBV7 ..
-        ninja
-        ninja flash
-elif [ "$TARGET" = "$XTENSA_QEMU_TARGET" ] ; then
-        cp prj_qemu_xtensa.conf prj.conf
-        rm -fr build && mkdir build && cd build
-        cmake -GNinja -DBOARD=qemu_xtensa -DWAMR_BUILD_TARGET=XTENSA ..
-        ninja
-        ninja run
-elif [ "$TARGET" = "$ESP32_TARGET" ] ; then
-        # suppose you have set environment variable ESP_IDF_PATH
-        west build -b esp32 . -p always -- \
-                -DESP_IDF_PATH=$ESP_IDF_PATH \
-                -DCONF_FILE=prj_esp32.conf \
-                -DWAMR_BUILD_TARGET=XTENSA
-        # suppose the serial port is /dev/ttyUSB1 and you should change to
-        # the real name accordingly
-        west flash -d ./build --skip-rebuild --esp-device /dev/ttyUSB1
-elif [ "$TARGET" = "$QEMU_CORTEX_A53" ] ; then
-        cp prj_qemu_cortex_a53.conf prj.conf
-        rm -fr build && mkdir build && cd build
-        cmake -GNinja -DBOARD=qemu_cortex_a53 -DWAMR_BUILD_TARGET=AARCH64 ..
-        ninja
-        ninja run
-else
-        echo "unsupported target: $TARGET"
-        exit 1
-fi

+ 77 - 0
product-mini/platforms/zephyr/simple/build_and_run.sh

@@ -0,0 +1,77 @@
+#!/bin/bash
+
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+X86_TARGET="x86"
+STM32_TARGET="stm32"
+QEMU_CORTEX_A53="qemu_cortex_a53"
+XTENSA_QEMU_TARGET="xtensa-qemu"
+ESP32_TARGET="esp32"
+
+usage ()
+{
+        echo "USAGE:"
+        echo "$0 $X86_TARGET|$STM32_TARGET|$QEMU_CORTEX_A53|$XTENSA_QEMU_TARGET|$ESP32_TARGET"
+        echo "Example:"
+        echo "        $0 $X86_TARGET"
+        echo "        $0 $STM32_TARGET"
+        echo "        $0 $QEMU_CORTEX_A53"
+        echo "        $0 $XTENSA_QEMU_TARGET"
+        echo "        $0 $ESP32_TARGET"
+        exit 1
+}
+
+if [ $# != 1 ] ; then
+        usage
+fi
+
+TARGET=$1
+
+case $TARGET in
+        $X86_TARGET)
+                west build -b qemu_x86_nommu \
+                           . -p always -- \
+                           -DCONF_FILE=prj_qemu_x86_nommu.conf \
+                           -DWAMR_BUILD_TARGET=X86_32
+                west build -t run
+                ;;
+        $STM32_TARGET)
+                west build -b nucleo_f767zi \
+                           . -p always -- \
+                           -DCONF_FILE=prj_nucleo767zi.conf \
+                           -DWAMR_BUILD_TARGET=THUMBV7
+                west flash
+                ;;
+        $XTENSA_QEMU_TARGET)
+                west build -b qemu_xtensa \
+                           . -p always -- \
+                           -DCONF_FILE=prj_qemu_xtensa.conf \
+                           -DWAMR_BUILD_TARGET=XTENSA
+                west build -t run
+                ;;
+        $ESP32_TARGET)
+                # suppose you have set environment variable ESP_IDF_PATH
+                west build -b esp32 \
+                           . -p always -- \
+                           -DESP_IDF_PATH=$ESP_IDF_PATH \
+                           -DCONF_FILE=prj_esp32.conf \
+                           -DWAMR_BUILD_TARGET=XTENSA
+                # suppose the serial port is /dev/ttyUSB1 and you should change to
+                # the real name accordingly
+                west flash --esp-device /dev/ttyUSB1
+                ;;
+        $QEMU_CORTEX_A53)
+                west build -b qemu_cortex_a53 \
+                           . -p always -- \
+                           -DCONF_FILE=prj_qemu_cortex_a53.conf \
+                           -DWAMR_BUILD_TARGET=AARCH64
+                west build -t run
+                ;;
+        *)
+                echo "unsupported target: $TARGET"
+                usage
+                exit 1
+                ;;
+esac
+

+ 1 - 0
samples/basic/.gitignore

@@ -0,0 +1 @@
+/out/

+ 1 - 0
samples/basic/build.sh

@@ -44,6 +44,7 @@ OUT_FILE=${i%.*}.wasm
         -Wl,--no-threads,--strip-all,--no-entry -nostdlib \
         -Wl,--export=generate_float \
         -Wl,--export=float_to_string \
+        -Wl,--export=calculate\
         -Wl,--allow-undefined \
         -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC}
 

+ 24 - 0
samples/basic/src/main.c

@@ -9,6 +9,7 @@
 
 int intToStr(int x, char* str, int str_len, int digit);
 int get_pow(int x, int y);
+int32_t calculate_native(int32_t n, int32_t func1, int32_t func2);
 
 void print_usage(void)
 {
@@ -75,6 +76,12 @@ int main(int argc, char *argv_main[])
             get_pow, 			// the native function pointer
             "(ii)i",			// the function prototype signature, avoid to use i32
             NULL                // attachment is NULL
+        },
+        {
+            "calculate_native",
+            calculate_native,
+            "(iii)i",
+            NULL
         }
     };
 
@@ -167,6 +174,23 @@ int main(int argc, char *argv_main[])
         goto fail;
     }
 
+    wasm_function_inst_t func3 = wasm_runtime_lookup_function(module_inst,
+                                                              "calculate",
+                                                              NULL);
+    if (!func3) {
+        printf("The wasm function calculate is not found.\n");
+        goto fail;
+    }
+
+    uint32_t argv3[1] = {3};
+    if (wasm_runtime_call_wasm(exec_env, func3, 1, argv3)) {
+        uint32_t result = *(uint32_t*)argv3;
+        printf("Native finished calling wasm function: calculate, return: %d\n", result);
+    } else {
+        printf("call wasm function calculate failed. error: %s\n", wasm_runtime_get_exception(module_inst));
+        goto fail;
+    }
+
 fail:
     if(exec_env) wasm_runtime_destroy_exec_env(exec_env);
     if(module_inst) {

+ 31 - 0
samples/basic/src/native_impl.c

@@ -7,6 +7,11 @@
 #include "wasm_export.h"
 #include "math.h"
 
+extern bool
+wasm_runtime_call_indirect(wasm_exec_env_t exec_env,
+                           uint32_t element_indices,
+                           uint32_t argc, uint32_t argv[]);
+
 // The first parameter is not exec_env because it is invoked by native funtions
 void reverse(char * str, int len)
 {
@@ -63,3 +68,29 @@ int get_pow(wasm_exec_env_t exec_env, int x, int y) {
     printf ("calling into native function: %s\n", __FUNCTION__);
     return (int)pow(x, y);
 }
+
+int32_t
+calculate_native(wasm_exec_env_t exec_env, int32_t n, int32_t func1,
+                 int32_t func2)
+{
+    printf("calling into native function: %s, n=%d, func1=%d, func2=%d\n",
+           __FUNCTION__, n, func1, func2);
+
+    uint32_t argv[] = { n };
+    if (!wasm_runtime_call_indirect(exec_env, func1, 1, argv)) {
+        printf("call func1 failed\n");
+        return 0xDEAD;
+    }
+
+    uint32_t n1 = argv[0];
+    printf("call func1 and return n1=%d\n", n1);
+
+    if (!wasm_runtime_call_indirect(exec_env, func2, 1, argv)) {
+        printf("call func2 failed\n");
+        return 0xDEAD;
+    }
+
+    uint32_t n2 = argv[0];
+    printf("call func2 and return n2=%d\n", n2);
+    return n1 + n2;
+}

+ 26 - 0
samples/basic/wasm-apps/testapp.c

@@ -6,9 +6,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h>
 
 int intToStr(int x, char* str, int str_len, int digit);
 int get_pow(int x, int y);
+int32_t calculate_native(int32_t n, int32_t func1, int32_t func2);
 
 //
 // Primitive parameters functions
@@ -54,3 +56,27 @@ void float_to_string(float n, char* res, int res_size, int afterpoint)
         intToStr((int)fpart, res + i + 1, sizeof(res + i + 1), afterpoint);
     }
 }
+
+int32_t mul7(int32_t n)
+{
+    printf ("calling into WASM function: %s,", __FUNCTION__);
+    n = n * 7;
+    printf ("    %s return %d \n", __FUNCTION__, n);
+    return n;
+}
+
+int32_t mul5(int32_t n)
+{
+    printf ("calling into WASM function: %s,", __FUNCTION__);
+    n = n * 5;
+    printf ("    %s return %d \n", __FUNCTION__, n);
+    return n;
+}
+
+int32_t calculate(int32_t n)
+{
+    printf ("calling into WASM function: %s\n", __FUNCTION__);
+    int32_t (*f1)(int32_t) = &mul5;
+    int32_t (*f2)(int32_t) = &mul7;
+    return calculate_native(n, (uint32_t)f1, (uint32_t)f2);
+}

+ 1 - 0
samples/simple/.gitignore

@@ -0,0 +1 @@
+/out