From 1329e1d3e1c9d693bdbb72c229ebad469e2d1381 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 21 Aug 2024 12:22:23 +0800 Subject: [PATCH] Add support for multi-memory proposal in classic interpreter (#3742) Implement multi-memory for classic-interpreter. Support core spec (and bulk memory) opcodes now, and will support atomic opcodes, and add multi-memory export APIs in the future. PS: Multi-memory spec test patched a lot for linking test to adapt for multi-module implementation. --- .../compilation_on_android_ubuntu.yml | 44 +- .github/workflows/nightly_run.yml | 26 +- build-scripts/config_common.cmake | 5 + core/config.h | 5 + core/iwasm/aot/aot_runtime.c | 7 + core/iwasm/aot/aot_runtime.h | 4 + core/iwasm/common/wasm_memory.c | 38 +- core/iwasm/common/wasm_runtime_common.c | 50 +- core/iwasm/compilation/aot.c | 1 + core/iwasm/compilation/aot_emit_memory.c | 1 + core/iwasm/fast-jit/fe/jit_emit_memory.c | 1 + core/iwasm/interpreter/wasm.h | 8 + core/iwasm/interpreter/wasm_interp_classic.c | 156 ++- core/iwasm/interpreter/wasm_interp_fast.c | 1 + core/iwasm/interpreter/wasm_loader.c | 107 +- core/iwasm/interpreter/wasm_mini_loader.c | 103 +- core/iwasm/interpreter/wasm_runtime.c | 259 +++-- core/iwasm/interpreter/wasm_runtime.h | 7 + .../wamr-test-suites/spec-test-script/all.py | 26 +- .../multi_memory_ignore_cases.patch | 1022 +++++++++++++++++ .../spec-test-script/runtest.py | 5 + tests/wamr-test-suites/test_wamr.sh | 44 +- 22 files changed, 1658 insertions(+), 262 deletions(-) create mode 100644 tests/wamr-test-suites/spec-test-script/multi_memory_ignore_cases.patch diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index d4d32908..249a6f27 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -68,6 +68,7 @@ env: WAMR_COMPILER_TEST_OPTIONS: "-s wamr_compiler -S -b -P" GC_TEST_OPTIONS: "-s spec -G -b -P" MEMORY64_TEST_OPTIONS: "-s spec -W -b -P" + MULTI_MEMORY_TEST_OPTIONS: "-s spec -E -b -P" jobs: build_llvm_libraries_on_ubuntu_2204: @@ -148,6 +149,7 @@ jobs: "-DWAMR_BUILD_TAIL_CALL=1", "-DWAMR_DISABLE_HW_BOUND_CHECK=1", "-DWAMR_BUILD_MEMORY64=1", + "-DWAMR_BUILD_MULTI_MEMORY=1", ] os: [ubuntu-22.04] platform: [android, linux] @@ -206,11 +208,9 @@ jobs: make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - # Memory64 only on CLASSIC INTERP mode, and only on 64-bit platform + # Memory64 only on CLASSIC INTERP and AOT mode, and only on 64-bit platform - make_options_feature: "-DWAMR_BUILD_MEMORY64=1" platform: android - - make_options_run_mode: $AOT_BUILD_OPTIONS - make_options_feature: "-DWAMR_BUILD_MEMORY64=1" - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MEMORY64=1" - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS @@ -221,6 +221,21 @@ jobs: make_options_feature: "-DWAMR_BUILD_MEMORY64=1" - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + # Multi memory only on CLASSIC INTERP mode, and only on 64-bit platform + - make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + platform: android + - make_options_run_mode: $AOT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" # Fast-JIT and Multi-Tier-JIT mode don't support android - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS platform: android @@ -593,6 +608,7 @@ jobs: $WASI_TEST_OPTIONS, $GC_TEST_OPTIONS, $MEMORY64_TEST_OPTIONS, + $MULTI_MEMORY_TEST_OPTIONS, ] wasi_sdk_release: [ @@ -640,18 +656,30 @@ jobs: test_option: $MEMORY64_TEST_OPTIONS - running_mode: "multi-tier-jit" test_option: $MEMORY64_TEST_OPTIONS + # aot, fast-interp, fast-jit, llvm-jit, multi-tier-jit don't support Multi Memory + - running_mode: "aot" + test_option: $MULTI_MEMORY_TEST_OPTIONS + - running_mode: "fast-interp" + test_option: $MULTI_MEMORY_TEST_OPTIONS + - running_mode: "fast-jit" + test_option: $MULTI_MEMORY_TEST_OPTIONS + - running_mode: "jit" + test_option: $MULTI_MEMORY_TEST_OPTIONS + - running_mode: "multi-tier-jit" + test_option: $MULTI_MEMORY_TEST_OPTIONS + steps: - name: checkout uses: actions/checkout@v4 - name: Set-up OCaml uses: ocaml/setup-ocaml@v3 - if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS' + if: matrix.test_option == '$GC_TEST_OPTIONS' with: ocaml-compiler: 4.13 - name: Set-up Ocamlbuild - if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS' + if: matrix.test_option == '$GC_TEST_OPTIONS' run: opam install ocamlbuild dune menhir - name: download and install wasi-sdk @@ -717,13 +745,13 @@ jobs: - name: run tests timeout-minutes: 30 - if: matrix.test_option != '$GC_TEST_OPTIONS' && matrix.test_option != '$MEMORY64_TEST_OPTIONS' + if: matrix.test_option != '$GC_TEST_OPTIONS' run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} working-directory: ./tests/wamr-test-suites - - name: run gc or memory64 tests + - name: run gc tests timeout-minutes: 20 - if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS' + if: matrix.test_option == '$GC_TEST_OPTIONS' run: | eval $(opam env) ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index 204cadc9..f39085d0 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -132,6 +132,7 @@ jobs: "-DWAMR_BUILD_TAIL_CALL=1", "-DWAMR_DISABLE_HW_BOUND_CHECK=1", "-DWAMR_BUILD_MEMORY64=1", + "-DWAMR_BUILD_MULTI_MEMORY=1", ] os: [ubuntu-20.04] platform: [android, linux] @@ -190,11 +191,9 @@ jobs: make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - # Memory64 only on CLASSIC INTERP mode, and only on 64-bit platform + # Memory64 only on CLASSIC INTERP and AOT mode, and only on 64-bit platform - make_options_feature: "-DWAMR_BUILD_MEMORY64=1" platform: android - - make_options_run_mode: $AOT_BUILD_OPTIONS - make_options_feature: "-DWAMR_BUILD_MEMORY64=1" - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MEMORY64=1" - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS @@ -205,6 +204,21 @@ jobs: make_options_feature: "-DWAMR_BUILD_MEMORY64=1" - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + # Multi memory only on CLASSIC INTERP mode, and only on 64-bit platform + - make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + platform: android + - make_options_run_mode: $AOT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" # Fast-JIT and Multi-Tier-JIT mode don't support android - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS platform: android @@ -289,6 +303,7 @@ jobs: "-DWAMR_BUILD_TAIL_CALL=1", "-DWAMR_DISABLE_HW_BOUND_CHECK=1", "-DWAMR_BUILD_MEMORY64=1", + "-DWAMR_BUILD_MULTI_MEMORY=1", ] exclude: # incompatible feature and platform @@ -322,6 +337,11 @@ jobs: make_options_feature: "-DWAMR_BUILD_MEMORY64=1" - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MEMORY64=1" + # Memory64 only on CLASSIC INTERP mode + - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" + - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MEMORY=1" steps: - name: Install dependencies run: | diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index d4dd2c0d..252ba3a8 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -265,6 +265,11 @@ if (WAMR_BUILD_MEMORY64 EQUAL 1) set (WAMR_DISABLE_HW_BOUND_CHECK 1) message (" Memory64 memory enabled") endif () +if (WAMR_BUILD_MULTI_MEMORY EQUAL 1) + add_definitions (-DWASM_ENABLE_MULTI_MEMORY=1) + message (" Multi memory enabled") + set (WAMR_BUILD_DEBUG_INTERP 0) +endif () if (WAMR_BUILD_THREAD_MGR EQUAL 1) message (" Thread manager enabled") endif () diff --git a/core/config.h b/core/config.h index 7c783dd3..a25eb543 100644 --- a/core/config.h +++ b/core/config.h @@ -664,6 +664,11 @@ #define WASM_ENABLE_MEMORY64 0 #endif +/* Disable multi-memory by default */ +#ifndef WASM_ENABLE_MULTI_MEMORY +#define WASM_ENABLE_MULTI_MEMORY 0 +#endif + #ifndef WASM_TABLE_MAX_SIZE #define WASM_TABLE_MAX_SIZE 1024 #endif diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 7e8799e0..3ca26114 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -2817,6 +2817,13 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) return wasm_enlarge_memory(module_inst, inc_page_count); } +bool +aot_enlarge_memory_with_idx(AOTModuleInstance *module_inst, + uint32 inc_page_count, uint32 memidx) +{ + return wasm_enlarge_memory_with_idx(module_inst, inc_page_count, memidx); +} + bool aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, uint32 *argv) diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index e3704f82..d109ceba 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -605,6 +605,10 @@ aot_module_dup_data(AOTModuleInstance *module_inst, const char *src, bool aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count); +bool +aot_enlarge_memory_with_idx(AOTModuleInstance *module_inst, + uint32 inc_page_count, uint32 memidx); + /** * Invoke native function from aot code */ diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 187b4de0..71d33754 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -670,6 +670,16 @@ wasm_get_default_memory(WASMModuleInstance *module_inst) return NULL; } +WASMMemoryInstance * +wasm_get_memory_with_idx(WASMModuleInstance *module_inst, uint32 index) +{ + bh_assert(index < module_inst->memory_count); + if (module_inst->memories) + return module_inst->memories[index]; + else + return NULL; +} + void wasm_runtime_set_mem_bound_check_bytes(WASMMemoryInstance *memory, uint64 memory_data_size) @@ -747,9 +757,14 @@ wasm_mmap_linear_memory(uint64_t map_size, uint64 commit_size) } bool -wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) +wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count, + uint32 memidx) { +#if WASM_ENABLE_MULTI_MEMORY != 0 + WASMMemoryInstance *memory = wasm_get_memory_with_idx(module, memidx); +#else WASMMemoryInstance *memory = wasm_get_default_memory(module); +#endif uint8 *memory_data_old, *memory_data_new, *heap_data_old; uint32 num_bytes_per_page, heap_size; uint32 cur_page_count, max_page_count, total_page_count; @@ -960,7 +975,7 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) if (module->memory_count > 0) shared_memory_lock(module->memories[0]); #endif - ret = wasm_enlarge_memory_internal(module, inc_page_count); + ret = wasm_enlarge_memory_internal(module, inc_page_count, 0); #if WASM_ENABLE_SHARED_MEMORY != 0 if (module->memory_count > 0) shared_memory_unlock(module->memories[0]); @@ -969,6 +984,25 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) return ret; } +bool +wasm_enlarge_memory_with_idx(WASMModuleInstance *module, uint32 inc_page_count, + uint32 memidx) +{ + bool ret = false; + +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (memidx < module->memory_count) + shared_memory_lock(module->memories[memidx]); +#endif + ret = wasm_enlarge_memory_internal(module, inc_page_count, memidx); +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (memidx < module->memory_count) + shared_memory_unlock(module->memories[memidx]); +#endif + + return ret; +} + void wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst) { diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index f54ac4ab..5dd2957d 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -181,15 +181,36 @@ static RunningMode runtime_running_mode = Mode_Default; of signal handler */ static os_thread_local_attribute WASMExecEnv *exec_env_tls = NULL; +static bool +is_sig_addr_in_guard_pages(void *sig_addr, WASMModuleInstance *module_inst) +{ + WASMMemoryInstance *memory_inst; + uint8 *mapped_mem_start_addr = NULL; + uint8 *mapped_mem_end_addr = NULL; + uint32 i; + + for (i = 0; i < module_inst->memory_count; ++i) { + /* To be compatible with multi memory, get the ith memory instance */ + memory_inst = wasm_get_memory_with_idx(module_inst, i); + mapped_mem_start_addr = memory_inst->memory_data; + mapped_mem_end_addr = memory_inst->memory_data + 8 * (uint64)BH_GB; + if (mapped_mem_start_addr <= (uint8 *)sig_addr + && (uint8 *)sig_addr < mapped_mem_end_addr) { + /* The address which causes segmentation fault is inside + the memory instance's guard regions */ + return true; + } + } + + return false; +} + #ifndef BH_PLATFORM_WINDOWS static void runtime_signal_handler(void *sig_addr) { WASMModuleInstance *module_inst; - WASMMemoryInstance *memory_inst; WASMJmpBuf *jmpbuf_node; - uint8 *mapped_mem_start_addr = NULL; - uint8 *mapped_mem_end_addr = NULL; uint32 page_size = os_getpagesize(); #if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 uint8 *stack_min_addr; @@ -201,23 +222,13 @@ runtime_signal_handler(void *sig_addr) && (jmpbuf_node = exec_env_tls->jmpbuf_stack_top)) { /* Get mapped mem info of current instance */ module_inst = (WASMModuleInstance *)exec_env_tls->module_inst; - /* Get the default memory instance */ - memory_inst = wasm_get_default_memory(module_inst); - if (memory_inst) { - mapped_mem_start_addr = memory_inst->memory_data; - mapped_mem_end_addr = memory_inst->memory_data + 8 * (uint64)BH_GB; - } #if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 /* Get stack info of current thread */ stack_min_addr = os_thread_get_stack_boundary(); #endif - if (memory_inst - && (mapped_mem_start_addr <= (uint8 *)sig_addr - && (uint8 *)sig_addr < mapped_mem_end_addr)) { - /* The address which causes segmentation fault is inside - the memory instance's guard regions */ + if (is_sig_addr_in_guard_pages(sig_addr, module_inst)) { wasm_set_exception(module_inst, "out of bounds memory access"); os_longjmp(jmpbuf_node->jmpbuf, 1); } @@ -340,16 +351,7 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) && (jmpbuf_node = exec_env_tls->jmpbuf_stack_top)) { module_inst = (WASMModuleInstance *)exec_env_tls->module_inst; if (ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { - /* Get the default memory instance */ - memory_inst = wasm_get_default_memory(module_inst); - if (memory_inst) { - mapped_mem_start_addr = memory_inst->memory_data; - mapped_mem_end_addr = - memory_inst->memory_data + 8 * (uint64)BH_GB; - } - - if (memory_inst && mapped_mem_start_addr <= (uint8 *)sig_addr - && (uint8 *)sig_addr < mapped_mem_end_addr) { + if (is_sig_addr_in_guard_pages(sig_addr, module_inst)) { /* The address which causes segmentation fault is inside the memory instance's guard regions. Set exception and let the wasm func continue to run, when diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c index 2bacae87..0a2cae1f 100644 --- a/core/iwasm/compilation/aot.c +++ b/core/iwasm/compilation/aot.c @@ -540,6 +540,7 @@ aot_create_comp_data(WASMModule *module, const char *target_arch, /* TODO: create import memories */ /* Allocate memory for memory array, reserve one AOTMemory space at least */ + /* TODO: multi-memory */ if (!comp_data->memory_count) comp_data->memory_count = 1; diff --git a/core/iwasm/compilation/aot_emit_memory.c b/core/iwasm/compilation/aot_emit_memory.c index e7c9b679..806150ff 100644 --- a/core/iwasm/compilation/aot_emit_memory.c +++ b/core/iwasm/compilation/aot_emit_memory.c @@ -895,6 +895,7 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) POP_PAGE_COUNT(delta); + /* TODO: multi-memory aot_enlarge_memory_with_idx() */ /* Function type of aot_enlarge_memory() */ param_types[0] = INT8_PTR_TYPE; param_types[1] = I32_TYPE; diff --git a/core/iwasm/fast-jit/fe/jit_emit_memory.c b/core/iwasm/fast-jit/fe/jit_emit_memory.c index ea245ba3..bbe82cf6 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_memory.c +++ b/core/iwasm/fast-jit/fe/jit_emit_memory.c @@ -602,6 +602,7 @@ jit_compile_op_memory_grow(JitCompContext *cc, uint32 mem_idx) args[0] = get_module_inst_reg(cc->jit_frame); args[1] = inc_page_count; + /* TODO: multi-memory wasm_enlarge_memory_with_idx() */ if (!jit_emit_callnative(cc, wasm_enlarge_memory, grow_res, args, 2)) { goto fail; } diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index ea93adb0..e043465d 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -94,6 +94,14 @@ extern "C" { #define SHARED_MEMORY_FLAG 0x02 #define MEMORY64_FLAG 0x04 +/** + * In the multi-memory proposal, the memarg in loads and stores are + * reinterpreted as a bitfield, bit 6 serves as a flag indicating the presence + * of the optional memory index, if it is set, then an i32 memory index follows + * after the alignment bitfield + */ +#define OPT_MEMIDX_FLAG 0x40 + #define DEFAULT_NUM_BYTES_PER_PAGE 65536 #define DEFAULT_MAX_PAGES 65536 #define DEFAULT_MEM64_MAX_PAGES UINT32_MAX diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 766d2f52..4a8ba4e2 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -697,6 +697,44 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame) #define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res) #endif +#if WASM_ENABLE_MULTI_MEMORY != 0 +/* If the current memidx differs than the last cached one, + * update memory related information */ +#define read_leb_memidx(p, p_end, res) \ + do { \ + read_leb_uint32(p, p_end, res); \ + if (res != memidx_cached) { \ + memory = wasm_get_memory_with_idx(module, res); \ + linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory); \ + memidx_cached = res; \ + } \ + } while (0) +/* First read the alignment, then if it has flag indicating following memidx, + * read and update memory related information, if it differs than the + * last(cached) one. If it doesn't have flag reset the + * memory instance to the default memories[0] */ +#define read_leb_memarg(p, p_end, res) \ + do { \ + read_leb_uint32(p, p_end, res); \ + if (!(res & OPT_MEMIDX_FLAG)) \ + memidx = 0; \ + else \ + read_leb_uint32(p, p_end, memidx); \ + if (memidx != memidx_cached) { \ + memory = wasm_get_memory_with_idx(module, memidx); \ + linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory); \ + memidx_cached = memidx; \ + } \ + } while (0) +#else +#define read_leb_memarg(p, p_end, res) \ + do { \ + read_leb_uint32(p, p_end, res); \ + (void)res; \ + } while (0) +#define read_leb_memidx(p, p_end, res) read_leb_memarg(p, p_end, res) +#endif + #if WASM_ENABLE_LABELS_AS_VALUES == 0 #define RECOVER_FRAME_IP_END() frame_ip_end = wasm_get_func_code_end(cur_func) #else @@ -1567,6 +1605,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (memory) is_memory64 = memory->is_memory64; #endif +#if WASM_ENABLE_MULTI_MEMORY != 0 + uint32 memidx = 0; + uint32 memidx_cached = (uint32)-1; +#endif #if WASM_ENABLE_DEBUG_INTERP != 0 uint8 *frame_ip_orig = NULL; @@ -4292,13 +4334,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(4); PUSH_I32(LOAD_I32(maddr)); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4308,13 +4349,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(8); PUSH_I64(LOAD_I64(maddr)); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4323,13 +4363,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(1); PUSH_I32(sign_ext_8_32(*(int8 *)maddr)); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4338,13 +4377,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(1); PUSH_I32((uint32)(*(uint8 *)maddr)); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4353,13 +4391,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(2); PUSH_I32(sign_ext_16_32(LOAD_I16(maddr))); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4368,13 +4405,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(2); PUSH_I32((uint32)(LOAD_U16(maddr))); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4383,13 +4419,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(1); PUSH_I64(sign_ext_8_64(*(int8 *)maddr)); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4398,13 +4433,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(1); PUSH_I64((uint64)(*(uint8 *)maddr)); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4413,13 +4447,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(2); PUSH_I64(sign_ext_16_64(LOAD_I16(maddr))); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4428,13 +4461,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(2); PUSH_I64((uint64)(LOAD_U16(maddr))); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4443,14 +4475,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - opcode = *(frame_ip - 1); - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(4); PUSH_I64(sign_ext_32_64(LOAD_I32(maddr))); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4459,13 +4489,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); addr = POP_MEM_OFFSET(); CHECK_MEMORY_OVERFLOW(4); PUSH_I64((uint64)(LOAD_U32(maddr))); CHECK_READ_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4476,7 +4505,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); frame_sp--; addr = POP_MEM_OFFSET(); @@ -4491,7 +4520,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, STORE_U32(maddr, frame_sp[1]); } CHECK_WRITE_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4501,7 +4529,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 flags; mem_offset_t offset, addr; - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); frame_sp -= 2; addr = POP_MEM_OFFSET(); @@ -4519,7 +4547,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, GET_I64_FROM_ADDR(frame_sp + 1)); } CHECK_WRITE_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4531,7 +4558,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 sval; opcode = *(frame_ip - 1); - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); sval = (uint32)POP_I32(); addr = POP_MEM_OFFSET(); @@ -4545,7 +4572,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, STORE_U16(maddr, (uint16)sval); } CHECK_WRITE_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } @@ -4558,7 +4584,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint64 sval; opcode = *(frame_ip - 1); - read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_memarg(frame_ip, frame_ip_end, flags); read_leb_mem_offset(frame_ip, frame_ip_end, offset); sval = (uint64)POP_I64(); addr = POP_MEM_OFFSET(); @@ -4576,29 +4602,27 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, STORE_U32(maddr, (uint32)sval); } CHECK_WRITE_WATCHPOINT(addr, offset); - (void)flags; HANDLE_OP_END(); } /* memory size and memory grow instructions */ HANDLE_OP(WASM_OP_MEMORY_SIZE) { - uint32 reserved; - read_leb_uint32(frame_ip, frame_ip_end, reserved); + uint32 mem_idx; + read_leb_memidx(frame_ip, frame_ip_end, mem_idx); PUSH_PAGE_COUNT(memory->cur_page_count); - (void)reserved; HANDLE_OP_END(); } HANDLE_OP(WASM_OP_MEMORY_GROW) { - uint32 reserved, delta, - prev_page_count = memory->cur_page_count; + uint32 mem_idx, delta, prev_page_count; - read_leb_uint32(frame_ip, frame_ip_end, reserved); + read_leb_memidx(frame_ip, frame_ip_end, mem_idx); + prev_page_count = memory->cur_page_count; delta = (uint32)POP_PAGE_COUNT(); - if (!wasm_enlarge_memory(module, delta)) { + if (!wasm_enlarge_memory_with_idx(module, delta, mem_idx)) { /* failed to memory.grow, return -1 */ PUSH_PAGE_COUNT(-1); } @@ -4614,7 +4638,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #endif } - (void)reserved; HANDLE_OP_END(); } @@ -5610,8 +5633,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint8 *data; read_leb_uint32(frame_ip, frame_ip_end, segment); +#if WASM_ENABLE_MULTI_MEMORY != 0 + read_leb_memidx(frame_ip, frame_ip_end, memidx); +#else /* skip memory index */ frame_ip++; +#endif bytes = (uint64)(uint32)POP_I32(); offset = (uint64)(uint32)POP_I32(); @@ -5660,33 +5687,54 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { mem_offset_t dst, src, len; uint8 *mdst, *msrc; + uint64 dlen; - frame_ip += 2; len = POP_MEM_OFFSET(); src = POP_MEM_OFFSET(); dst = POP_MEM_OFFSET(); +#if WASM_ENABLE_MULTI_MEMORY != 0 + /* dst memidx */ + read_leb_memidx(frame_ip, frame_ip_end, memidx); +#else + /* skip dst memidx */ + frame_ip += 1; +#endif #if WASM_ENABLE_THREAD_MGR != 0 linear_mem_size = get_linear_mem_size(); #endif - + /* dst boundary check */ #ifndef OS_ENABLE_HW_BOUND_CHECK - CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc); CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); #else - if ((uint64)(uint32)src + len > linear_mem_size) + if ((uint64)dst + len > linear_mem_size) goto out_of_bounds; - msrc = memory->memory_data + (uint32)src; + mdst = memory->memory_data + dst; +#endif + dlen = linear_mem_size - dst; - if ((uint64)(uint32)dst + len > linear_mem_size) +#if WASM_ENABLE_MULTI_MEMORY != 0 + /* src memidx */ + read_leb_memidx(frame_ip, frame_ip_end, memidx); +#else + /* skip src memidx */ + frame_ip += 1; +#endif +#if WASM_ENABLE_THREAD_MGR != 0 + linear_mem_size = get_linear_mem_size(); +#endif + /* src boundary check */ +#ifndef OS_ENABLE_HW_BOUND_CHECK + CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc); +#else + if ((uint64)src + len > linear_mem_size) goto out_of_bounds; - mdst = memory->memory_data + (uint32)dst; + msrc = memory->memory_data + src; #endif - /* allowing the destination and source to overlap */ #if WASM_ENABLE_MEMORY64 == 0 - bh_memmove_s(mdst, (uint32)(linear_mem_size - dst), - msrc, (uint32)len); + /* allowing the destination and source to overlap */ + bh_memmove_s(mdst, (uint32)dlen, msrc, (uint32)len); #else /* use memmove when memory64 is enabled since len may be larger than UINT32_MAX */ @@ -5698,7 +5746,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { mem_offset_t dst, len; uint8 fill_val, *mdst; + +#if WASM_ENABLE_MULTI_MEMORY != 0 + read_leb_memidx(frame_ip, frame_ip_end, memidx); +#else + /* skip memory index */ frame_ip++; +#endif len = POP_MEM_OFFSET(); fill_val = POP_I32(); diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 82507924..51963759 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -3837,6 +3837,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, addr_ret = GET_OFFSET(); delta = (uint32)frame_lp[addr1]; + /* TODO: multi-memory wasm_enlarge_memory_with_idx() */ if (!wasm_enlarge_memory(module, delta)) { /* failed to memory.grow, return -1 */ frame_lp[addr_ret] = -1; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 0891598d..13947ac8 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -127,6 +127,17 @@ check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length, #define skip_leb_uint32(p, p_end) skip_leb(p) #define skip_leb_int32(p, p_end) skip_leb(p) #define skip_leb_mem_offset(p, p_end) skip_leb(p) +#define skip_leb_memidx(p, p_end) skip_leb(p) +#if WASM_ENABLE_MULTI_MEMORY == 0 +#define skip_leb_align(p, p_end) skip_leb(p) +#else +/* Skip the following memidx if applicable */ +#define skip_leb_align(p, p_end) \ + do { \ + if (*p++ & OPT_MEMIDX_FLAG) \ + skip_leb_uint32(p, p_end); \ + } while (0) +#endif #define read_uint8(p) TEMPLATE_READ_VALUE(uint8, p) #define read_uint32(p) TEMPLATE_READ_VALUE(uint32, p) @@ -173,6 +184,40 @@ check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length, res = (int32)res64; \ } while (0) +#define read_leb_memidx(p, p_end, res) read_leb_uint32(p, p_end, res) +#if WASM_ENABLE_MULTI_MEMORY != 0 +#define check_memidx(module, memidx) \ + do { \ + if (memidx >= module->import_memory_count + module->memory_count) { \ + set_error_buf_v(error_buf, error_buf_size, "unknown memory %d", \ + memidx); \ + goto fail; \ + } \ + } while (0) +/* Bit 6(0x40) indicating the optional memidx, and reset bit 6 for + * alignment check */ +#define read_leb_memarg(p, p_end, res) \ + do { \ + read_leb_uint32(p, p_end, res); \ + if (res & OPT_MEMIDX_FLAG) { \ + res &= ~OPT_MEMIDX_FLAG; \ + read_leb_uint32(p, p_end, memidx); /* memidx */ \ + check_memidx(module, memidx); \ + } \ + } while (0) +#else +/* reserved byte 0x00 */ +#define check_memidx(module, memidx) \ + do { \ + (void)module; \ + if (memidx != 0) { \ + set_error_buf(error_buf, error_buf_size, "zero byte expected"); \ + goto fail; \ + } \ + } while (0) +#define read_leb_memarg(p, p_end, res) read_leb_uint32(p, p_end, res) +#endif + static char * type2str(uint8 type) { @@ -3288,11 +3333,13 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (flags & 1) read_leb_uint32(p, p_end, u32); module->import_memory_count++; +#if WASM_ENABLE_MULTI_MEMORY == 0 if (module->import_memory_count > 1) { set_error_buf(error_buf, error_buf_size, "multiple memories"); return false; } +#endif break; #if WASM_ENABLE_TAGS != 0 @@ -3903,11 +3950,14 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, WASMMemory *memory; read_leb_uint32(p, p_end, memory_count); + +#if WASM_ENABLE_MULTI_MEMORY == 0 /* a total of one memory is allowed */ if (module->import_memory_count + memory_count > 1) { set_error_buf(error_buf, error_buf_size, "multiple memories"); return false; } +#endif if (memory_count) { module->memory_count = memory_count; @@ -7258,13 +7308,13 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE32: - skip_leb_uint32(p, p_end); /* align */ + skip_leb_align(p, p_end); /* align */ skip_leb_mem_offset(p, p_end); /* offset */ break; case WASM_OP_MEMORY_SIZE: case WASM_OP_MEMORY_GROW: - skip_leb_uint32(p, p_end); /* 0x00 */ + skip_leb_memidx(p, p_end); /* memidx */ break; case WASM_OP_I32_CONST: @@ -7562,19 +7612,17 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if WASM_ENABLE_BULK_MEMORY != 0 case WASM_OP_MEMORY_INIT: skip_leb_uint32(p, p_end); - /* skip memory idx */ - p++; + skip_leb_memidx(p, p_end); break; case WASM_OP_DATA_DROP: skip_leb_uint32(p, p_end); break; case WASM_OP_MEMORY_COPY: - /* skip two memory idx */ - p += 2; + skip_leb_memidx(p, p_end); + skip_leb_memidx(p, p_end); break; case WASM_OP_MEMORY_FILL: - /* skip memory idx */ - p++; + skip_leb_memidx(p, p_end); break; #endif /* WASM_ENABLE_BULK_MEMORY */ #if WASM_ENABLE_REF_TYPES != 0 @@ -7701,7 +7749,6 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if WASM_ENABLE_SHARED_MEMORY != 0 case WASM_OP_ATOMIC_PREFIX: { - /* TODO: memory64 offset type changes */ uint32 opcode1; /* atomic_op (u32_leb) + memarg (2 u32_leb) */ @@ -10876,6 +10923,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #else mem_offset_type = VALUE_TYPE_I32; #endif + uint32 memidx; global_count = module->import_global_count + module->global_count; @@ -13155,7 +13203,7 @@ re_scan: } #endif CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ + read_leb_memarg(p, p_end, align); /* align */ read_leb_mem_offset(p, p_end, mem_offset); /* offset */ if (!check_memory_access_align(opcode, align, error_buf, error_buf_size)) { @@ -13221,12 +13269,8 @@ re_scan: case WASM_OP_MEMORY_SIZE: CHECK_MEMORY(); - /* reserved byte 0x00 */ - if (*p++ != 0x00) { - set_error_buf(error_buf, error_buf_size, - "zero byte expected"); - goto fail; - } + read_leb_uint32(p, p_end, memidx); + check_memidx(module, memidx); PUSH_PAGE_COUNT(); module->possible_memory_grow = true; @@ -13237,12 +13281,8 @@ re_scan: case WASM_OP_MEMORY_GROW: CHECK_MEMORY(); - /* reserved byte 0x00 */ - if (*p++ != 0x00) { - set_error_buf(error_buf, error_buf_size, - "zero byte expected"); - goto fail; - } + read_leb_uint32(p, p_end, memidx); + check_memidx(module, memidx); POP_AND_PUSH(mem_offset_type, mem_offset_type); module->possible_memory_grow = true; @@ -14594,8 +14634,8 @@ re_scan: && module->memory_count == 0) goto fail_unknown_memory; - if (*p++ != 0x00) - goto fail_zero_byte_expected; + read_leb_uint32(p, p_end, memidx); + check_memidx(module, memidx); if (data_seg_idx >= module->data_seg_count) { set_error_buf_v(error_buf, error_buf_size, @@ -14644,10 +14684,11 @@ re_scan: case WASM_OP_MEMORY_COPY: { CHECK_BUF(p, p_end, sizeof(int16)); - /* both src and dst memory index should be 0 */ - if (*(int16 *)p != 0x0000) - goto fail_zero_byte_expected; - p += 2; + /* check both src and dst memory index */ + read_leb_uint32(p, p_end, memidx); + check_memidx(module, memidx); + read_leb_uint32(p, p_end, memidx); + check_memidx(module, memidx); if (module->import_memory_count == 0 && module->memory_count == 0) @@ -14666,9 +14707,8 @@ re_scan: } case WASM_OP_MEMORY_FILL: { - if (*p++ != 0x00) { - goto fail_zero_byte_expected; - } + read_leb_uint32(p, p_end, memidx); + check_memidx(module, memidx); if (module->import_memory_count == 0 && module->memory_count == 0) { goto fail_unknown_memory; @@ -14684,10 +14724,6 @@ re_scan: #endif break; } - fail_zero_byte_expected: - set_error_buf(error_buf, error_buf_size, - "zero byte expected"); - goto fail; fail_unknown_memory: set_error_buf(error_buf, error_buf_size, @@ -14921,7 +14957,6 @@ re_scan: #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) case WASM_OP_SIMD_PREFIX: { - /* TODO: memory64 offset type changes */ uint32 opcode1; #if WASM_ENABLE_WAMR_COMPILER != 0 diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 0bb2f34e..8826f98d 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -62,6 +62,17 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) #define skip_leb_uint32(p, p_end) skip_leb(p) #define skip_leb_int32(p, p_end) skip_leb(p) #define skip_leb_mem_offset(p, p_end) skip_leb(p) +#define skip_leb_memidx(p, p_end) skip_leb(p) +#if WASM_ENABLE_MULTI_MEMORY == 0 +#define skip_leb_align(p, p_end) skip_leb(p) +#else +/* Skip the following memidx if applicable */ +#define skip_leb_align(p, p_end) \ + do { \ + if (*p++ & OPT_MEMIDX_FLAG) \ + skip_leb_uint32(p, p_end); \ + } while (0) +#endif static bool is_32bit_type(uint8 type) @@ -132,6 +143,35 @@ is_byte_a_type(uint8 type) #else #define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res) #endif +#define read_leb_memidx(p, p_end, res) read_leb_uint32(p, p_end, res) +#if WASM_ENABLE_MULTI_MEMORY != 0 +#define check_memidx(module, memidx) \ + do { \ + bh_assert(memidx \ + < module->import_memory_count + module->memory_count); \ + (void)memidx; \ + } while (0) +/* Bit 6 indicating the optional memidx, and reset bit 6 for + * alignment check */ +#define read_leb_memarg(p, p_end, res) \ + do { \ + read_leb_uint32(p, p_end, res); \ + if (res & OPT_MEMIDX_FLAG) { \ + res &= ~OPT_MEMIDX_FLAG; \ + read_leb_uint32(p, p_end, memidx); /* memidx */ \ + check_memidx(module, memidx); \ + } \ + } while (0) +#else +/* reserved byte 0x00 */ +#define check_memidx(module, memidx) \ + do { \ + (void)module; \ + bh_assert(memidx == 0); \ + (void)memidx; \ + } while (0) +#define read_leb_memarg(p, p_end, res) read_leb_uint32(p, p_end, res) +#endif static void * loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) @@ -882,7 +922,9 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (flags & 1) read_leb_uint32(p, p_end, u32); module->import_memory_count++; +#if WASM_ENABLE_MULTI_MEMORY != 0 bh_assert(module->import_memory_count <= 1); +#endif break; case IMPORT_KIND_GLOBAL: /* import global */ @@ -1223,7 +1265,9 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, WASMMemory *memory; read_leb_uint32(p, p_end, memory_count); +#if WASM_ENABLE_MULTI_MEMORY != 0 bh_assert(module->import_memory_count + memory_count <= 1); +#endif if (memory_count) { module->memory_count = memory_count; @@ -3585,13 +3629,13 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE32: - skip_leb_uint32(p, p_end); /* align */ + skip_leb_align(p, p_end); /* align */ skip_leb_mem_offset(p, p_end); /* offset */ break; case WASM_OP_MEMORY_SIZE: case WASM_OP_MEMORY_GROW: - skip_leb_uint32(p, p_end); /* 0x00 */ + skip_leb_memidx(p, p_end); /* memidx */ break; case WASM_OP_I32_CONST: @@ -3758,19 +3802,17 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if WASM_ENABLE_BULK_MEMORY != 0 case WASM_OP_MEMORY_INIT: skip_leb_uint32(p, p_end); - /* skip memory idx */ - p++; + skip_leb_memidx(p, p_end); break; case WASM_OP_DATA_DROP: skip_leb_uint32(p, p_end); break; case WASM_OP_MEMORY_COPY: - /* skip two memory idx */ - p += 2; + skip_leb_memidx(p, p_end); + skip_leb_memidx(p, p_end); break; case WASM_OP_MEMORY_FILL: - /* skip memory idx */ - p++; + skip_leb_memidx(p, p_end); break; #endif #if WASM_ENABLE_REF_TYPES != 0 @@ -5905,7 +5947,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint8 *param_types, *local_types, local_type, global_type, mem_offset_type; BlockType func_block_type; uint16 *local_offsets, local_offset; - uint32 count, local_idx, global_idx, u32, align, i; + uint32 count, local_idx, global_idx, u32, align, i, memidx; mem_offset_t mem_offset; int32 i32, i32_const = 0; int64 i64_const; @@ -7267,7 +7309,7 @@ re_scan: } #endif CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ + read_leb_memarg(p, p_end, align); /* align */ read_leb_mem_offset(p, p_end, mem_offset); /* offset */ #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, mem_offset); @@ -7329,9 +7371,8 @@ re_scan: case WASM_OP_MEMORY_SIZE: CHECK_MEMORY(); - /* reserved byte 0x00 */ - bh_assert(*p == 0x00); - p++; + read_leb_memidx(p, p_end, memidx); + check_memidx(module, memidx); PUSH_PAGE_COUNT(); module->possible_memory_grow = true; @@ -7342,9 +7383,8 @@ re_scan: case WASM_OP_MEMORY_GROW: CHECK_MEMORY(); - /* reserved byte 0x00 */ - bh_assert(*p == 0x00); - p++; + read_leb_memidx(p, p_end, memidx); + check_memidx(module, memidx); POP_AND_PUSH(mem_offset_type, mem_offset_type); module->possible_memory_grow = true; @@ -7682,16 +7722,13 @@ re_scan: #if WASM_ENABLE_BULK_MEMORY != 0 case WASM_OP_MEMORY_INIT: { + CHECK_MEMORY(); read_leb_uint32(p, p_end, segment_index); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, segment_index); #endif - bh_assert(module->import_memory_count - + module->memory_count - > 0); - - bh_assert(*p == 0x00); - p++; + read_leb_memidx(p, p_end, memidx); + check_memidx(module, memidx); bh_assert(segment_index < module->data_seg_count); bh_assert(module->data_seg_count1 > 0); @@ -7719,14 +7756,13 @@ re_scan: } case WASM_OP_MEMORY_COPY: { + CHECK_MEMORY(); CHECK_BUF(p, p_end, sizeof(int16)); - /* both src and dst memory index should be 0 */ - bh_assert(*(int16 *)p == 0x0000); - p += 2; - - bh_assert(module->import_memory_count - + module->memory_count - > 0); + /* check both src and dst memory index */ + read_leb_memidx(p, p_end, memidx); + check_memidx(module, memidx); + read_leb_memidx(p, p_end, memidx); + check_memidx(module, memidx); POP_MEM_OFFSET(); POP_MEM_OFFSET(); @@ -7738,12 +7774,9 @@ re_scan: } case WASM_OP_MEMORY_FILL: { - bh_assert(*p == 0); - p++; - - bh_assert(module->import_memory_count - + module->memory_count - > 0); + CHECK_MEMORY(); + read_leb_memidx(p, p_end, memidx); + check_memidx(module, memidx); POP_MEM_OFFSET(); POP_I32(); diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index f3b9b2e8..f70f9cb7 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -194,114 +194,119 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, default_max_page = memory->is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES; - if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1 - && module_inst->module->free_function != (uint32)-1) { - /* Disable app heap, use malloc/free function exported - by wasm app to allocate/free memory instead */ - heap_size = 0; - } + /* The app heap should be in the default memory */ + if (memory_idx == 0) { + if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1 + && module_inst->module->free_function != (uint32)-1) { + /* Disable app heap, use malloc/free function exported + by wasm app to allocate/free memory instead */ + heap_size = 0; + } - /* If initial memory is the largest size allowed, disallowing insert host - * managed heap */ - if (heap_size > 0 - && heap_offset == GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)) { - set_error_buf(error_buf, error_buf_size, - "failed to insert app heap into linear memory, " - "try using `--heap-size=0` option"); - return NULL; - } - - if (init_page_count == max_page_count && init_page_count == 1) { - /* If only one page and at most one page, we just append - the app heap to the end of linear memory, enlarge the - num_bytes_per_page, and don't change the page count */ - heap_offset = num_bytes_per_page; - num_bytes_per_page += heap_size; - if (num_bytes_per_page < heap_size) { + /* If initial memory is the largest size allowed, disallowing insert + * host managed heap */ + if (heap_size > 0 + && heap_offset == GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)) { set_error_buf(error_buf, error_buf_size, "failed to insert app heap into linear memory, " "try using `--heap-size=0` option"); return NULL; } - } - else if (heap_size > 0) { - if (init_page_count == max_page_count && init_page_count == 0) { - /* If the memory data size is always 0, we resize it to - one page for app heap */ - num_bytes_per_page = heap_size; - heap_offset = 0; - inc_page_count = 1; - } - else if (module->aux_heap_base_global_index != (uint32)-1 - && module->aux_heap_base - < (uint64)num_bytes_per_page * init_page_count) { - /* Insert app heap before __heap_base */ - aux_heap_base = module->aux_heap_base; - bytes_of_last_page = aux_heap_base % num_bytes_per_page; - if (bytes_of_last_page == 0) - bytes_of_last_page = num_bytes_per_page; - bytes_to_page_end = num_bytes_per_page - bytes_of_last_page; - inc_page_count = - (heap_size - bytes_to_page_end + num_bytes_per_page - 1) - / num_bytes_per_page; - heap_offset = aux_heap_base; - aux_heap_base += heap_size; - bytes_of_last_page = aux_heap_base % num_bytes_per_page; - if (bytes_of_last_page == 0) - bytes_of_last_page = num_bytes_per_page; - bytes_to_page_end = num_bytes_per_page - bytes_of_last_page; - if (bytes_to_page_end < 1 * BH_KB) { - aux_heap_base += 1 * BH_KB; - inc_page_count++; + if (init_page_count == max_page_count && init_page_count == 1) { + /* If only one page and at most one page, we just append + the app heap to the end of linear memory, enlarge the + num_bytes_per_page, and don't change the page count */ + heap_offset = num_bytes_per_page; + num_bytes_per_page += heap_size; + if (num_bytes_per_page < heap_size) { + set_error_buf(error_buf, error_buf_size, + "failed to insert app heap into linear memory, " + "try using `--heap-size=0` option"); + return NULL; } + } + else if (heap_size > 0) { + if (init_page_count == max_page_count && init_page_count == 0) { + /* If the memory data size is always 0, we resize it to + one page for app heap */ + num_bytes_per_page = heap_size; + heap_offset = 0; + inc_page_count = 1; + } + else if (module->aux_heap_base_global_index != (uint32)-1 + && module->aux_heap_base + < (uint64)num_bytes_per_page * init_page_count) { + /* Insert app heap before __heap_base */ + aux_heap_base = module->aux_heap_base; + bytes_of_last_page = aux_heap_base % num_bytes_per_page; + if (bytes_of_last_page == 0) + bytes_of_last_page = num_bytes_per_page; + bytes_to_page_end = num_bytes_per_page - bytes_of_last_page; + inc_page_count = + (heap_size - bytes_to_page_end + num_bytes_per_page - 1) + / num_bytes_per_page; + heap_offset = aux_heap_base; + aux_heap_base += heap_size; - /* Adjust __heap_base global value */ - global_idx = module->aux_heap_base_global_index; - bh_assert(module_inst->e->globals - && global_idx < module_inst->e->global_count); - global_addr = module_inst->global_data - + module_inst->e->globals[global_idx].data_offset; + bytes_of_last_page = aux_heap_base % num_bytes_per_page; + if (bytes_of_last_page == 0) + bytes_of_last_page = num_bytes_per_page; + bytes_to_page_end = num_bytes_per_page - bytes_of_last_page; + if (bytes_to_page_end < 1 * BH_KB) { + aux_heap_base += 1 * BH_KB; + inc_page_count++; + } + + /* Adjust __heap_base global value */ + global_idx = module->aux_heap_base_global_index; + bh_assert(module_inst->e->globals + && global_idx < module_inst->e->global_count); + global_addr = module_inst->global_data + + module_inst->e->globals[global_idx].data_offset; #if WASM_ENABLE_MEMORY64 != 0 - if (memory->is_memory64) { - /* For memory64, the global value should be i64 */ - *(uint64 *)global_addr = aux_heap_base; - } - else + if (memory->is_memory64) { + /* For memory64, the global value should be i64 */ + *(uint64 *)global_addr = aux_heap_base; + } + else #endif - { - /* For memory32, the global value should be i32 */ - *(uint32 *)global_addr = (uint32)aux_heap_base; + { + /* For memory32, the global value should be i32 */ + *(uint32 *)global_addr = (uint32)aux_heap_base; + } + LOG_VERBOSE("Reset __heap_base global to %" PRIu64, + aux_heap_base); + } + else { + /* Insert app heap before new page */ + inc_page_count = + (heap_size + num_bytes_per_page - 1) / num_bytes_per_page; + heap_offset = (uint64)num_bytes_per_page * init_page_count; + heap_size = (uint64)num_bytes_per_page * inc_page_count; + if (heap_size > 0) + heap_size -= 1 * BH_KB; + } + init_page_count += inc_page_count; + max_page_count += inc_page_count; + if (init_page_count > default_max_page) { + set_error_buf(error_buf, error_buf_size, + "failed to insert app heap into linear memory, " + "try using `--heap-size=0` option"); + return NULL; } - LOG_VERBOSE("Reset __heap_base global to %" PRIu64, aux_heap_base); - } - else { - /* Insert app heap before new page */ - inc_page_count = - (heap_size + num_bytes_per_page - 1) / num_bytes_per_page; - heap_offset = (uint64)num_bytes_per_page * init_page_count; - heap_size = (uint64)num_bytes_per_page * inc_page_count; - if (heap_size > 0) - heap_size -= 1 * BH_KB; - } - init_page_count += inc_page_count; - max_page_count += inc_page_count; - if (init_page_count > default_max_page) { - set_error_buf(error_buf, error_buf_size, - "failed to insert app heap into linear memory, " - "try using `--heap-size=0` option"); - return NULL; - } - if (max_page_count > default_max_page) - max_page_count = default_max_page; + if (max_page_count > default_max_page) + max_page_count = default_max_page; + } } LOG_VERBOSE("Memory instantiate:"); LOG_VERBOSE(" page bytes: %u, init pages: %u, max pages: %u", num_bytes_per_page, init_page_count, max_page_count); - LOG_VERBOSE(" heap offset: %" PRIu64 ", heap size: %u\n", heap_offset, - heap_size); + if (memory_idx == 0) + LOG_VERBOSE(" heap offset: %" PRIu64 ", heap size: %u\n", heap_offset, + heap_size); max_memory_data_size = (uint64)num_bytes_per_page * max_page_count; bh_assert(max_memory_data_size @@ -326,12 +331,14 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, memory->max_page_count = max_page_count; memory->memory_data_size = memory_data_size; - memory->heap_data = memory->memory_data + heap_offset; - memory->heap_data_end = memory->heap_data + heap_size; - memory->memory_data_end = memory->memory_data + memory_data_size; + if (memory_idx == 0) { + memory->heap_data = memory->memory_data + heap_offset; + memory->heap_data_end = memory->heap_data + heap_size; + memory->memory_data_end = memory->memory_data + memory_data_size; + } /* Initialize heap */ - if (heap_size > 0) { + if (memory_idx == 0 && heap_size > 0) { uint32 heap_struct_size = mem_allocator_get_heap_struct_size(); if (!(memory->heap_handle = runtime_malloc( @@ -361,7 +368,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, return memory; fail2: - if (heap_size > 0) + if (memory_idx == 0 && heap_size > 0) wasm_runtime_free(memory->heap_handle); fail1: if (memory->memory_data) @@ -1351,7 +1358,45 @@ export_globals_instantiate(const WASMModule *module, bh_assert((uint32)(export_global - export_globals) == export_glob_count); return export_globals; } -#endif + +#if WASM_ENABLE_MULTI_MEMORY != 0 +static void +export_memories_deinstantiate(WASMExportMemInstance *memories) +{ + if (memories) + wasm_runtime_free(memories); +} + +static WASMExportMemInstance * +export_memories_instantiate(const WASMModule *module, + WASMModuleInstance *module_inst, + uint32 export_mem_count, char *error_buf, + uint32 error_buf_size) +{ + WASMExportMemInstance *export_memories, *export_memory; + WASMExport *export = module->exports; + uint32 i; + uint64 total_size = + sizeof(WASMExportMemInstance) * (uint64)export_mem_count; + + if (!(export_memory = export_memories = + runtime_malloc(total_size, error_buf, error_buf_size))) { + return NULL; + } + + for (i = 0; i < module->export_count; i++, export ++) + if (export->kind == EXPORT_KIND_MEMORY) { + export_memory->name = export->name; + export_memory->memory = module_inst->memories[export->index]; + export_memory++; + } + + bh_assert((uint32)(export_memory - export_memories) == export_mem_count); + return export_memories; +} +#endif /* end of if WASM_ENABLE_MULTI_MEMORY != 0 */ + +#endif /* end of if WASM_ENABLE_MULTI_MODULE != 0 */ static WASMFunctionInstance * lookup_post_instantiate_func(WASMModuleInstance *module_inst, @@ -2387,6 +2432,12 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, module, module_inst, module_inst->export_global_count, error_buf, error_buf_size))) #endif +#if WASM_ENABLE_MULTI_MODULE != 0 && WASM_ENABLE_MULTI_MEMORY != 0 + || (module_inst->export_memory_count > 0 + && !(module_inst->export_memories = export_memories_instantiate( + module, module_inst, module_inst->export_memory_count, + error_buf, error_buf_size))) +#endif #if WASM_ENABLE_JIT != 0 || (module_inst->e->function_count > 0 && !init_func_ptrs(module_inst, module, error_buf, error_buf_size)) @@ -3189,6 +3240,10 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) export_globals_deinstantiate(module_inst->export_globals); #endif +#if WASM_ENABLE_MULTI_MODULE != 0 && WASM_ENABLE_MULTI_MEMORY != 0 + export_memories_deinstantiate(module_inst->export_memories); +#endif + #if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0 wasm_externref_cleanup((WASMModuleInstanceCommon *)module_inst); #endif @@ -3251,12 +3306,16 @@ wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name) WASMMemoryInstance * wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name) { - /** - * using a strong assumption that one module instance only has - * one memory instance - */ +#if WASM_ENABLE_MULTI_MEMORY != 0 + uint32 i; + for (i = 0; i < module_inst->export_memory_count; i++) + if (!strcmp(module_inst->export_memories[i].name, name)) + return module_inst->export_memories[i].memory; + return NULL; +#else (void)module_inst->export_memories; return module_inst->memories[0]; +#endif } WASMTableInstance * diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 80aee874..8666541f 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -620,9 +620,16 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, WASMMemoryInstance * wasm_get_default_memory(WASMModuleInstance *module_inst); +WASMMemoryInstance * +wasm_get_memory_with_idx(WASMModuleInstance *module_inst, uint32 index); + bool wasm_enlarge_memory(WASMModuleInstance *module_inst, uint32 inc_page_count); +bool +wasm_enlarge_memory_with_idx(WASMModuleInstance *module_inst, + uint32 inc_page_count, uint32 memidx); + bool wasm_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx, uint32 argc, uint32 argv[]); diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index fcc5ff15..005874ee 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -14,7 +14,7 @@ import time """ The script itself has to be put under the same directory with the "spec". -To run a single non-GC and non-memory64 case with interpreter mode: +To run a single non-GC case with interpreter mode: cd workspace python3 runtest.py --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \ spec/test/core/xxx.wast @@ -22,7 +22,7 @@ To run a single non-GC case with aot mode: cd workspace python3 runtest.py --aot --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \ --aot-compiler wamrc spec/test/core/xxx.wast -To run a single GC case or single memory64 case: +To run a single GC case case: cd workspace python3 runtest.py --wast2wasm spec/interpreter/wasm --interpreter iwasm \ --aot-compiler wamrc --gc spec/test/core/xxx.wast @@ -79,6 +79,7 @@ def ignore_the_case( simd_flag=False, gc_flag=False, memory64_flag=False, + multi_memory_flag=False, xip_flag=False, eh_flag=False, qemu_flag=False, @@ -165,6 +166,7 @@ def test_case( verbose_flag=True, gc_flag=False, memory64_flag=False, + multi_memory_flag=False, qemu_flag=False, qemu_firmware="", log="", @@ -223,6 +225,9 @@ def test_case( if memory64_flag: CMD.append("--memory64") + if multi_memory_flag: + CMD.append("--multi-memory") + if log != "": CMD.append("--log-dir") CMD.append(log) @@ -291,6 +296,7 @@ def test_suite( verbose_flag=True, gc_flag=False, memory64_flag=False, + multi_memory_flag=False, parl_flag=False, qemu_flag=False, qemu_firmware="", @@ -316,6 +322,10 @@ def test_suite( eh_case_list_include = [test for test in eh_case_list if test.stem in ["throw", "tag", "try_catch", "rethrow", "try_delegate"]] case_list.extend(eh_case_list_include) + if multi_memory_flag: + multi_memory_list = sorted(suite_path.glob("multi-memory/*.wast")) + case_list.extend(multi_memory_list) + # ignore based on command line options filtered_case_list = [] for case_path in case_list: @@ -330,6 +340,7 @@ def test_suite( simd_flag, gc_flag, memory64_flag, + multi_memory_flag, xip_flag, eh_flag, qemu_flag, @@ -366,6 +377,7 @@ def test_suite( verbose_flag, gc_flag, memory64_flag, + multi_memory_flag, qemu_flag, qemu_firmware, log, @@ -408,6 +420,7 @@ def test_suite( verbose_flag, gc_flag, memory64_flag, + multi_memory_flag, qemu_flag, qemu_firmware, log, @@ -546,6 +559,13 @@ def main(): dest="memory64_flag", help="Running with memory64 feature", ) + parser.add_argument( + "--multi-memory", + action="store_true", + default=False, + dest="multi_memory_flag", + help="Running with multi-memory feature", + ) parser.add_argument( "cases", metavar="path_to__case", @@ -591,6 +611,7 @@ def main(): options.verbose_flag, options.gc_flag, options.memory64_flag, + options.multi_memory_flag, options.parl_flag, options.qemu_flag, options.qemu_firmware, @@ -619,6 +640,7 @@ def main(): options.verbose_flag, options.gc_flag, options.memory64_flag, + options.multi_memory_flag, options.qemu_flag, options.qemu_firmware, options.log, diff --git a/tests/wamr-test-suites/spec-test-script/multi_memory_ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/multi_memory_ignore_cases.patch new file mode 100644 index 00000000..38b33175 --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/multi_memory_ignore_cases.patch @@ -0,0 +1,1022 @@ +diff --git a/test/core/elem.wast b/test/core/elem.wast +index 575ecef8..6eecab93 100644 +--- a/test/core/elem.wast ++++ b/test/core/elem.wast +@@ -571,9 +571,11 @@ + (func $const-i32-d (type $out-i32) (i32.const 68)) + ) + ++(; + (assert_return (invoke $module1 "call-7") (i32.const 67)) + (assert_return (invoke $module1 "call-8") (i32.const 68)) + (assert_return (invoke $module1 "call-9") (i32.const 66)) ++;) + + (module $module3 + (type $out-i32 (func (result i32))) +@@ -584,6 +586,8 @@ + (func $const-i32-f (type $out-i32) (i32.const 70)) + ) + ++(; + (assert_return (invoke $module1 "call-7") (i32.const 67)) + (assert_return (invoke $module1 "call-8") (i32.const 69)) + (assert_return (invoke $module1 "call-9") (i32.const 70)) ++;) +diff --git a/test/core/imports.wast b/test/core/imports.wast +index 94c1af5c..bb1704fc 100644 +--- a/test/core/imports.wast ++++ b/test/core/imports.wast +@@ -86,7 +86,7 @@ + (assert_return (invoke "print64" (i64.const 24))) + + (assert_invalid +- (module ++ (module + (type (func (result i32))) + (import "test" "func" (func (type 1))) + ) +@@ -559,6 +559,7 @@ + (assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) + (assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) + ++(; + (module $Mgm + (memory (export "memory") 1) ;; initial size is 1 + (func (export "grow") (result i32) (memory.grow (i32.const 1))) +@@ -567,7 +568,7 @@ + (assert_return (invoke $Mgm "grow") (i32.const 1)) ;; now size is 2 + (module $Mgim1 + ;; imported memory limits should match, because external memory size is 2 now +- (memory (export "memory") (import "grown-memory" "memory") 2) ++ (memory (export "memory") (import "grown-memory" "memory") 2) + (func (export "grow") (result i32) (memory.grow (i32.const 1))) + ) + (register "grown-imported-memory" $Mgim1) +@@ -578,7 +579,7 @@ + (func (export "size") (result i32) (memory.size)) + ) + (assert_return (invoke $Mgim2 "size") (i32.const 3)) +- ++;) + + ;; Syntax errors + +@@ -650,6 +651,7 @@ + "import after memory" + ) + ++(; + ;; This module is required to validate, regardless of whether it can be + ;; linked. Overloading is not possible in wasm itself, but it is possible + ;; in modules from which wasm can import. +@@ -676,3 +678,4 @@ + ) + "unknown import" + ) ++;) +\ No newline at end of file +diff --git a/test/core/linking.wast b/test/core/linking.wast +index 994e0f49..8fbcc021 100644 +--- a/test/core/linking.wast ++++ b/test/core/linking.wast +@@ -19,11 +19,11 @@ + (assert_return (invoke $Nf "call") (i32.const 3)) + (assert_return (invoke $Nf "call Mf.call") (i32.const 2)) + +-(module ++(module $M1 + (import "spectest" "print_i32" (func $f (param i32))) + (export "print" (func $f)) + ) +-(register "reexport_f") ++(register "reexport_f" $M1) + (assert_unlinkable + (module (import "reexport_f" "print" (func (param i64)))) + "incompatible import type" +@@ -35,7 +35,6 @@ + + + ;; Globals +- + (module $Mg + (global $glob (export "glob") i32 (i32.const 42)) + (func (export "get") (result i32) (global.get $glob)) +@@ -47,6 +46,7 @@ + ) + (register "Mg" $Mg) + ++(; only sharing initial values + (module $Ng + (global $x (import "Mg" "glob") i32) + (global $mut_glob (import "Mg" "mut_glob") (mut i32)) +@@ -81,7 +81,7 @@ + (assert_return (get $Ng "Mg.mut_glob") (i32.const 241)) + (assert_return (invoke $Mg "get_mut") (i32.const 241)) + (assert_return (invoke $Ng "Mg.get_mut") (i32.const 241)) +- ++;) + + (assert_unlinkable + (module (import "Mg" "mut_glob" (global i32))) +@@ -130,7 +130,7 @@ + + + ;; Tables +- ++(; no such support + (module $Mt + (type (func (result i32))) + (type (func)) +@@ -307,10 +307,11 @@ + (module (table (import "Mtable_ex" "t-extern") 1 funcref)) + "incompatible import type" + ) ++;) + + + ;; Memories +- ++(; no such support + (module $Mm + (memory (export "mem") 1 5) + (data (i32.const 10) "\00\01\02\03\04\05\06\07\08\09") +@@ -451,3 +452,4 @@ + + (assert_return (invoke $Ms "get memory[0]") (i32.const 104)) ;; 'h' + (assert_return (invoke $Ms "get table[0]") (i32.const 0xdead)) ++;) +\ No newline at end of file +diff --git a/test/core/load.wast b/test/core/load.wast +index 9fe48e2b..3e9c2f8c 100644 +--- a/test/core/load.wast ++++ b/test/core/load.wast +@@ -29,6 +29,8 @@ + (register "M") + + (module ++ (func $readM1 (import "M" "read") (param i32) (result i32)) ++ (export "readM1" (func $readM1)) + (memory $mem1 (import "M" "mem") 2) + (memory $mem2 3) + +@@ -43,11 +45,12 @@ + ) + ) + +-(assert_return (invoke $M "read" (i32.const 20)) (i32.const 1)) +-(assert_return (invoke $M "read" (i32.const 21)) (i32.const 2)) +-(assert_return (invoke $M "read" (i32.const 22)) (i32.const 3)) +-(assert_return (invoke $M "read" (i32.const 23)) (i32.const 4)) +-(assert_return (invoke $M "read" (i32.const 24)) (i32.const 5)) ++;; To invoke the function in M as a submodule, not as an independent module ++(assert_return (invoke "readM1" (i32.const 20)) (i32.const 1)) ++(assert_return (invoke "readM1" (i32.const 21)) (i32.const 2)) ++(assert_return (invoke "readM1" (i32.const 22)) (i32.const 3)) ++(assert_return (invoke "readM1" (i32.const 23)) (i32.const 4)) ++(assert_return (invoke "readM1" (i32.const 24)) (i32.const 5)) + + (assert_return (invoke "read1" (i32.const 20)) (i32.const 1)) + (assert_return (invoke "read1" (i32.const 21)) (i32.const 2)) +diff --git a/test/core/memory_grow.wast b/test/core/memory_grow.wast +index 4b6dbc83..dc46c029 100644 +--- a/test/core/memory_grow.wast ++++ b/test/core/memory_grow.wast +@@ -106,15 +106,15 @@ + + ;; Multiple memories + +-(module ++(module $MemroygrowM + (memory (export "mem1") 2 5) + (memory (export "mem2") 0) + ) +-(register "M") ++(register "MemroygrowM" $MemorygrowM) + + (module +- (memory $mem1 (import "M" "mem1") 1 6) +- (memory $mem2 (import "M" "mem2") 0) ++ (memory $mem1 (import "MemroygrowM" "mem1") 1 6) ++ (memory $mem2 (import "MemroygrowM" "mem2") 0) + (memory $mem3 3) + (memory $mem4 4 5) + +diff --git a/test/core/memory_size.wast b/test/core/memory_size.wast +index a1d6ea2d..b58c75d0 100644 +--- a/test/core/memory_size.wast ++++ b/test/core/memory_size.wast +@@ -65,15 +65,15 @@ + + ;; Multiple memories + +-(module ++(module $MemmorysizeM + (memory (export "mem1") 2 4) + (memory (export "mem2") 0) + ) +-(register "M") ++(register "MemmorysizeM" $MemmorysizeM) + + (module +- (memory $mem1 (import "M" "mem1") 1 5) +- (memory $mem2 (import "M" "mem2") 0) ++ (memory $mem1 (import "MemmorysizeM" "mem1") 1 5) ++ (memory $mem2 (import "MemmorysizeM" "mem2") 0) + (memory $mem3 3) + (memory $mem4 4 5) + +diff --git a/test/core/multi-memory/imports2.wast b/test/core/multi-memory/imports2.wast +index 314bc131..e1060599 100644 +--- a/test/core/multi-memory/imports2.wast ++++ b/test/core/multi-memory/imports2.wast +@@ -1,13 +1,13 @@ +-(module ++(module $imports2test + (memory (export "z") 0 0) + (memory (export "memory-2-inf") 2) + (memory (export "memory-2-4") 2 4) + ) + +-(register "test") ++(register "imports2test" $imports2test) + + (module +- (import "test" "z" (memory 0)) ++ (import "imports2test" "z" (memory 0)) + (memory $m (import "spectest" "memory") 1 2) + (data (memory 1) (i32.const 10) "\10") + +@@ -31,9 +31,9 @@ + (assert_trap (invoke "load" (i32.const 1000000)) "out of bounds memory access") + + (module +- (import "test" "memory-2-inf" (memory 2)) +- (import "test" "memory-2-inf" (memory 1)) +- (import "test" "memory-2-inf" (memory 0)) ++ (import "imports2test" "memory-2-inf" (memory 2)) ++ (import "imports2test" "memory-2-inf" (memory 1)) ++ (import "imports2test" "memory-2-inf" (memory 0)) + ) + + (module +@@ -46,7 +46,7 @@ + ) + + (assert_unlinkable +- (module (import "test" "unknown" (memory 1))) ++ (module (import "imports2test" "unknown" (memory 1))) + "unknown import" + ) + (assert_unlinkable +@@ -55,11 +55,11 @@ + ) + + (assert_unlinkable +- (module (import "test" "memory-2-inf" (memory 3))) ++ (module (import "imports2test" "memory-2-inf" (memory 3))) + "incompatible import type" + ) + (assert_unlinkable +- (module (import "test" "memory-2-inf" (memory 2 3))) ++ (module (import "imports2test" "memory-2-inf" (memory 2 3))) + "incompatible import type" + ) + (assert_unlinkable +diff --git a/test/core/multi-memory/imports4.wast b/test/core/multi-memory/imports4.wast +index 411b1c0f..0a819454 100644 +--- a/test/core/multi-memory/imports4.wast ++++ b/test/core/multi-memory/imports4.wast +@@ -1,12 +1,12 @@ +-(module ++(module $imports4test + (memory (export "memory-2-inf") 2) + (memory (export "memory-2-4") 2 4) + ) + +-(register "test") ++(register "imports4test") + + (module +- (import "test" "memory-2-4" (memory 1)) ++ (import "imports4test" "memory-2-4" (memory 1)) + (memory $m (import "spectest" "memory") 0 3) ;; actual has max size 2 + (func (export "grow") (param i32) (result i32) (memory.grow $m (local.get 0))) + ) +@@ -16,6 +16,8 @@ + (assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) + (assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) + ++;; TODO: Current implementation call grow on one submodule instance can't really change its definition ++(; + (module $Mgm + (memory 0) + (memory 0) +@@ -45,3 +47,4 @@ + (func (export "size") (result i32) (memory.size $m)) + ) + (assert_return (invoke $Mgim2 "size") (i32.const 3)) ++;) +\ No newline at end of file +diff --git a/test/core/multi-memory/linking0.wast b/test/core/multi-memory/linking0.wast +index b09c69f6..d57d484e 100644 +--- a/test/core/multi-memory/linking0.wast ++++ b/test/core/multi-memory/linking0.wast +@@ -24,8 +24,8 @@ + ) + "unknown import" + ) +-(assert_trap (invoke $Mt "call" (i32.const 7)) "uninitialized element") +- ++;; can't call function in submodule when module can't be instantiated ++;; (assert_trap (invoke "call" (i32.const 7)) "uninitialized element") + + (assert_trap + (module +@@ -39,4 +39,5 @@ + ) + "out of bounds memory access" + ) +-(assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) ++;; can't call function in submodule when module can't be instantiated ++;; (assert_return (invoke "call" (i32.const 7)) (i32.const 0)) +diff --git a/test/core/multi-memory/linking1.wast b/test/core/multi-memory/linking1.wast +index 39eabb00..49c87ce8 100644 +--- a/test/core/multi-memory/linking1.wast ++++ b/test/core/multi-memory/linking1.wast +@@ -1,4 +1,4 @@ +-(module $Mm ++(module $linking1Mm + (memory $mem0 (export "mem0") 0 0) + (memory $mem1 (export "mem1") 1 5) + (memory $mem2 (export "mem2") 0 0) +@@ -9,11 +9,11 @@ + (i32.load8_u $mem1 (local.get 0)) + ) + ) +-(register "Mm" $Mm) ++(register "linking1Mm" $linking1Mm) + +-(module $Nm +- (func $loadM (import "Mm" "load") (param i32) (result i32)) +- (memory (import "Mm" "mem0") 0) ++(module $linking1Nm ++ (func $loadM (import "linking1Mm" "load") (param i32) (result i32)) ++ (memory (import "linking1Mm" "mem0") 0) + + (memory $m 1) + (data (memory 1) (i32.const 10) "\f0\f1\f2\f3\f4\f5") +@@ -24,12 +24,14 @@ + ) + ) + +-(assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 2)) +-(assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 2)) +-(assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) ++(assert_return (invoke $linking1Mm "load" (i32.const 12)) (i32.const 2)) ++(assert_return (invoke $linking1Nm "Mm.load" (i32.const 12)) (i32.const 2)) ++(assert_return (invoke $linking1Nm "load" (i32.const 12)) (i32.const 0xf2)) + +-(module $Om +- (memory (import "Mm" "mem1") 1) ++(module $linking1Om ++ (func $loadM (import "linking1Mm" "load") (param i32) (result i32)) ++ (export "Mm.load" (func $loadM)) ++ (memory (import "linking1Mm" "mem1") 1) + (data (i32.const 5) "\a0\a1\a2\a3\a4\a5\a6\a7") + + (func (export "load") (param $a i32) (result i32) +@@ -37,19 +39,20 @@ + ) + ) + +-(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)) ++;; To invoke the function in Mm as a submodule, not as an independent module ++(assert_return (invoke $linking1Om "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 $linking1Om "load" (i32.const 12)) (i32.const 0xa7)) + + (module +- (memory (import "Mm" "mem1") 0) ++ (memory (import "linking1Mm" "mem1") 0) + (data (i32.const 0xffff) "a") + ) + + (assert_trap + (module +- (memory (import "Mm" "mem0") 0) ++ (memory (import "linking1Mm" "mem0") 0) + (data (i32.const 0xffff) "a") + ) + "out of bounds memory access" +@@ -57,7 +60,7 @@ + + (assert_trap + (module +- (memory (import "Mm" "mem1") 0) ++ (memory (import "linking1Mm" "mem1") 0) + (data (i32.const 0x10000) "a") + ) + "out of bounds memory access" +diff --git a/test/core/multi-memory/linking2.wast b/test/core/multi-memory/linking2.wast +index 26bf3cca..5eae4643 100644 +--- a/test/core/multi-memory/linking2.wast ++++ b/test/core/multi-memory/linking2.wast +@@ -1,4 +1,4 @@ +-(module $Mm ++(module $linking2Mm + (memory $mem0 (export "mem0") 0 0) + (memory $mem1 (export "mem1") 1 5) + (memory $mem2 (export "mem2") 0 0) +@@ -9,22 +9,22 @@ + (i32.load8_u $mem1 (local.get 0)) + ) + ) +-(register "Mm" $Mm) ++(register "linking2Mm" $linking2Mm) + +-(module $Pm +- (memory (import "Mm" "mem1") 1 8) ++(module ++ (memory (import "linking2Mm" "mem1") 1 8) + + (func (export "grow") (param $a i32) (result i32) + (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)) +-(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 3)) +-(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const 3)) +-(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const 4)) +-(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) +-(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1)) +-(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) ++(assert_return (invoke "grow" (i32.const 0)) (i32.const 1)) ++(assert_return (invoke "grow" (i32.const 2)) (i32.const 1)) ++(assert_return (invoke "grow" (i32.const 0)) (i32.const 3)) ++(assert_return (invoke "grow" (i32.const 1)) (i32.const 3)) ++(assert_return (invoke "grow" (i32.const 1)) (i32.const 4)) ++(assert_return (invoke "grow" (i32.const 0)) (i32.const 5)) ++(assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) ++(assert_return (invoke "grow" (i32.const 0)) (i32.const 5)) + +diff --git a/test/core/multi-memory/linking3.wast b/test/core/multi-memory/linking3.wast +index e23fbe4e..d3efe95a 100644 +--- a/test/core/multi-memory/linking3.wast ++++ b/test/core/multi-memory/linking3.wast +@@ -33,8 +33,9 @@ + ) + "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)) ++;; can't call function in submodule when module can't be instantiated ++;; (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 +@@ -46,7 +47,8 @@ + ) + "out of bounds table access" + ) +-(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) ++;; can't call function in submodule when module can't be instantiated ++;; (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) + + ;; Store is modified if the start function traps. + (module $Ms +@@ -79,5 +81,6 @@ + "unreachable" + ) + +-(assert_return (invoke $Ms "get memory[0]") (i32.const 104)) ;; 'h' +-(assert_return (invoke $Ms "get table[0]") (i32.const 0xdead)) ++;; can't call function in submodule when module can't be instantiated ++;; (assert_return (invoke $Ms "get memory[0]") (i32.const 104)) ;; 'h' ++;; (assert_return (invoke $Ms "get table[0]") (i32.const 0xdead)) +diff --git a/test/core/multi-memory/load1.wast b/test/core/multi-memory/load1.wast +index be309c39..6a0faf0d 100644 +--- a/test/core/multi-memory/load1.wast ++++ b/test/core/multi-memory/load1.wast +@@ -8,6 +8,8 @@ + (register "M") + + (module ++ (func $readM1 (import "M" "read") (param i32) (result i32)) ++ (export "readM1" (func $readM1)) + (memory $mem1 (import "M" "mem") 2) + (memory $mem2 3) + +@@ -22,11 +24,12 @@ + ) + ) + +-(assert_return (invoke $M "read" (i32.const 20)) (i32.const 1)) +-(assert_return (invoke $M "read" (i32.const 21)) (i32.const 2)) +-(assert_return (invoke $M "read" (i32.const 22)) (i32.const 3)) +-(assert_return (invoke $M "read" (i32.const 23)) (i32.const 4)) +-(assert_return (invoke $M "read" (i32.const 24)) (i32.const 5)) ++;; To invoke the function in M as a submodule, not as an independent module ++(assert_return (invoke "readM1" (i32.const 20)) (i32.const 1)) ++(assert_return (invoke "readM1" (i32.const 21)) (i32.const 2)) ++(assert_return (invoke "readM1" (i32.const 22)) (i32.const 3)) ++(assert_return (invoke "readM1" (i32.const 23)) (i32.const 4)) ++(assert_return (invoke "readM1" (i32.const 24)) (i32.const 5)) + + (assert_return (invoke "read1" (i32.const 20)) (i32.const 1)) + (assert_return (invoke "read1" (i32.const 21)) (i32.const 2)) +diff --git a/test/core/multi-memory/store1.wast b/test/core/multi-memory/store1.wast +index 10cf2c42..eafe6cc9 100644 +--- a/test/core/multi-memory/store1.wast ++++ b/test/core/multi-memory/store1.wast +@@ -10,6 +10,9 @@ + ) + (register "M1") + ++(invoke "store" (i32.const 0) (i64.const 1)) ++(assert_return (invoke "load" (i32.const 0)) (i64.const 1)) ++ + (module $M2 + (memory (export "mem") 1) + +@@ -22,10 +25,8 @@ + ) + (register "M2") + +-(invoke $M1 "store" (i32.const 0) (i64.const 1)) +-(invoke $M2 "store" (i32.const 0) (i64.const 2)) +-(assert_return (invoke $M1 "load" (i32.const 0)) (i64.const 1)) +-(assert_return (invoke $M2 "load" (i32.const 0)) (i64.const 2)) ++(invoke "store" (i32.const 0) (i64.const 2)) ++(assert_return (invoke "load" (i32.const 0)) (i64.const 2)) + + (module + (memory $mem1 (import "M1" "mem") 1) +diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast +index adb5cb78..6396013b 100644 +--- a/test/core/ref_func.wast ++++ b/test/core/ref_func.wast +@@ -4,7 +4,7 @@ + (register "M") + + (module +- (func $f (import "M" "f") (param i32) (result i32)) ++ (func $f (param $x i32) (result i32) (local.get $x)) + (func $g (param $x i32) (result i32) + (i32.add (local.get $x) (i32.const 1)) + ) +diff --git a/test/core/store.wast b/test/core/store.wast +index 86f6263a..65a0d4ee 100644 +--- a/test/core/store.wast ++++ b/test/core/store.wast +@@ -35,7 +35,10 @@ + (i64.store (local.get 0) (local.get 1)) + ) + ) +-(register "M1") ++(register "M1" $M1) ++ ++(invoke "store" (i32.const 0) (i64.const 1)) ++(assert_return (invoke "load" (i32.const 0)) (i64.const 1)) + + (module $M2 + (memory (export "mem") 1) +@@ -47,12 +50,10 @@ + (i64.store (local.get 0) (local.get 1)) + ) + ) +-(register "M2") ++(register "M2" $M2) + +-(invoke $M1 "store" (i32.const 0) (i64.const 1)) +-(invoke $M2 "store" (i32.const 0) (i64.const 2)) +-(assert_return (invoke $M1 "load" (i32.const 0)) (i64.const 1)) +-(assert_return (invoke $M2 "load" (i32.const 0)) (i64.const 2)) ++(invoke "store" (i32.const 0) (i64.const 2)) ++(assert_return (invoke "load" (i32.const 0)) (i64.const 2)) + + (module + (memory $mem1 (import "M1" "mem") 1) +diff --git a/test/core/table_copy.wast b/test/core/table_copy.wast +index 380e84ee..59230cfb 100644 +--- a/test/core/table_copy.wast ++++ b/test/core/table_copy.wast +@@ -14,11 +14,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -106,11 +106,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -198,11 +198,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -290,11 +290,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -382,11 +382,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -474,11 +474,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -566,11 +566,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -658,11 +658,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -750,11 +750,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -842,11 +842,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -934,11 +934,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1026,11 +1026,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1118,11 +1118,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1210,11 +1210,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1302,11 +1302,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1394,11 +1394,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1486,11 +1486,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1578,11 +1578,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +diff --git a/test/core/table_init.wast b/test/core/table_init.wast +index 0b2d26f7..3c595e5b 100644 +--- a/test/core/table_init.wast ++++ b/test/core/table_init.wast +@@ -14,11 +14,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -72,11 +72,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -130,11 +130,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -196,11 +196,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -254,11 +254,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -312,11 +312,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index 291718b6..97820eaa 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -327,6 +327,9 @@ parser.add_argument('--gc', default=False, action='store_true', parser.add_argument('--memory64', default=False, action='store_true', help='Test with Memory64') +parser.add_argument('--multi-memory', default=False, action='store_true', + help='Test with multi-memory(with multi-module auto enabled)') + parser.add_argument('--qemu', default=False, action='store_true', help="Enable QEMU") @@ -1097,6 +1100,8 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts): cmd = [opts.wast2wasm, "--enable-threads", "--no-check", "--enable-exceptions", "--enable-tail-call", wast_tempfile, "-o", wasm_tempfile ] elif opts.memory64: cmd = [opts.wast2wasm, "--enable-memory64", "--no-check", wast_tempfile, "-o", wasm_tempfile ] + elif opts.multi_memory: + cmd = [opts.wast2wasm, "--enable-multi-memory", "--no-check", wast_tempfile, "-o", wasm_tempfile ] else: cmd = [opts.wast2wasm, "--enable-threads", "--no-check", wast_tempfile, "-o", wasm_tempfile ] diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 54e2ac1a..8254cc71 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -25,6 +25,7 @@ function help() echo "-S enable SIMD feature" echo "-G enable GC feature" echo "-W enable memory64 feature" + echo "-E enable multi memory feature" echo "-X enable XIP feature" echo "-e enable exception handling" echo "-x test SGX" @@ -59,6 +60,7 @@ COLLECT_CODE_COVERAGE=0 ENABLE_SIMD=0 ENABLE_GC=0 ENABLE_MEMORY64=0 +ENABLE_MULTI_MEMORY=0 ENABLE_XIP=0 ENABLE_EH=0 ENABLE_DEBUG_VERSION=0 @@ -85,7 +87,7 @@ REQUIREMENT_NAME="" # Initialize an empty array for subrequirement IDs SUBREQUIREMENT_IDS=() -while getopts ":s:cabgvt:m:MCpSXexwWPGQF:j:T:r:A:" opt +while getopts ":s:cabgvt:m:MCpSXexwWEPGQF:j:T:r:A:" opt do OPT_PARSED="TRUE" case $opt in @@ -148,6 +150,11 @@ do echo "enable wasm64(memory64) feature" ENABLE_MEMORY64=1 ;; + E) + echo "enable multi memory feature(auto enable multi module)" + ENABLE_MULTI_MEMORY=1 + ENABLE_MULTI_MODULE=1 + ;; C) echo "enable code coverage" COLLECT_CODE_COVERAGE=1 @@ -496,6 +503,20 @@ function spec_test() git reset --hard 48e69f394869c55b7bbe14ac963c09f4605490b6 git checkout 044d0d2e77bdcbe891f7e0b9dd2ac01d56435f0b -- test/core/elem.wast test/core/data.wast git apply ../../spec-test-script/memory64_ignore_cases.patch || exit 1 + elif [[ ${ENABLE_MULTI_MEMORY} == 1 ]]; then + echo "checkout spec for multi memory proposal" + + # check spec test cases for multi memory + git clone -b main --single-branch https://github.com/WebAssembly/multi-memory.git spec + pushd spec + + # Reset to commit: "Merge pull request #48 from backes/specify-memcpy-immediate-order" + git reset --hard 48e69f394869c55b7bbe14ac963c09f4605490b6 + git checkout 044d0d2e77bdcbe891f7e0b9dd2ac01d56435f0b -- test/core/elem.wast + git apply ../../spec-test-script/multi_memory_ignore_cases.patch || exit 1 + if [[ ${RUNNING_MODE} == "aot" ]]; then + git apply ../../spec-test-script/multi_module_aot_ignore_cases.patch || exit 1 + fi else echo "checkout spec for default proposal" @@ -572,6 +593,13 @@ function spec_test() ARGS_FOR_SPEC_TEST+="--memory64 " fi + # multi memory is only enabled in interp and aot mode + if [[ 1 == ${ENABLE_MULTI_MEMORY} ]]; then + if [[ $1 == 'classic-interp' || $1 == 'aot' ]]; then + ARGS_FOR_SPEC_TEST+="--multi-memory " + fi + fi + if [[ ${ENABLE_QEMU} == 1 ]]; then ARGS_FOR_SPEC_TEST+="--qemu " ARGS_FOR_SPEC_TEST+="--qemu-firmware ${QEMU_FIRMWARE} " @@ -852,6 +880,14 @@ function do_execute_in_running_mode() { local RUNNING_MODE="$1" + if [[ ${ENABLE_MULTI_MEMORY} -eq 1 ]]; then + if [[ "${RUNNING_MODE}" != "classic-interp" \ + && "${RUNNING_MODE}" != "aot" ]]; then + echo "support multi-memory in classic-interp mode and aot mode" + return 0 + fi + fi + if [[ ${ENABLE_MEMORY64} -eq 1 ]]; then if [[ "${RUNNING_MODE}" != "classic-interp" \ && "${RUNNING_MODE}" != "aot" ]]; then @@ -941,6 +977,12 @@ function trigger() EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MEMORY64=0" fi + if [[ ${ENABLE_MULTI_MEMORY} == 1 ]];then + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MULTI_MEMORY=1" + else + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MULTI_MEMORY=0" + fi + if [[ ${ENABLE_MULTI_THREAD} == 1 ]];then EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_PTHREAD=1" fi