From 79b27c193461db91e00d5a9688c5697bb5334a8d Mon Sep 17 00:00:00 2001 From: dongsheng28849455 <68947925+dongsheng28849455@users.noreply.github.com> Date: Thu, 28 Sep 2023 08:56:11 +0800 Subject: [PATCH 01/17] Support muti-module for AOT mode (#2482) Support muti-module for AOT mode, currently only implement the multi-module's function import feature for AOT, the memory/table/ global import are not implemented yet. And update wamr-test-suites scripts, multi-module sample and some CIs accordingly. --- .../compilation_on_android_ubuntu.yml | 33 +- .github/workflows/compilation_on_macos.yml | 4 +- .github/workflows/nightly_run.yml | 35 +- core/iwasm/aot/aot_loader.c | 110 ++++- core/iwasm/aot/aot_runtime.c | 89 +++- core/iwasm/aot/aot_runtime.h | 14 + core/iwasm/common/wasm_runtime_common.c | 379 +++++++++++++++++- core/iwasm/common/wasm_runtime_common.h | 32 ++ core/iwasm/include/wasm_export.h | 2 +- core/iwasm/interpreter/wasm_loader.c | 198 +-------- core/iwasm/interpreter/wasm_runtime.c | 88 +--- core/iwasm/interpreter/wasm_runtime.h | 6 +- product-mini/platforms/posix/main.c | 23 +- product-mini/platforms/windows/main.c | 27 +- samples/multi-module/CMakeLists.txt | 45 ++- samples/multi-module/README.md | 20 + samples/multi-module/src/main.c | 64 +-- .../muti_module_aot_ignore_cases.patch | 174 ++++++++ .../spec-test-script/runtest.py | 11 + tests/wamr-test-suites/test_wamr.sh | 7 +- 20 files changed, 1018 insertions(+), 343 deletions(-) create mode 100644 samples/multi-module/README.md create mode 100644 tests/wamr-test-suites/spec-test-script/muti_module_aot_ignore_cases.patch diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index 927ef4d75..3c5b4e35e 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -328,7 +328,12 @@ jobs: working-directory: samples/wasm-c-api build_samples_others: - needs: [build_iwasm] + needs: + [ + build_iwasm, + build_llvm_libraries_on_ubuntu_2204, + build_wamrc, + ] runs-on: ${{ matrix.os }} strategy: matrix: @@ -341,6 +346,9 @@ jobs: [ "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz", ] + include: + - os: ubuntu-22.04 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout uses: actions/checkout@v3 @@ -358,7 +366,23 @@ jobs: sudo wget ${{ matrix.wabt_release }} sudo tar -xzf wabt-1.0.31-*.tar.gz sudo mv wabt-1.0.31 wabt - + - name: Get LLVM libraries + id: retrieve_llvm_libs + uses: actions/cache@v3 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: ${{ matrix.llvm_cache_key }} + - name: Build wamrc + run: | + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + working-directory: wamr-compiler - name: Build Sample [basic] run: | cd samples/basic @@ -385,9 +409,10 @@ jobs: run: | cd samples/multi-module mkdir build && cd build - cmake .. + cmake .. -DWAMR_BUILD_AOT=1 cmake --build . --config Release --parallel 4 - ./multi_module + ./multi_module mC.wasm + ./multi_module mC.aot - name: Build Sample [spawn-thread] run: | diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml index aaa97d038..f06833185 100644 --- a/.github/workflows/compilation_on_macos.yml +++ b/.github/workflows/compilation_on_macos.yml @@ -245,7 +245,7 @@ jobs: working-directory: samples/wasm-c-api build_samples_others: - needs: [build_iwasm] + needs: [build_iwasm, build_wamrc] runs-on: ${{ matrix.os }} strategy: matrix: @@ -304,7 +304,7 @@ jobs: mkdir build && cd build cmake .. cmake --build . --config Release --parallel 4 - ./multi_module + ./multi_module mC.wasm - name: Build Sample [spawn-thread] run: | diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index adedd1ef7..1cf4b51e3 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -380,7 +380,12 @@ jobs: working-directory: samples/wasm-c-api build_samples_others: - needs: [build_iwasm] + needs: + [ + build_iwasm, + build_llvm_libraries_on_ubuntu_2004, + build_wamrc, + ] runs-on: ${{ matrix.os }} strategy: matrix: @@ -393,6 +398,9 @@ jobs: [ "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz", ] + include: + - os: ubuntu-20.04 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} steps: - name: checkout uses: actions/checkout@v3 @@ -409,6 +417,26 @@ jobs: sudo wget ${{ matrix.wabt_release }} sudo tar -xzf wabt-1.0.31-*.tar.gz sudo mv wabt-1.0.31 wabt + + - name: Get LLVM libraries + id: retrieve_llvm_libs + uses: actions/cache@v3 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: ${{ matrix.llvm_cache_key }} + + - name: Build wamrc + run: | + mkdir build && cd build + cmake -D WAMR_BUILD_SANITIZER="${{matrix.sanitizer}}" .. + cmake --build . --config Release --parallel 4 + working-directory: wamr-compiler + - name: Build Sample [basic] run: | cd samples/basic @@ -432,9 +460,10 @@ jobs: run: | cd samples/multi-module mkdir build && cd build - cmake .. + cmake .. -DWAMR_BUILD_AOT=1 cmake --build . --config Release --parallel 4 - ./multi_module + ./multi_module mC.wasm + ./multi_module mC.aot - name: Build Sample [spawn-thread] run: | cd samples/spawn-thread diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 0ce2cf9da..b5fa33c0c 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -558,6 +558,56 @@ str2uint32(const char *buf, uint32 *p_res); static bool str2uint64(const char *buf, uint64 *p_res); +#if WASM_ENABLE_MULTI_MODULE != 0 +static void * +aot_loader_resolve_function(const char *module_name, const char *function_name, + const AOTFuncType *expected_function_type, + char *error_buf, uint32 error_buf_size) +{ + WASMModuleCommon *module_reg; + void *function = NULL; + AOTExport *export = NULL; + AOTModule *module = NULL; + AOTFuncType *target_function_type = NULL; + + module_reg = wasm_runtime_find_module_registered(module_name); + if (!module_reg || module_reg->module_type != Wasm_Module_AoT) { + LOG_DEBUG("can not find a module named %s for function %s", module_name, + function_name); + set_error_buf(error_buf, error_buf_size, "unknown import"); + return NULL; + } + + module = (AOTModule *)module_reg; + export = loader_find_export(module_reg, module_name, function_name, + EXPORT_KIND_FUNC, error_buf, error_buf_size); + if (!export) { + return NULL; + } + + /* resolve function type and function */ + if (export->index < module->import_func_count) { + target_function_type = module->import_funcs[export->index].func_type; + function = module->import_funcs[export->index].func_ptr_linked; + } + else { + target_function_type = + module->func_types[module->func_type_indexes + [export->index - module->import_func_count]]; + function = + (module->func_ptrs[export->index - module->import_func_count]); + } + /* check function type */ + if (!wasm_type_equal(expected_function_type, target_function_type)) { + LOG_DEBUG("%s.%s failed the type check", module_name, function_name); + set_error_buf(error_buf, error_buf_size, "incompatible import type"); + return NULL; + } + return function; +} + +#endif /* end of WASM_ENABLE_MULTI_MODULE */ + static bool load_native_symbol_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, bool is_load_from_file_buf, @@ -1357,11 +1407,16 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, bool is_load_from_file_buf, char *error_buf, uint32 error_buf_size) { - const char *module_name, *field_name; + char *module_name, *field_name; const uint8 *buf = *p_buf; AOTImportFunc *import_funcs; uint64 size; uint32 i; +#if WASM_ENABLE_MULTI_MODULE != 0 + AOTModule *sub_module = NULL; + AOTFunc *linked_func = NULL; + WASMType *declare_func_type = NULL; +#endif /* Allocate memory */ size = sizeof(AOTImportFunc) * (uint64)module->import_func_count; @@ -1377,17 +1432,46 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, set_error_buf(error_buf, error_buf_size, "unknown type"); return false; } + +#if WASM_ENABLE_MULTI_MODULE != 0 + declare_func_type = module->func_types[import_funcs[i].func_type_index]; + read_string(buf, buf_end, module_name); + read_string(buf, buf_end, field_name); + + import_funcs[i].module_name = module_name; + import_funcs[i].func_name = field_name; + linked_func = wasm_native_resolve_symbol( + module_name, field_name, declare_func_type, + &import_funcs[i].signature, &import_funcs[i].attachment, + &import_funcs[i].call_conv_raw); + if (!linked_func) { + if (!wasm_runtime_is_built_in_module(module_name)) { + sub_module = (AOTModule *)wasm_runtime_load_depended_module( + (WASMModuleCommon *)module, module_name, error_buf, + error_buf_size); + if (!sub_module) { + return false; + } + } + linked_func = aot_loader_resolve_function( + module_name, field_name, declare_func_type, error_buf, + error_buf_size); + } + import_funcs[i].func_ptr_linked = linked_func; + import_funcs[i].func_type = declare_func_type; + +#else import_funcs[i].func_type = module->func_types[import_funcs[i].func_type_index]; read_string(buf, buf_end, import_funcs[i].module_name); read_string(buf, buf_end, import_funcs[i].func_name); - module_name = import_funcs[i].module_name; field_name = import_funcs[i].func_name; import_funcs[i].func_ptr_linked = wasm_native_resolve_symbol( module_name, field_name, import_funcs[i].func_type, &import_funcs[i].signature, &import_funcs[i].attachment, &import_funcs[i].call_conv_raw); +#endif #if WASM_ENABLE_LIBC_WASI != 0 if (!strcmp(import_funcs[i].module_name, "wasi_unstable") @@ -2872,12 +2956,17 @@ create_module(char *error_buf, uint32 error_buf_size) AOTModule *module = loader_malloc(sizeof(AOTModule), error_buf, error_buf_size); + bh_list_status ret; if (!module) { return NULL; } - module->module_type = Wasm_Module_AoT; - +#if WASM_ENABLE_MULTI_MODULE != 0 + module->import_module_list = &module->import_module_list_head; + ret = bh_list_init(module->import_module_list); + bh_assert(ret == BH_LIST_SUCCESS); +#endif + (void)ret; return module; } @@ -3201,6 +3290,19 @@ aot_unload(AOTModule *module) if (module->const_str_set) bh_hash_map_destroy(module->const_str_set); +#if WASM_ENABLE_MULTI_MODULE != 0 + /* just release the sub module list */ + if (module->import_module_list) { + WASMRegisteredModule *node = + bh_list_first_elem(module->import_module_list); + while (node) { + WASMRegisteredModule *next = bh_list_elem_next(node); + bh_list_remove(module->import_module_list, node); + wasm_runtime_free(node); + node = next; + } + } +#endif if (module->code && !module->is_indirect_mode) { /* The layout is: literal size + literal + code (with plt table) */ diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 55cf2d985..abd4539be 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1091,6 +1091,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, uint8 *p; uint32 i, extra_info_offset; const bool is_sub_inst = parent != NULL; +#if WASM_ENABLE_MULTI_MODULE != 0 + bool ret = false; +#endif /* Check heap size */ heap_size = align_uint(heap_size, 8); @@ -1134,6 +1137,18 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, module_inst->e = (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset); +#if WASM_ENABLE_MULTI_MODULE != 0 + ((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list = + &((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list_head; + ret = wasm_runtime_sub_module_instantiate( + (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst, + stack_size, heap_size, error_buf, error_buf_size); + if (!ret) { + LOG_DEBUG("build a sub module list failed"); + goto fail; + } +#endif + /* Initialize global info */ p = (uint8 *)module_inst + module_inst_struct_size + module_inst_mem_inst_size; @@ -1256,6 +1271,11 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) } #endif +#if WASM_ENABLE_MULTI_MODULE != 0 + wasm_runtime_sub_module_deinstantiate( + (WASMModuleInstanceCommon *)module_inst); +#endif + if (module_inst->tables) wasm_runtime_free(module_inst->tables); @@ -1411,10 +1431,43 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, unsigned argc, uint32 argv[]) { AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; - AOTFuncType *func_type = function->u.func.func_type; + AOTFuncType *func_type = function->is_import_func + ? function->u.func_import->func_type + : function->u.func.func_type; uint32 result_count = func_type->result_count; uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0; bool ret; + void *func_ptr = function->is_import_func + ? function->u.func_import->func_ptr_linked + : function->u.func.func_ptr; +#if WASM_ENABLE_MULTI_MODULE != 0 + bh_list *sub_module_list_node = NULL; + const char *sub_inst_name = NULL; + const char *func_name = function->u.func_import->module_name; + if (function->is_import_func) { + sub_module_list_node = + ((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list; + sub_module_list_node = bh_list_first_elem(sub_module_list_node); + while (sub_module_list_node) { + sub_inst_name = + ((AOTSubModInstNode *)sub_module_list_node)->module_name; + if (strcmp(sub_inst_name, func_name) == 0) { + exec_env = wasm_runtime_get_exec_env_singleton( + (WASMModuleInstanceCommon *)((AOTSubModInstNode *) + sub_module_list_node) + ->module_inst); + module_inst = (AOTModuleInstance *)exec_env->module_inst; + break; + } + sub_module_list_node = bh_list_elem_next(sub_module_list_node); + } + if (exec_env == NULL) { + wasm_runtime_set_exception((WASMModuleInstanceCommon *)module_inst, + "create singleton exec_env failed"); + return false; + } + } +#endif if (argc < func_type->param_cell_num) { char buf[108]; @@ -1436,8 +1489,7 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, #endif /* func pointer was looked up previously */ - bh_assert(function->u.func.func_ptr != NULL); - + bh_assert(func_ptr != NULL); /* set thread handle and stack boundary */ wasm_exec_env_set_thread_info(exec_env); @@ -1546,8 +1598,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, } #endif - ret = invoke_native_internal(exec_env, function->u.func.func_ptr, - func_type, NULL, NULL, argv, argc, argv); + ret = invoke_native_internal(exec_env, func_ptr, func_type, NULL, NULL, + argv, argc, argv); #if WASM_ENABLE_DUMP_CALL_STACK != 0 if (aot_copy_exception(module_inst, NULL)) { @@ -1939,7 +1991,10 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, void *attachment; char buf[96]; bool ret = false; - +#if WASM_ENABLE_MULTI_MODULE != 0 + bh_list *sub_module_list_node = NULL; + const char *sub_inst_name = NULL; +#endif bh_assert(func_idx < aot_module->import_func_count); import_func = aot_module->import_funcs + func_idx; @@ -1963,6 +2018,28 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, } else if (!import_func->call_conv_raw) { signature = import_func->signature; +#if WASM_ENABLE_MULTI_MODULE != 0 + sub_module_list_node = + ((AOTModuleInstanceExtra *)module_inst->e)->sub_module_inst_list; + sub_module_list_node = bh_list_first_elem(sub_module_list_node); + while (sub_module_list_node) { + sub_inst_name = + ((AOTSubModInstNode *)sub_module_list_node)->module_name; + if (strcmp(sub_inst_name, import_func->module_name) == 0) { + exec_env = wasm_runtime_get_exec_env_singleton( + (WASMModuleInstanceCommon *)((AOTSubModInstNode *) + sub_module_list_node) + ->module_inst); + break; + } + sub_module_list_node = bh_list_elem_next(sub_module_list_node); + } + if (exec_env == NULL) { + wasm_runtime_set_exception((WASMModuleInstanceCommon *)module_inst, + "create singleton exec_env failed"); + goto fail; + } +#endif ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature, attachment, argv, argc, argv); diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 4358e3079..35c78bfa0 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -90,6 +90,10 @@ typedef struct AOTFunctionInstance { typedef struct AOTModuleInstanceExtra { DefPointer(const uint32 *, stack_sizes); WASMModuleInstanceExtraCommon common; +#if WASM_ENABLE_MULTI_MODULE != 0 + bh_list sub_module_inst_list_head; + bh_list *sub_module_inst_list; +#endif } AOTModuleInstanceExtra; #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) @@ -229,6 +233,12 @@ typedef struct AOTModule { WASIArguments wasi_args; bool import_wasi_api; #endif + +#if WASM_ENABLE_MULTI_MODULE != 0 + /* TODO: add mutex for mutli-thread? */ + bh_list import_module_list_head; + bh_list *import_module_list; +#endif #if WASM_ENABLE_DEBUG_AOT != 0 void *elf_hdr; uint32 elf_size; @@ -247,6 +257,10 @@ typedef struct AOTModule { #define AOTTableInstance WASMTableInstance #define AOTModuleInstance WASMModuleInstance +#if WASM_ENABLE_MULTI_MODULE != 0 +#define AOTSubModInstNode WASMSubModInstNode +#endif + /* Target info, read from ELF header of object file */ typedef struct AOTTargetInfo { /* Binary type, elf32l/elf32b/elf64l/elf64b */ diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 353985b13..d5c40d6e9 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -125,6 +125,36 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst, return mem; } +#if WASM_ENABLE_MULTI_MODULE != 0 +/* + TODO: + Let loader_malloc be a general API both for AOT and WASM. +*/ + +#define loader_malloc(size, error_buf, error_buf_size) \ + runtime_malloc(size, NULL, error_buf, error_buf_size) +static void +set_error_buf_v(const WASMModuleCommon *module, char *error_buf, + uint32 error_buf_size, const char *format, ...) +{ + va_list args; + char buf[128]; + if (error_buf != NULL) { + va_start(args, format); + vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + if (module->module_type == Wasm_Module_AoT) { + snprintf(error_buf, error_buf_size, "AOT module load failed: %s", + buf); + } + else if (module->module_type == Wasm_Module_Bytecode) { + snprintf(error_buf, error_buf_size, "WASM module load failed: %s", + buf); + } + } +} +#endif + #if WASM_ENABLE_FAST_JIT != 0 static JitCompOptions jit_options = { 0 }; #endif @@ -1198,27 +1228,34 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf, if (get_package_type(buf, size) == Wasm_Module_Bytecode) { #if WASM_ENABLE_INTERP != 0 module_common = - (WASMModuleCommon *)wasm_load(buf, size, error_buf, error_buf_size); - return register_module_with_null_name(module_common, error_buf, - error_buf_size); + (WASMModuleCommon *)wasm_load(buf, size, +#if WASM_ENABLE_MULTI_MODULE != 0 + true, +#endif + error_buf, error_buf_size); #endif } else if (get_package_type(buf, size) == Wasm_Module_AoT) { #if WASM_ENABLE_AOT != 0 module_common = (WASMModuleCommon *)aot_load_from_aot_file( buf, size, error_buf, error_buf_size); - return register_module_with_null_name(module_common, error_buf, - error_buf_size); #endif } - - if (size < 4) - set_error_buf(error_buf, error_buf_size, - "WASM module load failed: unexpected end"); - else - set_error_buf(error_buf, error_buf_size, - "WASM module load failed: magic header not detected"); - return NULL; + else { + if (size < 4) + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: unexpected end"); + else + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: magic header not detected"); + return NULL; + } + if (!module_common) { + LOG_DEBUG("WASM module load failed"); + return NULL; + } + return register_module_with_null_name(module_common, error_buf, + error_buf_size); } WASMModuleCommon * @@ -1231,6 +1268,10 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, #if WASM_ENABLE_INTERP != 0 module_common = (WASMModuleCommon *)wasm_load_from_sections( section_list, error_buf, error_buf_size); + if (!module_common) { + LOG_DEBUG("WASM module load failed from sections"); + return NULL; + } return register_module_with_null_name(module_common, error_buf, error_buf_size); #endif @@ -1239,6 +1280,10 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, #if WASM_ENABLE_AOT != 0 module_common = (WASMModuleCommon *)aot_load_from_sections( section_list, error_buf, error_buf_size); + if (!module_common) { + LOG_DEBUG("WASM module load failed from sections"); + return NULL; + } return register_module_with_null_name(module_common, error_buf, error_buf_size); #endif @@ -5663,6 +5708,314 @@ wasm_runtime_is_import_global_linked(const char *module_name, #endif } +#if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_MULTI_MODULE != 0 +WASMExport * +loader_find_export(const WASMModuleCommon *module, const char *module_name, + const char *field_name, uint8 export_kind, char *error_buf, + uint32 error_buf_size) +{ + WASMExport *exports = NULL, *result = NULL, *export; + uint32 export_count = 0, i; +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + AOTModule *aot_module = (AOTModule *)module; + exports = (WASMExport *)aot_module->exports; + export_count = aot_module->export_count; + } +#endif +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + WASMModule *wasm_module = (WASMModule *)module; + exports = wasm_module->exports; + export_count = wasm_module->export_count; + } +#endif + for (i = 0, export = exports; i < export_count; ++i, ++export) { + if (export->kind == export_kind && !strcmp(field_name, export->name)) { + result = export; + goto exit; + } + } + if (i == export_count) { + LOG_DEBUG("can not find an export %d named %s in the module %s", + export_kind, field_name, module_name); + set_error_buf(error_buf, error_buf_size, + "unknown import or incompatible import type"); + } +exit: + return result; +} +#endif + +#if WASM_ENABLE_MULTI_MODULE != 0 +WASMModuleCommon * +wasm_runtime_search_sub_module(const WASMModuleCommon *parent_module, + const char *sub_module_name) +{ + WASMRegisteredModule *node = NULL; +#if WASM_ENABLE_AOT != 0 + if (parent_module->module_type == Wasm_Module_AoT) { + node = bh_list_first_elem( + ((AOTModule *)parent_module)->import_module_list); + } +#endif +#if WASM_ENABLE_INTERP != 0 + if (parent_module->module_type == Wasm_Module_Bytecode) { + node = bh_list_first_elem( + ((WASMModule *)parent_module)->import_module_list); + } +#endif + while (node && strcmp(sub_module_name, node->module_name)) { + node = bh_list_elem_next(node); + } + return node ? node->module : NULL; +} + +bool +wasm_runtime_register_sub_module(const WASMModuleCommon *parent_module, + const char *sub_module_name, + WASMModuleCommon *sub_module) +{ + /* register sub_module into its parent sub module list */ + WASMRegisteredModule *node = NULL; + bh_list_status ret; + + if (wasm_runtime_search_sub_module(parent_module, sub_module_name)) { + LOG_DEBUG("%s has been registered in its parent", sub_module_name); + return true; + } + + node = loader_malloc(sizeof(WASMRegisteredModule), NULL, 0); + if (!node) { + return false; + } + + node->module_name = sub_module_name; + node->module = sub_module; +#if WASM_ENABLE_AOT != 0 + if (parent_module->module_type == Wasm_Module_AoT) { + ret = bh_list_insert(((AOTModule *)parent_module)->import_module_list, + node); + } +#endif +#if WASM_ENABLE_INTERP != 0 + if (parent_module->module_type == Wasm_Module_Bytecode) { + ret = bh_list_insert(((WASMModule *)parent_module)->import_module_list, + node); + } +#endif + bh_assert(BH_LIST_SUCCESS == ret); + (void)ret; + return true; +} + +WASMModuleCommon * +wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module, + const char *sub_module_name, char *error_buf, + uint32 error_buf_size) +{ + WASMModuleCommon *sub_module = NULL; + bool ret = false; + uint8 *buffer = NULL; + uint32 buffer_size = 0; + + /* check the registered module list of the parent */ + sub_module = wasm_runtime_search_sub_module(parent_module, sub_module_name); + if (sub_module) { + LOG_DEBUG("%s has been loaded before", sub_module_name); + return sub_module; + } + + /* check the global registered module list */ + sub_module = wasm_runtime_find_module_registered(sub_module_name); + if (sub_module) { + LOG_DEBUG("%s has been loaded", sub_module_name); + goto wasm_runtime_register_sub_module; + } + LOG_VERBOSE("loading %s", sub_module_name); + if (!reader) { + set_error_buf_v(parent_module, error_buf, error_buf_size, + "no sub module reader to load %s", sub_module_name); + return NULL; + } + /* start to maintain a loading module list */ + ret = wasm_runtime_is_loading_module(sub_module_name); + if (ret) { + set_error_buf_v(parent_module, error_buf, error_buf_size, + "found circular dependency on %s", sub_module_name); + return NULL; + } + ret = wasm_runtime_add_loading_module(sub_module_name, error_buf, + error_buf_size); + if (!ret) { + LOG_DEBUG("can not add %s into loading module list\n", sub_module_name); + return NULL; + } + + ret = reader(parent_module->module_type, sub_module_name, &buffer, + &buffer_size); + if (!ret) { + LOG_DEBUG("read the file of %s failed", sub_module_name); + set_error_buf_v(parent_module, error_buf, error_buf_size, + "unknown import", sub_module_name); + goto delete_loading_module; + } + if (get_package_type(buffer, buffer_size) != parent_module->module_type) { + LOG_DEBUG("moudle %s type error", sub_module_name); + goto delete_loading_module; + } + if (get_package_type(buffer, buffer_size) == Wasm_Module_Bytecode) { +#if WASM_ENABLE_INTERP != 0 + sub_module = (WASMModuleCommon *)wasm_load(buffer, buffer_size, false, + error_buf, error_buf_size); +#endif + } + else if (get_package_type(buffer, buffer_size) == Wasm_Module_AoT) { +#if WASM_ENABLE_AOT != 0 + sub_module = (WASMModuleCommon *)aot_load_from_aot_file( + buffer, buffer_size, error_buf, error_buf_size); +#endif + } + if (!sub_module) { + LOG_DEBUG("error: can not load the sub_module %s", sub_module_name); + /* others will be destroyed in runtime_destroy() */ + goto destroy_file_buffer; + } + wasm_runtime_delete_loading_module(sub_module_name); + /* register on a global list */ + ret = wasm_runtime_register_module_internal( + sub_module_name, (WASMModuleCommon *)sub_module, buffer, buffer_size, + error_buf, error_buf_size); + if (!ret) { + LOG_DEBUG("error: can not register module %s globally\n", + sub_module_name); + /* others will be unloaded in runtime_destroy() */ + goto unload_module; + } + + /* register into its parent list */ +wasm_runtime_register_sub_module: + ret = wasm_runtime_register_sub_module(parent_module, sub_module_name, + sub_module); + if (!ret) { + set_error_buf_v(parent_module, error_buf, error_buf_size, + "failed to register sub module %s", sub_module_name); + /* since it is in the global module list, no need to + * unload the module. the runtime_destroy() will do it + */ + return NULL; + } + + return sub_module; + +unload_module: + wasm_runtime_unload(sub_module); + +destroy_file_buffer: + if (destroyer) { + destroyer(buffer, buffer_size); + } + else { + LOG_WARNING("need to release the reading buffer of %s manually", + sub_module_name); + } + +delete_loading_module: + wasm_runtime_delete_loading_module(sub_module_name); + return NULL; +} + +bool +wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, + WASMModuleInstanceCommon *module_inst, + uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size) +{ + bh_list *sub_module_inst_list = NULL; + WASMRegisteredModule *sub_module_list_node = NULL; + +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + sub_module_inst_list = + ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e) + ->sub_module_inst_list; + sub_module_list_node = + bh_list_first_elem(((AOTModule *)module)->import_module_list); + } +#endif +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + sub_module_inst_list = + ((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e) + ->sub_module_inst_list; + sub_module_list_node = + bh_list_first_elem(((WASMModule *)module)->import_module_list); + } +#endif + while (sub_module_list_node) { + WASMSubModInstNode *sub_module_inst_list_node = NULL; + WASMModuleCommon *sub_module = sub_module_list_node->module; + WASMModuleInstanceCommon *sub_module_inst = NULL; + sub_module_inst = wasm_runtime_instantiate_internal( + sub_module, NULL, NULL, stack_size, heap_size, error_buf, + error_buf_size); + if (!sub_module_inst) { + LOG_DEBUG("instantiate %s failed", + sub_module_list_node->module_name); + return false; + } + sub_module_inst_list_node = loader_malloc(sizeof(WASMSubModInstNode), + error_buf, error_buf_size); + if (!sub_module_inst_list_node) { + LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d", + sizeof(WASMSubModInstNode)); + if (sub_module_inst) + wasm_runtime_deinstantiate_internal(sub_module_inst, false); + return false; + } + sub_module_inst_list_node->module_inst = + (WASMModuleInstance *)sub_module_inst; + sub_module_inst_list_node->module_name = + sub_module_list_node->module_name; + bh_list_status ret = + bh_list_insert(sub_module_inst_list, sub_module_inst_list_node); + bh_assert(BH_LIST_SUCCESS == ret); + (void)ret; + sub_module_list_node = bh_list_elem_next(sub_module_list_node); + } + + return true; +} + +void +wasm_runtime_sub_module_deinstantiate(WASMModuleInstanceCommon *module_inst) +{ + bh_list *list = NULL; +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + list = ((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e) + ->sub_module_inst_list; + } +#endif +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + list = + ((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e) + ->sub_module_inst_list; + } +#endif + + WASMSubModInstNode *node = bh_list_first_elem(list); + while (node) { + WASMSubModInstNode *next_node = bh_list_elem_next(node); + bh_list_remove(list, node); + wasm_runtime_deinstantiate_internal( + (WASMModuleInstanceCommon *)node->module_inst, false); + wasm_runtime_free(node); + node = next_node; + } +} +#endif /* end of WASM_ENABLE_MULTI_MODULE */ #if WASM_ENABLE_MODULE_INST_CONTEXT != 0 void * wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst, diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 19d0af117..a834d67f2 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -788,6 +788,9 @@ wasm_runtime_register_module_internal(const char *module_name, void wasm_runtime_unregister_module(const WASMModuleCommon *module); +WASMModuleCommon * +wasm_runtime_find_module_registered(const char *module_name); + bool wasm_runtime_add_loading_module(const char *module_name, char *error_buf, uint32 error_buf_size); @@ -800,6 +803,35 @@ wasm_runtime_is_loading_module(const char *module_name); void wasm_runtime_destroy_loading_module_list(); + +WASMModuleCommon * +wasm_runtime_search_sub_module(const WASMModuleCommon *parent_module, + const char *sub_module_name); + +bool +wasm_runtime_register_sub_module(const WASMModuleCommon *parent_module, + const char *sub_module_name, + WASMModuleCommon *sub_module); + +WASMModuleCommon * +wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module, + const char *sub_module_name, char *error_buf, + uint32 error_buf_size); + +bool +wasm_runtime_sub_module_instantiate(WASMModuleCommon *module, + WASMModuleInstanceCommon *module_inst, + uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size); +void +wasm_runtime_sub_module_deinstantiate(WASMModuleInstanceCommon *module_inst); +#endif + +#if WASM_ENABLE_LIBC_WASI != 0 || WASM_ENABLE_MULTI_MODULE != 0 +WASMExport * +loader_find_export(const WASMModuleCommon *module, const char *module_name, + const char *field_name, uint8 export_kind, char *error_buf, + uint32 error_buf_size); #endif /* WASM_ENALBE_MULTI_MODULE */ bool diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 48ed55933..2a30ddc93 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -311,7 +311,7 @@ wasm_runtime_is_xip_file(const uint8_t *buf, uint32_t size); /** * Callback to load a module file into a buffer in multi-module feature */ -typedef bool (*module_reader)(const char *module_name, +typedef bool (*module_reader)(package_type_t module_type,const char *module_name, uint8_t **p_buffer, uint32_t *p_size); /** diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 130ad4392..cf8b7719c 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -694,34 +694,10 @@ wasm_loader_find_export(const WASMModule *module, const char *module_name, const char *field_name, uint8 export_kind, char *error_buf, uint32 error_buf_size) { - WASMExport *export; - uint32 i; - - for (i = 0, export = module->exports; i < module->export_count; - ++i, ++export) { - /** - * need to consider a scenario that different kinds of exports - * may have the same name, like - * (table (export "m1" "exported") 10 funcref) - * (memory (export "m1" "exported") 10) - **/ - if (export->kind == export_kind && !strcmp(field_name, export->name)) { - break; - } - } - - if (i == module->export_count) { - LOG_DEBUG("can not find an export %d named %s in the module %s", - export_kind, field_name, module_name); - set_error_buf(error_buf, error_buf_size, - "unknown import or incompatible import type"); - return NULL; - } - - (void)module_name; - - /* since there is a validation in load_export_section(), it is for sure - * export->index is valid*/ + WASMExport *export = + loader_find_export((WASMModuleCommon *)module, module_name, field_name, + export_kind, error_buf, error_buf_size); + ; return export; } #endif @@ -912,152 +888,6 @@ wasm_loader_resolve_global(const char *module_name, const char *global_name, return global; } -static WASMModule * -search_sub_module(const WASMModule *parent_module, const char *sub_module_name) -{ - WASMRegisteredModule *node = - bh_list_first_elem(parent_module->import_module_list); - while (node && strcmp(sub_module_name, node->module_name)) { - node = bh_list_elem_next(node); - } - return node ? (WASMModule *)node->module : NULL; -} - -static bool -register_sub_module(const WASMModule *parent_module, - const char *sub_module_name, WASMModule *sub_module) -{ - /* register sub_module into its parent sub module list */ - WASMRegisteredModule *node = NULL; - bh_list_status ret; - - if (search_sub_module(parent_module, sub_module_name)) { - LOG_DEBUG("%s has been registered in its parent", sub_module_name); - return true; - } - - node = loader_malloc(sizeof(WASMRegisteredModule), NULL, 0); - if (!node) { - return false; - } - - node->module_name = sub_module_name; - node->module = (WASMModuleCommon *)sub_module; - ret = bh_list_insert(parent_module->import_module_list, node); - bh_assert(BH_LIST_SUCCESS == ret); - (void)ret; - return true; -} - -static WASMModule * -load_depended_module(const WASMModule *parent_module, - const char *sub_module_name, char *error_buf, - uint32 error_buf_size) -{ - WASMModule *sub_module = NULL; - bool ret = false; - uint8 *buffer = NULL; - uint32 buffer_size = 0; - const module_reader reader = wasm_runtime_get_module_reader(); - const module_destroyer destroyer = wasm_runtime_get_module_destroyer(); - - /* check the registered module list of the parent */ - sub_module = search_sub_module(parent_module, sub_module_name); - if (sub_module) { - LOG_DEBUG("%s has been loaded before", sub_module_name); - return sub_module; - } - - /* check the global registered module list */ - sub_module = - (WASMModule *)wasm_runtime_find_module_registered(sub_module_name); - if (sub_module) { - LOG_DEBUG("%s has been loaded", sub_module_name); - goto register_sub_module; - } - - LOG_VERBOSE("loading %s", sub_module_name); - - if (!reader) { - set_error_buf_v(error_buf, error_buf_size, - "no sub module reader to load %s", sub_module_name); - return NULL; - } - - /* start to maintain a loading module list */ - ret = wasm_runtime_is_loading_module(sub_module_name); - if (ret) { - set_error_buf_v(error_buf, error_buf_size, - "found circular dependency on %s", sub_module_name); - return NULL; - } - - ret = wasm_runtime_add_loading_module(sub_module_name, error_buf, - error_buf_size); - if (!ret) { - LOG_DEBUG("can not add %s into loading module list\n", sub_module_name); - return NULL; - } - - ret = reader(sub_module_name, &buffer, &buffer_size); - if (!ret) { - LOG_DEBUG("read the file of %s failed", sub_module_name); - set_error_buf_v(error_buf, error_buf_size, "unknown import", - sub_module_name); - goto delete_loading_module; - } - - sub_module = - wasm_loader_load(buffer, buffer_size, false, error_buf, error_buf_size); - if (!sub_module) { - LOG_DEBUG("error: can not load the sub_module %s", sub_module_name); - /* others will be destroyed in runtime_destroy() */ - goto destroy_file_buffer; - } - - wasm_runtime_delete_loading_module(sub_module_name); - - /* register on a global list */ - ret = wasm_runtime_register_module_internal( - sub_module_name, (WASMModuleCommon *)sub_module, buffer, buffer_size, - error_buf, error_buf_size); - if (!ret) { - LOG_DEBUG("error: can not register module %s globally\n", - sub_module_name); - /* others will be unloaded in runtime_destroy() */ - goto unload_module; - } - - /* register into its parent list */ -register_sub_module: - ret = register_sub_module(parent_module, sub_module_name, sub_module); - if (!ret) { - set_error_buf_v(error_buf, error_buf_size, - "failed to register sub module %s", sub_module_name); - /* since it is in the global module list, no need to - * unload the module. the runtime_destroy() will do it - */ - return NULL; - } - - return sub_module; - -unload_module: - wasm_loader_unload(sub_module); - -destroy_file_buffer: - if (destroyer) { - destroyer(buffer, buffer_size); - } - else { - LOG_WARNING("need to release the reading buffer of %s manually", - sub_module_name); - } - -delete_loading_module: - wasm_runtime_delete_loading_module(sub_module_name); - return NULL; -} #endif /* end of WASM_ENABLE_MULTI_MODULE */ static bool @@ -1104,8 +934,9 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end, #if WASM_ENABLE_MULTI_MODULE != 0 else { if (!wasm_runtime_is_built_in_module(sub_module_name)) { - sub_module = load_depended_module(parent_module, sub_module_name, - error_buf, error_buf_size); + sub_module = (WASMModule *)wasm_runtime_load_depended_module( + (WASMModuleCommon *)parent_module, sub_module_name, error_buf, + error_buf_size); if (!sub_module) { return false; } @@ -1193,8 +1024,9 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, #if WASM_ENABLE_MULTI_MODULE != 0 if (!wasm_runtime_is_built_in_module(sub_module_name)) { - sub_module = load_depended_module(parent_module, sub_module_name, - error_buf, error_buf_size); + sub_module = (WASMModule *)wasm_runtime_load_depended_module( + (WASMModuleCommon *)parent_module, sub_module_name, error_buf, + error_buf_size); if (!sub_module) { return false; } @@ -1327,8 +1159,9 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, #if WASM_ENABLE_MULTI_MODULE != 0 if (!wasm_runtime_is_built_in_module(sub_module_name)) { - sub_module = load_depended_module(parent_module, sub_module_name, - error_buf, error_buf_size); + sub_module = (WASMModule *)wasm_runtime_load_depended_module( + (WASMModuleCommon *)parent_module, sub_module_name, error_buf, + error_buf_size); if (!sub_module) { return false; } @@ -1427,8 +1260,9 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, #if WASM_ENABLE_MULTI_MODULE != 0 if (!global->is_linked && !wasm_runtime_is_built_in_module(sub_module_name)) { - sub_module = load_depended_module(parent_module, sub_module_name, - error_buf, error_buf_size); + sub_module = (WASMModule *)wasm_runtime_load_depended_module( + (WASMModuleCommon *)parent_module, sub_module_name, error_buf, + error_buf_size); if (!sub_module) { return false; } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 301038a4d..af2a61c88 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -51,11 +51,15 @@ set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...) } WASMModule * -wasm_load(uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size) +wasm_load(uint8 *buf, uint32 size, +#if WASM_ENABLE_MULTI_MODULE != 0 + bool main_module, +#endif + char *error_buf, uint32 error_buf_size) { return wasm_loader_load(buf, size, #if WASM_ENABLE_MULTI_MODULE != 0 - true, + main_module, #endif error_buf, error_buf_size); } @@ -1265,78 +1269,6 @@ execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, return ret; } -#if WASM_ENABLE_MULTI_MODULE != 0 -static bool -sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst, - uint32 stack_size, uint32 heap_size, char *error_buf, - uint32 error_buf_size) -{ - bh_list *sub_module_inst_list = module_inst->e->sub_module_inst_list; - WASMRegisteredModule *sub_module_list_node = - bh_list_first_elem(module->import_module_list); - - while (sub_module_list_node) { - WASMSubModInstNode *sub_module_inst_list_node = NULL; - WASMModule *sub_module = (WASMModule *)sub_module_list_node->module; - WASMModuleInstance *sub_module_inst = NULL; - - sub_module_inst = - wasm_instantiate(sub_module, NULL, NULL, stack_size, heap_size, - error_buf, error_buf_size); - if (!sub_module_inst) { - LOG_DEBUG("instantiate %s failed", - sub_module_list_node->module_name); - goto failed; - } - - sub_module_inst_list_node = runtime_malloc(sizeof(WASMSubModInstNode), - error_buf, error_buf_size); - if (!sub_module_inst_list_node) { - LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d", - sizeof(WASMSubModInstNode)); - goto failed; - } - - sub_module_inst_list_node->module_inst = sub_module_inst; - sub_module_inst_list_node->module_name = - sub_module_list_node->module_name; - bh_list_status ret = - bh_list_insert(sub_module_inst_list, sub_module_inst_list_node); - bh_assert(BH_LIST_SUCCESS == ret); - (void)ret; - - sub_module_list_node = bh_list_elem_next(sub_module_list_node); - - continue; - failed: - if (sub_module_inst_list_node) { - bh_list_remove(sub_module_inst_list, sub_module_inst_list_node); - wasm_runtime_free(sub_module_inst_list_node); - } - - if (sub_module_inst) - wasm_deinstantiate(sub_module_inst, false); - return false; - } - - return true; -} - -static void -sub_module_deinstantiate(WASMModuleInstance *module_inst) -{ - bh_list *list = module_inst->e->sub_module_inst_list; - WASMSubModInstNode *node = bh_list_first_elem(list); - while (node) { - WASMSubModInstNode *next_node = bh_list_elem_next(node); - bh_list_remove(list, node); - wasm_deinstantiate(node->module_inst, false); - wasm_runtime_free(node); - node = next_node; - } -} -#endif - static bool check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, uint32 error_buf_size) @@ -1713,8 +1645,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, #if WASM_ENABLE_MULTI_MODULE != 0 module_inst->e->sub_module_inst_list = &module_inst->e->sub_module_inst_list_head; - ret = sub_module_instantiate(module, module_inst, stack_size, heap_size, - error_buf, error_buf_size); + ret = wasm_runtime_sub_module_instantiate( + (WASMModuleCommon *)module, (WASMModuleInstanceCommon *)module_inst, + stack_size, heap_size, error_buf, error_buf_size); if (!ret) { LOG_DEBUG("build a sub module list failed"); goto fail; @@ -2197,7 +2130,8 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) #endif #if WASM_ENABLE_MULTI_MODULE != 0 - sub_module_deinstantiate(module_inst); + wasm_runtime_sub_module_deinstantiate( + (WASMModuleInstanceCommon *)module_inst); #endif if (module_inst->memory_count > 0) diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 605cefc6c..d6661fa0f 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -396,7 +396,11 @@ wasm_get_func_code_end(WASMFunctionInstance *func) } WASMModule * -wasm_load(uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size); +wasm_load(uint8 *buf, uint32 size, +#if WASM_ENABLE_MULTI_MODULE != 0 + bool main_module, +#endif + char *error_buf, uint32 error_buf_size); WASMModule * wasm_load_from_sections(WASMSection *section_list, char *error_buf, diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 45237a215..0051e628c 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -420,19 +420,28 @@ handle_module_path(const char *module_path) static char *module_search_path = "."; static bool -module_reader_callback(const char *module_name, uint8 **p_buffer, - uint32 *p_size) +module_reader_callback(package_type_t module_type, const char *module_name, + uint8 **p_buffer, uint32 *p_size) { - const char *format = "%s/%s.wasm"; + char *file_format; +#if WASM_ENABLE_INTERP != 0 + if (module_type == Wasm_Module_Bytecode) + file_format = ".wasm"; +#endif +#if WASM_ENABLE_AOT != 0 + if (module_type == Wasm_Module_AoT) + file_format = ".aot"; + +#endif + const char *format = "%s/%s%s"; int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) - + strlen(".wasm") + 1; + + strlen(file_format) + 1; char *wasm_file_name = BH_MALLOC(sz); if (!wasm_file_name) { return false; } - - snprintf(wasm_file_name, sz, format, module_search_path, module_name); - + snprintf(wasm_file_name, sz, format, module_search_path, module_name, + file_format); *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); wasm_runtime_free(wasm_file_name); diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 8b1b1f371..121be4195 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -204,20 +204,29 @@ handle_module_path(const char *module_path) static char *module_search_path = "."; static bool -module_reader_callback(const char *module_name, uint8 **p_buffer, - uint32 *p_size) +module_reader_callback(package_type_t module_type, const char *module_name, + uint8 **p_buffer, uint32 *p_size) { - const char *format = "%s/%s.wasm"; - uint32 sz = (uint32)(strlen(module_search_path) + strlen("/") - + strlen(module_name) + strlen(".wasm") + 1); + char *file_format; +#if WASM_ENABLE_INTERP != 0 + if (module_type == Wasm_Module_Bytecode) + file_format = ".wasm"; +#endif +#if WASM_ENABLE_AOT != 0 + if (module_type == Wasm_Module_AoT) + file_format = ".aot"; + +#endif + const char *format = "%s/%s%s"; + int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + + strlen(file_format) + 1; char *wasm_file_name = BH_MALLOC(sz); if (!wasm_file_name) { return false; } - - snprintf(wasm_file_name, sz, format, module_search_path, module_name); - - *p_buffer = (uint8 *)bh_read_file_to_buffer(wasm_file_name, p_size); + snprintf(wasm_file_name, sz, format, module_search_path, module_name, + file_format); + *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); wasm_runtime_free(wasm_file_name); return *p_buffer != NULL; diff --git a/samples/multi-module/CMakeLists.txt b/samples/multi-module/CMakeLists.txt index 2769b9779..ee6c98df4 100644 --- a/samples/multi-module/CMakeLists.txt +++ b/samples/multi-module/CMakeLists.txt @@ -43,8 +43,12 @@ if (NOT CMAKE_BUILD_TYPE) endif () set(WAMR_BUILD_INTERP 1) -set(WAMR_BUILD_AOT 0) -set(WAMR_BUILD_JIT 0) +if (NOT DEFINED WAMR_BUILD_AOT) + set(WAMR_BUILD_AOT 0) +endif () +if (NOT DEFINED WAMR_BUILD_JIT) + set(WAMR_BUILD_JIT 0) +endif () set(WAMR_BUILD_LIBC_BUILTIN 1) set(WAMR_BUILD_LIBC_WASI 1) set(WAMR_BUILD_MULTI_MODULE 1) @@ -144,6 +148,43 @@ ExternalProject_Add(WASM_MODULE ./mE.wasm ${CMAKE_BINARY_DIR} ) +################ WASM MODULES TO AOT +if (WAMR_BUILD_AOT EQUAL 1) + set(WAMR_COMPILER_DIR ${CMAKE_CURRENT_LIST_DIR}/../../wamr-compiler/build) + message(CHECK_START "Detecting WAMR_COMPILER at ${WAMR_COMPILER_DIR}") + find_file(WAMR_COMPILER + wamrc + PATHS "${CMAKE_CURRENT_LIST_DIR}/../../wamr-compiler/build" + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH + ) + if(WAMR_COMPILER) + message(CHECK_PASS "found") + else() + message(CHECK_FAIL "not found") + endif() + if((NOT EXISTS ${WAMR_COMPILER}) ) + message(FATAL_ERROR "Please build wamrc under the path=${WAMR_ROOT_DIR}/wamr-compiler/ ") + else() + message(STATUS "WAMR_COMPILER is ${WAMR_COMPILER}") + endif() + + add_custom_target( + wasm_to_aot + ALL + DEPENDS + WASM_MODULE ${WAMR_COMPILER} + COMMAND + ${WAMR_COMPILER} -o mA.aot ./mA.wasm + COMMAND + ${WAMR_COMPILER} -o mB.aot ./mB.wasm + COMMAND + ${WAMR_COMPILER} -o mC.aot ./mC.wasm + WORKING_DIRECTORY + ${CMAKE_BINARY_DIR} + ) +endif() + ################ NATIVE include_directories(${CMAKE_CURRENT_LIST_DIR}/src) include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) diff --git a/samples/multi-module/README.md b/samples/multi-module/README.md new file mode 100644 index 000000000..1ec92620c --- /dev/null +++ b/samples/multi-module/README.md @@ -0,0 +1,20 @@ +# WAMR MULTI-MODUEL SAMPLE +**WAMR supports *multi-module* in both *interpreter* mode and *aot* mode.** + +Multi-modules will determine the running mode based on the type of the main module. + + +``` shell +$ mkdir build +$ cd build +$ cmake .. +$ make +$ # It will build multi-module runtime and +$ # wasm file under the ./build . +$ # If you have built wamrc, +$ # aot file will also genrate. +$ ./multi-module mC.wasm +$ ... +$ ./multi-module mC.aot +$ ... + diff --git a/samples/multi-module/src/main.c b/samples/multi-module/src/main.c index ca95ded5f..361856136 100644 --- a/samples/multi-module/src/main.c +++ b/samples/multi-module/src/main.c @@ -1,59 +1,63 @@ #include #include #include - #include "bh_read_file.h" #include "platform_common.h" #include "wasm_export.h" -static char * -build_module_path(const char *module_name) +#if WASM_ENABLE_MULTI_MODULE != 0 +static char *module_search_path = "."; +static bool +module_reader_callback(package_type_t module_type, const char *module_name, + uint8 **p_buffer, uint32 *p_size) { - const char *module_search_path = "."; - const char *format = "%s/%s.wasm"; + char *file_format; +#if WASM_ENABLE_INTERP != 0 + if (module_type == Wasm_Module_Bytecode) + file_format = ".wasm"; +#endif +#if WASM_ENABLE_AOT != 0 + if (module_type == Wasm_Module_AoT) + file_format = ".aot"; + +#endif + const char *format = "%s/%s%s"; int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) - + strlen(".wasm") + 1; + + strlen(file_format) + 1; char *wasm_file_name = BH_MALLOC(sz); if (!wasm_file_name) { - return NULL; - } - - snprintf(wasm_file_name, sz, format, module_search_path, module_name); - return wasm_file_name; -} - -static bool -module_reader_cb(const char *module_name, uint8 **p_buffer, uint32 *p_size) -{ - char *wasm_file_path = build_module_path(module_name); - if (!wasm_file_path) { return false; } + snprintf(wasm_file_name, sz, format, module_search_path, module_name, + file_format); + *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); - printf("- bh_read_file_to_buffer %s\n", wasm_file_path); - *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_path, p_size); - BH_FREE(wasm_file_path); + wasm_runtime_free(wasm_file_name); return *p_buffer != NULL; } static void -module_destroyer_cb(uint8 *buffer, uint32 size) +moudle_destroyer(uint8 *buffer, uint32 size) { - printf("- release the read file buffer\n"); if (!buffer) { return; } - BH_FREE(buffer); + wasm_runtime_free(buffer); buffer = NULL; } +#endif /* WASM_ENABLE_MULTI_MODULE */ /* 10M */ static char sandbox_memory_space[10 * 1024 * 1024] = { 0 }; int -main() +main(int argc, char *argv[]) { bool ret = false; + if (argc != 2) { + return -1; + } + char *wasm_file = argv[1]; /* 16K */ const uint32 stack_size = 16 * 1024; const uint32 heap_size = 16 * 1024; @@ -84,16 +88,16 @@ main() #if WASM_ENABLE_MULTI_MODULE != 0 printf("- wasm_runtime_set_module_reader\n"); /* set module reader and destroyer */ - wasm_runtime_set_module_reader(module_reader_cb, module_destroyer_cb); + wasm_runtime_set_module_reader(module_reader_callback, moudle_destroyer); #endif /* load WASM byte buffer from WASM bin file */ - if (!module_reader_cb("mC", &file_buf, &file_buf_size)) { + if (!(file_buf = + (uint8 *)bh_read_file_to_buffer(wasm_file, &file_buf_size))) goto RELEASE_RUNTIME; - } - /* load mC and let WAMR load mA and mB */ printf("- wasm_runtime_load\n"); + if (!(module = wasm_runtime_load(file_buf, file_buf_size, error_buf, sizeof(error_buf)))) { printf("%s\n", error_buf); @@ -158,7 +162,7 @@ UNLOAD_MODULE: printf("- wasm_runtime_unload\n"); wasm_runtime_unload(module); RELEASE_BINARY: - module_destroyer_cb(file_buf, file_buf_size); + moudle_destroyer(file_buf, file_buf_size); RELEASE_RUNTIME: printf("- wasm_runtime_destroy\n"); wasm_runtime_destroy(); diff --git a/tests/wamr-test-suites/spec-test-script/muti_module_aot_ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/muti_module_aot_ignore_cases.patch new file mode 100644 index 000000000..4494e0856 --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/muti_module_aot_ignore_cases.patch @@ -0,0 +1,174 @@ +diff --git a/test/core/linking.wast b/test/core/linking.wast +index d0bfb5f..6617945 100644 +--- a/test/core/linking.wast ++++ b/test/core/linking.wast +@@ -35,7 +35,7 @@ + + + ;; Globals +- ++(; + (module $Mg + (global $glob (export "glob") i32 (i32.const 42)) + (func (export "get") (result i32) (global.get $glob)) +@@ -63,7 +63,7 @@ + (export "Mg.get_mut" (func $get_mut)) + (export "Mg.set_mut" (func $set_mut)) + ) +- ++;) + (; + (assert_return (get $Mg "glob") (i32.const 42)) + (assert_return (get $Ng "Mg.glob") (i32.const 42)) +@@ -84,7 +84,7 @@ + (assert_return (invoke $Ng "Mg.get_mut") (i32.const 241)) + ;) + +- ++(; + (assert_unlinkable + (module (import "Mg" "mut_glob" (global i32))) + "incompatible import type" +@@ -166,7 +166,7 @@ + (call_indirect (type 1) (local.get 0)) + ) + ) +- ++;) + (; + (assert_return (invoke $Mt "call" (i32.const 2)) (i32.const 4)) + (assert_return (invoke $Nt "Mt.call" (i32.const 2)) (i32.const 4)) +@@ -191,7 +191,7 @@ + (assert_return (invoke $Nt "call" (i32.const 3)) (i32.const -4)) + (assert_trap (invoke $Nt "call" (i32.const 4)) "indirect call type mismatch") + ;) +- ++(; + (module $Ot + (type (func (result i32))) + +@@ -204,7 +204,7 @@ + (call_indirect (type 0) (local.get 0)) + ) + ) +- ++;) + (; + (assert_return (invoke $Mt "call" (i32.const 3)) (i32.const 4)) + (assert_return (invoke $Nt "Mt.call" (i32.const 3)) (i32.const 4)) +@@ -231,7 +231,7 @@ + + (assert_trap (invoke $Ot "call" (i32.const 20)) "undefined element") + ;) +- ++(; + (module + (table (import "Mt" "tab") 0 funcref) + (elem (i32.const 9) $f) +@@ -266,7 +266,7 @@ + "unknown import" + ) + (assert_trap (invoke $Mt "call" (i32.const 7)) "uninitialized element") +- ++;) + ;; Unlike in the v1 spec, active element segments stored before an + ;; out-of-bounds access persist after the instantiation failure. + (; +@@ -297,7 +297,7 @@ + (assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) + ;) + +- ++(; + (module $Mtable_ex + (table $t1 (export "t-func") 1 funcref) + (table $t2 (export "t-extern") 1 externref) +@@ -308,7 +308,7 @@ + (table (import "Mtable_ex" "t-func") 1 funcref) + (table (import "Mtable_ex" "t-extern") 1 externref) + ) +- ++;) + (; + (assert_unlinkable + (module (table (import "Mtable_ex" "t-func") 1 externref)) +@@ -322,7 +322,7 @@ + + + ;; Memories +- ++(; + (module $Mm + (memory (export "mem") 1 5) + (data (i32.const 10) "\00\01\02\03\04\05\06\07\08\09") +@@ -357,14 +357,14 @@ + (i32.load8_u (local.get 0)) + ) + ) +- ++;) + (; + (assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 0xa7)) + (assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 0xa7)) + (assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) + (assert_return (invoke $Om "load" (i32.const 12)) (i32.const 0xa7)) + ;) +- ++(; + (module + (memory (import "Mm" "mem") 0) + (data (i32.const 0xffff) "a") +@@ -385,7 +385,7 @@ + (memory.grow (local.get 0)) + ) + ) +- ++;) + (; + (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 1)) + (assert_return (invoke $Pm "grow" (i32.const 2)) (i32.const 1)) +@@ -396,7 +396,7 @@ + (assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1)) + (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) + ;) +- ++(; + (assert_unlinkable + (module + (func $host (import "spectest" "print")) +@@ -419,11 +419,12 @@ + ) + "out of bounds memory access" + ) ++;) + (; + (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) + (assert_return (invoke $Mm "load" (i32.const 327670)) (i32.const 0)) + ;) +- ++(; + (assert_trap + (module + (memory (import "Mm" "mem") 1) +@@ -434,10 +435,11 @@ + ) + "out of bounds table access" + ) ++;) + (; + (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) + ;) +- ++(; + ;; Store is modified if the start function traps. + (module $Ms + (type $t (func (result i32))) +@@ -451,7 +453,7 @@ + ) + ) + (register "Ms" $Ms) +- ++;) + (; + (assert_trap + (module diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index a1e505bd0..633a57313 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -1299,6 +1299,16 @@ if __name__ == "__main__": # add new_module copied from the old into temp_file_repo[] temp_file_repo.append(new_module) + + if test_aot: + new_module_aot = os.path.join(tempfile.gettempdir(), name_new + ".aot") + r = compile_wasm_to_aot(new_module, new_module_aot, True, opts, r) + try: + assert_prompt(r, ['Compile success'], opts.start_timeout, True) + except: + raise Exception("compile wasm to aot failed") + # add aot module into temp_file_repo[] + temp_file_repo.append(new_module_aot) else: # there is no name defined in register cmd raise Exception("can not find module name from the register") @@ -1341,3 +1351,4 @@ if __name__ == "__main__": log("Leaving tempfiles: %s" % ([wast_tempfile, wasm_tempfile])) sys.exit(ret_code) + \ No newline at end of file diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 11650651c..1caaa89b0 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -333,6 +333,9 @@ function spec_test() if [[ ${ENABLE_SIMD} == 1 ]]; then git apply ../../spec-test-script/simd_ignore_cases.patch fi + if [[ ${ENABLE_MULTI_MODULE} == 1 && $1 == 'aot' ]]; then + git apply ../../spec-test-script/muti_module_aot_ignore_cases.patch + fi # udpate thread cases if [ ${ENABLE_MULTI_THREAD} == 1 ]; then @@ -424,7 +427,7 @@ function spec_test() # multi-module only enable in interp mode if [[ 1 == ${ENABLE_MULTI_MODULE} ]]; then - if [[ $1 == 'classic-interp' || $1 == 'fast-interp' ]]; then + if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' ]]; then ARGS_FOR_SPEC_TEST+="-M " fi fi @@ -897,4 +900,4 @@ fi echo -e "Test finish. Reports are under ${REPORT_DIR}" DEBUG set +xv pipefail echo "TEST SUCCESSFUL" -exit 0 +exit 0 \ No newline at end of file From cd0cec5bebff3dcca2d2900017bb0f386e488157 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Thu, 28 Sep 2023 09:15:56 +0800 Subject: [PATCH 02/17] Check ValueKind before extracting a constant int value (#2595) Only when the value kind is LLVMConstantIntValueKind and the value is not undef and not poison can we extract the value of a constant int. Fixes #2557 and #2559. --- core/iwasm/compilation/aot_compiler.h | 13 +++++++++++++ core/iwasm/compilation/aot_emit_control.c | 7 ++++--- core/iwasm/compilation/aot_emit_memory.c | 13 +++---------- core/iwasm/compilation/aot_emit_numberic.c | 10 +++++----- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h index 40d79cf86..b6347c89d 100644 --- a/core/iwasm/compilation/aot_compiler.h +++ b/core/iwasm/compilation/aot_compiler.h @@ -363,6 +363,19 @@ check_type_compatible(uint8 src_type, uint8 dst_type) } \ } while (0) +/* if val is a constant integer and its value is not undef or poison */ +static inline bool +LLVMIsEfficientConstInt(LLVMValueRef val) +{ + return LLVMIsConstant(val) + && LLVMGetValueKind(val) == LLVMConstantIntValueKind + && !LLVMIsUndef(val) +#if LLVM_VERSION_NUMBER >= 12 + && !LLVMIsPoison(addr) +#endif + ; +} + bool aot_compile_wasm(AOTCompContext *comp_ctx); diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index 75d1e622e..7e710f914 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -4,6 +4,7 @@ */ #include "aot_emit_control.h" +#include "aot_compiler.h" #include "aot_emit_exception.h" #include "../aot/aot_runtime.h" #include "../interpreter/wasm_loader.h" @@ -469,7 +470,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, p_frame_ip); } - if (!LLVMIsConstant(value)) { + if (!LLVMIsEfficientConstInt(value)) { /* Compare value is not constant, create condition br IR */ /* Create entry block */ format_block_name(name, sizeof(name), block->block_index, @@ -835,7 +836,7 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); } - if (!LLVMIsConstant(value_cmp)) { + if (!LLVMIsEfficientConstInt(value_cmp)) { /* Compare value is not constant, create condition br IR */ if (!(block_dst = get_target_block(func_ctx, br_depth))) { return false; @@ -972,7 +973,7 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); } - if (!LLVMIsConstant(value_cmp)) { + if (!LLVMIsEfficientConstInt(value_cmp)) { /* Compare value is not constant, create switch IR */ for (i = 0; i <= br_count; i++) { target_block = get_target_block(func_ctx, br_depths[i]); diff --git a/core/iwasm/compilation/aot_emit_memory.c b/core/iwasm/compilation/aot_emit_memory.c index c11989ebf..7484d4b5b 100644 --- a/core/iwasm/compilation/aot_emit_memory.c +++ b/core/iwasm/compilation/aot_emit_memory.c @@ -4,6 +4,7 @@ */ #include "aot_emit_memory.h" +#include "aot_compiler.h" #include "aot_emit_exception.h" #include "../aot/aot_runtime.h" #include "aot_intrinsic.h" @@ -145,11 +146,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, * have been thrown when converting float to integer before */ /* return addres directly if constant offset and inside memory space */ - if (LLVMIsConstant(addr) && !LLVMIsUndef(addr) -#if LLVM_VERSION_NUMBER >= 12 - && !LLVMIsPoison(addr) -#endif - ) { + if (LLVMIsEfficientConstInt(addr)) { uint64 mem_offset = (uint64)LLVMConstIntGetZExtValue(addr) + (uint64)offset; uint32 num_bytes_per_page = @@ -911,11 +908,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, * have been thrown when converting float to integer before */ /* return addres directly if constant offset and inside memory space */ - if (!LLVMIsUndef(offset) && !LLVMIsUndef(bytes) -#if LLVM_VERSION_NUMBER >= 12 - && !LLVMIsPoison(offset) && !LLVMIsPoison(bytes) -#endif - && LLVMIsConstant(offset) && LLVMIsConstant(bytes)) { + if (LLVMIsEfficientConstInt(offset) && LLVMIsEfficientConstInt(bytes)) { uint64 mem_offset = (uint64)LLVMConstIntGetZExtValue(offset); uint64 mem_len = (uint64)LLVMConstIntGetZExtValue(bytes); uint32 num_bytes_per_page = diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index 4c63e8a40..f540dbe04 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -54,13 +54,13 @@ } while (0) #if LLVM_VERSION_NUMBER >= 12 -#define IS_CONST_ZERO(val) \ - (!LLVMIsUndef(val) && !LLVMIsPoison(val) && LLVMIsConstant(val) \ - && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \ +#define IS_CONST_ZERO(val) \ + (LLVMIsEfficientConstInt(val) \ + && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \ || (!is_i32 && (int64)LLVMConstIntGetSExtValue(val) == 0))) #else #define IS_CONST_ZERO(val) \ - (!LLVMIsUndef(val) && LLVMIsConstant(val) \ + (LLVMIsEfficientConstInt(val) \ && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \ || (!is_i32 && (int64)LLVMConstIntGetSExtValue(val) == 0))) #endif @@ -473,7 +473,7 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); } - if (LLVMIsConstant(right)) { + if (LLVMIsEfficientConstInt(right)) { int64 right_val = (int64)LLVMConstIntGetSExtValue(right); switch (right_val) { case 0: From ac6435884fb012863544a094d315c5886dca229a Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 28 Sep 2023 10:27:33 +0900 Subject: [PATCH 03/17] doc/memory_tune.md: "remove malloc" hack is not relevant to wasi-threads (#2603) --- doc/memory_tune.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/memory_tune.md b/doc/memory_tune.md index e14a1a164..05a1a633f 100644 --- a/doc/memory_tune.md +++ b/doc/memory_tune.md @@ -16,7 +16,7 @@ Note: - **linear memory**: a contiguous, mutable array of raw bytes. It is created with an initial size but might be grown dynamically. For most compilers, e.g. wasi-sdk, emsdk, rustc or asc, normally it includes three parts, data area, auxiliary stack area and heap area. For wasi-sdk, the initial/max size can be specified with `-Wl,--initial-memory=n1,--max-memory=n2`, for emsdk, the initial/max size can be specified with `-s INITIAL_MEMORY=n1 -s MAXIMUM_MEMORY=n2 -s ALLOW_MEMORY_GROWTH=1` or `-s TOTAL_MEMORY=n`, and for asc, they can be specified with `--initialMemory` and `--maximumMemory` flags. - If the memory access boundary check with hardware trap feature is enabled, e.g. in Linux/MacOS/Windows x86-64 by default, the linear memory is allocated by `os_mmap` from virtual address space instead of global heap. - **aux stack**: the auxiliary stack resides in linear memory to store some temporary data when calling wasm functions, for example, calling a wasm function with complex struct arguments. For wasi-sdk, the size can be specified with `-z stack-size=n`, for emsdk, the size can be specified with `-s TOTAL_STACK=n`. -- **app heap and libc heap**: the heap to allocate memory for wasm app, note that app heap is created only when the malloc/free functions (or __new/__release functions for AssemblyScript) are not exported and runtime can not detect the libc heap. To export the malloc/free functions, for wasi-sdk and emsdk, developer can use `-Wl,--export=malloc -Wl,--export=free` options, for asc, developer can use `--exportRuntime` option. For app heap, the size is specified by `wasm_runtime_instantiate`. It is recommended to export the malloc/free functions and disable app heap in single thread mode, and for multi-threading, as the libc heap isn't thread-safe, it is recommended to remove the dlmalloc.o from libc.a for wasi-sdk and use `-s MALLOC="none"` for emsdk, refer to [WAMR pthread library](./pthread_library.md) for more details. And developer can use `wasm_runtime_module_malloc/wasm_runtime_module_free` to allocate/free memory from/to app heap (or libc heap if malloc/free functions are exported). +- **app heap and libc heap**: the heap to allocate memory for wasm app, note that app heap is created only when the malloc/free functions (or __new/__release functions for AssemblyScript) are not exported and runtime can not detect the libc heap. To export the malloc/free functions, for wasi-sdk and emsdk, developer can use `-Wl,--export=malloc -Wl,--export=free` options, for asc, developer can use `--exportRuntime` option. For app heap, the size is specified by `wasm_runtime_instantiate`. It is recommended to export the malloc/free functions and disable app heap. However, if you are using [the old pthread implementation](./pthread_impls.md), you might need some workaround to avoid the libc heap as mentioned in [WAMR pthread library](./pthread_library.md). And developer can use `wasm_runtime_module_malloc/wasm_runtime_module_free` to allocate/free memory from/to app heap (or libc heap if malloc/free functions are exported). - **__data_end global and __heap_base global**: two globals exported by wasm application to indicate the end of data area and the base address of libc heap. For WAMR, it is recommended to export them as when there are no possible memory grow operations, runtime will truncate the linear memory into the size indicated by `__heap_base`, so as to reduce the footprint, or at least one page (64KB) is required by linear memory. ## Tune the memory usage From 3c17a36ccb09dfea1dc48a5a85ef17697d943b3e Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Thu, 28 Sep 2023 09:32:01 +0800 Subject: [PATCH 04/17] Patch implementations of vfbinop(min,max,pmin,pax) (#2584) According to the specification, - fNxM_pmin/max returns v1 or v2 based on flt(v1,v2) result - fNxM_min/max returns +/-NaN, +/-Inf, v1 or v2 based on more than flt(v1,v2) result Fixes issue #2561. --- .../compilation/simd/simd_floating_point.c | 249 ++++++++++++++---- 1 file changed, 204 insertions(+), 45 deletions(-) diff --git a/core/iwasm/compilation/simd/simd_floating_point.c b/core/iwasm/compilation/simd/simd_floating_point.c index d850fe8f7..7fcc1ab65 100644 --- a/core/iwasm/compilation/simd/simd_floating_point.c +++ b/core/iwasm/compilation/simd/simd_floating_point.c @@ -217,10 +217,9 @@ aot_compile_simd_f64x2_nearest(AOTCompContext *comp_ctx, static bool simd_float_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - FloatArithmetic arith_op, LLVMTypeRef vector_type) + FloatArithmetic op, LLVMTypeRef vector_type) { - LLVMValueRef lhs, rhs, result; - LLVMRealPredicate op = FLOAT_MIN == arith_op ? LLVMRealULT : LLVMRealUGT; + LLVMValueRef lhs, rhs, cmp, selected; if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs")) @@ -229,80 +228,240 @@ simd_float_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } - if (!(result = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) { + if (!(cmp = LLVMBuildFCmp(comp_ctx->builder, + op == FLOAT_MIN ? LLVMRealOLT : LLVMRealOGT, rhs, + lhs, "cmp"))) { HANDLE_FAILURE("LLVMBuildFCmp"); return false; } - if (!(result = - LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) { + if (!(selected = + LLVMBuildSelect(comp_ctx->builder, cmp, rhs, lhs, "selected"))) { HANDLE_FAILURE("LLVMBuildSelect"); return false; } - return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, selected, "result"); +} + +static bool +simd_float_min(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMTypeRef vector_type) +{ + LLVMValueRef lhs, rhs, lhs_nan, rhs_nan, olt_ret, ogt_ret, or_ret, ret1, + ret2, ret3, ret4; + + if (!(rhs = + simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs")) + || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "lhs"))) { + return false; + } + + if (!(lhs_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, lhs, lhs, + "lhs_nan"))) { + HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealUNO"); + return false; + } + + if (!(rhs_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, rhs, rhs, + "rhs_nan"))) { + HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealUNO"); + return false; + } + + if (!(olt_ret = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLT, lhs, rhs, + "olt_ret"))) { + HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealOLT"); + return false; + } + + if (!(ogt_ret = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGT, lhs, rhs, + "ogt_ret"))) { + HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealOGT"); + return false; + } + + /* lhs or rhs */ + { + LLVMValueRef integer_l, integer_r, integer_or; + + if (!(integer_l = LLVMBuildBitCast(comp_ctx->builder, lhs, + V128_i64x2_TYPE, "lhs_to_int"))) { + HANDLE_FAILURE("LLVMBuildBitCas"); + return false; + } + + if (!(integer_r = LLVMBuildBitCast(comp_ctx->builder, rhs, + V128_i64x2_TYPE, "rhs_to_int"))) { + HANDLE_FAILURE("LLVMBuildBitCas"); + return false; + } + + if (!(integer_or = + LLVMBuildOr(comp_ctx->builder, integer_l, integer_r, "or"))) { + HANDLE_FAILURE("LLVMBuildOr"); + return false; + } + + if (!(or_ret = LLVMBuildBitCast(comp_ctx->builder, integer_or, + vector_type, "holder"))) { + HANDLE_FAILURE("LLVMBuildBitCast"); + return false; + } + } + + if (!(ret1 = LLVMBuildSelect(comp_ctx->builder, olt_ret, lhs, or_ret, + "sel_olt"))) { + HANDLE_FAILURE("LLVMBuildSelect"); + return false; + } + + if (!(ret2 = LLVMBuildSelect(comp_ctx->builder, ogt_ret, rhs, ret1, + "sel_ogt"))) { + HANDLE_FAILURE("LLVMBuildSelect"); + return false; + } + + if (!(ret3 = LLVMBuildSelect(comp_ctx->builder, lhs_nan, lhs, ret2, + "sel_lhs_nan"))) { + HANDLE_FAILURE("LLVMBuildSelect"); + return false; + } + + if (!(ret4 = LLVMBuildSelect(comp_ctx->builder, rhs_nan, rhs, ret3, + "sel_rhs_nan"))) { + HANDLE_FAILURE("LLVMBuildSelect"); + return false; + } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, ret4, "result"); +} + +static bool +simd_float_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMTypeRef vector_type) +{ + LLVMValueRef lhs, rhs, lhs_nan, rhs_nan, olt_ret, ogt_ret, and_ret, ret1, + ret2, ret3, ret4; + + if (!(rhs = + simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs")) + || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "lhs"))) { + return false; + } + + if (!(lhs_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, lhs, lhs, + "lhs_nan"))) { + HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealUNO"); + return false; + } + + if (!(rhs_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, rhs, rhs, + "rhs_nan"))) { + HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealUNO"); + return false; + } + + if (!(olt_ret = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLT, lhs, rhs, + "olt_ret"))) { + HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealOLT"); + return false; + } + + if (!(ogt_ret = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGT, lhs, rhs, + "ogt_ret"))) { + HANDLE_FAILURE("LLVMBuildFCmp + LLVMRealOGT"); + return false; + } + + /* lhs and rhs */ + { + LLVMValueRef integer_l, integer_r, integer_and; + + if (!(integer_l = LLVMBuildBitCast(comp_ctx->builder, lhs, + V128_i64x2_TYPE, "lhs_to_int"))) { + HANDLE_FAILURE("LLVMBuildBitCas"); + return false; + } + + if (!(integer_r = LLVMBuildBitCast(comp_ctx->builder, rhs, + V128_i64x2_TYPE, "rhs_to_int"))) { + HANDLE_FAILURE("LLVMBuildBitCas"); + return false; + } + + if (!(integer_and = LLVMBuildAnd(comp_ctx->builder, integer_l, + integer_r, "and"))) { + HANDLE_FAILURE("LLVMBuildOr"); + return false; + } + + if (!(and_ret = LLVMBuildBitCast(comp_ctx->builder, integer_and, + vector_type, "holder"))) { + HANDLE_FAILURE("LLVMBuildBitCast"); + return false; + } + } + + if (!(ret1 = LLVMBuildSelect(comp_ctx->builder, ogt_ret, lhs, and_ret, + "sel_ogt"))) { + HANDLE_FAILURE("LLVMBuildSelect"); + return false; + } + + if (!(ret2 = LLVMBuildSelect(comp_ctx->builder, olt_ret, rhs, ret1, + "sel_olt"))) { + HANDLE_FAILURE("LLVMBuildSelect"); + return false; + } + + if (!(ret3 = LLVMBuildSelect(comp_ctx->builder, lhs_nan, lhs, ret2, + "sel_lhs_nan"))) { + HANDLE_FAILURE("LLVMBuildSelect"); + return false; + } + + if (!(ret4 = LLVMBuildSelect(comp_ctx->builder, rhs_nan, rhs, ret3, + "sel_rhs_nan"))) { + HANDLE_FAILURE("LLVMBuildSelect"); + return false; + } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, ret4, "result"); } -/*TODO: sugggest non-IA platforms check with "llvm.minimum.*" and - * "llvm.maximum.*" firstly */ bool aot_compile_simd_f32x4_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool run_min) { - return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX, - V128_f32x4_TYPE); + return run_min ? simd_float_min(comp_ctx, func_ctx, V128_f32x4_TYPE) + : simd_float_max(comp_ctx, func_ctx, V128_f32x4_TYPE); } bool aot_compile_simd_f64x2_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool run_min) { - return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX, - V128_f64x2_TYPE); -} - -static bool -simd_float_pmin_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - LLVMTypeRef vector_type, const char *intrinsic) -{ - LLVMValueRef lhs, rhs, result; - LLVMTypeRef param_types[2]; - - param_types[0] = vector_type; - param_types[1] = vector_type; - - if (!(rhs = - simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs")) - || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "lhs"))) { - return false; - } - - if (!(result = - aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, - vector_type, param_types, 2, lhs, rhs))) { - return false; - } - - return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); + return run_min ? simd_float_min(comp_ctx, func_ctx, V128_f64x2_TYPE) + : simd_float_max(comp_ctx, func_ctx, V128_f64x2_TYPE); } bool aot_compile_simd_f32x4_pmin_pmax(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool run_min) { - return simd_float_pmin_max(comp_ctx, func_ctx, V128_f32x4_TYPE, - run_min ? "llvm.minnum.v4f32" - : "llvm.maxnum.v4f32"); + return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX, + V128_f32x4_TYPE); } bool aot_compile_simd_f64x2_pmin_pmax(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool run_min) { - return simd_float_pmin_max(comp_ctx, func_ctx, V128_f64x2_TYPE, - run_min ? "llvm.minnum.v2f64" - : "llvm.maxnum.v2f64"); + return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX, + V128_f64x2_TYPE); } bool From 00539620e9522b41eec5776d8d6168ebba2f6f06 Mon Sep 17 00:00:00 2001 From: Enrico Loparco Date: Fri, 29 Sep 2023 04:52:54 +0200 Subject: [PATCH 05/17] Improve stack trace dump and fix coding guideline CI (#2599) Avoid the stack traces getting mixed up together when multi-threading is enabled by using exception_lock/unlock in dumping the call stacks. And remove duplicated call stack dump in wasm_application.c. Also update coding guideline CI to fix the clang-format-12 not found issue. --- .github/workflows/coding_guidelines.yml | 2 +- core/iwasm/aot/aot_runtime.c | 4 ++++ core/iwasm/common/wasm_application.c | 10 +--------- core/iwasm/interpreter/wasm_interp_classic.c | 3 --- core/iwasm/interpreter/wasm_interp_fast.c | 3 --- core/iwasm/interpreter/wasm_runtime.c | 4 ++++ product-mini/platforms/posix/main.c | 13 +++++++++---- product-mini/platforms/windows/main.c | 13 +++++++++---- 8 files changed, 28 insertions(+), 24 deletions(-) diff --git a/.github/workflows/coding_guidelines.yml b/.github/workflows/coding_guidelines.yml index 259e84fe5..17d60ac43 100644 --- a/.github/workflows/coding_guidelines.yml +++ b/.github/workflows/coding_guidelines.yml @@ -16,7 +16,7 @@ concurrency: jobs: compliance_job: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - name: checkout uses: actions/checkout@v3 diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index abd4539be..0799d625f 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -2807,6 +2807,7 @@ aot_create_call_stack(struct WASMExecEnv *exec_env) total_len += \ wasm_runtime_dump_line_buf_impl(line_buf, print, &buf, &len); \ if ((!print) && buf && (len == 0)) { \ + exception_unlock(module_inst); \ return total_len; \ } \ } while (0) @@ -2829,6 +2830,7 @@ aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len) return 0; } + exception_lock(module_inst); snprintf(line_buf, sizeof(line_buf), "\n"); PRINT_OR_DUMP(); @@ -2837,6 +2839,7 @@ aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len) uint32 line_length, i; if (!bh_vector_get(module_inst->frames, n, &frame)) { + exception_unlock(module_inst); return 0; } @@ -2867,6 +2870,7 @@ aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len) } snprintf(line_buf, sizeof(line_buf), "\n"); PRINT_OR_DUMP(); + exception_unlock(module_inst); return total_len + 1; } diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 795d65c8c..02999584f 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -231,7 +231,7 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) { bool ret; -#if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0) +#if (WASM_ENABLE_MEMORY_PROFILING != 0) WASMExecEnv *exec_env; #endif @@ -251,14 +251,6 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, if (ret) ret = wasm_runtime_get_exception(module_inst) == NULL; -#if WASM_ENABLE_DUMP_CALL_STACK != 0 - if (!ret) { - exec_env = wasm_runtime_get_exec_env_singleton(module_inst); - if (exec_env) - wasm_runtime_dump_call_stack(exec_env); - } -#endif - return ret; } diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 2a48c1bde..ce090d1f0 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -4209,7 +4209,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num); unsigned i; bool copy_argv_from_frame = true; - char exception[EXCEPTION_BUF_LEN]; if (argc < function->param_cell_num) { char buf[128]; @@ -4342,8 +4341,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, wasm_interp_dump_call_stack(exec_env, true, NULL, 0); } #endif - wasm_copy_exception(module_inst, exception); - LOG_DEBUG("meet an exception %s", exception); } wasm_exec_env_set_cur_frame(exec_env, prev_frame); diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 229a2151d..e565c2c89 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -3945,7 +3945,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, /* This frame won't be used by JITed code, so only allocate interp frame here. */ unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num); - char exception[EXCEPTION_BUF_LEN]; if (argc < function->param_cell_num) { char buf[128]; @@ -4030,8 +4029,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, wasm_interp_dump_call_stack(exec_env, true, NULL, 0); } #endif - wasm_copy_exception(module_inst, exception); - LOG_DEBUG("meet an exception %s", exception); } wasm_exec_env_set_cur_frame(exec_env, prev_frame); diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index af2a61c88..8fb19d52e 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -2915,6 +2915,7 @@ wasm_interp_create_call_stack(struct WASMExecEnv *exec_env) total_len += \ wasm_runtime_dump_line_buf_impl(line_buf, print, &buf, &len); \ if ((!print) && buf && (len == 0)) { \ + exception_unlock(module_inst); \ return total_len; \ } \ } while (0) @@ -2939,6 +2940,7 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf, return 0; } + exception_lock(module_inst); snprintf(line_buf, sizeof(line_buf), "\n"); PRINT_OR_DUMP(); @@ -2947,6 +2949,7 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf, uint32 line_length, i; if (!bh_vector_get(module_inst->frames, n, &frame)) { + exception_unlock(module_inst); return 0; } @@ -2977,6 +2980,7 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env, bool print, char *buf, } snprintf(line_buf, sizeof(line_buf), "\n"); PRINT_OR_DUMP(); + exception_unlock(module_inst); return total_len + 1; } diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 0051e628c..b7d755410 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -120,8 +120,7 @@ app_instance_main(wasm_module_inst_t module_inst) const char *exception; wasm_application_execute_main(module_inst, app_argc, app_argv); - if ((exception = wasm_runtime_get_exception(module_inst))) - printf("%s\n", exception); + exception = wasm_runtime_get_exception(module_inst); return exception; } @@ -977,17 +976,20 @@ main(int argc, char *argv[]) #endif ret = 0; + const char *exception = NULL; if (is_repl_mode) { app_instance_repl(wasm_module_inst); } else if (func_name) { - if (app_instance_func(wasm_module_inst, func_name)) { + exception = app_instance_func(wasm_module_inst, func_name); + if (exception) { /* got an exception */ ret = 1; } } else { - if (app_instance_main(wasm_module_inst)) { + exception = app_instance_main(wasm_module_inst); + if (exception) { /* got an exception */ ret = 1; } @@ -1000,6 +1002,9 @@ main(int argc, char *argv[]) } #endif + if (exception) + printf("%s\n", exception); + #if WASM_ENABLE_STATIC_PGO != 0 && WASM_ENABLE_AOT != 0 if (get_package_type(wasm_file_buf, wasm_file_size) == Wasm_Module_AoT && gen_prof_file) diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 121be4195..985c9e6c7 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -77,8 +77,7 @@ app_instance_main(wasm_module_inst_t module_inst) const char *exception; wasm_application_execute_main(module_inst, app_argc, app_argv); - if ((exception = wasm_runtime_get_exception(module_inst))) - printf("%s\n", exception); + exception = wasm_runtime_get_exception(module_inst); return exception; } @@ -545,17 +544,20 @@ main(int argc, char *argv[]) #endif ret = 0; + const char *exception = NULL; if (is_repl_mode) { app_instance_repl(wasm_module_inst); } else if (func_name) { - if (app_instance_func(wasm_module_inst, func_name)) { + exception = app_instance_func(wasm_module_inst, func_name); + if (exception) { /* got an exception */ ret = 1; } } else { - if (app_instance_main(wasm_module_inst)) { + exception = app_instance_main(wasm_module_inst); + if (exception) { /* got an exception */ ret = 1; } @@ -568,6 +570,9 @@ main(int argc, char *argv[]) } #endif + if (exception) + printf("%s\n", exception); + #if WASM_ENABLE_DEBUG_INTERP != 0 fail4: #endif From e1ea15d94e9afb73f1bbe9c5191558b715539667 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 29 Sep 2023 16:30:52 +0900 Subject: [PATCH 06/17] aot_resolve_stack_sizes: Disable the size check for now (#2608) cf. https://github.com/bytecodealliance/wasm-micro-runtime/issues/2555#issuecomment-1738530877 https://github.com/llvm/llvm-project/issues/67765 --- core/iwasm/compilation/aot_emit_aot_file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 622187755..103b2750e 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -2703,6 +2703,7 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data) || (obj_data->target_info.bin_type == AOT_COFF32_BIN_TYPE && !strncmp(name, "_", 1) && !strcmp(name + 1, aot_stack_sizes_alias_name)))) { +#if 0 /* cf. https://github.com/llvm/llvm-project/issues/67765 */ uint64 sz = LLVMGetSymbolSize(sym_itr); if (sz != sizeof(uint32) * obj_data->func_count /* sz of COFF64/COFF32 is 0, ignore the check */ @@ -2711,6 +2712,7 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data) aot_set_last_error("stack_sizes had unexpected size."); goto fail; } +#endif uint64 addr = LLVMGetSymbolAddress(sym_itr); if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) { From 1a8810416034e59657d38f8a746fd896012181ae Mon Sep 17 00:00:00 2001 From: Zhen Kong Date: Mon, 2 Oct 2023 17:33:11 -0700 Subject: [PATCH 07/17] Remove module instance from hashmap in wasi_nn_destroy (#2613) When destroying wasi-nn context, module instance should be also removed from hashmap to avoid memory leak. --- core/iwasm/libraries/wasi-nn/src/wasi_nn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn.c b/core/iwasm/libraries/wasi-nn/src/wasi_nn.c index ba27055ea..c234e450a 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn.c +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn.c @@ -163,6 +163,7 @@ void wasi_nn_destroy(wasm_module_inst_t instance) { WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); + bh_hash_map_remove(hashmap, (void *)instance, NULL, NULL); wasi_nn_ctx_destroy(wasi_nn_ctx); } From 64baf54d8881e9475a9e579a82c0f6148022f350 Mon Sep 17 00:00:00 2001 From: funera1 <60760935+funera1@users.noreply.github.com> Date: Tue, 3 Oct 2023 11:33:00 +0900 Subject: [PATCH 08/17] Fix label index out-of-range references in op_br_table_cache (#2615) Fixed a bug in the processing of the br_table_cache opcode that caused out-of-range references when the label index was greater than the length of the label. --- core/iwasm/interpreter/wasm_interp_classic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index ce090d1f0..50860d3a3 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1418,6 +1418,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, while (node_cache) { node_next = bh_list_elem_next(node_cache); if (node_cache->br_table_op_addr == frame_ip - 1) { + if (lidx > node_cache->br_count) + lidx = node_cache->br_count; depth = node_cache->br_depths[lidx]; goto label_pop_csp_n; } From 28ebd57400df4944e270cd71b2c063acf8c02630 Mon Sep 17 00:00:00 2001 From: Maks Litskevich Date: Wed, 4 Oct 2023 01:10:10 +0100 Subject: [PATCH 09/17] Refactor stress tests to make them runnable in reactor mode (#2614) --- .github/workflows/nightly_run.yml | 4 +- .../lib-wasi-threads/stress-test/build.sh | 1 + .../errorcheck_mutex_stress_test.c | 11 +++- .../stress-test/normal_mutex_stress_test.c | 11 +++- .../stress-test/recursive_mutex_stress_test.c | 11 +++- .../stress-test/spawn_stress_test.c | 54 +++++++++++-------- .../stress_test_threads_creation.c | 42 ++++++++------- 7 files changed, 86 insertions(+), 48 deletions(-) diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index 1cf4b51e3..ea79b3f23 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -8,9 +8,11 @@ on: types: - opened - synchronize - #running nightly pipeline if you're changing it + # running nightly pipeline if you're changing it + # stress tests are run only in nightly at the moment, so running them in they are changed paths: - ".github/workflows/nightly_run.yml" + - "core/iwasm/libraries/lib-wasi-threads/stress-test/**" # midnight UTC schedule: diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh b/core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh index 341f3ef12..1ea95cb97 100755 --- a/core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/build.sh @@ -60,6 +60,7 @@ for test_c in *.c; do -Wl,--export=wasi_thread_start \ -Wl,--export=malloc \ -Wl,--export=free \ + -Wl,--export=test \ $sysroot_command \ $test_c -o $test_wasm done diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c index 3b594657f..946e8bd63 100644 --- a/core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/errorcheck_mutex_stress_test.c @@ -7,8 +7,8 @@ #include #include "mutex_common.h" -int -main() +void +test() { pthread_mutex_t mutex; @@ -25,3 +25,10 @@ main() fprintf(stderr, "Errorcheck mutex test is completed\n"); pthread_mutex_destroy(&mutex); } + +int +main() +{ + test(); + return 0; +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c index 6c75f8814..c7ffae279 100644 --- a/core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/normal_mutex_stress_test.c @@ -7,8 +7,8 @@ #include #include "mutex_common.h" -int -main() +void +test() { pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); @@ -18,3 +18,10 @@ main() fprintf(stderr, "Normal mutex test is completed\n"); pthread_mutex_destroy(&mutex); } + +int +main() +{ + test(); + return 0; +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c index 8c3e325e8..5874372cb 100644 --- a/core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/recursive_mutex_stress_test.c @@ -31,8 +31,8 @@ same_thread_multiple_rec_mutex_lock(void *mutex) return NULL; } -int -main() +void +test() { pthread_mutex_t mutex; @@ -63,3 +63,10 @@ main() fprintf(stderr, "Recursive mutex test is completed\n"); pthread_mutex_destroy(&mutex); } + +int +main() +{ + test(); + return 0; +} diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c index a35337f35..8cb61a2a6 100644 --- a/core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/spawn_stress_test.c @@ -16,13 +16,6 @@ #include #include -enum CONSTANTS { - NUM_ITER = 100000, - NUM_RETRY = 8, - MAX_NUM_THREADS = 12, - RETRY_SLEEP_TIME_US = 2000, -}; - unsigned prime_numbers_count = 0; bool @@ -49,10 +42,10 @@ check_if_prime(void *value) } unsigned int -validate() +validate(int iter_num) { unsigned int counter = 0; - for (unsigned int i = 2; i <= NUM_ITER; ++i) { + for (unsigned int i = 2; i <= iter_num; ++i) { counter += is_prime(i); } @@ -60,11 +53,12 @@ validate() } void -spawn_thread(pthread_t *thread, unsigned int *arg) +spawn_thread(pthread_t *thread, int retry_time_us, int retry_num, + unsigned int *arg) { int status_code = -1; - int timeout_us = RETRY_SLEEP_TIME_US; - for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) { + int timeout_us = retry_time_us; + for (int tries = 0; status_code != 0 && tries < retry_num; ++tries) { status_code = pthread_create(thread, NULL, &check_if_prime, arg); assert(status_code == 0 || status_code == EAGAIN); if (status_code == EAGAIN) { @@ -76,42 +70,56 @@ spawn_thread(pthread_t *thread, unsigned int *arg) assert(status_code == 0 && "Thread creation should succeed"); } -int -main(int argc, char **argv) +void +test(int iter_num, int retry_num, int max_threads_num, int retry_time_us) { - pthread_t threads[MAX_NUM_THREADS]; - unsigned int args[MAX_NUM_THREADS]; + pthread_t threads[max_threads_num]; + unsigned int args[max_threads_num]; double percentage = 0.1; - for (unsigned int factorised_number = 2; factorised_number < NUM_ITER; + for (unsigned int factorised_number = 2; factorised_number < iter_num; ++factorised_number) { - if (factorised_number > NUM_ITER * percentage) { + if (factorised_number > iter_num * percentage) { fprintf(stderr, "Stress test is %d%% finished\n", (unsigned int)(percentage * 100)); percentage += 0.1; } - unsigned int thread_num = factorised_number % MAX_NUM_THREADS; + unsigned int thread_num = factorised_number % max_threads_num; if (threads[thread_num] != 0) { assert(pthread_join(threads[thread_num], NULL) == 0); } args[thread_num] = factorised_number; - usleep(RETRY_SLEEP_TIME_US); - spawn_thread(&threads[thread_num], &args[thread_num]); + usleep(retry_time_us); + spawn_thread(&threads[thread_num], retry_time_us, retry_num, + &args[thread_num]); assert(threads[thread_num] != 0); } - for (int i = 0; i < MAX_NUM_THREADS; ++i) { + for (int i = 0; i < max_threads_num; ++i) { assert(threads[i] == 0 || pthread_join(threads[i], NULL) == 0); } // Check the test results assert( - prime_numbers_count == validate() + prime_numbers_count == validate(iter_num) && "Answer mismatch between tested code and reference implementation"); fprintf(stderr, "Stress test finished successfully\n"); +} + +enum DEFAULT_PARAMETERS { + ITER_NUM = 20000, + RETRY_NUM = 8, + MAX_THREADS_NUM = 12, + RETRY_SLEEP_TIME_US = 2000, +}; + +int +main(int argc, char **argv) +{ + test(ITER_NUM, RETRY_NUM, MAX_THREADS_NUM, RETRY_SLEEP_TIME_US); return 0; } diff --git a/core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c b/core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c index f991fa7ab..c4c2d2857 100644 --- a/core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c +++ b/core/iwasm/libraries/lib-wasi-threads/stress-test/stress_test_threads_creation.c @@ -9,14 +9,6 @@ #include #include -enum CONSTANTS { - NUM_ITER = 200000, - NUM_RETRY = 8, - MAX_NUM_THREADS = 12, - RETRY_SLEEP_TIME_US = 4000, - SECOND = 1000 * 1000 * 1000 -}; - int threads_executed = 0; unsigned int threads_creation_tried = 0; unsigned int threads_in_use = 0; @@ -31,11 +23,11 @@ thread_func(void *arg) } void -spawn_thread(pthread_t *thread) +spawn_thread(pthread_t *thread, int retry_time, int iter_num) { int status_code = -1; - int timeout_us = RETRY_SLEEP_TIME_US; - for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) { + int timeout_us = retry_time; + for (int tries = 0; status_code != 0 && tries < iter_num; ++tries) { status_code = pthread_create(thread, NULL, &thread_func, NULL); __atomic_fetch_add(&threads_creation_tried, 1, __ATOMIC_RELAXED); @@ -49,32 +41,33 @@ spawn_thread(pthread_t *thread) assert(status_code == 0 && "Thread creation should succeed"); } -int -main(int argc, char **argv) +void +test(int iter_num, int max_threads_num, int retry_num, int retry_time_us) { double percentage = 0.1; + int second_us = 1000 * 1000 * 1000; // 1 second in us - for (int iter = 0; iter < NUM_ITER; ++iter) { - if (iter > NUM_ITER * percentage) { + for (int iter = 0; iter < iter_num; ++iter) { + if (iter > iter_num * percentage) { fprintf(stderr, "Spawning stress test is %d%% finished\n", (unsigned int)(percentage * 100)); percentage += 0.1; } while (__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) - == MAX_NUM_THREADS) { + == max_threads_num) { usleep(100); } __atomic_fetch_add(&threads_in_use, 1, __ATOMIC_SEQ_CST); pthread_t tmp; - spawn_thread(&tmp); + spawn_thread(&tmp, retry_time_us, iter_num); pthread_detach(tmp); } while ((__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) != 0)) { // Casting to int* to supress compiler warning __builtin_wasm_memory_atomic_wait32((int *)(&threads_in_use), 0, - SECOND); + second_us); } assert(__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) == 0); @@ -91,5 +84,18 @@ main(int argc, char **argv) "with retry ratio %f\n", threads_creation_tried, (1. * threads_creation_tried) / threads_executed); +} + +enum DEFAULT_PARAMETERS { + ITER_NUM = 50000, + RETRY_NUM = 8, + MAX_NUM_THREADS = 12, + RETRY_SLEEP_TIME_US = 4000, +}; + +int +main(int argc, char **argv) +{ + test(ITER_NUM, MAX_NUM_THREADS, RETRY_NUM, RETRY_SLEEP_TIME_US); return 0; } From 8987432f369d8cd70bc632be55ed2eb2a1cb5aed Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Wed, 4 Oct 2023 14:02:25 +0100 Subject: [PATCH 10/17] libc-wasi: Conditionally support SYNC flags (#2581) To make it clearer to users when synchronization behaviour is not supported, return ENOTSUP when O_RSYNC, O_DSYNC or O_SYNC are respectively not defined. Linux also doesn't support O_RSYNC despite the O_RSYNC flag being defined. --- .../sandboxed-system-primitives/src/posix.c | 38 ++++++++++++------- .../src/ssp_config.h | 16 +++++++- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index eda65b8da..5c85a81d6 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -1282,18 +1282,20 @@ wasmtime_ssp_fd_fdstat_get(wasm_exec_env_t exec_env, struct fd_table *curfds, if ((ret & O_APPEND) != 0) buf->fs_flags |= __WASI_FDFLAG_APPEND; -#ifdef O_DSYNC +#ifdef CONFIG_HAS_O_DSYNC if ((ret & O_DSYNC) != 0) buf->fs_flags |= __WASI_FDFLAG_DSYNC; #endif if ((ret & O_NONBLOCK) != 0) buf->fs_flags |= __WASI_FDFLAG_NONBLOCK; -#ifdef O_RSYNC +#ifdef CONFIG_HAS_O_RSYNC if ((ret & O_RSYNC) != 0) buf->fs_flags |= __WASI_FDFLAG_RSYNC; #endif +#ifdef CONFIG_HAS_O_SYNC if ((ret & O_SYNC) != 0) buf->fs_flags |= __WASI_FDFLAG_SYNC; +#endif return 0; } @@ -1306,21 +1308,25 @@ wasmtime_ssp_fd_fdstat_set_flags(wasm_exec_env_t exec_env, if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) noflags |= O_APPEND; if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) -#ifdef O_DSYNC +#ifdef CONFIG_HAS_O_DSYNC noflags |= O_DSYNC; #else - noflags |= O_SYNC; + return __WASI_ENOTSUP; #endif if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) noflags |= O_NONBLOCK; if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) -#ifdef O_RSYNC +#ifdef CONFIG_HAS_O_RSYNC noflags |= O_RSYNC; #else - noflags |= O_SYNC; + return __WASI_ENOTSUP; #endif if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) +#ifdef CONFIG_HAS_O_SYNC noflags |= O_SYNC; +#else + return __WASI_ENOTSUP; +#endif struct fd_object *fo; __wasi_errno_t error = @@ -1971,26 +1977,30 @@ wasmtime_ssp_path_open(wasm_exec_env_t exec_env, struct fd_table *curfds, if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) noflags |= O_APPEND; if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) { -#ifdef O_DSYNC +#ifdef CONFIG_HAS_O_DSYNC noflags |= O_DSYNC; -#else - noflags |= O_SYNC; -#endif needed_inheriting |= __WASI_RIGHT_FD_DATASYNC; +#else + return __WASI_ENOTSUP; +#endif } if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) noflags |= O_NONBLOCK; if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) { -#ifdef O_RSYNC +#ifdef CONFIG_HAS_O_RSYNC noflags |= O_RSYNC; -#else - noflags |= O_SYNC; -#endif needed_inheriting |= __WASI_RIGHT_FD_SYNC; +#else + return __WASI_ENOTSUP; +#endif } if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) { +#ifdef CONFIG_HAS_O_SYNC noflags |= O_SYNC; needed_inheriting |= __WASI_RIGHT_FD_SYNC; +#else + return __WASI_ENOTSUP; +#endif } if (write && (noflags & (O_APPEND | O_TRUNC)) == 0) needed_inheriting |= __WASI_RIGHT_FD_SEEK; diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h index f5e130a9e..f75da5d8a 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h @@ -14,8 +14,8 @@ #ifndef SSP_CONFIG_H #define SSP_CONFIG_H +#include "bh_platform.h" #include "gnuc.h" -#include #if defined(__FreeBSD__) || defined(__APPLE__) \ || (defined(ANDROID) && __ANDROID_API__ < 28) @@ -101,6 +101,20 @@ #define st_mtim st_mtimespec #endif +#if defined(O_DSYNC) +#define CONFIG_HAS_O_DSYNC +#endif + +// POSIX requires O_RSYNC to be defined, but Linux explicitly doesn't support +// it. +#if defined(O_RSYNC) && !defined(__linux__) +#define CONFIG_HAS_O_RSYNC +#endif + +#if defined(O_SYNC) +#define CONFIG_HAS_O_SYNC +#endif + #if !defined(BH_PLATFORM_LINUX_SGX) /* Clang's __GNUC_PREREQ macro has a different meaning than GCC one, so we have to handle this case specially */ From d8ee771e28e4e32f29894803824dda736452c970 Mon Sep 17 00:00:00 2001 From: Gavin Hayes Date: Wed, 4 Oct 2023 09:55:37 -0400 Subject: [PATCH 11/17] Add Cosmopolitan Libc Platform (#2598) This PR adds the Cosmopolitan Libc platform enabling compatibility with multiple x86_64 operating systems with the same binary. The platform is similar to the Linux platform, but for now only x86_64 with interpreter modes are supported. The only major change to the core is `posix.c/convert_errno()` was rewritten to use a switch statement. With Cosmopolitan errno values depend on the currently running operating system, and so they are non-constant and cannot be used in array designators. However, the `cosmocc` compiler allows non-constant case labels in switch statements, enabling the new version. And updated wamr-test-suites script to add `-j ` option. The spec tests can be ran via `CC=cosmocc ./test_wamr.sh -j cosmopolitan -t classic-interp` or `CC=cosmocc ./test_wamr.sh -j cosmopolitan -t fast-interp`. --- .../sandboxed-system-primitives/src/posix.c | 179 +++++++++--------- .../src/ssp_config.h | 5 +- .../platform/common/posix/posix_socket.c | 4 +- .../platform/cosmopolitan/platform_init.c | 43 +++++ .../platform/cosmopolitan/platform_internal.h | 122 ++++++++++++ .../cosmopolitan/shared_platform.cmake | 19 ++ product-mini/README.md | 20 ++ .../platforms/cosmopolitan/CMakeLists.txt | 175 +++++++++++++++++ .../platforms/cosmopolitan/build_cosmocc.sh | 10 + product-mini/platforms/cosmopolitan/main.c | 6 + tests/wamr-test-suites/test_wamr.sh | 23 ++- 11 files changed, 512 insertions(+), 94 deletions(-) create mode 100644 core/shared/platform/cosmopolitan/platform_init.c create mode 100644 core/shared/platform/cosmopolitan/platform_internal.h create mode 100644 core/shared/platform/cosmopolitan/shared_platform.cmake create mode 100644 product-mini/platforms/cosmopolitan/CMakeLists.txt create mode 100755 product-mini/platforms/cosmopolitan/build_cosmocc.sh create mode 100644 product-mini/platforms/cosmopolitan/main.c diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 5c85a81d6..415a66463 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -60,98 +60,99 @@ static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t), static __wasi_errno_t convert_errno(int error) { - static const __wasi_errno_t errors[] = { -#define X(v) [v] = __WASI_##v - X(E2BIG), - X(EACCES), - X(EADDRINUSE), - X(EADDRNOTAVAIL), - X(EAFNOSUPPORT), - X(EAGAIN), - X(EALREADY), - X(EBADF), - X(EBADMSG), - X(EBUSY), - X(ECANCELED), - X(ECHILD), - X(ECONNABORTED), - X(ECONNREFUSED), - X(ECONNRESET), - X(EDEADLK), - X(EDESTADDRREQ), - X(EDOM), - X(EDQUOT), - X(EEXIST), - X(EFAULT), - X(EFBIG), - X(EHOSTUNREACH), - X(EIDRM), - X(EILSEQ), - X(EINPROGRESS), - X(EINTR), - X(EINVAL), - X(EIO), - X(EISCONN), - X(EISDIR), - X(ELOOP), - X(EMFILE), - X(EMLINK), - X(EMSGSIZE), - X(EMULTIHOP), - X(ENAMETOOLONG), - X(ENETDOWN), - X(ENETRESET), - X(ENETUNREACH), - X(ENFILE), - X(ENOBUFS), - X(ENODEV), - X(ENOENT), - X(ENOEXEC), - X(ENOLCK), - X(ENOLINK), - X(ENOMEM), - X(ENOMSG), - X(ENOPROTOOPT), - X(ENOSPC), - X(ENOSYS), + __wasi_errno_t code = __WASI_ENOSYS; +#define X(v) \ + case v: \ + code = __WASI_##v; \ + break; + switch (error) { + X(E2BIG) + X(EACCES) + X(EADDRINUSE) + X(EADDRNOTAVAIL) + X(EAFNOSUPPORT) + X(EAGAIN) + X(EALREADY) + X(EBADF) + X(EBADMSG) + X(EBUSY) + X(ECANCELED) + X(ECHILD) + X(ECONNABORTED) + X(ECONNREFUSED) + X(ECONNRESET) + X(EDEADLK) + X(EDESTADDRREQ) + X(EDOM) + X(EDQUOT) + X(EEXIST) + X(EFAULT) + X(EFBIG) + X(EHOSTUNREACH) + X(EIDRM) + X(EILSEQ) + X(EINPROGRESS) + X(EINTR) + X(EINVAL) + X(EIO) + X(EISCONN) + X(EISDIR) + X(ELOOP) + X(EMFILE) + X(EMLINK) + X(EMSGSIZE) + X(EMULTIHOP) + X(ENAMETOOLONG) + X(ENETDOWN) + X(ENETRESET) + X(ENETUNREACH) + X(ENFILE) + X(ENOBUFS) + X(ENODEV) + X(ENOENT) + X(ENOEXEC) + X(ENOLCK) + X(ENOLINK) + X(ENOMEM) + X(ENOMSG) + X(ENOPROTOOPT) + X(ENOSPC) + X(ENOSYS) #ifdef ENOTCAPABLE - X(ENOTCAPABLE), + X(ENOTCAPABLE) #endif - X(ENOTCONN), - X(ENOTDIR), - X(ENOTEMPTY), - X(ENOTRECOVERABLE), - X(ENOTSOCK), - X(ENOTSUP), - X(ENOTTY), - X(ENXIO), - X(EOVERFLOW), - X(EOWNERDEAD), - X(EPERM), - X(EPIPE), - X(EPROTO), - X(EPROTONOSUPPORT), - X(EPROTOTYPE), - X(ERANGE), - X(EROFS), - X(ESPIPE), - X(ESRCH), - X(ESTALE), - X(ETIMEDOUT), - X(ETXTBSY), - X(EXDEV), + X(ENOTCONN) + X(ENOTDIR) + X(ENOTEMPTY) + X(ENOTRECOVERABLE) + X(ENOTSOCK) + X(ENOTSUP) + X(ENOTTY) + X(ENXIO) + X(EOVERFLOW) + X(EOWNERDEAD) + X(EPERM) + X(EPIPE) + X(EPROTO) + X(EPROTONOSUPPORT) + X(EPROTOTYPE) + X(ERANGE) + X(EROFS) + X(ESPIPE) + X(ESRCH) + X(ESTALE) + X(ETIMEDOUT) + X(ETXTBSY) + X(EXDEV) + default: + if (error == EOPNOTSUPP) + code = __WASI_ENOTSUP; + else if (code == EWOULDBLOCK) + code = __WASI_EAGAIN; + break; + } #undef X -#if EOPNOTSUPP != ENOTSUP - [EOPNOTSUPP] = __WASI_ENOTSUP, -#endif -#if EWOULDBLOCK != EAGAIN - [EWOULDBLOCK] = __WASI_EAGAIN, -#endif - }; - if (error < 0 || (size_t)error >= sizeof(errors) / sizeof(errors[0]) - || errors[error] == 0) - return __WASI_ENOSYS; - return errors[error]; + return code; } static bool diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h index f75da5d8a..a69d6ca38 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h @@ -65,7 +65,7 @@ #endif #endif -#if !defined(__APPLE__) && !defined(ESP_PLATFORM) +#if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(__COSMOPOLITAN__) #define CONFIG_HAS_POSIX_FALLOCATE 1 #else #define CONFIG_HAS_POSIX_FALLOCATE 0 @@ -83,7 +83,8 @@ #define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 0 #endif -#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) +#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) \ + && !defined(__COSMOPOLITAN__) #define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 1 #else #define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0 diff --git a/core/shared/platform/common/posix/posix_socket.c b/core/shared/platform/common/posix/posix_socket.c index 9f5538b5c..11c56e723 100644 --- a/core/shared/platform/common/posix/posix_socket.c +++ b/core/shared/platform/common/posix/posix_socket.c @@ -799,7 +799,7 @@ os_socket_set_ip_add_membership(bh_socket_t socket, { assert(imr_multiaddr); if (is_ipv6) { -#ifdef IPPROTO_IPV6 +#if defined(IPPROTO_IPV6) && !defined(BH_PLATFORM_COSMOPOLITAN) struct ipv6_mreq mreq; for (int i = 0; i < 8; i++) { ((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] = @@ -837,7 +837,7 @@ os_socket_set_ip_drop_membership(bh_socket_t socket, { assert(imr_multiaddr); if (is_ipv6) { -#ifdef IPPROTO_IPV6 +#if defined(IPPROTO_IPV6) && !defined(BH_PLATFORM_COSMOPOLITAN) struct ipv6_mreq mreq; for (int i = 0; i < 8; i++) { ((uint16_t *)mreq.ipv6mr_multiaddr.s6_addr)[i] = diff --git a/core/shared/platform/cosmopolitan/platform_init.c b/core/shared/platform/cosmopolitan/platform_init.c new file mode 100644 index 000000000..2aae13fa1 --- /dev/null +++ b/core/shared/platform/cosmopolitan/platform_init.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +int +bh_platform_init() +{ + return 0; +} + +void +bh_platform_destroy() +{} + +int +os_printf(const char *format, ...) +{ + int ret = 0; + va_list ap; + + va_start(ap, format); +#ifndef BH_VPRINTF + ret += vprintf(format, ap); +#else + ret += BH_VPRINTF(format, ap); +#endif + va_end(ap); + + return ret; +} + +int +os_vprintf(const char *format, va_list ap) +{ +#ifndef BH_VPRINTF + return vprintf(format, ap); +#else + return BH_VPRINTF(format, ap); +#endif +} diff --git a/core/shared/platform/cosmopolitan/platform_internal.h b/core/shared/platform/cosmopolitan/platform_internal.h new file mode 100644 index 000000000..ed2545436 --- /dev/null +++ b/core/shared/platform/cosmopolitan/platform_internal.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * Copyright (C) 2023 Dylibso. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_COSMOPOLITAN +#define BH_PLATFORM_COSMOPOLITAN +#endif + +/* Stack size of applet threads's native part. */ +#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef pthread_t korp_tid; +typedef pthread_mutex_t korp_mutex; +typedef pthread_cond_t korp_cond; +typedef pthread_t korp_thread; +typedef sem_t korp_sem; + +#define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER + +#define os_thread_local_attribute __thread + +#define bh_socket_t int + +#if WASM_DISABLE_WRITE_GS_BASE == 0 +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) +#define os_writegsbase(base_addr) \ + do { \ + uint64 __gs_value = (uint64)(uintptr_t)base_addr; \ + asm volatile("wrgsbase %0" ::"r"(__gs_value) : "memory"); \ + } while (0) +#if 0 +/* _writegsbase_u64 also works, but need to add -mfsgsbase flag for gcc */ +#include +#define os_writegsbase(base_addr) \ + _writegsbase_u64(((uint64)(uintptr_t)base_addr)) +#endif +#endif +#endif + +#if WASM_DISABLE_HW_BOUND_CHECK == 0 +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ + || defined(BUILD_TARGET_RISCV64_LP64) + +#include + +#define OS_ENABLE_HW_BOUND_CHECK + +typedef jmp_buf korp_jmpbuf; + +#define os_setjmp setjmp +#define os_longjmp longjmp +#define os_alloca alloca + +#define os_getpagesize getpagesize + +typedef void (*os_signal_handler)(void *sig_addr); + +int +os_thread_signal_init(os_signal_handler handler); + +void +os_thread_signal_destroy(); + +bool +os_thread_signal_inited(); + +void +os_signal_unmask(); + +void +os_sigreturn(); +#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ +#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ diff --git a/core/shared/platform/cosmopolitan/shared_platform.cmake b/core/shared/platform/cosmopolitan/shared_platform.cmake new file mode 100644 index 000000000..929ecb9e4 --- /dev/null +++ b/core/shared/platform/cosmopolitan/shared_platform.cmake @@ -0,0 +1,19 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# Copyright (C) 2023 Dylibso. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions(-DBH_PLATFORM_COSMOPOLITAN) + +include_directories(${PLATFORM_SHARED_DIR}) +include_directories(${PLATFORM_SHARED_DIR}/../include) + +include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake) + +file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) + +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE}) + +file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) diff --git a/product-mini/README.md b/product-mini/README.md index 92f8183e0..22acfeaf4 100644 --- a/product-mini/README.md +++ b/product-mini/README.md @@ -443,3 +443,23 @@ make aos make ``` download the binary to developerkit board, check the output from serial port + +## Cosmopolitan Libc +Currently, only x86_64 architecture with interpreter modes is supported. + +Clone the Cosmopolitan Libc. Setup `cosmocc` as described in [Getting Started](https://github.com/jart/cosmopolitan/#getting-started) being sure to get it into `PATH`. + +Build iwasm +``` Bash +export CC=cosmocc +export CXX=cosmoc++ +rm -rf build +mkdir build +cmake -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=1 -B build +cmake --build build -j +``` + +Run like +``` Bash +./build/iwasm.com +``` diff --git a/product-mini/platforms/cosmopolitan/CMakeLists.txt b/product-mini/platforms/cosmopolitan/CMakeLists.txt new file mode 100644 index 000000000..8533ea68c --- /dev/null +++ b/product-mini/platforms/cosmopolitan/CMakeLists.txt @@ -0,0 +1,175 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# Copyright (C) 2023 Dylibso. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +include(CheckPIESupported) + +project (iwasm) + +set (CMAKE_VERBOSE_MAKEFILE OFF) + +set (WAMR_BUILD_PLATFORM "cosmopolitan") + +set(CMAKE_EXECUTABLE_SUFFIX ".com") + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +set (CMAKE_C_STANDARD 99) +set (CMAKE_CXX_STANDARD 17) + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Enable AOT by default. + set (WAMR_BUILD_AOT 1) +endif () + +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_FAST_JIT) + # Disable Fast JIT by default + set (WAMR_BUILD_FAST_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Enable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 1) +endif () + +if (NOT DEFINED WAMR_BUILD_FAST_INTERP) + # Enable fast interpreter + set (WAMR_BUILD_FAST_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_MULTI_MODULE) + # Disable multiple modules by default + set (WAMR_BUILD_MULTI_MODULE 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD) + # Disable pthread library by default + set (WAMR_BUILD_LIB_PTHREAD 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS) + # Disable wasi threads library by default + set (WAMR_BUILD_LIB_WASI_THREADS 0) +endif() + + +if (NOT DEFINED WAMR_BUILD_MINI_LOADER) + # Disable wasm mini loader by default + set (WAMR_BUILD_MINI_LOADER 0) +endif () + +if (NOT DEFINED WAMR_BUILD_SIMD) + # Enable SIMD by default + set (WAMR_BUILD_SIMD 1) +endif () + +if (NOT DEFINED WAMR_BUILD_REF_TYPES) + # Disable reference types by default + set (WAMR_BUILD_REF_TYPES 0) +endif () + +if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP) + # Disable Debug feature by default + set (WAMR_BUILD_DEBUG_INTERP 0) +endif () + +if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) + set (WAMR_BUILD_FAST_INTERP 0) + set (WAMR_BUILD_MINI_LOADER 0) + set (WAMR_BUILD_SIMD 0) +endif () + +set (WAMR_DISABLE_STACK_HW_BOUND_CHECK 1) +set (WAMR_BUILD_AOT 0) +set (WAMR_DISABLE_WRITE_GS_BASE 1) + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) + +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +check_pie_supported() +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +set_target_properties (vmlib PROPERTIES POSITION_INDEPENDENT_CODE ON) + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wshadow") +# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion") + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wno-unused") + +if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mindirect-branch-register") + # UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub + endif () +endif () + +# The following flags are to enhance security, but it may impact performance, +# we disable them by default. +#if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") +# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftrapv -D_FORTIFY_SOURCE=2") +#endif () +#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") +#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") + +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) + +set_target_properties (iwasm PROPERTIES POSITION_INDEPENDENT_CODE ON) + +install (TARGETS iwasm DESTINATION bin) + +target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} ${WASI_NN_LIBS} -lm -ldl -lpthread) + +add_library (libiwasm STATIC ${WAMR_RUNTIME_LIB_SOURCE}) + +install (TARGETS libiwasm DESTINATION lib) + +set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) + +target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} ${WASI_NN_LIBS} -lm -ldl -lpthread) diff --git a/product-mini/platforms/cosmopolitan/build_cosmocc.sh b/product-mini/platforms/cosmopolitan/build_cosmocc.sh new file mode 100755 index 000000000..b2ce15d33 --- /dev/null +++ b/product-mini/platforms/cosmopolitan/build_cosmocc.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# Copyright (C) 2023 Dylibso. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +export CC=cosmocc +export CXX=cosmoc++ +rm -rf build +mkdir build +cmake -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=1 -B build +cmake --build build -j diff --git a/product-mini/platforms/cosmopolitan/main.c b/product-mini/platforms/cosmopolitan/main.c new file mode 100644 index 000000000..8f0e84a97 --- /dev/null +++ b/product-mini/platforms/cosmopolitan/main.c @@ -0,0 +1,6 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "../posix/main.c" diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 1caaa89b0..1966de5e0 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -31,6 +31,7 @@ function help() echo "-Q enable qemu" echo "-F set the firmware path used by qemu" echo "-C enable code coverage collect" + echo "-j set the platform to test" } OPT_PARSED="" @@ -58,7 +59,7 @@ QEMU_FIRMWARE="" # prod/testsuite-all branch WASI_TESTSUITE_COMMIT="cf64229727f71043d5849e73934e249e12cb9e06" -while getopts ":s:cabgvt:m:MCpSXxwPGQF:" opt +while getopts ":s:cabgvt:m:MCpSXxwPGQF:j:" opt do OPT_PARSED="TRUE" case $opt in @@ -160,6 +161,10 @@ do echo "QEMU firmware" ${OPTARG} QEMU_FIRMWARE=${OPTARG} ;; + j) + echo "test platform " ${OPTARG} + PLATFORM=${OPTARG} + ;; ?) help exit 1;; @@ -383,6 +388,8 @@ function spec_test() local WAT2WASM=${WORK_DIR}/wabt/out/gcc/Release/wat2wasm if [ ! -f ${WAT2WASM} ]; then case ${PLATFORM} in + cosmopolitan) + ;& linux) WABT_PLATFORM=ubuntu ;; @@ -656,6 +663,20 @@ function build_iwasm_with_cfg() echo -e "build iwasm failed" exit 1 fi + + if [[ ${PLATFORM} == "cosmopolitan" ]]; then + # convert from APE to ELF so it can be ran easier + # HACK: link to linux so tests work when platform is detected by uname + cp iwasm.com iwasm \ + && ./iwasm --assimilate \ + && rm -rf ../../linux/build \ + && mkdir ../../linux/build \ + && ln -s ../../cosmopolitan/build/iwasm ../../linux/build/iwasm + if [ "$?" != 0 ];then + echo -e "build iwasm failed (cosmopolitan)" + exit 1 + fi + fi } function build_wamrc() From 74acfd964ee6a0b93621f93d9de279be69c56c7d Mon Sep 17 00:00:00 2001 From: zoraaver <55952569+zoraaver@users.noreply.github.com> Date: Fri, 6 Oct 2023 13:12:08 +0100 Subject: [PATCH 12/17] Run rust tests from wasi-testsuite (#2484) --- tests/wamr-test-suites/test_wamr.sh | 2 +- tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 1966de5e0..a08031331 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -57,7 +57,7 @@ PARALLELISM=0 ENABLE_QEMU=0 QEMU_FIRMWARE="" # prod/testsuite-all branch -WASI_TESTSUITE_COMMIT="cf64229727f71043d5849e73934e249e12cb9e06" +WASI_TESTSUITE_COMMIT="ee807fc551978490bf1c277059aabfa1e589a6c2" while getopts ":s:cabgvt:m:MCpSXxwPGQF:j:" opt do diff --git a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh index c4b27390e..b8e3ddfec 100755 --- a/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh +++ b/tests/wamr-test-suites/wasi-test-script/run_wasi_tests.sh @@ -20,6 +20,7 @@ readonly IWASM_CMD="${WORK_DIR}/../../../../product-mini/platforms/${PLATFORM}/b readonly IWASM_CMD_STRESS="${IWASM_CMD} --max-threads=12" readonly WAMRC_CMD="${WORK_DIR}/../../../../wamr-compiler/build/wamrc" readonly C_TESTS="tests/c/testsuite/" +readonly RUST_TESTS="tests/rust/testsuite/" readonly ASSEMBLYSCRIPT_TESTS="tests/assemblyscript/testsuite/" readonly THREAD_PROPOSAL_TESTS="tests/proposals/wasi-threads/" readonly THREAD_INTERNAL_TESTS="${WAMR_DIR}/core/iwasm/libraries/lib-wasi-threads/test/" @@ -70,6 +71,7 @@ if [[ $MODE != "aot" ]];then -r adapters/wasm-micro-runtime.py \ -t \ ${C_TESTS} \ + ${RUST_TESTS} \ ${ASSEMBLYSCRIPT_TESTS} \ ${THREAD_PROPOSAL_TESTS} \ ${THREAD_INTERNAL_TESTS} \ From 1ef7c1c83d101b9f9fd6f81884929fa96b512d40 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Sat, 7 Oct 2023 15:50:29 +0800 Subject: [PATCH 13/17] spec-test-script: Fix NaN comparision between v128 values (#2605) --- .../wamr-test-suites/spec-test-script/all.py | 4 +-- .../spec-test-script/runtest.py | 29 +++++++------------ 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index 44b0a14bd..12ac005bb 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -199,7 +199,8 @@ def test_case( case_path = pathlib.Path(case_path).resolve() case_name = case_path.stem - CMD.append(case_path) + CMD.append(str(case_path)) + # print(f"============> use {' '.join(CMD)}") print(f"============> run {case_name} ", end="") with subprocess.Popen( CMD, @@ -481,7 +482,6 @@ def main(): ) options = parser.parse_args() - print(options) if not preflight_check(options.aot_flag): return False diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index 633a57313..566a165f3 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -400,7 +400,7 @@ def cast_v128_to_i64x2(numbers, type, lane_type): assert(packed) unpacked = struct.unpack("Q Q", packed) - return unpacked, "[{} {}]:{}:v128".format(unpacked[0], unpacked[1], lane_type) + return unpacked, f"[{unpacked[0]:#x} {unpacked[1]:#x}]:{lane_type}:v128" def parse_simple_const_w_type(number, type): @@ -412,13 +412,7 @@ def parse_simple_const_w_type(number, type): else "-0x{:x}:{}".format(0 - number, type) elif type in ["f32", "f64"]: if "nan:" in number: - # TODO: how to handle this correctly - if "nan:canonical" in number: - return float.fromhex("0x200000"), "nan:{}".format(type) - elif "nan:arithmetic" in number: - return float.fromhex("-0x200000"), "nan:{}".format(type) - else: - return float('nan'), "nan:{}".format(type) + return float('nan'), "nan:{}".format(type) else: number = float.fromhex(number) if '0x' in number else float(number) return number, "{:.7g}:{}".format(number, type) @@ -542,9 +536,6 @@ def vector_value_comparison(out, expected): if out_type != expected_type: return False - if out_val == expected_val: - return True - out_val = out_val.split(" ") expected_val = expected_val.split(" ") @@ -568,12 +559,14 @@ def vector_value_comparison(out, expected): out_is_nan = [math.isnan(o) for o in out_unpacked] expected_is_nan = [math.isnan(e) for e in expected_unpacked] - if out_is_nan and expected_is_nan: - return True; + if any(out_is_nan): + nan_comparision = [o == e for o, e in zip(out_is_nan, expected_is_nan)] + if all(nan_comparision): + print(f"Pass NaN comparision") + return True - # print("compare {} and {}".format(out_unpacked, expected_unpacked)) + # print(f"compare {out_unpacked} and {expected_unpacked}") result = [o == e for o, e in zip(out_unpacked, expected_unpacked)] - if not all(result): result = [ "{:.7g}".format(o) == "{:.7g}".format(e) @@ -778,7 +771,7 @@ def test_assert_return(r, opts, form): numbers, _ = cast_v128_to_i64x2(splitted[2:], 'v128', splitted[1]) assert(len(numbers) == 2), "has to reform arguments into i64x2" - args.append("{}\{}".format(numbers[0], numbers[1])) + args.append(f"{numbers[0]:#x}\{numbers[1]:#x}") elif "ref.null" == splitted[0]: args.append("null") elif "ref.extern" == splitted[0]: @@ -1129,7 +1122,7 @@ def test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, if __name__ == "__main__": opts = parser.parse_args(sys.argv[1:]) - print('Input param :',opts) + # print('Input param :',opts) if opts.aot: test_aot = True # default x86_64 @@ -1152,7 +1145,7 @@ if __name__ == "__main__": ret_code = 0 try: - log("################################################") + log("\n################################################") log("### Testing %s" % opts.test_file.name) log("################################################") forms = read_forms(opts.test_file.read()) From 3668093053bc57f2c6e08c1a637b828b3792facf Mon Sep 17 00:00:00 2001 From: Enrico Loparco Date: Sat, 7 Oct 2023 08:05:10 +0000 Subject: [PATCH 14/17] Enable AOT usage on M1 mac (#2618) --- core/iwasm/aot/aot_loader.c | 3 +++ core/iwasm/aot/arch/aot_reloc_aarch64.c | 5 +++++ core/shared/platform/alios/alios_platform.c | 4 ++++ core/shared/platform/alios/alios_thread.c | 4 ++++ core/shared/platform/common/posix/posix_memmap.c | 16 ++++++++++++++++ core/shared/platform/common/posix/posix_thread.c | 8 ++++++++ core/shared/platform/esp-idf/espidf_memmap.c | 4 ++++ core/shared/platform/esp-idf/espidf_platform.c | 4 ++++ .../platform/include/platform_api_vmcore.h | 13 +++++++++++++ core/shared/platform/linux-sgx/sgx_platform.c | 4 ++++ core/shared/platform/linux-sgx/sgx_thread.c | 4 ++++ core/shared/platform/nuttx/nuttx_platform.c | 4 ++++ core/shared/platform/riot/riot_platform.c | 4 ++++ core/shared/platform/riot/riot_thread.c | 4 ++++ core/shared/platform/rt-thread/rtt_platform.c | 8 ++++++++ core/shared/platform/windows/platform_init.c | 4 ++++ core/shared/platform/windows/win_thread.c | 4 ++++ core/shared/platform/zephyr/zephyr_platform.c | 4 ++++ core/shared/platform/zephyr/zephyr_thread.c | 4 ++++ 19 files changed, 105 insertions(+) diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index b5fa33c0c..6e2fc3248 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -3232,10 +3232,13 @@ aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf, if (!module) return NULL; + os_thread_jit_write_protect_np(false); /* Make memory writable */ if (!load(buf, size, module, error_buf, error_buf_size)) { aot_unload(module); return NULL; } + os_thread_jit_write_protect_np(true); /* Make memory executable */ + os_icache_flush(module->code, module->code_size); LOG_VERBOSE("Load module success.\n"); return module; diff --git a/core/iwasm/aot/arch/aot_reloc_aarch64.c b/core/iwasm/aot/arch/aot_reloc_aarch64.c index 4c46eaa00..b4bb6024a 100644 --- a/core/iwasm/aot/arch/aot_reloc_aarch64.c +++ b/core/iwasm/aot/arch/aot_reloc_aarch64.c @@ -53,7 +53,12 @@ get_target_symbol_map(uint32 *sym_num) return target_sym_map; } +#if (defined(__APPLE__) || defined(__MACH__)) && defined(__arm64__) +#define BUILD_TARGET_AARCH64_DEFAULT "arm64" +#else #define BUILD_TARGET_AARCH64_DEFAULT "aarch64v8" +#endif + void get_current_target(char *target_buf, uint32 target_buf_size) { diff --git a/core/shared/platform/alios/alios_platform.c b/core/shared/platform/alios/alios_platform.c index c9f5f17e6..60393ae52 100644 --- a/core/shared/platform/alios/alios_platform.c +++ b/core/shared/platform/alios/alios_platform.c @@ -69,3 +69,7 @@ os_mprotect(void *addr, size_t size, int prot) void os_dcache_flush() {} + +void +os_icache_flush(void *start, size_t len) +{} diff --git a/core/shared/platform/alios/alios_thread.c b/core/shared/platform/alios/alios_thread.c index 0efd2f394..9fe927db0 100644 --- a/core/shared/platform/alios/alios_thread.c +++ b/core/shared/platform/alios/alios_thread.c @@ -359,3 +359,7 @@ os_thread_get_stack_boundary() /* TODO: get alios stack boundary */ return NULL; } + +void +os_thread_jit_write_protect_np(bool enabled) +{} \ No newline at end of file diff --git a/core/shared/platform/common/posix/posix_memmap.c b/core/shared/platform/common/posix/posix_memmap.c index 2dfbee453..5d33dcc81 100644 --- a/core/shared/platform/common/posix/posix_memmap.c +++ b/core/shared/platform/common/posix/posix_memmap.c @@ -5,6 +5,10 @@ #include "platform_api_vmcore.h" +#if (defined(__APPLE__) || defined(__MACH__)) && defined(__arm64__) +#include +#endif + #ifndef BH_ENABLE_TRACE_MMAP #define BH_ENABLE_TRACE_MMAP 0 #endif @@ -36,7 +40,11 @@ void * os_mmap(void *hint, size_t size, int prot, int flags) { int map_prot = PROT_NONE; +#if (defined(__APPLE__) || defined(__MACH__)) && defined(__arm64__) + int map_flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_JIT; +#else int map_flags = MAP_ANONYMOUS | MAP_PRIVATE; +#endif uint64 request_size, page_size; uint8 *addr = MAP_FAILED; uint32 i; @@ -251,3 +259,11 @@ os_mprotect(void *addr, size_t size, int prot) void os_dcache_flush(void) {} + +void +os_icache_flush(void *start, size_t len) +{ +#if (defined(__APPLE__) || defined(__MACH__)) && defined(__arm64__) + sys_icache_invalidate(start, len); +#endif +} \ No newline at end of file diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index a7bdc6d10..498f5f5a2 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -418,6 +418,14 @@ os_thread_get_stack_boundary() return addr; } +void +os_thread_jit_write_protect_np(bool enabled) +{ +#if (defined(__APPLE__) || defined(__MACH__)) && defined(__arm64__) + pthread_jit_write_protect_np(enabled); +#endif +} + #ifdef OS_ENABLE_HW_BOUND_CHECK #define SIG_ALT_STACK_SIZE (32 * 1024) diff --git a/core/shared/platform/esp-idf/espidf_memmap.c b/core/shared/platform/esp-idf/espidf_memmap.c index 0a1fd4fe4..ce94a9549 100644 --- a/core/shared/platform/esp-idf/espidf_memmap.c +++ b/core/shared/platform/esp-idf/espidf_memmap.c @@ -100,6 +100,10 @@ void #endif } +void +os_icache_flush(void *start, size_t len) +{} + #if (WASM_MEM_DUAL_BUS_MIRROR != 0) void * os_get_dbus_mirror(void *ibus) diff --git a/core/shared/platform/esp-idf/espidf_platform.c b/core/shared/platform/esp-idf/espidf_platform.c index 35b893d81..bbc18f69b 100644 --- a/core/shared/platform/esp-idf/espidf_platform.c +++ b/core/shared/platform/esp-idf/espidf_platform.c @@ -53,6 +53,10 @@ os_thread_get_stack_boundary(void) #endif } +void +os_thread_jit_write_protect_np(bool enabled) +{} + int os_usleep(uint32 usec) { diff --git a/core/shared/platform/include/platform_api_vmcore.h b/core/shared/platform/include/platform_api_vmcore.h index 15fc1d387..c803c12e4 100644 --- a/core/shared/platform/include/platform_api_vmcore.h +++ b/core/shared/platform/include/platform_api_vmcore.h @@ -81,6 +81,13 @@ os_self_thread(void); uint8 * os_thread_get_stack_boundary(void); +/** + * Set whether the MAP_JIT region write protection is enabled for this thread. + * Pass true to make the region executable, false to make it writable. + */ +void +os_thread_jit_write_protect_np(bool enabled); + /** ************** mutext APIs *********** * vmcore: Not required until pthread is supported by runtime @@ -143,6 +150,12 @@ os_get_dbus_mirror(void *ibus); void os_dcache_flush(void); +/** + * Flush instruction cache. + */ +void +os_icache_flush(void *start, size_t len); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/linux-sgx/sgx_platform.c b/core/shared/platform/linux-sgx/sgx_platform.c index b40eaf79c..1a90af4c6 100644 --- a/core/shared/platform/linux-sgx/sgx_platform.c +++ b/core/shared/platform/linux-sgx/sgx_platform.c @@ -195,3 +195,7 @@ os_mprotect(void *addr, size_t size, int prot) void os_dcache_flush(void) {} + +void +os_icache_flush(void *start, size_t len) +{} \ No newline at end of file diff --git a/core/shared/platform/linux-sgx/sgx_thread.c b/core/shared/platform/linux-sgx/sgx_thread.c index 1cb2f5d09..d9412927b 100644 --- a/core/shared/platform/linux-sgx/sgx_thread.c +++ b/core/shared/platform/linux-sgx/sgx_thread.c @@ -210,3 +210,7 @@ os_thread_get_stack_boundary() /* TODO: get sgx stack boundary */ return NULL; } + +void +os_thread_jit_write_protect_np(bool enabled) +{} \ No newline at end of file diff --git a/core/shared/platform/nuttx/nuttx_platform.c b/core/shared/platform/nuttx/nuttx_platform.c index 0bd1f6808..92c17ed48 100644 --- a/core/shared/platform/nuttx/nuttx_platform.c +++ b/core/shared/platform/nuttx/nuttx_platform.c @@ -144,6 +144,10 @@ os_dcache_flush() bus_sync(); } +void +os_icache_flush(void *start, size_t len) +{} + #if (WASM_MEM_DUAL_BUS_MIRROR != 0) void * os_get_dbus_mirror(void *ibus) diff --git a/core/shared/platform/riot/riot_platform.c b/core/shared/platform/riot/riot_platform.c index a0c38e8c9..6fd6617b4 100644 --- a/core/shared/platform/riot/riot_platform.c +++ b/core/shared/platform/riot/riot_platform.c @@ -79,3 +79,7 @@ os_dcache_flush(void) irq_unlock(key); #endif } + +void +os_icache_flush(void *start, size_t len) +{} \ No newline at end of file diff --git a/core/shared/platform/riot/riot_thread.c b/core/shared/platform/riot/riot_thread.c index 0ebcf30e0..a9062bfec 100644 --- a/core/shared/platform/riot/riot_thread.c +++ b/core/shared/platform/riot/riot_thread.c @@ -430,3 +430,7 @@ os_thread_get_stack_boundary() return NULL; #endif } + +void +os_thread_jit_write_protect_np(bool enabled) +{} \ No newline at end of file diff --git a/core/shared/platform/rt-thread/rtt_platform.c b/core/shared/platform/rt-thread/rtt_platform.c index 4685e1ea3..6dc719f01 100644 --- a/core/shared/platform/rt-thread/rtt_platform.c +++ b/core/shared/platform/rt-thread/rtt_platform.c @@ -140,6 +140,10 @@ os_thread_get_stack_boundary(void) return tid->stack_addr; } +void +os_thread_jit_write_protect_np(bool enabled) +{} + int os_mutex_init(korp_mutex *mutex) { @@ -207,3 +211,7 @@ os_mprotect(void *addr, size_t size, int prot) void os_dcache_flush(void) {} + +void +os_icache_flush(void *start, size_t len) +{} \ No newline at end of file diff --git a/core/shared/platform/windows/platform_init.c b/core/shared/platform/windows/platform_init.c index db5885387..96bcf9ab1 100644 --- a/core/shared/platform/windows/platform_init.c +++ b/core/shared/platform/windows/platform_init.c @@ -73,3 +73,7 @@ os_getpagesize() void os_dcache_flush(void) {} + +void +os_icache_flush(void *start, size_t len) +{} \ No newline at end of file diff --git a/core/shared/platform/windows/win_thread.c b/core/shared/platform/windows/win_thread.c index 09cf0c63f..abc36f2fc 100644 --- a/core/shared/platform/windows/win_thread.c +++ b/core/shared/platform/windows/win_thread.c @@ -712,6 +712,10 @@ os_thread_get_stack_boundary() return thread_stack_boundary; } +void +os_thread_jit_write_protect_np(bool enabled) +{} + #ifdef OS_ENABLE_HW_BOUND_CHECK static os_thread_local_attribute bool thread_signal_inited = false; diff --git a/core/shared/platform/zephyr/zephyr_platform.c b/core/shared/platform/zephyr/zephyr_platform.c index b4f2e5ec7..715be8b94 100644 --- a/core/shared/platform/zephyr/zephyr_platform.c +++ b/core/shared/platform/zephyr/zephyr_platform.c @@ -214,6 +214,10 @@ os_dcache_flush() #endif } +void +os_icache_flush(void *start, size_t len) +{} + void set_exec_mem_alloc_func(exec_mem_alloc_func_t alloc_func, exec_mem_free_func_t free_func) diff --git a/core/shared/platform/zephyr/zephyr_thread.c b/core/shared/platform/zephyr/zephyr_thread.c index 1ee2c5cef..105d53993 100644 --- a/core/shared/platform/zephyr/zephyr_thread.c +++ b/core/shared/platform/zephyr/zephyr_thread.c @@ -574,3 +574,7 @@ os_thread_get_stack_boundary() return NULL; #endif } + +void +os_thread_jit_write_protect_np(bool enabled) +{} \ No newline at end of file From b115b7baac4d7c1a2f4d92278ad18cd53d265ff1 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Sat, 7 Oct 2023 12:55:14 +0100 Subject: [PATCH 15/17] Fix compilation of shift opcodes on x86_64 and i386 architectures (#2619) This change fixes the case where the right parameter of shift operator is negative, specifically, when both parameters of shift opcode are constants. --- .../compilation_on_android_ubuntu.yml | 7 +- core/iwasm/compilation/aot_emit_numberic.c | 18 ++- tests/wamr-compiler/.gitignore | 2 + tests/wamr-compiler/README.md | 3 + .../test_shift_negative_constants.wat | 43 +++++++ tests/wamr-test-suites/test_wamr.sh | 115 +++++++++++------- .../run_wamr_compiler_tests.sh | 22 ++++ 7 files changed, 159 insertions(+), 51 deletions(-) create mode 100644 tests/wamr-compiler/.gitignore create mode 100644 tests/wamr-compiler/README.md create mode 100644 tests/wamr-compiler/test_shift_negative_constants.wat create mode 100755 tests/wamr-test-suites/wamr-compiler-test-script/run_wamr_compiler_tests.sh diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index 3c5b4e35e..3d6e44c6b 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -65,6 +65,7 @@ env: THREADS_TEST_OPTIONS: "-s spec -b -p -P" X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P" WASI_TEST_OPTIONS: "-s wasi_certification -w" + WAMR_COMPILER_TEST_OPTIONS: "-s wamr_compiler -b -P" jobs: build_llvm_libraries_on_ubuntu_2204: @@ -333,7 +334,7 @@ jobs: build_iwasm, build_llvm_libraries_on_ubuntu_2204, build_wamrc, - ] + ] runs-on: ${{ matrix.os }} strategy: matrix: @@ -482,6 +483,10 @@ jobs: - os: ubuntu-22.04 llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} ubuntu_version: "22.04" + - os: ubuntu-22.04 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} + running_mode: aot + test_option: $WAMR_COMPILER_TEST_OPTIONS exclude: # uncompatiable modes and features # classic-interp and fast-interp don't support simd diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index f540dbe04..bda64f831 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -171,6 +171,15 @@ right = shift_count_mask; \ } while (0) +static bool +is_shift_count_mask_needed(AOTCompContext *comp_ctx, LLVMValueRef left, + LLVMValueRef right) +{ + return (strcmp(comp_ctx->target_arch, "x86_64") != 0 + && strcmp(comp_ctx->target_arch, "i386") != 0) + || (LLVMIsEfficientConstInt(left) && LLVMIsEfficientConstInt(right)); +} + /* Call llvm constrained floating-point intrinsic */ static LLVMValueRef call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx, @@ -728,8 +737,7 @@ compile_int_shl(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right, { LLVMValueRef res; - if (strcmp(comp_ctx->target_arch, "x86_64") != 0 - && strcmp(comp_ctx->target_arch, "i386") != 0) + if (is_shift_count_mask_needed(comp_ctx, left, right)) SHIFT_COUNT_MASK; /* Build shl */ @@ -744,8 +752,7 @@ compile_int_shr_s(AOTCompContext *comp_ctx, LLVMValueRef left, { LLVMValueRef res; - if (strcmp(comp_ctx->target_arch, "x86_64") != 0 - && strcmp(comp_ctx->target_arch, "i386") != 0) + if (is_shift_count_mask_needed(comp_ctx, left, right)) SHIFT_COUNT_MASK; /* Build shl */ @@ -760,8 +767,7 @@ compile_int_shr_u(AOTCompContext *comp_ctx, LLVMValueRef left, { LLVMValueRef res; - if (strcmp(comp_ctx->target_arch, "x86_64") != 0 - && strcmp(comp_ctx->target_arch, "i386") != 0) + if (is_shift_count_mask_needed(comp_ctx, left, right)) SHIFT_COUNT_MASK; /* Build shl */ diff --git a/tests/wamr-compiler/.gitignore b/tests/wamr-compiler/.gitignore new file mode 100644 index 000000000..5425c41bd --- /dev/null +++ b/tests/wamr-compiler/.gitignore @@ -0,0 +1,2 @@ +*.aot +*.wasm \ No newline at end of file diff --git a/tests/wamr-compiler/README.md b/tests/wamr-compiler/README.md new file mode 100644 index 000000000..d48ea9827 --- /dev/null +++ b/tests/wamr-compiler/README.md @@ -0,0 +1,3 @@ +# WAMR test benchmarks + +This folder contains tests for WAMR AOT compiler and its generated code. diff --git a/tests/wamr-compiler/test_shift_negative_constants.wat b/tests/wamr-compiler/test_shift_negative_constants.wat new file mode 100644 index 000000000..030cc8983 --- /dev/null +++ b/tests/wamr-compiler/test_shift_negative_constants.wat @@ -0,0 +1,43 @@ +;; Copyright (C) 2023 Amazon Inc. All rights reserved. +;; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +;; +;; Those tests verify if passing constant negative value +;; as a right parameter of the shift operator (along +;; with a constant value of the left operator) causes +;; any problems. See: https://github.com/bytecodealliance/wasm-micro-runtime/pull/2619 +(module + (memory (export "memory") 1 1) + (func $assert_eq (param i32 i32) + (i32.ne (local.get 0) (local.get 1)) + if + unreachable + end + ) + + (func $i32_shr_u + (call $assert_eq + (i32.shr_u (i32.const -1) (i32.const -5)) + (i32.const 31) + ) + ) + + (func $i32_shr_s + (call $assert_eq + (i32.shr_u (i32.const 32) (i32.const -30)) + (i32.const 8) + ) + ) + + (func $i32_shl + (call $assert_eq + (i32.shl (i32.const -1) (i32.const -30)) + (i32.const -4) + ) + ) + + (func (export "_start") + call $i32_shr_u + call $i32_shr_s + call $i32_shl + ) +) diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index a08031331..81844f0e7 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -14,7 +14,7 @@ function help() { echo "test_wamr.sh [options]" echo "-c clean previous test results, not start test" - echo "-s {suite_name} test only one suite (spec|wasi_certification)" + echo "-s {suite_name} test only one suite (spec|wasi_certification|wamr_compiler)" echo "-m set compile target of iwasm(x86_64|x86_32|armv7_vfp|thumbv7_vfp|riscv64_lp64d|riscv64_lp64|aarch64)" echo "-t set compile type of iwasm(classic-interp|fast-interp|jit|aot|fast-jit|multi-tier-jit)" echo "-M enable multi module feature" @@ -309,6 +309,53 @@ function sightglass_test() echo "Finish sightglass benchmark tests" } +function setup_wabt() +{ + if [ ${WABT_BINARY_RELEASE} == "YES" ]; then + echo "download a binary release and install" + local WAT2WASM=${WORK_DIR}/wabt/out/gcc/Release/wat2wasm + if [ ! -f ${WAT2WASM} ]; then + case ${PLATFORM} in + cosmopolitan) + ;& + linux) + WABT_PLATFORM=ubuntu + ;; + darwin) + WABT_PLATFORM=macos + ;; + *) + echo "wabt platform for ${PLATFORM} in unknown" + exit 1 + ;; + esac + if [ ! -f /tmp/wabt-1.0.31-${WABT_PLATFORM}.tar.gz ]; then + wget \ + https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-${WABT_PLATFORM}.tar.gz \ + -P /tmp + fi + + cd /tmp \ + && tar zxf wabt-1.0.31-${WABT_PLATFORM}.tar.gz \ + && mkdir -p ${WORK_DIR}/wabt/out/gcc/Release/ \ + && install wabt-1.0.31/bin/wa* ${WORK_DIR}/wabt/out/gcc/Release/ \ + && cd - + fi + else + echo "download source code and compile and install" + if [ ! -d "wabt" ];then + echo "wabt not exist, clone it from github" + git clone --recursive https://github.com/WebAssembly/wabt + fi + echo "upate wabt" + cd wabt + git pull + git reset --hard origin/main + cd .. + make -C wabt gcc-release -j 4 + fi +} + # TODO: with iwasm only function spec_test() { @@ -383,49 +430,7 @@ function spec_test() popd echo $(pwd) - if [ ${WABT_BINARY_RELEASE} == "YES" ]; then - echo "download a binary release and install" - local WAT2WASM=${WORK_DIR}/wabt/out/gcc/Release/wat2wasm - if [ ! -f ${WAT2WASM} ]; then - case ${PLATFORM} in - cosmopolitan) - ;& - linux) - WABT_PLATFORM=ubuntu - ;; - darwin) - WABT_PLATFORM=macos - ;; - *) - echo "wabt platform for ${PLATFORM} in unknown" - exit 1 - ;; - esac - if [ ! -f /tmp/wabt-1.0.31-${WABT_PLATFORM}.tar.gz ]; then - wget \ - https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-${WABT_PLATFORM}.tar.gz \ - -P /tmp - fi - - cd /tmp \ - && tar zxf wabt-1.0.31-${WABT_PLATFORM}.tar.gz \ - && mkdir -p ${WORK_DIR}/wabt/out/gcc/Release/ \ - && install wabt-1.0.31/bin/wa* ${WORK_DIR}/wabt/out/gcc/Release/ \ - && cd - - fi - else - echo "download source code and compile and install" - if [ ! -d "wabt" ];then - echo "wabt not exist, clone it from github" - git clone --recursive https://github.com/WebAssembly/wabt - fi - echo "upate wabt" - cd wabt - git pull - git reset --hard origin/main - cd .. - make -C wabt gcc-release -j 4 - fi + setup_wabt ln -sf ${WORK_DIR}/../spec-test-script/all.py . ln -sf ${WORK_DIR}/../spec-test-script/runtest.py . @@ -513,6 +518,28 @@ function wasi_test() echo "Finish wasi tests" } +function wamr_compiler_test() +{ + if [[ $1 != "aot" ]]; then + echo "WAMR compiler tests only support AOT mode" + exit 1 + fi + + echo "Now start WAMR compiler tests" + setup_wabt + cd ${WORK_DIR}/../wamr-compiler-test-script + ./run_wamr_compiler_tests.sh ${WORK_DIR}/wabt/out/gcc/Release/wat2wasm $WAMRC_CMD $IWASM_CMD \ + | tee -a ${REPORT_DIR}/wamr_compiler_test_report.txt + + ret=${PIPESTATUS[0]} + + if [[ ${ret} -ne 0 ]];then + echo -e "\nWAMR compiler tests FAILED" | tee -a ${REPORT_DIR}/wamr_compiler_test_report.txt + exit 1 + fi + echo -e "\nFinish WAMR compiler tests" | tee -a ${REPORT_DIR}/wamr_compiler_test_report.txt +} + function wasi_certification_test() { echo "Now start wasi certification tests" diff --git a/tests/wamr-test-suites/wamr-compiler-test-script/run_wamr_compiler_tests.sh b/tests/wamr-test-suites/wamr-compiler-test-script/run_wamr_compiler_tests.sh new file mode 100755 index 000000000..19c8030d0 --- /dev/null +++ b/tests/wamr-test-suites/wamr-compiler-test-script/run_wamr_compiler_tests.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Copyright (C) 2023 Amazon Inc. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set -e + +WAT2WASM_CMD=$1 +WAMRC_CMD=$2 +IWASM_CMD=$3 + +for wat_file in ../../wamr-compiler/*.wat; do + wasm_file="${wat_file%.wat}.wasm" + aot_file="${wat_file%.wat}.aot" + + echo "Compiling $wat_file to $wasm_file" + $WAT2WASM_CMD "$wat_file" -o "$wasm_file" + echo "Compiling $wasm_file to $aot_file" + $WAMRC_CMD -o $aot_file $wasm_file + echo "Testing $aot_file" + $IWASM_CMD "$aot_file" +done From 7c22bde8dc8e5aa748f1d65c10f7943087401009 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Sun, 8 Oct 2023 08:36:49 +0800 Subject: [PATCH 16/17] CI: Enable testing AOT multi-module feature (#2621) And refine some code pieces. --- .github/workflows/compilation_on_android_ubuntu.yml | 8 ++------ .github/workflows/compilation_on_macos.yml | 4 +--- .github/workflows/compilation_on_sgx.yml | 3 --- .github/workflows/nightly_run.yml | 12 ++++-------- core/iwasm/aot/aot_loader.c | 5 ++++- core/iwasm/common/wasm_runtime_common.c | 6 ++---- .../sandboxed-system-primitives/src/posix.c | 4 ++-- product-mini/platforms/posix/main.c | 4 ++-- product-mini/platforms/windows/main.c | 4 ++-- 9 files changed, 19 insertions(+), 31 deletions(-) diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index 3d6e44c6b..6b653b501 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -151,9 +151,7 @@ jobs: exclude: # uncompatiable feature and platform # uncompatiable mode and feature - # MULTI_MODULE only on INTERP mode - - make_options_run_mode: $AOT_BUILD_OPTIONS - make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" + # MULTI_MODULE only on INTERP mode and AOT mode - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS @@ -494,9 +492,7 @@ jobs: test_option: $SIMD_TEST_OPTIONS - running_mode: "fast-interp" test_option: $SIMD_TEST_OPTIONS - # aot and jit don't support multi module - - running_mode: "aot" - test_option: $MULTI_MODULES_TEST_OPTIONS + # llvm jit doesn't support multi module - running_mode: "jit" test_option: $MULTI_MODULES_TEST_OPTIONS # fast-jit doesn't support multi module, simd diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml index f06833185..aac16898b 100644 --- a/.github/workflows/compilation_on_macos.yml +++ b/.github/workflows/compilation_on_macos.yml @@ -133,13 +133,11 @@ jobs: exclude: # uncompatiable feature and platform # uncompatiable mode and feature - # MULTI_MODULE only on INTERP mode + # MULTI_MODULE only on INTERP mode and AOT mode - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" - - make_options_run_mode: $AOT_BUILD_OPTIONS - make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" # SIMD only on JIT/AOT mode - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_SIMD=1" diff --git a/.github/workflows/compilation_on_sgx.yml b/.github/workflows/compilation_on_sgx.yml index dd6317067..0d19d83ad 100644 --- a/.github/workflows/compilation_on_sgx.yml +++ b/.github/workflows/compilation_on_sgx.yml @@ -101,9 +101,6 @@ jobs: platform: [linux-sgx] exclude: # uncompatiable mode and feature - # MULTI_MODULE only on INTERP mode - - make_options_run_mode: $AOT_BUILD_OPTIONS - make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" # MINI_LOADER only on INTERP mode - make_options_run_mode: $AOT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index ea79b3f23..bef639792 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -127,9 +127,7 @@ jobs: exclude: # uncompatiable feature and platform # uncompatiable mode and feature - # MULTI_MODULE only on INTERP mode - - make_options_run_mode: $AOT_BUILD_OPTIONS - make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" + # MULTI_MODULE only on INTERP mode and AOT mode - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS @@ -252,7 +250,7 @@ jobs: exclude: # uncompatiable feature and platform # uncompatiable mode and feature - # MULTI_MODULE only on INTERP mode + # MULTI_MODULE only on INTERP mode and AOT mode - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" # SIMD only on JIT/AOT mode @@ -553,9 +551,7 @@ jobs: test_option: $SIMD_TEST_OPTIONS - running_mode: "fast-interp" test_option: $SIMD_TEST_OPTIONS - # aot and jit don't support multi module - - running_mode: "aot" - test_option: $MULTI_MODULES_TEST_OPTIONS + # llvm jit doesn't support multi module - running_mode: "jit" test_option: $MULTI_MODULES_TEST_OPTIONS # fast-jit doesn't support multi module, simd @@ -660,4 +656,4 @@ jobs: timeout-minutes: 40 if: env.TEST_ON_X86_32 == 'true' run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }} - working-directory: ./tests/wamr-test-suites \ No newline at end of file + working-directory: ./tests/wamr-test-suites diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 6e2fc3248..6575c8aca 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -2955,18 +2955,21 @@ create_module(char *error_buf, uint32 error_buf_size) { AOTModule *module = loader_malloc(sizeof(AOTModule), error_buf, error_buf_size); - bh_list_status ret; + if (!module) { return NULL; } + module->module_type = Wasm_Module_AoT; + #if WASM_ENABLE_MULTI_MODULE != 0 module->import_module_list = &module->import_module_list_head; ret = bh_list_init(module->import_module_list); bh_assert(ret == BH_LIST_SUCCESS); #endif (void)ret; + return module; } diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index d5c40d6e9..8faa5e444 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -126,13 +126,11 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst, } #if WASM_ENABLE_MULTI_MODULE != 0 -/* - TODO: - Let loader_malloc be a general API both for AOT and WASM. -*/ +/* TODO: Let loader_malloc be a general API both for AOT and WASM. */ #define loader_malloc(size, error_buf, error_buf_size) \ runtime_malloc(size, NULL, error_buf, error_buf_size) + static void set_error_buf_v(const WASMModuleCommon *module, char *error_buf, uint32 error_buf_size, const char *format, ...) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 415a66463..0ba91a7e9 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -710,8 +710,8 @@ fd_object_release(wasm_exec_env_t env, struct fd_object *fo) bool fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) { - __wasi_filetype_t type; - __wasi_rights_t rights_base, rights_inheriting; + __wasi_filetype_t type = __WASI_FILETYPE_UNKNOWN; + __wasi_rights_t rights_base = 0, rights_inheriting = 0; struct fd_object *fo; __wasi_errno_t error; diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index b7d755410..b27bd8c2e 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -422,7 +422,7 @@ static bool module_reader_callback(package_type_t module_type, const char *module_name, uint8 **p_buffer, uint32 *p_size) { - char *file_format; + char *file_format = NULL; #if WASM_ENABLE_INTERP != 0 if (module_type == Wasm_Module_Bytecode) file_format = ".wasm"; @@ -430,8 +430,8 @@ module_reader_callback(package_type_t module_type, const char *module_name, #if WASM_ENABLE_AOT != 0 if (module_type == Wasm_Module_AoT) file_format = ".aot"; - #endif + bh_assert(file_format); const char *format = "%s/%s%s"; int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + strlen(file_format) + 1; diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 985c9e6c7..f6347919b 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -206,7 +206,7 @@ static bool module_reader_callback(package_type_t module_type, const char *module_name, uint8 **p_buffer, uint32 *p_size) { - char *file_format; + char *file_format = NULL; #if WASM_ENABLE_INTERP != 0 if (module_type == Wasm_Module_Bytecode) file_format = ".wasm"; @@ -214,8 +214,8 @@ module_reader_callback(package_type_t module_type, const char *module_name, #if WASM_ENABLE_AOT != 0 if (module_type == Wasm_Module_AoT) file_format = ".aot"; - #endif + bh_assert(file_format); const char *format = "%s/%s%s"; int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + strlen(file_format) + 1; From 059fbfc2523e8f64e4613d38de681e2365ed76fb Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Sun, 8 Oct 2023 09:17:54 +0800 Subject: [PATCH 17/17] Fix potential issue in aot compiler when translating block opcodes (#2622) The LLVM zext IR may be inserted after the terminator of a basic block when popping the arguments of a wasm block. Change to insert the zext IR before the terminator of the basic block to resolve the issue. Reported in #2620. --- core/iwasm/compilation/aot_emit_control.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index 7e710f914..446ca5ea6 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -281,7 +281,7 @@ push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx, AOTBlock *block) { uint32 i, param_index; - LLVMValueRef value; + LLVMValueRef value, br_inst; uint64 size; char name[32]; LLVMBasicBlockRef block_curr = CURR_BLOCK(); @@ -329,7 +329,14 @@ push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx, } } } - SET_BUILDER_POS(block_curr); + + /* At this point, the branch instruction was already built to jump to + * the new BB, to avoid generating zext instruction from the popped + * operand that would come after branch instruction, we should position + * the builder before the last branch instruction */ + br_inst = LLVMGetLastInstruction(block_curr); + bh_assert(LLVMGetInstructionOpcode(br_inst) == LLVMBr); + LLVMPositionBuilderBefore(comp_ctx->builder, br_inst); /* Pop param values from current block's * value stack and add to param phis.