Implement memory64 for classic interpreter (#3266)

Adding a new cmake flag (cache variable) `WAMR_BUILD_MEMORY64` to enable
the memory64 feature, it can only be enabled on the 64-bit platform/target and
can only use software boundary check. And when it is enabled, it can support both
i32 and i64 linear memory types. The main modifications are:

- wasm loader & mini-loader: loading and bytecode validating process 
- wasm runtime: memory instantiating process
- classic-interpreter: wasm code executing process
- Support memory64 memory in related runtime APIs
- Modify main function type check when it's memory64 wasm file
- Modify `wasm_runtime_invoke_native` and `wasm_runtime_invoke_native_raw` to
  handle registered native function pointer argument when memory64 is enabled
- memory64 classic-interpreter spec test in `test_wamr.sh` and in CI

Currently, it supports memory64 memory wasm file that uses core spec
(including bulk memory proposal) opcodes and threads opcodes.

ps.
https://github.com/bytecodealliance/wasm-micro-runtime/issues/3091
https://github.com/bytecodealliance/wasm-micro-runtime/pull/3240
https://github.com/bytecodealliance/wasm-micro-runtime/pull/3260
This commit is contained in:
Wenyong Huang 2024-04-02 15:22:07 +08:00 committed by GitHub
parent 6b0b5de1c5
commit a23fa9f86c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 1084 additions and 342 deletions

View File

@ -65,6 +65,7 @@ env:
WASI_TEST_OPTIONS: "-s wasi_certification -w" WASI_TEST_OPTIONS: "-s wasi_certification -w"
WAMR_COMPILER_TEST_OPTIONS: "-s wamr_compiler -S -b -P" WAMR_COMPILER_TEST_OPTIONS: "-s wamr_compiler -S -b -P"
GC_TEST_OPTIONS: "-s spec -G -b -P" GC_TEST_OPTIONS: "-s spec -G -b -P"
MEMORY64_TEST_OPTIONS: "-s spec -W -b -P"
jobs: jobs:
build_llvm_libraries_on_ubuntu_2204: build_llvm_libraries_on_ubuntu_2204:
@ -144,6 +145,7 @@ jobs:
"-DWAMR_BUILD_SIMD=1", "-DWAMR_BUILD_SIMD=1",
"-DWAMR_BUILD_TAIL_CALL=1", "-DWAMR_BUILD_TAIL_CALL=1",
"-DWAMR_DISABLE_HW_BOUND_CHECK=1", "-DWAMR_DISABLE_HW_BOUND_CHECK=1",
"-DWAMR_BUILD_MEMORY64=1",
] ]
os: [ubuntu-22.04] os: [ubuntu-22.04]
platform: [android, linux] platform: [android, linux]
@ -202,6 +204,21 @@ jobs:
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Memory64 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_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
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
# Fast-JIT and Multi-Tier-JIT mode don't support android # Fast-JIT and Multi-Tier-JIT mode don't support android
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
platform: android platform: android
@ -503,6 +520,7 @@ jobs:
$THREADS_TEST_OPTIONS, $THREADS_TEST_OPTIONS,
$WASI_TEST_OPTIONS, $WASI_TEST_OPTIONS,
$GC_TEST_OPTIONS, $GC_TEST_OPTIONS,
$MEMORY64_TEST_OPTIONS,
] ]
wasi_sdk_release: wasi_sdk_release:
[ [
@ -541,19 +559,30 @@ jobs:
test_option: $GC_TEST_OPTIONS test_option: $GC_TEST_OPTIONS
- running_mode: "multi-tier-jit" - running_mode: "multi-tier-jit"
test_option: $GC_TEST_OPTIONS test_option: $GC_TEST_OPTIONS
# aot, fast-interp, fast-jit, llvm-jit, multi-tier-jit don't support Memory64
- running_mode: "aot"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "fast-interp"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "fast-jit"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "jit"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "multi-tier-jit"
test_option: $MEMORY64_TEST_OPTIONS
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set-up OCaml - name: Set-up OCaml
uses: ocaml/setup-ocaml@v2 uses: ocaml/setup-ocaml@v2
if: matrix.test_option == '$GC_TEST_OPTIONS' if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS'
with: with:
ocaml-compiler: 4.13 ocaml-compiler: 4.13
- name: Set-up Ocamlbuild - name: Set-up Ocamlbuild
if: matrix.test_option == '$GC_TEST_OPTIONS' if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS'
run: opam install ocamlbuild dune run: opam install ocamlbuild dune menhir
- name: download and install wasi-sdk - name: download and install wasi-sdk
if: matrix.test_option == '$WASI_TEST_OPTIONS' if: matrix.test_option == '$WASI_TEST_OPTIONS'
@ -617,13 +646,13 @@ jobs:
- name: run tests - name: run tests
timeout-minutes: 30 timeout-minutes: 30
if: matrix.test_option != '$GC_TEST_OPTIONS' if: matrix.test_option != '$GC_TEST_OPTIONS' && matrix.test_option != '$MEMORY64_TEST_OPTIONS'
run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
working-directory: ./tests/wamr-test-suites working-directory: ./tests/wamr-test-suites
- name: run gc tests - name: run gc or memory64 tests
timeout-minutes: 20 timeout-minutes: 20
if: matrix.test_option == '$GC_TEST_OPTIONS' if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS'
run: | run: |
eval $(opam env) eval $(opam env)
./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}

View File

@ -130,6 +130,7 @@ jobs:
"-DWAMR_BUILD_SIMD=1", "-DWAMR_BUILD_SIMD=1",
"-DWAMR_BUILD_TAIL_CALL=1", "-DWAMR_BUILD_TAIL_CALL=1",
"-DWAMR_DISABLE_HW_BOUND_CHECK=1", "-DWAMR_DISABLE_HW_BOUND_CHECK=1",
"-DWAMR_BUILD_MEMORY64=1",
] ]
os: [ubuntu-20.04] os: [ubuntu-20.04]
platform: [android, linux] platform: [android, linux]
@ -188,6 +189,21 @@ jobs:
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Memory64 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_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
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
# Fast-JIT and Multi-Tier-JIT mode don't support android # Fast-JIT and Multi-Tier-JIT mode don't support android
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
platform: android platform: android
@ -271,6 +287,7 @@ jobs:
"-DWAMR_BUILD_SIMD=1", "-DWAMR_BUILD_SIMD=1",
"-DWAMR_BUILD_TAIL_CALL=1", "-DWAMR_BUILD_TAIL_CALL=1",
"-DWAMR_DISABLE_HW_BOUND_CHECK=1", "-DWAMR_DISABLE_HW_BOUND_CHECK=1",
"-DWAMR_BUILD_MEMORY64=1",
] ]
exclude: exclude:
# uncompatiable feature and platform # uncompatiable feature and platform
@ -299,6 +316,11 @@ jobs:
# MINI_LOADER only on INTERP mode # MINI_LOADER only on INTERP mode
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Memory64 only on CLASSIC INTERP mode
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3

View File

@ -248,6 +248,15 @@ if (WAMR_BUILD_SHARED_MEMORY EQUAL 1)
else () else ()
add_definitions (-DWASM_ENABLE_SHARED_MEMORY=0) add_definitions (-DWASM_ENABLE_SHARED_MEMORY=0)
endif () endif ()
if (WAMR_BUILD_MEMORY64 EQUAL 1)
# if native is 32-bit or cross-compiled to 32-bit
if (NOT WAMR_BUILD_TARGET MATCHES ".*64.*")
message (FATAL_ERROR "-- Memory64 is only available on the 64-bit platform/target")
endif()
add_definitions (-DWASM_ENABLE_MEMORY64=1)
set (WAMR_DISABLE_HW_BOUND_CHECK 1)
message (" Memory64 memory enabled")
endif ()
if (WAMR_BUILD_THREAD_MGR EQUAL 1) if (WAMR_BUILD_THREAD_MGR EQUAL 1)
message (" Thread manager enabled") message (" Thread manager enabled")
endif () endif ()

View File

@ -415,7 +415,7 @@
#else #else
#define DEFAULT_WASM_STACK_SIZE (12 * 1024) #define DEFAULT_WASM_STACK_SIZE (12 * 1024)
#endif #endif
/* Min auxilliary stack size of each wasm thread */ /* Min auxiliary stack size of each wasm thread */
#define WASM_THREAD_AUX_STACK_SIZE_MIN (256) #define WASM_THREAD_AUX_STACK_SIZE_MIN (256)
/* Default/min native stack size of each app thread */ /* Default/min native stack size of each app thread */
@ -564,7 +564,7 @@
#endif #endif
/* Support registering quick AOT/JIT function entries of some func types /* Support registering quick AOT/JIT function entries of some func types
to speedup the calling process of invoking the AOT/JIT functions of to speed up the calling process of invoking the AOT/JIT functions of
these types from the host embedder */ these types from the host embedder */
#ifndef WASM_ENABLE_QUICK_AOT_ENTRY #ifndef WASM_ENABLE_QUICK_AOT_ENTRY
#define WASM_ENABLE_QUICK_AOT_ENTRY 1 #define WASM_ENABLE_QUICK_AOT_ENTRY 1
@ -578,6 +578,11 @@
#define WASM_ENABLE_AOT_INTRINSICS 1 #define WASM_ENABLE_AOT_INTRINSICS 1
#endif #endif
/* Disable memory64 by default */
#ifndef WASM_ENABLE_MEMORY64
#define WASM_ENABLE_MEMORY64 0
#endif
#ifndef WASM_TABLE_MAX_SIZE #ifndef WASM_TABLE_MAX_SIZE
#define WASM_TABLE_MAX_SIZE 1024 #define WASM_TABLE_MAX_SIZE 1024
#endif #endif

View File

@ -914,9 +914,10 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
bh_assert(max_memory_data_size <= MAX_LINEAR_MEMORY_SIZE); bh_assert(max_memory_data_size <= MAX_LINEAR_MEMORY_SIZE);
(void)max_memory_data_size; (void)max_memory_data_size;
if (wasm_allocate_linear_memory(&p, is_shared_memory, num_bytes_per_page, /* TODO: memory64 uses is_memory64 flag */
init_page_count, max_page_count, if (wasm_allocate_linear_memory(&p, is_shared_memory, false,
&memory_data_size) num_bytes_per_page, init_page_count,
max_page_count, &memory_data_size)
!= BHT_OK) { != BHT_OK) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"allocate linear memory failed"); "allocate linear memory failed");

View File

@ -61,7 +61,7 @@ static union {
* Implementation of wasm_application_execute_main() * Implementation of wasm_application_execute_main()
*/ */
static bool static bool
check_main_func_type(const WASMFuncType *type) check_main_func_type(const WASMFuncType *type, bool is_memory64)
{ {
if (!(type->param_count == 0 || type->param_count == 2) if (!(type->param_count == 0 || type->param_count == 2)
|| type->result_count > 1) { || type->result_count > 1) {
@ -72,7 +72,8 @@ check_main_func_type(const WASMFuncType *type)
if (type->param_count == 2 if (type->param_count == 2
&& !(type->types[0] == VALUE_TYPE_I32 && !(type->types[0] == VALUE_TYPE_I32
&& type->types[1] == VALUE_TYPE_I32)) { && type->types[1]
== (is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32))) {
LOG_ERROR( LOG_ERROR(
"WASM execute application failed: invalid main function type.\n"); "WASM execute application failed: invalid main function type.\n");
return false; return false;
@ -94,14 +95,18 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
WASMFunctionInstanceCommon *func; WASMFunctionInstanceCommon *func;
WASMFuncType *func_type = NULL; WASMFuncType *func_type = NULL;
WASMExecEnv *exec_env = NULL; WASMExecEnv *exec_env = NULL;
uint32 argc1 = 0, argv1[2] = { 0 }; uint32 argc1 = 0, argv1[3] = { 0 };
uint32 total_argv_size = 0; uint32 total_argv_size = 0;
uint64 total_size; uint64 total_size;
uint64 argv_buf_offset = 0; uint64 argv_buf_offset = 0;
int32 i; int32 i;
char *argv_buf, *p, *p_end; char *argv_buf, *p, *p_end;
uint32 *argv_offsets, module_type; uint32 *argv_offsets, module_type;
bool ret, is_import_func = true; bool ret, is_import_func = true, is_memory64 = false;
#if WASM_ENABLE_MEMORY64 != 0
WASMModuleInstance *wasm_module_inst = (WASMModuleInstance *)module_inst;
is_memory64 = wasm_module_inst->memories[0]->is_memory64;
#endif
exec_env = wasm_runtime_get_exec_env_singleton(module_inst); exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (!exec_env) { if (!exec_env) {
@ -187,7 +192,7 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
return false; return false;
} }
if (!check_main_func_type(func_type)) { if (!check_main_func_type(func_type, is_memory64)) {
wasm_runtime_set_exception(module_inst, wasm_runtime_set_exception(module_inst,
"invalid function type of main function"); "invalid function type of main function");
return false; return false;
@ -218,11 +223,21 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
p += strlen(argv[i]) + 1; p += strlen(argv[i]) + 1;
} }
argc1 = 2;
argv1[0] = (uint32)argc; argv1[0] = (uint32)argc;
/* TODO: memory64 uint64 when the memory idx is i64 */ #if WASM_ENABLE_MEMORY64 != 0
argv1[1] = if (is_memory64) {
(uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets); argc1 = 3;
uint64 app_addr =
wasm_runtime_addr_native_to_app(module_inst, argv_offsets);
PUT_I64_TO_ADDR(&argv[1], app_addr);
}
else
#endif
{
argc1 = 2;
argv1[1] = (uint32)wasm_runtime_addr_native_to_app(module_inst,
argv_offsets);
}
} }
ret = wasm_runtime_call_wasm(exec_env, func, argc1, argv1); ret = wasm_runtime_call_wasm(exec_env, func, argc1, argv1);

View File

@ -286,6 +286,7 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
{ {
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
WASMMemoryInstance *memory_inst; WASMMemoryInstance *memory_inst;
uint64 max_linear_memory_size = MAX_LINEAR_MEMORY_SIZE;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT); || module_inst_comm->module_type == Wasm_Module_AoT);
@ -299,9 +300,13 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
goto fail; goto fail;
} }
#if WASM_ENABLE_MEMORY64 != 0
if (memory_inst->is_memory64)
max_linear_memory_size = MAX_LINEAR_MEM64_MEMORY_SIZE;
#endif
/* boundary overflow check */ /* boundary overflow check */
if (size > MAX_LINEAR_MEMORY_SIZE if (size > max_linear_memory_size
|| app_offset > MAX_LINEAR_MEMORY_SIZE - size) { || app_offset > max_linear_memory_size - size) {
goto fail; goto fail;
} }
@ -324,7 +329,7 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
uint64 app_str_offset) uint64 app_str_offset)
{ {
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
uint64 app_end_offset; uint64 app_end_offset, max_linear_memory_size = MAX_LINEAR_MEMORY_SIZE;
char *str, *str_end; char *str, *str_end;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
@ -338,10 +343,14 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
&app_end_offset)) &app_end_offset))
goto fail; goto fail;
#if WASM_ENABLE_MEMORY64 != 0
if (module_inst->memories[0]->is_memory64)
max_linear_memory_size = MAX_LINEAR_MEM64_MEMORY_SIZE;
#endif
/* boundary overflow check, max start offset can only be size - 1, while end /* boundary overflow check, max start offset can only be size - 1, while end
* offset can be size */ * offset can be size */
if (app_str_offset >= MAX_LINEAR_MEMORY_SIZE if (app_str_offset >= max_linear_memory_size
|| app_end_offset > MAX_LINEAR_MEMORY_SIZE) || app_end_offset > max_linear_memory_size)
goto fail; goto fail;
str = wasm_runtime_addr_app_to_native(module_inst_comm, app_str_offset); str = wasm_runtime_addr_app_to_native(module_inst_comm, app_str_offset);
@ -364,6 +373,7 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm; WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
WASMMemoryInstance *memory_inst; WASMMemoryInstance *memory_inst;
uint8 *addr = (uint8 *)native_ptr; uint8 *addr = (uint8 *)native_ptr;
uint64 max_linear_memory_size = MAX_LINEAR_MEMORY_SIZE;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT); || module_inst_comm->module_type == Wasm_Module_AoT);
@ -377,8 +387,12 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
goto fail; goto fail;
} }
#if WASM_ENABLE_MEMORY64 != 0
if (memory_inst->is_memory64)
max_linear_memory_size = MAX_LINEAR_MEM64_MEMORY_SIZE;
#endif
/* boundary overflow check */ /* boundary overflow check */
if (size > MAX_LINEAR_MEMORY_SIZE || (uintptr_t)addr > UINTPTR_MAX - size) { if (size > max_linear_memory_size || (uintptr_t)addr > UINTPTR_MAX - size) {
goto fail; goto fail;
} }
@ -748,12 +762,13 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
goto return_func; goto return_func;
} }
bh_assert(total_size_new <= MAX_LINEAR_MEMORY_SIZE); bh_assert(total_size_new
<= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64));
if (full_size_mmaped) { if (full_size_mmaped) {
#ifdef BH_PLATFORM_WINDOWS #ifdef BH_PLATFORM_WINDOWS
if (!os_mem_commit(memory->memory_data_end, if (!os_mem_commit(memory->memory_data_end,
(uint32)(total_size_new - total_size_old), (mem_offset_t)(total_size_new - total_size_old),
MMAP_PROT_READ | MMAP_PROT_WRITE)) { MMAP_PROT_READ | MMAP_PROT_WRITE)) {
ret = false; ret = false;
goto return_func; goto return_func;
@ -761,12 +776,12 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
#endif #endif
if (os_mprotect(memory->memory_data_end, if (os_mprotect(memory->memory_data_end,
(uint32)(total_size_new - total_size_old), (mem_offset_t)(total_size_new - total_size_old),
MMAP_PROT_READ | MMAP_PROT_WRITE) MMAP_PROT_READ | MMAP_PROT_WRITE)
!= 0) { != 0) {
#ifdef BH_PLATFORM_WINDOWS #ifdef BH_PLATFORM_WINDOWS
os_mem_decommit(memory->memory_data_end, os_mem_decommit(memory->memory_data_end,
(uint32)(total_size_new - total_size_old)); (mem_offset_t)(total_size_new - total_size_old));
#endif #endif
ret = false; ret = false;
goto return_func; goto return_func;
@ -895,8 +910,9 @@ wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst)
int int
wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory, wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory,
uint64 num_bytes_per_page, uint64 init_page_count, bool is_memory64, uint64 num_bytes_per_page,
uint64 max_page_count, uint64 *memory_data_size) uint64 init_page_count, uint64 max_page_count,
uint64 *memory_data_size)
{ {
uint64 map_size, page_size; uint64 map_size, page_size;
@ -925,7 +941,16 @@ wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory,
page_size = os_getpagesize(); page_size = os_getpagesize();
*memory_data_size = init_page_count * num_bytes_per_page; *memory_data_size = init_page_count * num_bytes_per_page;
bh_assert(*memory_data_size <= MAX_LINEAR_MEMORY_SIZE);
#if WASM_ENABLE_MEMORY64 != 0
if (is_memory64) {
bh_assert(*memory_data_size <= MAX_LINEAR_MEM64_MEMORY_SIZE);
}
else
#endif
{
bh_assert(*memory_data_size <= MAX_LINEAR_MEMORY_SIZE);
}
align_as_and_cast(*memory_data_size, page_size); align_as_and_cast(*memory_data_size, page_size);
if (map_size > 0) { if (map_size > 0) {

View File

@ -64,8 +64,9 @@ wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst);
int int
wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory, wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory,
uint64 num_bytes_per_page, uint64 init_page_count, bool is_memory64, uint64 num_bytes_per_page,
uint64 max_page_count, uint64 *memory_data_size); uint64 init_page_count, uint64 max_page_count,
uint64 *memory_data_size);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -3746,7 +3746,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
typedef void (*NativeRawFuncPtr)(WASMExecEnv *, uint64 *); typedef void (*NativeRawFuncPtr)(WASMExecEnv *, uint64 *);
NativeRawFuncPtr invoke_native_raw = (NativeRawFuncPtr)func_ptr; NativeRawFuncPtr invoke_native_raw = (NativeRawFuncPtr)func_ptr;
uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size; uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size, arg_i64;
uint32 *argv_src = argv, i, argc1, ptr_len; uint32 *argv_src = argv, i, argc1, ptr_len;
uint32 arg_i32; uint32 arg_i32;
bool ret = false; bool ret = false;
@ -3770,9 +3770,11 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_FUNCREF: case VALUE_TYPE_FUNCREF:
#endif #endif
{ {
/* TODO: memory64 the data type of ptr_len and argc depends on
* mem idx type */
*(uint32 *)argv_dst = arg_i32 = *argv_src++; *(uint32 *)argv_dst = arg_i32 = *argv_src++;
/* TODO: memory64 if future there is a way for supporting
* wasm64 and wasm32 in libc at the same time, remove the
* macro control */
#if WASM_ENABLE_MEMORY64 == 0
if (signature) { if (signature) {
if (signature[i + 1] == '*') { if (signature[i + 1] == '*') {
/* param is a pointer */ /* param is a pointer */
@ -3802,9 +3804,49 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
module, (uint64)arg_i32); module, (uint64)arg_i32);
} }
} }
#endif
break; break;
} }
case VALUE_TYPE_I64: case VALUE_TYPE_I64:
#if WASM_ENABLE_MEMORY64 != 0
{
PUT_I64_TO_ADDR((uint32 *)argv_dst,
GET_I64_FROM_ADDR(argv_src));
argv_src += 2;
arg_i64 = *argv_dst;
if (signature) {
/* TODO: memory64 pointer with length need a new symbol
* to represent type i64, with '~' still represent i32
* length */
if (signature[i + 1] == '*') {
/* param is a pointer */
if (signature[i + 2] == '~')
/* pointer with length followed */
ptr_len = *argv_src;
else
/* pointer without length followed */
ptr_len = 1;
if (!wasm_runtime_validate_app_addr(module, arg_i64,
(uint64)ptr_len))
goto fail;
*argv_dst = (uint64)wasm_runtime_addr_app_to_native(
module, arg_i64);
}
else if (signature[i + 1] == '$') {
/* param is a string */
if (!wasm_runtime_validate_app_str_addr(module,
arg_i64))
goto fail;
*argv_dst = (uint64)wasm_runtime_addr_app_to_native(
module, arg_i64);
}
}
break;
}
#endif
case VALUE_TYPE_F64: case VALUE_TYPE_F64:
bh_memcpy_s(argv_dst, sizeof(uint64), argv_src, bh_memcpy_s(argv_dst, sizeof(uint64), argv_src,
sizeof(uint32) * 2); sizeof(uint32) * 2);
@ -3933,6 +3975,9 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
fail: fail:
if (argv1 != argv_buf) if (argv1 != argv_buf)
wasm_runtime_free(argv1); wasm_runtime_free(argv1);
#if WASM_ENABLE_MEMORY64 == 0
(void)arg_i64;
#endif
return ret; return ret;
} }
@ -4195,8 +4240,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
{ {
arg_i32 = *argv_src++; arg_i32 = *argv_src++;
/* TODO: memory64 the data type of ptr_len and argc depends on
* mem idx type */
if (signature) { if (signature) {
if (signature[i + 1] == '*') { if (signature[i + 1] == '*') {
/* param is a pointer */ /* param is a pointer */
@ -4572,8 +4615,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
{ {
arg_i32 = *argv++; arg_i32 = *argv++;
/* TODO: memory64 the data type of ptr_len and argc depends on
* mem idx type */
if (signature) { if (signature) {
if (signature[i + 1] == '*') { if (signature[i + 1] == '*') {
/* param is a pointer */ /* param is a pointer */
@ -4889,8 +4930,10 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
{ {
arg_i32 = *argv_src++; arg_i32 = *argv_src++;
arg_i64 = arg_i32; arg_i64 = arg_i32;
/* TODO: memory64 the data type of ptr_len and argc depends on /* TODO: memory64 if future there is a way for supporting
* mem idx type */ * wasm64 and wasm32 in libc at the same time, remove the
* macro control */
#if WASM_ENABLE_MEMORY64 == 0
if (signature) { if (signature) {
if (signature[i + 1] == '*') { if (signature[i + 1] == '*') {
/* param is a pointer */ /* param is a pointer */
@ -4918,6 +4961,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
module, (uint64)arg_i32); module, (uint64)arg_i32);
} }
} }
#endif
if (n_ints < MAX_REG_INTS) if (n_ints < MAX_REG_INTS)
ints[n_ints++] = arg_i64; ints[n_ints++] = arg_i64;
else else
@ -4925,6 +4969,47 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break; break;
} }
case VALUE_TYPE_I64: case VALUE_TYPE_I64:
#if WASM_ENABLE_MEMORY64 != 0
{
arg_i64 = GET_I64_FROM_ADDR(argv_src);
argv_src += 2;
if (signature) {
/* TODO: memory64 pointer with length need a new symbol
* to represent type i64, with '~' still represent i32
* length */
if (signature[i + 1] == '*') {
/* param is a pointer */
if (signature[i + 2] == '~')
/* pointer with length followed */
ptr_len = *argv_src;
else
/* pointer without length followed */
ptr_len = 1;
if (!wasm_runtime_validate_app_addr(module, arg_i64,
(uint64)ptr_len))
goto fail;
arg_i64 = (uint64)wasm_runtime_addr_app_to_native(
module, arg_i64);
}
else if (signature[i + 1] == '$') {
/* param is a string */
if (!wasm_runtime_validate_app_str_addr(module,
arg_i64))
goto fail;
arg_i64 = (uint64)wasm_runtime_addr_app_to_native(
module, arg_i64);
}
}
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = arg_i64;
else
stacks[n_stacks++] = arg_i64;
break;
}
#endif
#if WASM_ENABLE_GC != 0 #if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF: case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF: case REF_TYPE_EXTERNREF:

View File

@ -373,7 +373,7 @@ typedef struct WASMModuleCommon {
/* The following uint8[1] member is a dummy just to indicate /* The following uint8[1] member is a dummy just to indicate
some module_type dependent members follow. some module_type dependent members follow.
Typically it should be accessed by casting to the corresponding Typically, it should be accessed by casting to the corresponding
actual module_type dependent structure, not via this member. */ actual module_type dependent structure, not via this member. */
uint8 module_data[1]; uint8 module_data[1];
} WASMModuleCommon; } WASMModuleCommon;
@ -389,7 +389,7 @@ typedef struct WASMModuleInstanceCommon {
/* The following uint8[1] member is a dummy just to indicate /* The following uint8[1] member is a dummy just to indicate
some module_type dependent members follow. some module_type dependent members follow.
Typically it should be accessed by casting to the corresponding Typically, it should be accessed by casting to the corresponding
actual module_type dependent structure, not via this member. */ actual module_type dependent structure, not via this member. */
uint8 module_inst_data[1]; uint8 module_inst_data[1];
} WASMModuleInstanceCommon; } WASMModuleInstanceCommon;

View File

@ -90,11 +90,22 @@ extern "C" {
*/ */
#define VALUE_TYPE_GC_REF 0x43 #define VALUE_TYPE_GC_REF 0x43
#define MAX_PAGE_COUNT_FLAG 0x01
#define SHARED_MEMORY_FLAG 0x02
#define MEMORY64_FLAG 0x04
#define DEFAULT_NUM_BYTES_PER_PAGE 65536 #define DEFAULT_NUM_BYTES_PER_PAGE 65536
#define DEFAULT_MAX_PAGES 65536 #define DEFAULT_MAX_PAGES 65536
#define DEFAULT_MEM64_MAX_PAGES UINT32_MAX
/* Max size of linear memory */ /* Max size of linear memory */
#define MAX_LINEAR_MEMORY_SIZE (4 * (uint64)BH_GB) #define MAX_LINEAR_MEMORY_SIZE (4 * (uint64)BH_GB)
/* Roughly 274 TB */
#define MAX_LINEAR_MEM64_MEMORY_SIZE \
(DEFAULT_MEM64_MAX_PAGES * (uint64)64 * (uint64)BH_KB)
/* Macro to check memory flag and return appropriate memory size */
#define GET_MAX_LINEAR_MEMORY_SIZE(is_memory64) \
(is_memory64 ? MAX_LINEAR_MEM64_MEMORY_SIZE : MAX_LINEAR_MEMORY_SIZE)
#if WASM_ENABLE_GC == 0 #if WASM_ENABLE_GC == 0
typedef uintptr_t table_elem_type_t; typedef uintptr_t table_elem_type_t;
@ -484,6 +495,12 @@ typedef struct WASMTable {
#endif #endif
} WASMTable; } WASMTable;
#if WASM_ENABLE_MEMORY64 != 0
typedef uint64 mem_offset_t;
#else
typedef uint32 mem_offset_t;
#endif
typedef struct WASMMemory { typedef struct WASMMemory {
uint32 flags; uint32 flags;
uint32 num_bytes_per_page; uint32 num_bytes_per_page;

View File

@ -46,8 +46,10 @@ typedef float64 CellType_F64;
#define get_linear_mem_size() GET_LINEAR_MEMORY_SIZE(memory) #define get_linear_mem_size() GET_LINEAR_MEMORY_SIZE(memory)
#endif #endif
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ #if WASM_ENABLE_MEMORY64 == 0
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
#if (!defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0)
#define CHECK_MEMORY_OVERFLOW(bytes) \ #define CHECK_MEMORY_OVERFLOW(bytes) \
do { \ do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \ uint64 offset1 = (uint64)offset + (uint64)addr; \
@ -69,7 +71,8 @@ typedef float64 CellType_F64;
else \ else \
goto out_of_bounds; \ goto out_of_bounds; \
} while (0) } while (0)
#else #else /* else of !defined(OS_ENABLE_HW_BOUND_CHECK) || \
WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */
#define CHECK_MEMORY_OVERFLOW(bytes) \ #define CHECK_MEMORY_OVERFLOW(bytes) \
do { \ do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \ uint64 offset1 = (uint64)offset + (uint64)addr; \
@ -80,8 +83,37 @@ typedef float64 CellType_F64;
do { \ do { \
maddr = memory->memory_data + (uint32)(start); \ maddr = memory->memory_data + (uint32)(start); \
} while (0) } while (0)
#endif /* !defined(OS_ENABLE_HW_BOUND_CHECK) \ #endif /* end of !defined(OS_ENABLE_HW_BOUND_CHECK) || \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */ WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */
#else /* else of WASM_ENABLE_MEMORY64 == 0 */
#define CHECK_MEMORY_OVERFLOW(bytes) \
do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \
/* If memory64 is enabled, offset1, offset1 + bytes can overflow */ \
if (disable_bounds_checks \
|| (offset1 >= offset && offset1 + bytes >= offset1 \
&& offset1 + bytes <= get_linear_mem_size())) \
maddr = memory->memory_data + offset1; \
else \
goto out_of_bounds; \
} while (0)
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
do { \
uint64 offset1 = (uint64)(start); \
/* If memory64 is enabled, offset1 + bytes can overflow */ \
if (disable_bounds_checks \
|| (offset1 + bytes >= offset1 \
&& offset1 + bytes <= get_linear_mem_size())) \
/* App heap space is not valid space for \
bulk memory operation */ \
maddr = memory->memory_data + offset1; \
else \
goto out_of_bounds; \
} while (0)
#endif /* end of WASM_ENABLE_MEMORY64 == 0 */
#define CHECK_ATOMIC_MEMORY_ACCESS() \ #define CHECK_ATOMIC_MEMORY_ACCESS() \
do { \ do { \
@ -472,6 +504,23 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
#define SET_LABEL_TYPE(_label_type) (void)0 #define SET_LABEL_TYPE(_label_type) (void)0
#endif #endif
#if WASM_ENABLE_MEMORY64 != 0
#define PUSH_MEM_OFFSET(value) \
do { \
if (is_memory64) { \
PUT_I64_TO_ADDR(frame_sp, value); \
frame_sp += 2; \
} \
else { \
*(int32 *)frame_sp++ = (int32)(value); \
} \
} while (0)
#else
#define PUSH_MEM_OFFSET(value) PUSH_I32(value)
#endif
#define PUSH_PAGE_COUNT(value) PUSH_MEM_OFFSET(value)
#define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \ #define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \
do { \ do { \
bh_assert(frame_csp < frame->csp_boundary); \ bh_assert(frame_csp < frame->csp_boundary); \
@ -501,6 +550,14 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
GET_REF_FROM_ADDR(frame_sp)) GET_REF_FROM_ADDR(frame_sp))
#endif #endif
#if WASM_ENABLE_MEMORY64 != 0
#define POP_MEM_OFFSET() (is_memory64 ? POP_I64() : POP_I32())
#else
#define POP_MEM_OFFSET() POP_I32()
#endif
#define POP_PAGE_COUNT() POP_MEM_OFFSET()
#define POP_CSP_CHECK_OVERFLOW(n) \ #define POP_CSP_CHECK_OVERFLOW(n) \
do { \ do { \
bh_assert(frame_csp - n >= frame->csp_bottom); \ bh_assert(frame_csp - n >= frame->csp_bottom); \
@ -567,51 +624,73 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
frame_csp = frame->csp; \ frame_csp = frame->csp; \
} while (0) } while (0)
#define read_leb_int64(p, p_end, res) \ #define read_leb_int64(p, p_end, res) \
do { \ do { \
uint8 _val = *p; \ uint8 _val = *p; \
if (!(_val & 0x80)) { \ if (!(_val & 0x80)) { \
res = (int64)_val; \ res = (int64)_val; \
if (_val & 0x40) \ if (_val & 0x40) \
/* sign extend */ \ /* sign extend */ \
res |= 0xFFFFFFFFFFFFFF80LL; \ res |= 0xFFFFFFFFFFFFFF80LL; \
p++; \ p++; \
break; \ } \
} \ else { \
uint32 _off = 0; \ uint32 _off = 0; \
res = (int64)read_leb(p, &_off, 64, true); \ res = (int64)read_leb(p, &_off, 64, true); \
p += _off; \ p += _off; \
} \
} while (0) } while (0)
#define read_leb_uint32(p, p_end, res) \ #define read_leb_uint32(p, p_end, res) \
do { \ do { \
uint8 _val = *p; \ uint8 _val = *p; \
if (!(_val & 0x80)) { \ if (!(_val & 0x80)) { \
res = _val; \ res = _val; \
p++; \ p++; \
break; \ } \
} \ else { \
uint32 _off = 0; \ uint32 _off = 0; \
res = (uint32)read_leb(p, &_off, 32, false); \ res = (uint32)read_leb(p, &_off, 32, false); \
p += _off; \ p += _off; \
} \
} while (0) } while (0)
#define read_leb_int32(p, p_end, res) \ #define read_leb_int32(p, p_end, res) \
do { \ do { \
uint8 _val = *p; \ uint8 _val = *p; \
if (!(_val & 0x80)) { \ if (!(_val & 0x80)) { \
res = (int32)_val; \ res = (int32)_val; \
if (_val & 0x40) \ if (_val & 0x40) \
/* sign extend */ \ /* sign extend */ \
res |= 0xFFFFFF80; \ res |= 0xFFFFFF80; \
p++; \ p++; \
break; \ } \
} \ else { \
uint32 _off = 0; \ uint32 _off = 0; \
res = (int32)read_leb(p, &_off, 32, true); \ res = (int32)read_leb(p, &_off, 32, true); \
p += _off; \ p += _off; \
} \
} while (0) } while (0)
#if WASM_ENABLE_MEMORY64 != 0
#define read_leb_mem_offset(p, p_end, res) \
do { \
uint8 _val = *p; \
if (!(_val & 0x80)) { \
res = (mem_offset_t)_val; \
p++; \
} \
else { \
uint32 _off = 0; \
res = (mem_offset_t)read_leb(p, &_off, is_memory64 ? 64 : 32, \
false); \
p += _off; \
} \
} while (0)
#else
#define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res)
#endif
#if WASM_ENABLE_LABELS_AS_VALUES == 0 #if WASM_ENABLE_LABELS_AS_VALUES == 0
#define RECOVER_FRAME_IP_END() frame_ip_end = wasm_get_func_code_end(cur_func) #define RECOVER_FRAME_IP_END() frame_ip_end = wasm_get_func_code_end(cur_func)
#else #else
@ -872,7 +951,7 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
uint32 readv, sval; \ uint32 readv, sval; \
\ \
sval = POP_I32(); \ sval = POP_I32(); \
addr = POP_I32(); \ addr = POP_MEM_OFFSET(); \
\ \
if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U) { \ if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U) { \
CHECK_MEMORY_OVERFLOW(1); \ CHECK_MEMORY_OVERFLOW(1); \
@ -912,7 +991,7 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
uint64 readv, sval; \ uint64 readv, sval; \
\ \
sval = (uint64)POP_I64(); \ sval = (uint64)POP_I64(); \
addr = POP_I32(); \ addr = POP_MEM_OFFSET(); \
\ \
if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U) { \ if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U) { \
CHECK_MEMORY_OVERFLOW(1); \ CHECK_MEMORY_OVERFLOW(1); \
@ -1430,6 +1509,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMStringviewIterObjectRef stringview_iter_obj; WASMStringviewIterObjectRef stringview_iter_obj;
#endif #endif
#endif #endif
#if WASM_ENABLE_MEMORY64 != 0
/* TODO: multi-memories for now assuming the memory idx type is consistent
* across multi-memories */
bool is_memory64 = false;
if (memory)
is_memory64 = memory->is_memory64;
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0 #if WASM_ENABLE_DEBUG_INTERP != 0
uint8 *frame_ip_orig = NULL; uint8 *frame_ip_orig = NULL;
@ -4087,8 +4173,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
bh_assert(global_idx < module->e->global_count); bh_assert(global_idx < module->e->global_count);
global = globals + global_idx; global = globals + global_idx;
global_addr = get_global_addr(global_data, global); global_addr = get_global_addr(global_data, global);
/* TODO: Memory64 the data type depends on mem idx type */ #if WASM_ENABLE_MEMORY64 != 0
aux_stack_top = (uint64)(*(uint32 *)(frame_sp - 1)); if (is_memory64) {
aux_stack_top = *(uint64 *)(frame_sp - 2);
}
else
#endif
{
aux_stack_top = (uint64)(*(uint32 *)(frame_sp - 1));
}
if (aux_stack_top <= (uint64)exec_env->aux_stack_boundary) { if (aux_stack_top <= (uint64)exec_env->aux_stack_boundary) {
wasm_set_exception(module, "wasm auxiliary stack overflow"); wasm_set_exception(module, "wasm auxiliary stack overflow");
goto got_exception; goto got_exception;
@ -4098,8 +4191,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
"wasm auxiliary stack underflow"); "wasm auxiliary stack underflow");
goto got_exception; goto got_exception;
} }
*(int32 *)global_addr = aux_stack_top; #if WASM_ENABLE_MEMORY64 != 0
frame_sp--; if (is_memory64) {
*(uint64 *)global_addr = aux_stack_top;
frame_sp -= 2;
}
else
#endif
{
*(uint32 *)global_addr = aux_stack_top;
frame_sp--;
}
#if WASM_ENABLE_MEMORY_PROFILING != 0 #if WASM_ENABLE_MEMORY_PROFILING != 0
if (module->module->aux_stack_top_global_index != (uint32)-1) { if (module->module->aux_stack_top_global_index != (uint32)-1) {
uint32 aux_stack_used = uint32 aux_stack_used =
@ -4126,11 +4228,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_LOAD) HANDLE_OP(WASM_OP_I32_LOAD)
HANDLE_OP(WASM_OP_F32_LOAD) HANDLE_OP(WASM_OP_F32_LOAD)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4); CHECK_MEMORY_OVERFLOW(4);
PUSH_I32(LOAD_I32(maddr)); PUSH_I32(LOAD_I32(maddr));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4141,11 +4244,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD) HANDLE_OP(WASM_OP_I64_LOAD)
HANDLE_OP(WASM_OP_F64_LOAD) HANDLE_OP(WASM_OP_F64_LOAD)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(8); CHECK_MEMORY_OVERFLOW(8);
PUSH_I64(LOAD_I64(maddr)); PUSH_I64(LOAD_I64(maddr));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4155,11 +4259,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_LOAD8_S) HANDLE_OP(WASM_OP_I32_LOAD8_S)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
PUSH_I32(sign_ext_8_32(*(int8 *)maddr)); PUSH_I32(sign_ext_8_32(*(int8 *)maddr));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4169,11 +4274,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_LOAD8_U) HANDLE_OP(WASM_OP_I32_LOAD8_U)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
PUSH_I32((uint32)(*(uint8 *)maddr)); PUSH_I32((uint32)(*(uint8 *)maddr));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4183,11 +4289,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_LOAD16_S) HANDLE_OP(WASM_OP_I32_LOAD16_S)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(2); CHECK_MEMORY_OVERFLOW(2);
PUSH_I32(sign_ext_16_32(LOAD_I16(maddr))); PUSH_I32(sign_ext_16_32(LOAD_I16(maddr)));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4197,11 +4304,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_LOAD16_U) HANDLE_OP(WASM_OP_I32_LOAD16_U)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(2); CHECK_MEMORY_OVERFLOW(2);
PUSH_I32((uint32)(LOAD_U16(maddr))); PUSH_I32((uint32)(LOAD_U16(maddr)));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4211,11 +4319,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD8_S) HANDLE_OP(WASM_OP_I64_LOAD8_S)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
PUSH_I64(sign_ext_8_64(*(int8 *)maddr)); PUSH_I64(sign_ext_8_64(*(int8 *)maddr));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4225,11 +4334,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD8_U) HANDLE_OP(WASM_OP_I64_LOAD8_U)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
PUSH_I64((uint64)(*(uint8 *)maddr)); PUSH_I64((uint64)(*(uint8 *)maddr));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4239,11 +4349,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD16_S) HANDLE_OP(WASM_OP_I64_LOAD16_S)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(2); CHECK_MEMORY_OVERFLOW(2);
PUSH_I64(sign_ext_16_64(LOAD_I16(maddr))); PUSH_I64(sign_ext_16_64(LOAD_I16(maddr)));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4253,11 +4364,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD16_U) HANDLE_OP(WASM_OP_I64_LOAD16_U)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(2); CHECK_MEMORY_OVERFLOW(2);
PUSH_I64((uint64)(LOAD_U16(maddr))); PUSH_I64((uint64)(LOAD_U16(maddr)));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4267,12 +4379,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD32_S) HANDLE_OP(WASM_OP_I64_LOAD32_S)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
opcode = *(frame_ip - 1); opcode = *(frame_ip - 1);
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4); CHECK_MEMORY_OVERFLOW(4);
PUSH_I64(sign_ext_32_64(LOAD_I32(maddr))); PUSH_I64(sign_ext_32_64(LOAD_I32(maddr)));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4282,11 +4395,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD32_U) HANDLE_OP(WASM_OP_I64_LOAD32_U)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4); CHECK_MEMORY_OVERFLOW(4);
PUSH_I64((uint64)(LOAD_U32(maddr))); PUSH_I64((uint64)(LOAD_U32(maddr)));
CHECK_READ_WATCHPOINT(addr, offset); CHECK_READ_WATCHPOINT(addr, offset);
@ -4298,14 +4412,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_STORE) HANDLE_OP(WASM_OP_I32_STORE)
HANDLE_OP(WASM_OP_F32_STORE) HANDLE_OP(WASM_OP_F32_STORE)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
frame_sp--; frame_sp--;
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4); CHECK_MEMORY_OVERFLOW(4);
STORE_U32(maddr, frame_sp[1]); #if WASM_ENABLE_MEMORY64 != 0
if (is_memory64) {
STORE_U32(maddr, frame_sp[2]);
}
else
#endif
{
STORE_U32(maddr, frame_sp[1]);
}
CHECK_WRITE_WATCHPOINT(addr, offset); CHECK_WRITE_WATCHPOINT(addr, offset);
(void)flags; (void)flags;
HANDLE_OP_END(); HANDLE_OP_END();
@ -4314,15 +4437,26 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_STORE) HANDLE_OP(WASM_OP_I64_STORE)
HANDLE_OP(WASM_OP_F64_STORE) HANDLE_OP(WASM_OP_F64_STORE)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
frame_sp -= 2; frame_sp -= 2;
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(8); CHECK_MEMORY_OVERFLOW(8);
PUT_I64_TO_ADDR((uint32 *)maddr,
GET_I64_FROM_ADDR(frame_sp + 1)); #if WASM_ENABLE_MEMORY64 != 0
if (is_memory64) {
PUT_I64_TO_ADDR((mem_offset_t *)maddr,
GET_I64_FROM_ADDR(frame_sp + 2));
}
else
#endif
{
PUT_I64_TO_ADDR((uint32 *)maddr,
GET_I64_FROM_ADDR(frame_sp + 1));
}
CHECK_WRITE_WATCHPOINT(addr, offset); CHECK_WRITE_WATCHPOINT(addr, offset);
(void)flags; (void)flags;
HANDLE_OP_END(); HANDLE_OP_END();
@ -4331,14 +4465,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_STORE8) HANDLE_OP(WASM_OP_I32_STORE8)
HANDLE_OP(WASM_OP_I32_STORE16) HANDLE_OP(WASM_OP_I32_STORE16)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
uint32 sval; uint32 sval;
opcode = *(frame_ip - 1); opcode = *(frame_ip - 1);
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
sval = (uint32)POP_I32(); sval = (uint32)POP_I32();
addr = POP_I32(); addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_I32_STORE8) { if (opcode == WASM_OP_I32_STORE8) {
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
@ -4357,14 +4492,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_STORE16) HANDLE_OP(WASM_OP_I64_STORE16)
HANDLE_OP(WASM_OP_I64_STORE32) HANDLE_OP(WASM_OP_I64_STORE32)
{ {
uint32 offset, flags, addr; uint32 flags;
mem_offset_t offset, addr;
uint64 sval; uint64 sval;
opcode = *(frame_ip - 1); opcode = *(frame_ip - 1);
read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
sval = (uint64)POP_I64(); sval = (uint64)POP_I64();
addr = POP_I32(); addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_I64_STORE8) { if (opcode == WASM_OP_I64_STORE8) {
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
@ -4388,7 +4524,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{ {
uint32 reserved; uint32 reserved;
read_leb_uint32(frame_ip, frame_ip_end, reserved); read_leb_uint32(frame_ip, frame_ip_end, reserved);
PUSH_I32(memory->cur_page_count); PUSH_PAGE_COUNT(memory->cur_page_count);
(void)reserved; (void)reserved;
HANDLE_OP_END(); HANDLE_OP_END();
} }
@ -4399,15 +4535,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
prev_page_count = memory->cur_page_count; prev_page_count = memory->cur_page_count;
read_leb_uint32(frame_ip, frame_ip_end, reserved); read_leb_uint32(frame_ip, frame_ip_end, reserved);
delta = (uint32)POP_I32(); delta = (uint32)POP_PAGE_COUNT();
if (!wasm_enlarge_memory(module, delta)) { if (!wasm_enlarge_memory(module, delta)) {
/* failed to memory.grow, return -1 */ /* failed to memory.grow, return -1 */
PUSH_I32(-1); PUSH_PAGE_COUNT(-1);
} }
else { else {
/* success, return previous page count */ /* success, return previous page count */
PUSH_I32(prev_page_count); PUSH_PAGE_COUNT(prev_page_count);
/* update memory size, no need to update memory ptr as /* update memory size, no need to update memory ptr as
it isn't changed in wasm_enlarge_memory */ it isn't changed in wasm_enlarge_memory */
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ #if !defined(OS_ENABLE_HW_BOUND_CHECK) \
@ -5407,7 +5543,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#if WASM_ENABLE_BULK_MEMORY != 0 #if WASM_ENABLE_BULK_MEMORY != 0
case WASM_OP_MEMORY_INIT: case WASM_OP_MEMORY_INIT:
{ {
uint32 addr, segment; uint32 segment;
mem_offset_t addr;
uint64 bytes, offset, seg_len; uint64 bytes, offset, seg_len;
uint8 *data; uint8 *data;
@ -5417,7 +5554,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
bytes = (uint64)(uint32)POP_I32(); bytes = (uint64)(uint32)POP_I32();
offset = (uint64)(uint32)POP_I32(); offset = (uint64)(uint32)POP_I32();
addr = (uint32)POP_I32(); addr = (mem_offset_t)POP_MEM_OFFSET();
#if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_THREAD_MGR != 0
linear_mem_size = get_linear_mem_size(); linear_mem_size = get_linear_mem_size();
@ -5460,14 +5597,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
} }
case WASM_OP_MEMORY_COPY: case WASM_OP_MEMORY_COPY:
{ {
uint32 dst, src, len; mem_offset_t dst, src, len;
uint8 *mdst, *msrc; uint8 *mdst, *msrc;
frame_ip += 2; frame_ip += 2;
len = POP_MEM_OFFSET();
len = POP_I32(); src = POP_MEM_OFFSET();
src = POP_I32(); dst = POP_MEM_OFFSET();
dst = POP_I32();
#if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_THREAD_MGR != 0
linear_mem_size = get_linear_mem_size(); linear_mem_size = get_linear_mem_size();
@ -5493,13 +5629,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
} }
case WASM_OP_MEMORY_FILL: case WASM_OP_MEMORY_FILL:
{ {
uint32 dst, len; mem_offset_t dst, len;
uint8 fill_val, *mdst; uint8 fill_val, *mdst;
frame_ip++; frame_ip++;
len = POP_I32(); len = POP_MEM_OFFSET();
fill_val = POP_I32(); fill_val = POP_I32();
dst = POP_I32(); dst = POP_MEM_OFFSET();
#if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_THREAD_MGR != 0
linear_mem_size = get_linear_mem_size(); linear_mem_size = get_linear_mem_size();
@ -5729,7 +5865,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#if WASM_ENABLE_SHARED_MEMORY != 0 #if WASM_ENABLE_SHARED_MEMORY != 0
HANDLE_OP(WASM_OP_ATOMIC_PREFIX) HANDLE_OP(WASM_OP_ATOMIC_PREFIX)
{ {
uint32 offset = 0, align = 0, addr; mem_offset_t offset = 0, addr;
uint32 align = 0;
uint32 opcode1; uint32 opcode1;
read_leb_uint32(frame_ip, frame_ip_end, opcode1); read_leb_uint32(frame_ip, frame_ip_end, opcode1);
@ -5739,7 +5876,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode != WASM_OP_ATOMIC_FENCE) { if (opcode != WASM_OP_ATOMIC_FENCE) {
read_leb_uint32(frame_ip, frame_ip_end, align); read_leb_uint32(frame_ip, frame_ip_end, align);
read_leb_uint32(frame_ip, frame_ip_end, offset); read_leb_mem_offset(frame_ip, frame_ip_end, offset);
} }
switch (opcode) { switch (opcode) {
@ -5748,7 +5885,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 notify_count, ret; uint32 notify_count, ret;
notify_count = POP_I32(); notify_count = POP_I32();
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4); CHECK_MEMORY_OVERFLOW(4);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
@ -5768,7 +5905,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
timeout = POP_I64(); timeout = POP_I64();
expect = POP_I32(); expect = POP_I32();
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4); CHECK_MEMORY_OVERFLOW(4);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
@ -5792,7 +5929,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
timeout = POP_I64(); timeout = POP_I64();
expect = POP_I64(); expect = POP_I64();
addr = POP_I32(); addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(8); CHECK_MEMORY_OVERFLOW(8);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
@ -5823,7 +5960,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{ {
uint32 readv; uint32 readv;
addr = POP_I32(); addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
@ -5858,7 +5995,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{ {
uint64 readv; uint64 readv;
addr = POP_I32(); addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
@ -5900,7 +6037,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 sval; uint32 sval;
sval = (uint32)POP_I32(); sval = (uint32)POP_I32();
addr = POP_I32(); addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_I32_STORE8) { if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
@ -5934,7 +6071,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint64 sval; uint64 sval;
sval = (uint64)POP_I64(); sval = (uint64)POP_I64();
addr = POP_I32(); addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_I64_STORE8) { if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
@ -5961,7 +6098,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_MEMORY_OVERFLOW(8); CHECK_MEMORY_OVERFLOW(8);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
shared_memory_lock(memory); shared_memory_lock(memory);
PUT_I64_TO_ADDR((uint32 *)maddr, sval); STORE_I64(maddr, sval);
shared_memory_unlock(memory); shared_memory_unlock(memory);
} }
break; break;
@ -5975,7 +6112,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
sval = POP_I32(); sval = POP_I32();
expect = POP_I32(); expect = POP_I32();
addr = POP_I32(); addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U) { if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U) {
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);
@ -6021,7 +6158,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
sval = (uint64)POP_I64(); sval = (uint64)POP_I64();
expect = (uint64)POP_I64(); expect = (uint64)POP_I64();
addr = POP_I32(); addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U) { if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U) {
CHECK_MEMORY_OVERFLOW(1); CHECK_MEMORY_OVERFLOW(1);

View File

@ -45,6 +45,16 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
} }
} }
#if WASM_ENABLE_MEMORY64 != 0
static void
set_error_buf_mem_offset_out_of_range(char *error_buf, uint32 error_buf_size)
{
if (error_buf != NULL) {
snprintf(error_buf, error_buf_size, "offset out of range");
}
}
#endif
static void static void
set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...) set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...)
{ {
@ -102,6 +112,7 @@ check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length,
#define skip_leb_int64(p, p_end) skip_leb(p) #define skip_leb_int64(p, p_end) skip_leb(p)
#define skip_leb_uint32(p, p_end) skip_leb(p) #define skip_leb_uint32(p, p_end) skip_leb(p)
#define skip_leb_int32(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)
static bool static bool
read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
@ -139,7 +150,7 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
} }
else if (sign && maxbits == 32) { else if (sign && maxbits == 32) {
if (shift < maxbits) { if (shift < maxbits) {
/* Sign extend, second highest bit is the sign bit */ /* Sign extend, second-highest bit is the sign bit */
if ((uint8)byte & 0x40) if ((uint8)byte & 0x40)
result |= (~((uint64)0)) << shift; result |= (~((uint64)0)) << shift;
} }
@ -154,7 +165,7 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
} }
else if (sign && maxbits == 64) { else if (sign && maxbits == 64) {
if (shift < maxbits) { if (shift < maxbits) {
/* Sign extend, second highest bit is the sign bit */ /* Sign extend, second-highest bit is the sign bit */
if ((uint8)byte & 0x40) if ((uint8)byte & 0x40)
result |= (~((uint64)0)) << shift; result |= (~((uint64)0)) << shift;
} }
@ -191,6 +202,21 @@ fail:
res = (int64)res64; \ res = (int64)res64; \
} while (0) } while (0)
#if WASM_ENABLE_MEMORY64 != 0
#define read_leb_mem_offset(p, p_end, res) \
do { \
uint64 res64; \
if (!read_leb((uint8 **)&p, p_end, is_memory64 ? 64 : 32, false, \
&res64, error_buf, error_buf_size)) { \
set_error_buf_mem_offset_out_of_range(error_buf, error_buf_size); \
goto fail; \
} \
res = (mem_offset_t)res64; \
} while (0)
#else
#define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res)
#endif
#define read_leb_uint32(p, p_end, res) \ #define read_leb_uint32(p, p_end, res) \
do { \ do { \
uint64 res64; \ uint64 res64; \
@ -2582,31 +2608,92 @@ fail:
} }
static bool static bool
check_memory_init_size(uint32 init_size, char *error_buf, uint32 error_buf_size) check_memory_init_size(bool is_memory64, uint32 init_size, char *error_buf,
uint32 error_buf_size)
{ {
if (init_size > DEFAULT_MAX_PAGES) { uint32 default_max_size =
is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
if (!is_memory64 && init_size > default_max_size) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"memory size must be at most 65536 pages (4GiB)"); "memory size must be at most 65536 pages (4GiB)");
return false; return false;
} }
#if WASM_ENABLE_MEMORY64 != 0
else if (is_memory64 && init_size > default_max_size) {
set_error_buf(
error_buf, error_buf_size,
"memory size must be at most 4,294,967,295 pages (274 Terabyte)");
return false;
}
#endif
return true; return true;
} }
static bool static bool
check_memory_max_size(uint32 init_size, uint32 max_size, char *error_buf, check_memory_max_size(bool is_memory64, uint32 init_size, uint32 max_size,
uint32 error_buf_size) char *error_buf, uint32 error_buf_size)
{ {
uint32 default_max_size =
is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
if (max_size < init_size) { if (max_size < init_size) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"size minimum must not be greater than maximum"); "size minimum must not be greater than maximum");
return false; return false;
} }
if (max_size > DEFAULT_MAX_PAGES) { if (!is_memory64 && max_size > default_max_size) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"memory size must be at most 65536 pages (4GiB)"); "memory size must be at most 65536 pages (4GiB)");
return false; return false;
} }
#if WASM_ENABLE_MEMORY64 != 0
else if (is_memory64 && max_size > default_max_size) {
set_error_buf(
error_buf, error_buf_size,
"memory size must be at most 4,294,967,295 pages (274 Terabyte)");
return false;
}
#endif
return true;
}
static bool
check_memory_flag(const uint8 mem_flag, char *error_buf, uint32 error_buf_size)
{
/* Check whether certain features indicated by mem_flag are enabled in
* runtime */
if (mem_flag > MAX_PAGE_COUNT_FLAG) {
#if WASM_ENABLE_SHARED_MEMORY == 0
if (mem_flag & SHARED_MEMORY_FLAG) {
LOG_VERBOSE("shared memory flag was found, please enable shared "
"memory, lib-pthread or lib-wasi-threads");
set_error_buf(error_buf, error_buf_size, "invalid limits flags");
return false;
}
#endif
#if WASM_ENABLE_MEMORY64 == 0
if (mem_flag & MEMORY64_FLAG) {
LOG_VERBOSE("memory64 flag was found, please enable memory64");
set_error_buf(error_buf, error_buf_size, "invalid limits flags");
return false;
}
#endif
}
if (mem_flag > MAX_PAGE_COUNT_FLAG + SHARED_MEMORY_FLAG + MEMORY64_FLAG) {
set_error_buf(error_buf, error_buf_size, "invalid limits flags");
return false;
}
else if ((mem_flag & SHARED_MEMORY_FLAG)
&& !(mem_flag & MAX_PAGE_COUNT_FLAG)) {
set_error_buf(error_buf, error_buf_size,
"shared memory must have maximum");
return false;
}
return true; return true;
} }
@ -2616,15 +2703,16 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
const char *memory_name, WASMMemoryImport *memory, const char *memory_name, WASMMemoryImport *memory,
char *error_buf, uint32 error_buf_size) char *error_buf, uint32 error_buf_size)
{ {
const uint8 *p = *p_buf, *p_end = buf_end; const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
#if WASM_ENABLE_APP_FRAMEWORK != 0 #if WASM_ENABLE_APP_FRAMEWORK != 0
uint32 pool_size = wasm_runtime_memory_pool_size(); uint32 pool_size = wasm_runtime_memory_pool_size();
uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
/ DEFAULT_NUM_BYTES_PER_PAGE; / DEFAULT_NUM_BYTES_PER_PAGE;
#else #else
uint32 max_page_count = DEFAULT_MAX_PAGES; uint32 max_page_count;
#endif /* WASM_ENABLE_APP_FRAMEWORK */ #endif /* WASM_ENABLE_APP_FRAMEWORK */
uint32 declare_max_page_count_flag = 0; uint32 mem_flag = 0;
bool is_memory64 = false;
uint32 declare_init_page_count = 0; uint32 declare_init_page_count = 0;
uint32 declare_max_page_count = 0; uint32 declare_max_page_count = 0;
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
@ -2632,16 +2720,31 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
WASMMemory *linked_memory = NULL; WASMMemory *linked_memory = NULL;
#endif #endif
read_leb_uint32(p, p_end, declare_max_page_count_flag); p_org = p;
read_leb_uint32(p, p_end, mem_flag);
is_memory64 = mem_flag & MEMORY64_FLAG;
if (p - p_org > 1) {
LOG_VERBOSE("integer representation too long");
set_error_buf(error_buf, error_buf_size, "invalid limits flags");
return false;
}
if (!check_memory_flag(mem_flag, error_buf, error_buf_size)) {
return false;
}
read_leb_uint32(p, p_end, declare_init_page_count); read_leb_uint32(p, p_end, declare_init_page_count);
if (!check_memory_init_size(declare_init_page_count, error_buf, if (!check_memory_init_size(is_memory64, declare_init_page_count, error_buf,
error_buf_size)) { error_buf_size)) {
return false; return false;
} }
if (declare_max_page_count_flag & 1) { #if WASM_ENABLE_APP_FRAMEWORK == 0
max_page_count = is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
#endif
if (mem_flag & MAX_PAGE_COUNT_FLAG) {
read_leb_uint32(p, p_end, declare_max_page_count); read_leb_uint32(p, p_end, declare_max_page_count);
if (!check_memory_max_size(declare_init_page_count, if (!check_memory_max_size(is_memory64, declare_init_page_count,
declare_max_page_count, error_buf, declare_max_page_count, error_buf,
error_buf_size)) { error_buf_size)) {
return false; return false;
@ -2664,7 +2767,7 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
#if WASM_ENABLE_LIB_WASI_THREADS != 0 #if WASM_ENABLE_LIB_WASI_THREADS != 0
/* Avoid memory import failure when wasi-threads is enabled /* Avoid memory import failure when wasi-threads is enabled
and the memory is shared */ and the memory is shared */
if (!(declare_max_page_count_flag & 2)) if (!(mem_flag & SHARED_MEMORY_FLAG))
return false; return false;
#else #else
return false; return false;
@ -2712,7 +2815,7 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
} }
/* now we believe all declaration are ok */ /* now we believe all declaration are ok */
memory->flags = declare_max_page_count_flag; memory->flags = mem_flag;
memory->init_page_count = declare_init_page_count; memory->init_page_count = declare_init_page_count;
memory->max_page_count = declare_max_page_count; memory->max_page_count = declare_max_page_count;
memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
@ -3013,53 +3116,34 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory,
uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
/ DEFAULT_NUM_BYTES_PER_PAGE; / DEFAULT_NUM_BYTES_PER_PAGE;
#else #else
uint32 max_page_count = DEFAULT_MAX_PAGES; uint32 max_page_count;
#endif #endif
bool is_memory64 = false;
p_org = p; p_org = p;
read_leb_uint32(p, p_end, memory->flags); read_leb_uint32(p, p_end, memory->flags);
#if WASM_ENABLE_SHARED_MEMORY == 0 is_memory64 = memory->flags & MEMORY64_FLAG;
if (p - p_org > 1) {
set_error_buf(error_buf, error_buf_size,
"integer representation too long");
return false;
}
if (memory->flags > 1) {
if (memory->flags & 2) {
set_error_buf(error_buf, error_buf_size,
"shared memory flag was found, "
"please enable shared memory, lib-pthread "
"or lib-wasi-threads");
}
else {
set_error_buf(error_buf, error_buf_size, "invalid memory flags");
}
return false;
}
#else
if (p - p_org > 1) { if (p - p_org > 1) {
LOG_VERBOSE("integer representation too long");
set_error_buf(error_buf, error_buf_size, "invalid limits flags"); set_error_buf(error_buf, error_buf_size, "invalid limits flags");
return false; return false;
} }
if (memory->flags > 3) {
set_error_buf(error_buf, error_buf_size, "invalid limits flags"); if (!check_memory_flag(memory->flags, error_buf, error_buf_size)) {
return false; return false;
} }
else if (memory->flags == 2) {
set_error_buf(error_buf, error_buf_size,
"shared memory must have maximum");
return false;
}
#endif
read_leb_uint32(p, p_end, memory->init_page_count); read_leb_uint32(p, p_end, memory->init_page_count);
if (!check_memory_init_size(memory->init_page_count, error_buf, if (!check_memory_init_size(is_memory64, memory->init_page_count, error_buf,
error_buf_size)) error_buf_size))
return false; return false;
#if WASM_ENABLE_APP_FRAMEWORK == 0
max_page_count = is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
#endif
if (memory->flags & 1) { if (memory->flags & 1) {
read_leb_uint32(p, p_end, memory->max_page_count); read_leb_uint32(p, p_end, memory->max_page_count);
if (!check_memory_max_size(memory->init_page_count, if (!check_memory_max_size(is_memory64, memory->init_page_count,
memory->max_page_count, error_buf, memory->max_page_count, error_buf,
error_buf_size)) error_buf_size))
return false; return false;
@ -4450,6 +4534,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
bool is_passive = false; bool is_passive = false;
uint32 mem_flag; uint32 mem_flag;
#endif #endif
uint8 mem_offset_type;
read_leb_uint32(p, p_end, data_seg_count); read_leb_uint32(p, p_end, data_seg_count);
@ -4515,11 +4600,35 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
} }
#endif /* WASM_ENABLE_BULK_MEMORY */ #endif /* WASM_ENABLE_BULK_MEMORY */
#if WASM_ENABLE_BULK_MEMORY != 0
if (!is_passive)
#endif
{
#if WASM_ENABLE_MEMORY64 != 0
/* This memory_flag is from memory instead of data segment */
uint8 memory_flag;
if (module->import_memory_count > 0) {
memory_flag =
module->import_memories[mem_index].u.memory.flags;
}
else {
memory_flag =
module
->memories[mem_index - module->import_memory_count]
.flags;
}
mem_offset_type = memory_flag & MEMORY64_FLAG ? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
}
#if WASM_ENABLE_BULK_MEMORY != 0 #if WASM_ENABLE_BULK_MEMORY != 0
if (!is_passive) if (!is_passive)
#endif #endif
if (!load_init_expr(module, &p, p_end, &init_expr, if (!load_init_expr(module, &p, p_end, &init_expr,
VALUE_TYPE_I32, NULL, error_buf, mem_offset_type, NULL, error_buf,
error_buf_size)) error_buf_size))
return false; return false;
@ -6979,8 +7088,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE8:
case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE16:
case WASM_OP_I64_STORE32: case WASM_OP_I64_STORE32:
skip_leb_uint32(p, p_end); /* align */ skip_leb_uint32(p, p_end); /* align */
skip_leb_uint32(p, p_end); /* offset */ skip_leb_mem_offset(p, p_end); /* offset */
break; break;
case WASM_OP_MEMORY_SIZE: case WASM_OP_MEMORY_SIZE:
@ -7326,6 +7435,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
case WASM_OP_SIMD_PREFIX: case WASM_OP_SIMD_PREFIX:
{ {
/* TODO: memory64 offset type changes */
uint32 opcode1; uint32 opcode1;
read_leb_uint32(p, p_end, opcode1); read_leb_uint32(p, p_end, opcode1);
@ -7422,6 +7532,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
#if WASM_ENABLE_SHARED_MEMORY != 0 #if WASM_ENABLE_SHARED_MEMORY != 0
case WASM_OP_ATOMIC_PREFIX: case WASM_OP_ATOMIC_PREFIX:
{ {
/* TODO: memory64 offset type changes */
uint32 opcode1; uint32 opcode1;
/* atomic_op (u32_leb) + memarg (2 u32_leb) */ /* atomic_op (u32_leb) + memarg (2 u32_leb) */
@ -7431,8 +7542,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
opcode = (uint8)opcode1; opcode = (uint8)opcode1;
if (opcode != WASM_OP_ATOMIC_FENCE) { if (opcode != WASM_OP_ATOMIC_FENCE) {
skip_leb_uint32(p, p_end); /* align */ skip_leb_uint32(p, p_end); /* align */
skip_leb_uint32(p, p_end); /* offset */ skip_leb_mem_offset(p, p_end); /* offset */
} }
else { else {
/* atomic.fence doesn't have memarg */ /* atomic.fence doesn't have memarg */
@ -9334,6 +9445,8 @@ fail:
#define PUSH_EXTERNREF() TEMPLATE_PUSH(EXTERNREF) #define PUSH_EXTERNREF() TEMPLATE_PUSH(EXTERNREF)
#define PUSH_REF(Type) TEMPLATE_PUSH_REF(Type) #define PUSH_REF(Type) TEMPLATE_PUSH_REF(Type)
#define POP_REF(Type) TEMPLATE_POP_REF(Type) #define POP_REF(Type) TEMPLATE_POP_REF(Type)
#define PUSH_MEM_OFFSET() TEMPLATE_PUSH_REF(mem_offset_type)
#define PUSH_PAGE_COUNT() PUSH_MEM_OFFSET()
#define POP_I32() TEMPLATE_POP(I32) #define POP_I32() TEMPLATE_POP(I32)
#define POP_F32() TEMPLATE_POP(F32) #define POP_F32() TEMPLATE_POP(F32)
@ -9343,6 +9456,7 @@ fail:
#define POP_FUNCREF() TEMPLATE_POP(FUNCREF) #define POP_FUNCREF() TEMPLATE_POP(FUNCREF)
#define POP_EXTERNREF() TEMPLATE_POP(EXTERNREF) #define POP_EXTERNREF() TEMPLATE_POP(EXTERNREF)
#define POP_STRINGREF() TEMPLATE_POP(STRINGREF) #define POP_STRINGREF() TEMPLATE_POP(STRINGREF)
#define POP_MEM_OFFSET() TEMPLATE_POP_REF(mem_offset_type)
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
@ -10510,11 +10624,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
{ {
uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org; uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org;
uint32 param_count, local_count, global_count; uint32 param_count, local_count, global_count;
uint8 *param_types, *local_types, local_type, global_type; uint8 *param_types, *local_types, local_type, global_type, mem_offset_type;
BlockType func_block_type; BlockType func_block_type;
uint16 *local_offsets, local_offset; uint16 *local_offsets, local_offset;
uint32 type_idx, func_idx, local_idx, global_idx, table_idx; uint32 type_idx, func_idx, local_idx, global_idx, table_idx;
uint32 table_seg_idx, data_seg_idx, count, align, mem_offset, i; uint32 table_seg_idx, data_seg_idx, count, align, i;
mem_offset_t mem_offset;
int32 i32_const = 0; int32 i32_const = 0;
int64 i64_const; int64 i64_const;
uint8 opcode; uint8 opcode;
@ -10539,6 +10654,19 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n", LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n",
func->param_cell_num, func->local_cell_num, func->ret_cell_num); func->param_cell_num, func->local_cell_num, func->ret_cell_num);
#endif #endif
#if WASM_ENABLE_MEMORY64 != 0
bool is_memory64 = false;
/* TODO: multi-memories for now assuming the memory idx type is consistent
* across multi-memories */
if (module->import_memory_count > 0)
is_memory64 = module->import_memories[0].u.memory.flags & MEMORY64_FLAG;
else if (module->memory_count > 0)
is_memory64 = module->memories[0].flags & MEMORY64_FLAG;
mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
global_count = module->import_global_count + module->global_count; global_count = module->import_global_count + module->global_count;
@ -12730,8 +12858,8 @@ re_scan:
} }
#endif #endif
CHECK_MEMORY(); CHECK_MEMORY();
read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, align); /* align */
read_leb_uint32(p, p_end, mem_offset); /* offset */ read_leb_mem_offset(p, p_end, mem_offset); /* offset */
if (!check_memory_access_align(opcode, align, error_buf, if (!check_memory_access_align(opcode, align, error_buf,
error_buf_size)) { error_buf_size)) {
goto fail; goto fail;
@ -12749,7 +12877,7 @@ re_scan:
case WASM_OP_I32_LOAD8_U: case WASM_OP_I32_LOAD8_U:
case WASM_OP_I32_LOAD16_S: case WASM_OP_I32_LOAD16_S:
case WASM_OP_I32_LOAD16_U: case WASM_OP_I32_LOAD16_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I32);
break; break;
case WASM_OP_I64_LOAD: case WASM_OP_I64_LOAD:
case WASM_OP_I64_LOAD8_S: case WASM_OP_I64_LOAD8_S:
@ -12758,35 +12886,35 @@ re_scan:
case WASM_OP_I64_LOAD16_U: case WASM_OP_I64_LOAD16_U:
case WASM_OP_I64_LOAD32_S: case WASM_OP_I64_LOAD32_S:
case WASM_OP_I64_LOAD32_U: case WASM_OP_I64_LOAD32_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I64);
break; break;
case WASM_OP_F32_LOAD: case WASM_OP_F32_LOAD:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_F32);
break; break;
case WASM_OP_F64_LOAD: case WASM_OP_F64_LOAD:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_F64);
break; break;
/* store */ /* store */
case WASM_OP_I32_STORE: case WASM_OP_I32_STORE:
case WASM_OP_I32_STORE8: case WASM_OP_I32_STORE8:
case WASM_OP_I32_STORE16: case WASM_OP_I32_STORE16:
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
break; break;
case WASM_OP_I64_STORE: case WASM_OP_I64_STORE:
case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE8:
case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE16:
case WASM_OP_I64_STORE32: case WASM_OP_I64_STORE32:
POP_I64(); POP_I64();
POP_I32(); POP_MEM_OFFSET();
break; break;
case WASM_OP_F32_STORE: case WASM_OP_F32_STORE:
POP_F32(); POP_F32();
POP_I32(); POP_MEM_OFFSET();
break; break;
case WASM_OP_F64_STORE: case WASM_OP_F64_STORE:
POP_F64(); POP_F64();
POP_I32(); POP_MEM_OFFSET();
break; break;
default: default:
break; break;
@ -12802,7 +12930,7 @@ re_scan:
"zero byte expected"); "zero byte expected");
goto fail; goto fail;
} }
PUSH_I32(); PUSH_PAGE_COUNT();
module->possible_memory_grow = true; module->possible_memory_grow = true;
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
@ -12818,7 +12946,7 @@ re_scan:
"zero byte expected"); "zero byte expected");
goto fail; goto fail;
} }
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); POP_AND_PUSH(mem_offset_type, mem_offset_type);
module->possible_memory_grow = true; module->possible_memory_grow = true;
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
@ -14179,7 +14307,7 @@ re_scan:
POP_I32(); POP_I32();
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true; func->has_memory_operations = true;
#endif #endif
@ -14222,9 +14350,9 @@ re_scan:
&& module->memory_count == 0) && module->memory_count == 0)
goto fail_unknown_memory; goto fail_unknown_memory;
POP_I32(); POP_MEM_OFFSET();
POP_I32(); POP_MEM_OFFSET();
POP_I32(); POP_MEM_OFFSET();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true; func->has_memory_operations = true;
#endif #endif
@ -14242,10 +14370,9 @@ re_scan:
&& module->memory_count == 0) { && module->memory_count == 0) {
goto fail_unknown_memory; goto fail_unknown_memory;
} }
POP_MEM_OFFSET();
POP_I32();
POP_I32();
POP_I32(); POP_I32();
POP_MEM_OFFSET();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true; func->has_memory_operations = true;
#endif #endif
@ -14491,6 +14618,7 @@ re_scan:
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
case WASM_OP_SIMD_PREFIX: case WASM_OP_SIMD_PREFIX:
{ {
/* TODO: memory64 offset type changes */
uint32 opcode1; uint32 opcode1;
#if WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_WAMR_COMPILER != 0
@ -15167,8 +15295,8 @@ re_scan:
#endif #endif
if (opcode1 != WASM_OP_ATOMIC_FENCE) { if (opcode1 != WASM_OP_ATOMIC_FENCE) {
CHECK_MEMORY(); CHECK_MEMORY();
read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, align); /* align */
read_leb_uint32(p, p_end, mem_offset); /* offset */ read_leb_mem_offset(p, p_end, mem_offset); /* offset */
if (!check_memory_align_equal(opcode1, align, error_buf, if (!check_memory_align_equal(opcode1, align, error_buf,
error_buf_size)) { error_buf_size)) {
goto fail; goto fail;
@ -15182,18 +15310,20 @@ re_scan:
#endif #endif
switch (opcode1) { switch (opcode1) {
case WASM_OP_ATOMIC_NOTIFY: case WASM_OP_ATOMIC_NOTIFY:
POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); POP_I32();
POP_MEM_OFFSET();
PUSH_I32();
break; break;
case WASM_OP_ATOMIC_WAIT32: case WASM_OP_ATOMIC_WAIT32:
POP_I64(); POP_I64();
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
PUSH_I32(); PUSH_I32();
break; break;
case WASM_OP_ATOMIC_WAIT64: case WASM_OP_ATOMIC_WAIT64:
POP_I64(); POP_I64();
POP_I64(); POP_I64();
POP_I32(); POP_MEM_OFFSET();
PUSH_I32(); PUSH_I32();
break; break;
case WASM_OP_ATOMIC_FENCE: case WASM_OP_ATOMIC_FENCE:
@ -15207,26 +15337,26 @@ re_scan:
case WASM_OP_ATOMIC_I32_LOAD: case WASM_OP_ATOMIC_I32_LOAD:
case WASM_OP_ATOMIC_I32_LOAD8_U: case WASM_OP_ATOMIC_I32_LOAD8_U:
case WASM_OP_ATOMIC_I32_LOAD16_U: case WASM_OP_ATOMIC_I32_LOAD16_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I32);
break; break;
case WASM_OP_ATOMIC_I32_STORE: case WASM_OP_ATOMIC_I32_STORE:
case WASM_OP_ATOMIC_I32_STORE8: case WASM_OP_ATOMIC_I32_STORE8:
case WASM_OP_ATOMIC_I32_STORE16: case WASM_OP_ATOMIC_I32_STORE16:
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
break; break;
case WASM_OP_ATOMIC_I64_LOAD: case WASM_OP_ATOMIC_I64_LOAD:
case WASM_OP_ATOMIC_I64_LOAD8_U: case WASM_OP_ATOMIC_I64_LOAD8_U:
case WASM_OP_ATOMIC_I64_LOAD16_U: case WASM_OP_ATOMIC_I64_LOAD16_U:
case WASM_OP_ATOMIC_I64_LOAD32_U: case WASM_OP_ATOMIC_I64_LOAD32_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I64);
break; break;
case WASM_OP_ATOMIC_I64_STORE: case WASM_OP_ATOMIC_I64_STORE:
case WASM_OP_ATOMIC_I64_STORE8: case WASM_OP_ATOMIC_I64_STORE8:
case WASM_OP_ATOMIC_I64_STORE16: case WASM_OP_ATOMIC_I64_STORE16:
case WASM_OP_ATOMIC_I64_STORE32: case WASM_OP_ATOMIC_I64_STORE32:
POP_I64(); POP_I64();
POP_I32(); POP_MEM_OFFSET();
break; break;
case WASM_OP_ATOMIC_RMW_I32_ADD: case WASM_OP_ATOMIC_RMW_I32_ADD:
case WASM_OP_ATOMIC_RMW_I32_ADD8_U: case WASM_OP_ATOMIC_RMW_I32_ADD8_U:
@ -15246,7 +15376,9 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I32_XCHG: case WASM_OP_ATOMIC_RMW_I32_XCHG:
case WASM_OP_ATOMIC_RMW_I32_XCHG8_U: case WASM_OP_ATOMIC_RMW_I32_XCHG8_U:
case WASM_OP_ATOMIC_RMW_I32_XCHG16_U: case WASM_OP_ATOMIC_RMW_I32_XCHG16_U:
POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); POP_I32();
POP_MEM_OFFSET();
PUSH_I32();
break; break;
case WASM_OP_ATOMIC_RMW_I64_ADD: case WASM_OP_ATOMIC_RMW_I64_ADD:
case WASM_OP_ATOMIC_RMW_I64_ADD8_U: case WASM_OP_ATOMIC_RMW_I64_ADD8_U:
@ -15273,7 +15405,7 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I64_XCHG16_U: case WASM_OP_ATOMIC_RMW_I64_XCHG16_U:
case WASM_OP_ATOMIC_RMW_I64_XCHG32_U: case WASM_OP_ATOMIC_RMW_I64_XCHG32_U:
POP_I64(); POP_I64();
POP_I32(); POP_MEM_OFFSET();
PUSH_I64(); PUSH_I64();
break; break;
case WASM_OP_ATOMIC_RMW_I32_CMPXCHG: case WASM_OP_ATOMIC_RMW_I32_CMPXCHG:
@ -15281,7 +15413,7 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U: case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U:
POP_I32(); POP_I32();
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
PUSH_I32(); PUSH_I32();
break; break;
case WASM_OP_ATOMIC_RMW_I64_CMPXCHG: case WASM_OP_ATOMIC_RMW_I64_CMPXCHG:
@ -15290,7 +15422,7 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U: case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U:
POP_I64(); POP_I64();
POP_I64(); POP_I64();
POP_I32(); POP_MEM_OFFSET();
PUSH_I64(); PUSH_I64();
break; break;
default: default:

View File

@ -47,6 +47,7 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
#define skip_leb_int64(p, p_end) skip_leb(p) #define skip_leb_int64(p, p_end) skip_leb(p)
#define skip_leb_uint32(p, p_end) skip_leb(p) #define skip_leb_uint32(p, p_end) skip_leb(p)
#define skip_leb_int32(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)
static bool static bool
is_32bit_type(uint8 type) is_32bit_type(uint8 type)
@ -116,7 +117,7 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
} }
else if (sign && maxbits == 32) { else if (sign && maxbits == 32) {
if (shift < maxbits) { if (shift < maxbits) {
/* Sign extend, second highest bit is the sign bit */ /* Sign extend, second-highest bit is the sign bit */
if ((uint8)byte & 0x40) if ((uint8)byte & 0x40)
result |= (~((uint64)0)) << shift; result |= (~((uint64)0)) << shift;
} }
@ -132,7 +133,7 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
} }
else if (sign && maxbits == 64) { else if (sign && maxbits == 64) {
if (shift < maxbits) { if (shift < maxbits) {
/* Sign extend, second highest bit is the sign bit */ /* Sign extend, second-highest bit is the sign bit */
if ((uint8)byte & 0x40) if ((uint8)byte & 0x40)
result |= (~((uint64)0)) << shift; result |= (~((uint64)0)) << shift;
} }
@ -180,6 +181,18 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
res = (int32)res64; \ res = (int32)res64; \
} while (0) } while (0)
#if WASM_ENABLE_MEMORY64 != 0
#define read_leb_mem_offset(p, p_end, res) \
do { \
uint64 res64; \
read_leb((uint8 **)&p, p_end, is_memory64 ? 64 : 32, false, &res64, \
error_buf, error_buf_size); \
res = (mem_offset_t)res64; \
} while (0)
#else
#define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res)
#endif
static void * static void *
loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
{ {
@ -683,6 +696,38 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
return true; return true;
} }
static bool
check_memory_flag(const uint8 mem_flag)
{
/* Check whether certain features indicated by mem_flag are enabled in
* runtime */
if (mem_flag > MAX_PAGE_COUNT_FLAG) {
#if WASM_ENABLE_SHARED_MEMORY == 0
if (mem_flag & SHARED_MEMORY_FLAG) {
LOG_VERBOSE("shared memory flag was found, please enable shared "
"memory, lib-pthread or lib-wasi-threads");
return false;
}
#endif
#if WASM_ENABLE_MEMORY64 == 0
if (mem_flag & MEMORY64_FLAG) {
LOG_VERBOSE("memory64 flag was found, please enable memory64");
return false;
}
#endif
}
if (mem_flag > MAX_PAGE_COUNT_FLAG + SHARED_MEMORY_FLAG + MEMORY64_FLAG) {
return false;
}
else if ((mem_flag & SHARED_MEMORY_FLAG)
&& !(mem_flag & MAX_PAGE_COUNT_FLAG)) {
return false;
}
return true;
}
static bool static bool
load_memory_import(const uint8 **p_buf, const uint8 *buf_end, load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
WASMModule *parent_module, const char *sub_module_name, WASMModule *parent_module, const char *sub_module_name,
@ -695,20 +740,28 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
/ DEFAULT_NUM_BYTES_PER_PAGE; / DEFAULT_NUM_BYTES_PER_PAGE;
#else #else
uint32 max_page_count = DEFAULT_MAX_PAGES; uint32 max_page_count;
#endif /* WASM_ENABLE_APP_FRAMEWORK */ #endif /* WASM_ENABLE_APP_FRAMEWORK */
uint32 declare_max_page_count_flag = 0; uint32 mem_flag = 0;
bool is_memory64 = false;
uint32 declare_init_page_count = 0; uint32 declare_init_page_count = 0;
uint32 declare_max_page_count = 0; uint32 declare_max_page_count = 0;
read_leb_uint32(p, p_end, declare_max_page_count_flag); read_leb_uint32(p, p_end, mem_flag);
read_leb_uint32(p, p_end, declare_init_page_count); bh_assert(check_memory_flag(mem_flag));
bh_assert(declare_init_page_count <= 65536);
if (declare_max_page_count_flag & 1) { #if WASM_ENABLE_APP_FRAMEWORK == 0
is_memory64 = mem_flag & MEMORY64_FLAG;
max_page_count = is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
#endif
read_leb_uint32(p, p_end, declare_init_page_count);
bh_assert(declare_init_page_count <= max_page_count);
if (mem_flag & MAX_PAGE_COUNT_FLAG) {
read_leb_uint32(p, p_end, declare_max_page_count); read_leb_uint32(p, p_end, declare_max_page_count);
bh_assert(declare_init_page_count <= declare_max_page_count); bh_assert(declare_init_page_count <= declare_max_page_count);
bh_assert(declare_max_page_count <= 65536); bh_assert(declare_max_page_count <= max_page_count);
if (declare_max_page_count > max_page_count) { if (declare_max_page_count > max_page_count) {
declare_max_page_count = max_page_count; declare_max_page_count = max_page_count;
} }
@ -719,12 +772,13 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
} }
/* now we believe all declaration are ok */ /* now we believe all declaration are ok */
memory->flags = declare_max_page_count_flag; memory->flags = mem_flag;
memory->init_page_count = declare_init_page_count; memory->init_page_count = declare_init_page_count;
memory->max_page_count = declare_max_page_count; memory->max_page_count = declare_max_page_count;
memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
*p_buf = p; *p_buf = p;
(void)check_memory_flag;
return true; return true;
} }
@ -811,26 +865,28 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory,
uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
/ DEFAULT_NUM_BYTES_PER_PAGE; / DEFAULT_NUM_BYTES_PER_PAGE;
#else #else
uint32 max_page_count = DEFAULT_MAX_PAGES; uint32 max_page_count;
bool is_memory64 = false;
#endif #endif
p_org = p; p_org = p;
read_leb_uint32(p, p_end, memory->flags); read_leb_uint32(p, p_end, memory->flags);
bh_assert(p - p_org <= 1); bh_assert(p - p_org <= 1);
(void)p_org; (void)p_org;
#if WASM_ENABLE_SHARED_MEMORY == 0 bh_assert(check_memory_flag(memory->flags));
bh_assert(memory->flags <= 1);
#else #if WASM_ENABLE_APP_FRAMEWORK == 0
bh_assert(memory->flags <= 3 && memory->flags != 2); is_memory64 = memory->flags & MEMORY64_FLAG;
max_page_count = is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
#endif #endif
read_leb_uint32(p, p_end, memory->init_page_count); read_leb_uint32(p, p_end, memory->init_page_count);
bh_assert(memory->init_page_count <= 65536); bh_assert(memory->init_page_count <= max_page_count);
if (memory->flags & 1) { if (memory->flags & 1) {
read_leb_uint32(p, p_end, memory->max_page_count); read_leb_uint32(p, p_end, memory->max_page_count);
bh_assert(memory->init_page_count <= memory->max_page_count); bh_assert(memory->init_page_count <= memory->max_page_count);
bh_assert(memory->max_page_count <= 65536); bh_assert(memory->max_page_count <= max_page_count);
if (memory->max_page_count > max_page_count) if (memory->max_page_count > max_page_count)
memory->max_page_count = max_page_count; memory->max_page_count = max_page_count;
} }
@ -842,6 +898,7 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory,
memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
*p_buf = p; *p_buf = p;
(void)check_memory_flag;
return true; return true;
} }
@ -1704,6 +1761,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
bool is_passive = false; bool is_passive = false;
uint32 mem_flag; uint32 mem_flag;
#endif #endif
uint8 mem_offset_type;
read_leb_uint32(p, p_end, data_seg_count); read_leb_uint32(p, p_end, data_seg_count);
@ -1750,11 +1808,35 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
< module->import_memory_count + module->memory_count); < module->import_memory_count + module->memory_count);
#endif /* WASM_ENABLE_BULK_MEMORY */ #endif /* WASM_ENABLE_BULK_MEMORY */
#if WASM_ENABLE_BULK_MEMORY != 0
if (!is_passive)
#endif /* WASM_ENABLE_BULK_MEMORY */
{
#if WASM_ENABLE_MEMORY64 != 0
/* This memory_flag is from memory instead of data segment */
uint8 memory_flag;
if (module->import_memory_count > 0) {
memory_flag =
module->import_memories[mem_index].u.memory.flags;
}
else {
memory_flag =
module
->memories[mem_index - module->import_memory_count]
.flags;
}
mem_offset_type = memory_flag & MEMORY64_FLAG ? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif /* WASM_ENABLE_MEMORY64 */
}
#if WASM_ENABLE_BULK_MEMORY != 0 #if WASM_ENABLE_BULK_MEMORY != 0
if (!is_passive) if (!is_passive)
#endif #endif
if (!load_init_expr(module, &p, p_end, &init_expr, if (!load_init_expr(module, &p, p_end, &init_expr,
VALUE_TYPE_I32, error_buf, error_buf_size)) mem_offset_type, error_buf, error_buf_size))
return false; return false;
read_leb_uint32(p, p_end, data_seg_len); read_leb_uint32(p, p_end, data_seg_len);
@ -3532,8 +3614,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE8:
case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE16:
case WASM_OP_I64_STORE32: case WASM_OP_I64_STORE32:
skip_leb_uint32(p, p_end); /* align */ skip_leb_uint32(p, p_end); /* align */
skip_leb_uint32(p, p_end); /* offset */ skip_leb_mem_offset(p, p_end); /* offset */
break; break;
case WASM_OP_MEMORY_SIZE: case WASM_OP_MEMORY_SIZE:
@ -3748,6 +3830,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
#if WASM_ENABLE_SHARED_MEMORY != 0 #if WASM_ENABLE_SHARED_MEMORY != 0
case WASM_OP_ATOMIC_PREFIX: case WASM_OP_ATOMIC_PREFIX:
{ {
/* TODO: memory64 offset type changes */
uint32 opcode1; uint32 opcode1;
/* atomic_op (u32_leb) + memarg (2 u32_leb) */ /* atomic_op (u32_leb) + memarg (2 u32_leb) */
@ -3757,8 +3840,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
opcode = (uint8)opcode1; opcode = (uint8)opcode1;
if (opcode != WASM_OP_ATOMIC_FENCE) { if (opcode != WASM_OP_ATOMIC_FENCE) {
skip_leb_uint32(p, p_end); /* align */ skip_leb_uint32(p, p_end); /* align */
skip_leb_uint32(p, p_end); /* offset */ skip_leb_mem_offset(p, p_end); /* offset */
} }
else { else {
/* atomic.fence doesn't have memarg */ /* atomic.fence doesn't have memarg */
@ -5075,6 +5158,11 @@ fail:
goto fail; \ goto fail; \
} while (0) } while (0)
#define PUSH_MEM_OFFSET() PUSH_OFFSET_TYPE(mem_offset_type)
#define PUSH_PAGE_COUNT() PUSH_MEM_OFFSET()
#define POP_MEM_OFFSET() POP_OFFSET_TYPE(mem_offset_type)
#define POP_AND_PUSH(type_pop, type_push) \ #define POP_AND_PUSH(type_pop, type_push) \
do { \ do { \
if (!(wasm_loader_push_pop_frame_ref_offset( \ if (!(wasm_loader_push_pop_frame_ref_offset( \
@ -5129,6 +5217,15 @@ fail:
goto fail; \ goto fail; \
} while (0) } while (0)
#define PUSH_MEM_OFFSET() \
do { \
if (!(wasm_loader_push_frame_ref(loader_ctx, mem_offset_type, \
error_buf, error_buf_size))) \
goto fail; \
} while (0)
#define PUSH_PAGE_COUNT() PUSH_MEM_OFFSET()
#define POP_I32() \ #define POP_I32() \
do { \ do { \
if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I32, error_buf, \ if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I32, error_buf, \
@ -5164,6 +5261,13 @@ fail:
goto fail; \ goto fail; \
} while (0) } while (0)
#define POP_MEM_OFFSET() \
do { \
if (!(wasm_loader_pop_frame_ref(loader_ctx, mem_offset_type, \
error_buf, error_buf_size))) \
goto fail; \
} while (0)
#define POP_AND_PUSH(type_pop, type_push) \ #define POP_AND_PUSH(type_pop, type_push) \
do { \ do { \
if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1, type_push, \ if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1, type_push, \
@ -5774,10 +5878,11 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
{ {
uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org; uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org;
uint32 param_count, local_count, global_count; uint32 param_count, local_count, global_count;
uint8 *param_types, *local_types, local_type, global_type; uint8 *param_types, *local_types, local_type, global_type, mem_offset_type;
BlockType func_block_type; BlockType func_block_type;
uint16 *local_offsets, local_offset; uint16 *local_offsets, local_offset;
uint32 count, local_idx, global_idx, u32, align, mem_offset, i; uint32 count, local_idx, global_idx, u32, align, i;
mem_offset_t mem_offset;
int32 i32, i32_const = 0; int32 i32, i32_const = 0;
int64 i64_const; int64 i64_const;
uint8 opcode, u8; uint8 opcode, u8;
@ -5799,6 +5904,19 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n", LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n",
func->param_cell_num, func->local_cell_num, func->ret_cell_num); func->param_cell_num, func->local_cell_num, func->ret_cell_num);
#endif #endif
#if WASM_ENABLE_MEMORY64 != 0
bool is_memory64 = false;
/* TODO: multi-memories for now assuming the memory idx type is consistent
* across multi-memories */
if (module->import_memory_count > 0)
is_memory64 = module->import_memories[0].u.memory.flags & MEMORY64_FLAG;
else if (module->memory_count > 0)
is_memory64 = module->memories[0].flags & MEMORY64_FLAG;
mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
global_count = module->import_global_count + module->global_count; global_count = module->import_global_count + module->global_count;
@ -7107,8 +7225,8 @@ re_scan:
} }
#endif #endif
CHECK_MEMORY(); CHECK_MEMORY();
read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, align); /* align */
read_leb_uint32(p, p_end, mem_offset); /* offset */ read_leb_mem_offset(p, p_end, mem_offset); /* offset */
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, mem_offset); emit_uint32(loader_ctx, mem_offset);
#endif #endif
@ -7122,7 +7240,7 @@ re_scan:
case WASM_OP_I32_LOAD8_U: case WASM_OP_I32_LOAD8_U:
case WASM_OP_I32_LOAD16_S: case WASM_OP_I32_LOAD16_S:
case WASM_OP_I32_LOAD16_U: case WASM_OP_I32_LOAD16_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I32);
break; break;
case WASM_OP_I64_LOAD: case WASM_OP_I64_LOAD:
case WASM_OP_I64_LOAD8_S: case WASM_OP_I64_LOAD8_S:
@ -7131,35 +7249,35 @@ re_scan:
case WASM_OP_I64_LOAD16_U: case WASM_OP_I64_LOAD16_U:
case WASM_OP_I64_LOAD32_S: case WASM_OP_I64_LOAD32_S:
case WASM_OP_I64_LOAD32_U: case WASM_OP_I64_LOAD32_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I64);
break; break;
case WASM_OP_F32_LOAD: case WASM_OP_F32_LOAD:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_F32);
break; break;
case WASM_OP_F64_LOAD: case WASM_OP_F64_LOAD:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_F64);
break; break;
/* store */ /* store */
case WASM_OP_I32_STORE: case WASM_OP_I32_STORE:
case WASM_OP_I32_STORE8: case WASM_OP_I32_STORE8:
case WASM_OP_I32_STORE16: case WASM_OP_I32_STORE16:
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
break; break;
case WASM_OP_I64_STORE: case WASM_OP_I64_STORE:
case WASM_OP_I64_STORE8: case WASM_OP_I64_STORE8:
case WASM_OP_I64_STORE16: case WASM_OP_I64_STORE16:
case WASM_OP_I64_STORE32: case WASM_OP_I64_STORE32:
POP_I64(); POP_I64();
POP_I32(); POP_MEM_OFFSET();
break; break;
case WASM_OP_F32_STORE: case WASM_OP_F32_STORE:
POP_F32(); POP_F32();
POP_I32(); POP_MEM_OFFSET();
break; break;
case WASM_OP_F64_STORE: case WASM_OP_F64_STORE:
POP_F64(); POP_F64();
POP_I32(); POP_MEM_OFFSET();
break; break;
default: default:
break; break;
@ -7172,7 +7290,7 @@ re_scan:
/* reserved byte 0x00 */ /* reserved byte 0x00 */
bh_assert(*p == 0x00); bh_assert(*p == 0x00);
p++; p++;
PUSH_I32(); PUSH_PAGE_COUNT();
module->possible_memory_grow = true; module->possible_memory_grow = true;
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
@ -7185,7 +7303,7 @@ re_scan:
/* reserved byte 0x00 */ /* reserved byte 0x00 */
bh_assert(*p == 0x00); bh_assert(*p == 0x00);
p++; p++;
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); POP_AND_PUSH(mem_offset_type, mem_offset_type);
module->possible_memory_grow = true; module->possible_memory_grow = true;
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
@ -7536,7 +7654,7 @@ re_scan:
POP_I32(); POP_I32();
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true; func->has_memory_operations = true;
#endif #endif
@ -7565,9 +7683,9 @@ re_scan:
+ module->memory_count + module->memory_count
> 0); > 0);
POP_I32(); POP_MEM_OFFSET();
POP_I32(); POP_MEM_OFFSET();
POP_I32(); POP_MEM_OFFSET();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true; func->has_memory_operations = true;
#endif #endif
@ -7582,9 +7700,9 @@ re_scan:
+ module->memory_count + module->memory_count
> 0); > 0);
POP_MEM_OFFSET();
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
POP_I32();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true; func->has_memory_operations = true;
#endif #endif
@ -7748,8 +7866,8 @@ re_scan:
#endif #endif
if (opcode1 != WASM_OP_ATOMIC_FENCE) { if (opcode1 != WASM_OP_ATOMIC_FENCE) {
CHECK_MEMORY(); CHECK_MEMORY();
read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, align); /* align */
read_leb_uint32(p, p_end, mem_offset); /* offset */ read_leb_mem_offset(p, p_end, mem_offset); /* offset */
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, mem_offset); emit_uint32(loader_ctx, mem_offset);
#endif #endif
@ -7759,18 +7877,20 @@ re_scan:
#endif #endif
switch (opcode1) { switch (opcode1) {
case WASM_OP_ATOMIC_NOTIFY: case WASM_OP_ATOMIC_NOTIFY:
POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); POP_I32();
POP_MEM_OFFSET();
PUSH_I32();
break; break;
case WASM_OP_ATOMIC_WAIT32: case WASM_OP_ATOMIC_WAIT32:
POP_I64(); POP_I64();
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
PUSH_I32(); PUSH_I32();
break; break;
case WASM_OP_ATOMIC_WAIT64: case WASM_OP_ATOMIC_WAIT64:
POP_I64(); POP_I64();
POP_I64(); POP_I64();
POP_I32(); POP_MEM_OFFSET();
PUSH_I32(); PUSH_I32();
break; break;
case WASM_OP_ATOMIC_FENCE: case WASM_OP_ATOMIC_FENCE:
@ -7781,26 +7901,26 @@ re_scan:
case WASM_OP_ATOMIC_I32_LOAD: case WASM_OP_ATOMIC_I32_LOAD:
case WASM_OP_ATOMIC_I32_LOAD8_U: case WASM_OP_ATOMIC_I32_LOAD8_U:
case WASM_OP_ATOMIC_I32_LOAD16_U: case WASM_OP_ATOMIC_I32_LOAD16_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I32);
break; break;
case WASM_OP_ATOMIC_I32_STORE: case WASM_OP_ATOMIC_I32_STORE:
case WASM_OP_ATOMIC_I32_STORE8: case WASM_OP_ATOMIC_I32_STORE8:
case WASM_OP_ATOMIC_I32_STORE16: case WASM_OP_ATOMIC_I32_STORE16:
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
break; break;
case WASM_OP_ATOMIC_I64_LOAD: case WASM_OP_ATOMIC_I64_LOAD:
case WASM_OP_ATOMIC_I64_LOAD8_U: case WASM_OP_ATOMIC_I64_LOAD8_U:
case WASM_OP_ATOMIC_I64_LOAD16_U: case WASM_OP_ATOMIC_I64_LOAD16_U:
case WASM_OP_ATOMIC_I64_LOAD32_U: case WASM_OP_ATOMIC_I64_LOAD32_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64); POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I64);
break; break;
case WASM_OP_ATOMIC_I64_STORE: case WASM_OP_ATOMIC_I64_STORE:
case WASM_OP_ATOMIC_I64_STORE8: case WASM_OP_ATOMIC_I64_STORE8:
case WASM_OP_ATOMIC_I64_STORE16: case WASM_OP_ATOMIC_I64_STORE16:
case WASM_OP_ATOMIC_I64_STORE32: case WASM_OP_ATOMIC_I64_STORE32:
POP_I64(); POP_I64();
POP_I32(); POP_MEM_OFFSET();
break; break;
case WASM_OP_ATOMIC_RMW_I32_ADD: case WASM_OP_ATOMIC_RMW_I32_ADD:
case WASM_OP_ATOMIC_RMW_I32_ADD8_U: case WASM_OP_ATOMIC_RMW_I32_ADD8_U:
@ -7820,7 +7940,9 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I32_XCHG: case WASM_OP_ATOMIC_RMW_I32_XCHG:
case WASM_OP_ATOMIC_RMW_I32_XCHG8_U: case WASM_OP_ATOMIC_RMW_I32_XCHG8_U:
case WASM_OP_ATOMIC_RMW_I32_XCHG16_U: case WASM_OP_ATOMIC_RMW_I32_XCHG16_U:
POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); POP_I32();
POP_MEM_OFFSET();
PUSH_I32();
break; break;
case WASM_OP_ATOMIC_RMW_I64_ADD: case WASM_OP_ATOMIC_RMW_I64_ADD:
case WASM_OP_ATOMIC_RMW_I64_ADD8_U: case WASM_OP_ATOMIC_RMW_I64_ADD8_U:
@ -7847,7 +7969,7 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I64_XCHG16_U: case WASM_OP_ATOMIC_RMW_I64_XCHG16_U:
case WASM_OP_ATOMIC_RMW_I64_XCHG32_U: case WASM_OP_ATOMIC_RMW_I64_XCHG32_U:
POP_I64(); POP_I64();
POP_I32(); POP_MEM_OFFSET();
PUSH_I64(); PUSH_I64();
break; break;
case WASM_OP_ATOMIC_RMW_I32_CMPXCHG: case WASM_OP_ATOMIC_RMW_I32_CMPXCHG:
@ -7855,7 +7977,7 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U: case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U:
POP_I32(); POP_I32();
POP_I32(); POP_I32();
POP_I32(); POP_MEM_OFFSET();
PUSH_I32(); PUSH_I32();
break; break;
case WASM_OP_ATOMIC_RMW_I64_CMPXCHG: case WASM_OP_ATOMIC_RMW_I64_CMPXCHG:
@ -7864,7 +7986,7 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U: case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U:
POP_I64(); POP_I64();
POP_I64(); POP_I64();
POP_I32(); POP_MEM_OFFSET();
PUSH_I64(); PUSH_I64();
break; break;
default: default:

View File

@ -162,7 +162,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
char *error_buf, uint32 error_buf_size) char *error_buf, uint32 error_buf_size)
{ {
WASMModule *module = module_inst->module; WASMModule *module = module_inst->module;
uint32 inc_page_count, global_idx; uint32 inc_page_count, global_idx, default_max_page;
uint32 bytes_of_last_page, bytes_to_page_end; uint32 bytes_of_last_page, bytes_to_page_end;
uint64 aux_heap_base, uint64 aux_heap_base,
heap_offset = (uint64)num_bytes_per_page * init_page_count; heap_offset = (uint64)num_bytes_per_page * init_page_count;
@ -171,7 +171,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
bool is_shared_memory = false; bool is_shared_memory = false;
#if WASM_ENABLE_SHARED_MEMORY != 0 #if WASM_ENABLE_SHARED_MEMORY != 0
is_shared_memory = flags & 0x02 ? true : false; is_shared_memory = flags & SHARED_MEMORY_FLAG ? true : false;
/* shared memory */ /* shared memory */
if (is_shared_memory && parent != NULL) { if (is_shared_memory && parent != NULL) {
@ -186,6 +186,14 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
(void)flags; (void)flags;
#endif /* end of WASM_ENABLE_SHARED_MEMORY */ #endif /* end of WASM_ENABLE_SHARED_MEMORY */
#if WASM_ENABLE_MEMORY64 != 0
if (flags & MEMORY64_FLAG) {
memory->is_memory64 = 1;
}
#endif
default_max_page =
memory->is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1 if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1
&& module_inst->module->free_function != (uint32)-1) { && module_inst->module->free_function != (uint32)-1) {
/* Disable app heap, use malloc/free function exported /* Disable app heap, use malloc/free function exported
@ -195,7 +203,8 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
/* If initial memory is the largest size allowed, disallowing insert host /* If initial memory is the largest size allowed, disallowing insert host
* managed heap */ * managed heap */
if (heap_size > 0 && heap_offset == MAX_LINEAR_MEMORY_SIZE) { if (heap_size > 0
&& heap_offset == GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"failed to insert app heap into linear memory, " "failed to insert app heap into linear memory, "
"try using `--heap-size=0` option"); "try using `--heap-size=0` option");
@ -253,8 +262,18 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
&& global_idx < module_inst->e->global_count); && global_idx < module_inst->e->global_count);
global_addr = module_inst->global_data global_addr = module_inst->global_data
+ module_inst->e->globals[global_idx].data_offset; + module_inst->e->globals[global_idx].data_offset;
*(uint32 *)global_addr = (uint32)aux_heap_base; #if WASM_ENABLE_MEMORY64 != 0
LOG_VERBOSE("Reset __heap_base global to %u", aux_heap_base); 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;
}
LOG_VERBOSE("Reset __heap_base global to %lu", aux_heap_base);
} }
else { else {
/* Insert app heap before new page */ /* Insert app heap before new page */
@ -267,14 +286,15 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
} }
init_page_count += inc_page_count; init_page_count += inc_page_count;
max_page_count += inc_page_count; max_page_count += inc_page_count;
if (init_page_count > DEFAULT_MAX_PAGES) { if (init_page_count > default_max_page) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"failed to insert app heap into linear memory, " "failed to insert app heap into linear memory, "
"try using `--heap-size=0` option"); "try using `--heap-size=0` option");
return NULL; return NULL;
} }
if (max_page_count > DEFAULT_MAX_PAGES)
max_page_count = DEFAULT_MAX_PAGES; if (max_page_count > default_max_page)
max_page_count = default_max_page;
} }
LOG_VERBOSE("Memory instantiate:"); LOG_VERBOSE("Memory instantiate:");
@ -283,14 +303,16 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size); LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size);
max_memory_data_size = (uint64)num_bytes_per_page * max_page_count; max_memory_data_size = (uint64)num_bytes_per_page * max_page_count;
bh_assert(max_memory_data_size <= MAX_LINEAR_MEMORY_SIZE); bh_assert(max_memory_data_size
<= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64));
(void)max_memory_data_size; (void)max_memory_data_size;
bh_assert(memory != NULL); bh_assert(memory != NULL);
if (wasm_allocate_linear_memory(&memory->memory_data, is_shared_memory, if (wasm_allocate_linear_memory(&memory->memory_data, is_shared_memory,
num_bytes_per_page, init_page_count, memory->is_memory64, num_bytes_per_page,
max_page_count, &memory_data_size) init_page_count, max_page_count,
&memory_data_size)
!= BHT_OK) { != BHT_OK) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"allocate linear memory failed"); "allocate linear memory failed");
@ -1947,7 +1969,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
WASMGlobalInstance *globals = NULL, *global; WASMGlobalInstance *globals = NULL, *global;
WASMTableInstance *first_table; WASMTableInstance *first_table;
uint32 global_count, i; uint32 global_count, i;
uint32 base_offset, length, extra_info_offset; uint32 length, extra_info_offset;
mem_offset_t base_offset;
uint32 module_inst_struct_size = uint32 module_inst_struct_size =
offsetof(WASMModuleInstance, global_table_data.bytes); offsetof(WASMModuleInstance, global_table_data.bytes);
uint64 module_inst_mem_inst_size; uint64 module_inst_mem_inst_size;
@ -2305,10 +2328,12 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
(uint64)memory->num_bytes_per_page * memory->cur_page_count; (uint64)memory->num_bytes_per_page * memory->cur_page_count;
bh_assert(memory_data || memory_size == 0); bh_assert(memory_data || memory_size == 0);
bh_assert(data_seg->base_offset.init_expr_type bh_assert(
== INIT_EXPR_TYPE_I32_CONST data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
|| data_seg->base_offset.init_expr_type || (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
== INIT_EXPR_TYPE_GET_GLOBAL); && !memory->is_memory64)
|| (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I64_CONST
&& memory->is_memory64));
if (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { if (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
if (!check_global_init_expr(module, if (!check_global_init_expr(module,
@ -2319,17 +2344,37 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
if (!globals if (!globals
|| globals[data_seg->base_offset.u.global_index].type || globals[data_seg->base_offset.u.global_index].type
!= VALUE_TYPE_I32) { != (memory->is_memory64 ? VALUE_TYPE_I64
: VALUE_TYPE_I32)) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"data segment does not fit"); "data segment does not fit");
goto fail; goto fail;
} }
base_offset = #if WASM_ENABLE_MEMORY64 != 0
globals[data_seg->base_offset.u.global_index].initial_value.i32; if (memory->is_memory64) {
base_offset =
(uint64)globals[data_seg->base_offset.u.global_index]
.initial_value.i64;
}
else
#endif
{
base_offset =
(uint32)globals[data_seg->base_offset.u.global_index]
.initial_value.i32;
}
} }
else { else {
base_offset = (uint32)data_seg->base_offset.u.i32; #if WASM_ENABLE_MEMORY64 != 0
if (memory->is_memory64) {
base_offset = (uint64)data_seg->base_offset.u.i64;
}
else
#endif
{
base_offset = (uint32)data_seg->base_offset.u.i32;
}
} }
/* check offset */ /* check offset */

View File

@ -103,7 +103,7 @@ struct WASMMemoryInstance {
/* Whether the memory is shared */ /* Whether the memory is shared */
uint8 is_shared_memory; uint8 is_shared_memory;
/* TODO: Memory64 whether the memory has 64-bit memory addresses */ /* Whether the memory has 64-bit memory addresses */
uint8 is_memory64; uint8 is_memory64;
/* Reference count of the memory instance: /* Reference count of the memory instance:

View File

@ -17,7 +17,7 @@ void
wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
uint32 uint32
wasm_runtime_module_realloc(wasm_module_inst_t module, uint32 ptr, uint32 size, wasm_runtime_module_realloc(wasm_module_inst_t module, uint64 ptr, uint64 size,
void **p_native_addr); void **p_native_addr);
/* clang-format off */ /* clang-format off */

View File

@ -65,9 +65,11 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file)
/* integer overflow */ /* integer overflow */
return NULL; return NULL;
#if WASM_ENABLE_MEMORY64 == 0
if (request_size > 16 * (uint64)UINT32_MAX) if (request_size > 16 * (uint64)UINT32_MAX)
/* at most 16 G is allowed */ /* at most 64 G is allowed */
return NULL; return NULL;
#endif
if (prot & MMAP_PROT_READ) if (prot & MMAP_PROT_READ)
map_prot |= PROT_READ; map_prot |= PROT_READ;

View File

@ -14,7 +14,7 @@ import time
""" """
The script itself has to be put under the same directory with the "spec". The script itself has to be put under the same directory with the "spec".
To run a single non-GC case with interpreter mode: To run a single non-GC and non-memory64 case with interpreter mode:
cd workspace cd workspace
python3 runtest.py --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \ python3 runtest.py --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \
spec/test/core/xxx.wast spec/test/core/xxx.wast
@ -22,7 +22,7 @@ To run a single non-GC case with aot mode:
cd workspace cd workspace
python3 runtest.py --aot --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \ python3 runtest.py --aot --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \
--aot-compiler wamrc spec/test/core/xxx.wast --aot-compiler wamrc spec/test/core/xxx.wast
To run a single GC case: To run a single GC case or single memory64 case:
cd workspace cd workspace
python3 runtest.py --wast2wasm spec/interpreter/wasm --interpreter iwasm \ python3 runtest.py --wast2wasm spec/interpreter/wasm --interpreter iwasm \
--aot-compiler wamrc --gc spec/test/core/xxx.wast --aot-compiler wamrc --gc spec/test/core/xxx.wast
@ -78,6 +78,7 @@ def ignore_the_case(
multi_thread_flag=False, multi_thread_flag=False,
simd_flag=False, simd_flag=False,
gc_flag=False, gc_flag=False,
memory64_flag=False,
xip_flag=False, xip_flag=False,
eh_flag=False, eh_flag=False,
qemu_flag=False, qemu_flag=False,
@ -162,6 +163,7 @@ def test_case(
clean_up_flag=True, clean_up_flag=True,
verbose_flag=True, verbose_flag=True,
gc_flag=False, gc_flag=False,
memory64_flag=False,
qemu_flag=False, qemu_flag=False,
qemu_firmware="", qemu_firmware="",
log="", log="",
@ -169,7 +171,7 @@ def test_case(
): ):
CMD = [sys.executable, "runtest.py"] CMD = [sys.executable, "runtest.py"]
CMD.append("--wast2wasm") CMD.append("--wast2wasm")
CMD.append(WAST2WASM_CMD if not gc_flag else SPEC_INTERPRETER_CMD) CMD.append(WAST2WASM_CMD if not gc_flag and not memory64_flag else SPEC_INTERPRETER_CMD)
CMD.append("--interpreter") CMD.append("--interpreter")
if sgx_flag: if sgx_flag:
CMD.append(IWASM_SGX_CMD) CMD.append(IWASM_SGX_CMD)
@ -217,6 +219,9 @@ def test_case(
if gc_flag: if gc_flag:
CMD.append("--gc") CMD.append("--gc")
if memory64_flag:
CMD.append("--memory64")
if log != "": if log != "":
CMD.append("--log-dir") CMD.append("--log-dir")
CMD.append(log) CMD.append(log)
@ -283,6 +288,7 @@ def test_suite(
clean_up_flag=True, clean_up_flag=True,
verbose_flag=True, verbose_flag=True,
gc_flag=False, gc_flag=False,
memory64_flag=False,
parl_flag=False, parl_flag=False,
qemu_flag=False, qemu_flag=False,
qemu_firmware="", qemu_firmware="",
@ -325,6 +331,7 @@ def test_suite(
multi_thread_flag, multi_thread_flag,
simd_flag, simd_flag,
gc_flag, gc_flag,
memory64_flag,
xip_flag, xip_flag,
eh_flag, eh_flag,
qemu_flag, qemu_flag,
@ -357,6 +364,7 @@ def test_suite(
clean_up_flag, clean_up_flag,
verbose_flag, verbose_flag,
gc_flag, gc_flag,
memory64_flag,
qemu_flag, qemu_flag,
qemu_firmware, qemu_firmware,
log, log,
@ -382,6 +390,7 @@ def test_suite(
else: else:
print(f"----- Run the whole spec test suite -----") print(f"----- Run the whole spec test suite -----")
for case_path in case_list: for case_path in case_list:
print(case_path)
try: try:
test_case( test_case(
str(case_path), str(case_path),
@ -396,6 +405,7 @@ def test_suite(
clean_up_flag, clean_up_flag,
verbose_flag, verbose_flag,
gc_flag, gc_flag,
memory64_flag,
qemu_flag, qemu_flag,
qemu_firmware, qemu_firmware,
log, log,
@ -521,6 +531,13 @@ def main():
dest="gc_flag", dest="gc_flag",
help="Running with GC feature", help="Running with GC feature",
) )
parser.add_argument(
"--memory64",
action="store_true",
default=False,
dest="memory64_flag",
help="Running with memory64 feature",
)
parser.add_argument( parser.add_argument(
"cases", "cases",
metavar="path_to__case", metavar="path_to__case",
@ -563,6 +580,7 @@ def main():
options.clean_up_flag, options.clean_up_flag,
options.verbose_flag, options.verbose_flag,
options.gc_flag, options.gc_flag,
options.memory64_flag,
options.parl_flag, options.parl_flag,
options.qemu_flag, options.qemu_flag,
options.qemu_firmware, options.qemu_firmware,
@ -589,6 +607,7 @@ def main():
options.clean_up_flag, options.clean_up_flag,
options.verbose_flag, options.verbose_flag,
options.gc_flag, options.gc_flag,
options.memory64_flag,
options.qemu_flag, options.qemu_flag,
options.qemu_firmware, options.qemu_firmware,
options.log, options.log,

View File

@ -0,0 +1,28 @@
diff --git a/test/core/memory.wast b/test/core/memory.wast
index 1dd5b84..497b69f 100644
--- a/test/core/memory.wast
+++ b/test/core/memory.wast
@@ -76,17 +76,17 @@
"memory size must be at most 65536 pages (4GiB)"
)
-(assert_invalid
+(assert_malformed
(module quote "(memory 0x1_0000_0000)")
- "memory size must be at most 65536 pages (4GiB)"
+ "i32 constant out of range"
)
-(assert_invalid
+(assert_malformed
(module quote "(memory 0x1_0000_0000 0x1_0000_0000)")
- "memory size must be at most 65536 pages (4GiB)"
+ "i32 constant out of range"
)
-(assert_invalid
+(assert_malformed
(module quote "(memory 0 0x1_0000_0000)")
- "memory size must be at most 65536 pages (4GiB)"
+ "i32 constant out of range"
)
(module

View File

@ -313,6 +313,9 @@ parser.add_argument('--multi-thread', default=False, action='store_true',
parser.add_argument('--gc', default=False, action='store_true', parser.add_argument('--gc', default=False, action='store_true',
help='Test with GC') help='Test with GC')
parser.add_argument('--memory64', default=False, action='store_true',
help='Test with Memory64')
parser.add_argument('--qemu', default=False, action='store_true', parser.add_argument('--qemu', default=False, action='store_true',
help="Enable QEMU") help="Enable QEMU")
@ -1071,7 +1074,7 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts):
log("Compiling WASM to '%s'" % wasm_tempfile) log("Compiling WASM to '%s'" % wasm_tempfile)
# default arguments # default arguments
if opts.gc: if opts.gc or opts.memory64:
cmd = [opts.wast2wasm, "-u", "-d", wast_tempfile, "-o", wasm_tempfile] cmd = [opts.wast2wasm, "-u", "-d", wast_tempfile, "-o", wasm_tempfile]
elif opts.eh: elif opts.eh:
cmd = [opts.wast2wasm, "--enable-thread", "--no-check", "--enable-exceptions", "--enable-tail-call", wast_tempfile, "-o", wasm_tempfile ] cmd = [opts.wast2wasm, "--enable-thread", "--no-check", "--enable-exceptions", "--enable-tail-call", wast_tempfile, "-o", wasm_tempfile ]
@ -1116,6 +1119,9 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = '
cmd.append("--enable-gc") cmd.append("--enable-gc")
cmd.append("--enable-tail-call") cmd.append("--enable-tail-call")
if opts.memory64:
cmd.append("--enable-memory64")
if output == 'object': if output == 'object':
cmd.append("--format=object") cmd.append("--format=object")
elif output == 'ir': elif output == 'ir':

View File

@ -23,6 +23,7 @@ function help()
echo "-p enable multi thread feature" echo "-p enable multi thread feature"
echo "-S enable SIMD feature" echo "-S enable SIMD feature"
echo "-G enable GC feature" echo "-G enable GC feature"
echo "-W enable memory64 feature"
echo "-X enable XIP feature" echo "-X enable XIP feature"
echo "-e enable exception handling" echo "-e enable exception handling"
echo "-x test SGX" echo "-x test SGX"
@ -50,6 +51,7 @@ ENABLE_MULTI_THREAD=0
COLLECT_CODE_COVERAGE=0 COLLECT_CODE_COVERAGE=0
ENABLE_SIMD=0 ENABLE_SIMD=0
ENABLE_GC=0 ENABLE_GC=0
ENABLE_MEMORY64=0
ENABLE_XIP=0 ENABLE_XIP=0
ENABLE_EH=0 ENABLE_EH=0
ENABLE_DEBUG_VERSION=0 ENABLE_DEBUG_VERSION=0
@ -72,7 +74,7 @@ WASI_TESTSUITE_COMMIT="ee807fc551978490bf1c277059aabfa1e589a6c2"
TARGET_LIST=("AARCH64" "AARCH64_VFP" "ARMV7" "ARMV7_VFP" "THUMBV7" "THUMBV7_VFP" \ TARGET_LIST=("AARCH64" "AARCH64_VFP" "ARMV7" "ARMV7_VFP" "THUMBV7" "THUMBV7_VFP" \
"RISCV32" "RISCV32_ILP32F" "RISCV32_ILP32D" "RISCV64" "RISCV64_LP64F" "RISCV64_LP64D") "RISCV32" "RISCV32_ILP32F" "RISCV32_ILP32D" "RISCV64" "RISCV64_LP64F" "RISCV64_LP64D")
while getopts ":s:cabgvt:m:MCpSXexwPGQF:j:T:" opt while getopts ":s:cabgvt:m:MCpSXexwWPGQF:j:T:" opt
do do
OPT_PARSED="TRUE" OPT_PARSED="TRUE"
case $opt in case $opt in
@ -131,6 +133,10 @@ do
echo "enable multi module feature" echo "enable multi module feature"
ENABLE_MULTI_MODULE=1 ENABLE_MULTI_MODULE=1
;; ;;
W)
echo "enable wasm64(memory64) feature"
ENABLE_MEMORY64=1
;;
C) C)
echo "enable code coverage" echo "enable code coverage"
COLLECT_CODE_COVERAGE=1 COLLECT_CODE_COVERAGE=1
@ -478,6 +484,29 @@ function spec_test()
popd popd
fi fi
# update memory64 cases
if [[ ${ENABLE_MEMORY64} == 1 ]]; then
echo "checkout spec for memory64 proposal"
popd
rm -fr spec
# check spec test cases for memory64
git clone -b main --single-branch https://github.com/WebAssembly/memory64.git spec
pushd spec
git restore . && git clean -ffd .
# Reset to commit: "Merge remote-tracking branch 'upstream/main' into merge2"
git reset --hard 48e69f394869c55b7bbe14ac963c09f4605490b6
git checkout 044d0d2e77bdcbe891f7e0b9dd2ac01d56435f0b -- test/core/elem.wast
git apply ../../spec-test-script/ignore_cases.patch
git apply ../../spec-test-script/memory64.patch
echo "compile the reference intepreter"
pushd interpreter
make
popd
fi
popd popd
echo $(pwd) echo $(pwd)
@ -488,7 +517,7 @@ function spec_test()
local ARGS_FOR_SPEC_TEST="" local ARGS_FOR_SPEC_TEST=""
# multi-module only enable in interp mode # multi-module only enable in interp mode and aot mode
if [[ 1 == ${ENABLE_MULTI_MODULE} ]]; then if [[ 1 == ${ENABLE_MULTI_MODULE} ]]; then
if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' ]]; then if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' ]]; then
ARGS_FOR_SPEC_TEST+="-M " ARGS_FOR_SPEC_TEST+="-M "
@ -537,6 +566,13 @@ function spec_test()
ARGS_FOR_SPEC_TEST+="--gc " ARGS_FOR_SPEC_TEST+="--gc "
fi fi
# wasm64(memory64) is only enabled in interp and aot mode
if [[ 1 == ${ENABLE_MEMORY64} ]]; then
if [[ $1 == 'classic-interp' || $1 == 'aot' ]]; then
ARGS_FOR_SPEC_TEST+="--memory64 "
fi
fi
if [[ ${ENABLE_QEMU} == 1 ]]; then if [[ ${ENABLE_QEMU} == 1 ]]; then
ARGS_FOR_SPEC_TEST+="--qemu " ARGS_FOR_SPEC_TEST+="--qemu "
ARGS_FOR_SPEC_TEST+="--qemu-firmware ${QEMU_FIRMWARE} " ARGS_FOR_SPEC_TEST+="--qemu-firmware ${QEMU_FIRMWARE} "
@ -833,6 +869,12 @@ function trigger()
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MULTI_MODULE=0" EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MULTI_MODULE=0"
fi fi
if [[ ${ENABLE_MEMORY64} == 1 ]];then
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MEMORY64=1"
else
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MEMORY64=0"
fi
if [[ ${ENABLE_MULTI_THREAD} == 1 ]];then if [[ ${ENABLE_MULTI_THREAD} == 1 ]];then
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_PTHREAD=1" EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_PTHREAD=1"
fi fi