Basic Memory64 support for classic-interpreter (#3240)

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
- memory64 classic-interpreter spec test in `test_wamr.sh` and in CI

Currently, it supports memory64 memory wasm files that only use core spec
(including bulk memory proposal) opcodes. 

Future TODOs when memory64 is enabled:
1. support threads opcodes in classic-interpreter
2. support memory64 memory in related runtime API
This commit is contained in:
TianlongLiang 2024-03-26 10:52:45 +08:00 committed by GitHub
parent 06ce060591
commit 2c06e22d4a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 996 additions and 262 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 */
@ -570,6 +570,11 @@
#define WASM_ENABLE_QUICK_AOT_ENTRY 1 #define WASM_ENABLE_QUICK_AOT_ENTRY 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

@ -748,12 +748,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 +762,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;

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); \
@ -576,11 +633,12 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
/* 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) \
@ -589,11 +647,12 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
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) \
@ -605,13 +664,33 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
/* 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
@ -1430,6 +1509,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMStringviewIterObjectRef stringview_iter_obj; WASMStringviewIterObjectRef stringview_iter_obj;
#endif #endif
#endif #endif
#if WASM_ENABLE_MEMORY64 != 0
bool is_memory64 = false;
#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 +4169,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
if (module->memories[0]->is_memory64) {
aux_stack_top = *(uint64 *)(frame_sp - 2);
}
else
#endif
{
aux_stack_top = (uint64)(*(uint32 *)(frame_sp - 1)); 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 +4187,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
if (module->memories[0]->is_memory64) {
*(uint64 *)global_addr = aux_stack_top;
frame_sp -= 2;
}
else
#endif
{
*(uint32 *)global_addr = aux_stack_top;
frame_sp--; 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 +4224,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4243,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4261,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4279,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4297,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4315,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4333,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4351,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4369,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4387,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4405,16 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4424,15 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
addr = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
#endif
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
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 +4444,26 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
is_memory64 = module->memories[0]->is_memory64;
#endif
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);
#if WASM_ENABLE_MEMORY64 != 0
if (is_memory64) {
STORE_U32(maddr, frame_sp[2]);
}
else
#endif
{
STORE_U32(maddr, frame_sp[1]); 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 +4472,29 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
is_memory64 = module->memories[0]->is_memory64;
#endif
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);
#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, PUT_I64_TO_ADDR((uint32 *)maddr,
GET_I64_FROM_ADDR(frame_sp + 1)); 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 +4503,18 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
is_memory64 = module->memories[0]->is_memory64;
#endif
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 +4533,18 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
is_memory64 = module->memories[0]->is_memory64;
#endif
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 +4568,10 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
is_memory64 = module->memories[0]->is_memory64;
#endif
PUSH_PAGE_COUNT(memory->cur_page_count);
(void)reserved; (void)reserved;
HANDLE_OP_END(); HANDLE_OP_END();
} }
@ -4398,16 +4581,19 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 reserved, delta, uint32 reserved, delta,
prev_page_count = memory->cur_page_count; prev_page_count = memory->cur_page_count;
#if WASM_ENABLE_MEMORY64 != 0
is_memory64 = module->memories[0]->is_memory64;
#endif
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,17 +5593,21 @@ 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;
read_leb_uint32(frame_ip, frame_ip_end, segment); read_leb_uint32(frame_ip, frame_ip_end, segment);
/* skip memory index */ /* skip memory index */
frame_ip++; frame_ip++;
#if WASM_ENABLE_MEMORY64 != 0
is_memory64 = module->memories[0]->is_memory64;
#endif
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 +5650,16 @@ 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;
#if WASM_ENABLE_MEMORY64 != 0
len = POP_I32(); is_memory64 = module->memories[0]->is_memory64;
src = POP_I32(); #endif
dst = POP_I32(); len = POP_MEM_OFFSET();
src = POP_MEM_OFFSET();
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();
@ -5493,13 +5685,16 @@ 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(); #if WASM_ENABLE_MEMORY64 != 0
is_memory64 = module->memories[0]->is_memory64;
#endif
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();

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; \
@ -2714,31 +2740,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;
} }
@ -2748,15 +2835,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
@ -2764,16 +2852,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;
@ -2796,7 +2899,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;
@ -2844,7 +2947,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;
@ -3145,53 +3248,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;
@ -4582,6 +4666,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);
@ -4647,11 +4732,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;
@ -7110,7 +7219,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
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:
@ -7456,6 +7565,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);
@ -7552,6 +7662,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) */
@ -9463,6 +9574,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)
@ -9472,6 +9585,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
@ -10639,11 +10753,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;
@ -10668,6 +10783,9 @@ 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;
#endif
global_count = module->import_global_count + module->global_count; global_count = module->import_global_count + module->global_count;
@ -12860,7 +12978,13 @@ 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 */ #if WASM_ENABLE_MEMORY64 != 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
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;
@ -12878,7 +13002,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:
@ -12887,35 +13011,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;
@ -12931,7 +13055,15 @@ re_scan:
"zero byte expected"); "zero byte expected");
goto fail; goto fail;
} }
PUSH_I32();
#if WASM_ENABLE_MEMORY64 != 0
mem_offset_type = module->memories[0].flags & MEMORY64_FLAG
? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
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
@ -12947,7 +13079,14 @@ re_scan:
"zero byte expected"); "zero byte expected");
goto fail; goto fail;
} }
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); #if WASM_ENABLE_MEMORY64 != 0
mem_offset_type = module->memories[0].flags & MEMORY64_FLAG
? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
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 \
@ -14308,7 +14447,15 @@ re_scan:
POP_I32(); POP_I32();
POP_I32(); POP_I32();
POP_I32(); #if WASM_ENABLE_MEMORY64 != 0
mem_offset_type =
module->memories[0].flags & MEMORY64_FLAG
? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
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
@ -14351,9 +14498,17 @@ re_scan:
&& module->memory_count == 0) && module->memory_count == 0)
goto fail_unknown_memory; goto fail_unknown_memory;
POP_I32(); #if WASM_ENABLE_MEMORY64 != 0
POP_I32(); mem_offset_type =
POP_I32(); module->memories[0].flags & MEMORY64_FLAG
? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
POP_MEM_OFFSET();
POP_MEM_OFFSET();
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
@ -14371,10 +14526,17 @@ re_scan:
&& module->memory_count == 0) { && module->memory_count == 0) {
goto fail_unknown_memory; goto fail_unknown_memory;
} }
#if WASM_ENABLE_MEMORY64 != 0
POP_I32(); mem_offset_type =
POP_I32(); module->memories[0].flags & MEMORY64_FLAG
? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
POP_MEM_OFFSET();
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
@ -14620,6 +14782,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
@ -15287,6 +15450,7 @@ re_scan:
#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;
read_leb_uint32(p, p_end, opcode1); read_leb_uint32(p, p_end, opcode1);

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)
{ {
@ -740,6 +753,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,
@ -752,20 +797,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;
} }
@ -776,12 +829,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;
} }
@ -868,26 +922,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;
} }
@ -899,6 +955,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;
} }
@ -1761,6 +1818,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);
@ -1807,11 +1865,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);
@ -3588,7 +3670,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
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:
@ -3803,6 +3885,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) */
@ -5129,6 +5212,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( \
@ -5183,6 +5271,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, \
@ -5218,6 +5315,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, \
@ -5828,10 +5932,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;
@ -5853,6 +5958,9 @@ 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;
#endif
global_count = module->import_global_count + module->global_count; global_count = module->import_global_count + module->global_count;
@ -7162,7 +7270,13 @@ 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 */ #if WASM_ENABLE_MEMORY64 != 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
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
@ -7176,7 +7290,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:
@ -7185,35 +7299,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;
@ -7226,7 +7340,14 @@ re_scan:
/* reserved byte 0x00 */ /* reserved byte 0x00 */
bh_assert(*p == 0x00); bh_assert(*p == 0x00);
p++; p++;
PUSH_I32(); #if WASM_ENABLE_MEMORY64 != 0
mem_offset_type = module->memories[0].flags & MEMORY64_FLAG
? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
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
@ -7239,7 +7360,14 @@ 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); #if WASM_ENABLE_MEMORY64 != 0
mem_offset_type = module->memories[0].flags & MEMORY64_FLAG
? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
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 \
@ -7590,7 +7718,15 @@ re_scan:
POP_I32(); POP_I32();
POP_I32(); POP_I32();
POP_I32(); #if WASM_ENABLE_MEMORY64 != 0
mem_offset_type =
module->memories[0].flags & MEMORY64_FLAG
? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
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
@ -7619,9 +7755,17 @@ re_scan:
+ module->memory_count + module->memory_count
> 0); > 0);
POP_I32(); #if WASM_ENABLE_MEMORY64 != 0
POP_I32(); mem_offset_type =
POP_I32(); module->memories[0].flags & MEMORY64_FLAG
? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
POP_MEM_OFFSET();
POP_MEM_OFFSET();
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
@ -7636,9 +7780,17 @@ re_scan:
+ module->memory_count + module->memory_count
> 0); > 0);
#if WASM_ENABLE_MEMORY64 != 0
mem_offset_type =
module->memories[0].flags & MEMORY64_FLAG
? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
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
@ -7793,6 +7945,7 @@ re_scan:
#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;
read_leb_uint32(p, p_end, opcode1); read_leb_uint32(p, p_end, opcode1);

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;
#if WASM_ENABLE_MEMORY64 != 0
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; *(uint32 *)global_addr = (uint32)aux_heap_base;
LOG_VERBOSE("Reset __heap_base global to %u", 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,7 +303,8 @@ 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);
@ -1947,7 +1968,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 +2327,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,18 +2343,38 @@ 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;
} }
#if WASM_ENABLE_MEMORY64 != 0
if (memory->is_memory64) {
base_offset = base_offset =
globals[data_seg->base_offset.u.global_index].initial_value.i32; (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 {
#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; base_offset = (uint32)data_seg->base_offset.u.i32;
} }
}
/* check offset */ /* check offset */
if (base_offset > memory_size) { if (base_offset > memory_size) {

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

@ -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