Implement memory64 for classic interpreter (#3266)

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

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

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

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

View File

@ -14,7 +14,7 @@ import time
"""
The script itself has to be put under the same directory with the "spec".
To run a single non-GC case with interpreter mode:
To run a single non-GC and non-memory64 case with interpreter mode:
cd workspace
python3 runtest.py --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \
spec/test/core/xxx.wast
@ -22,7 +22,7 @@ To run a single non-GC case with aot mode:
cd workspace
python3 runtest.py --aot --wast2wasm wabt/bin/wat2wasm --interpreter iwasm \
--aot-compiler wamrc spec/test/core/xxx.wast
To run a single GC case:
To run a single GC case or single memory64 case:
cd workspace
python3 runtest.py --wast2wasm spec/interpreter/wasm --interpreter iwasm \
--aot-compiler wamrc --gc spec/test/core/xxx.wast
@ -78,6 +78,7 @@ def ignore_the_case(
multi_thread_flag=False,
simd_flag=False,
gc_flag=False,
memory64_flag=False,
xip_flag=False,
eh_flag=False,
qemu_flag=False,
@ -162,6 +163,7 @@ def test_case(
clean_up_flag=True,
verbose_flag=True,
gc_flag=False,
memory64_flag=False,
qemu_flag=False,
qemu_firmware="",
log="",
@ -169,7 +171,7 @@ def test_case(
):
CMD = [sys.executable, "runtest.py"]
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")
if sgx_flag:
CMD.append(IWASM_SGX_CMD)
@ -217,6 +219,9 @@ def test_case(
if gc_flag:
CMD.append("--gc")
if memory64_flag:
CMD.append("--memory64")
if log != "":
CMD.append("--log-dir")
CMD.append(log)
@ -283,6 +288,7 @@ def test_suite(
clean_up_flag=True,
verbose_flag=True,
gc_flag=False,
memory64_flag=False,
parl_flag=False,
qemu_flag=False,
qemu_firmware="",
@ -325,6 +331,7 @@ def test_suite(
multi_thread_flag,
simd_flag,
gc_flag,
memory64_flag,
xip_flag,
eh_flag,
qemu_flag,
@ -357,6 +364,7 @@ def test_suite(
clean_up_flag,
verbose_flag,
gc_flag,
memory64_flag,
qemu_flag,
qemu_firmware,
log,
@ -382,6 +390,7 @@ def test_suite(
else:
print(f"----- Run the whole spec test suite -----")
for case_path in case_list:
print(case_path)
try:
test_case(
str(case_path),
@ -396,6 +405,7 @@ def test_suite(
clean_up_flag,
verbose_flag,
gc_flag,
memory64_flag,
qemu_flag,
qemu_firmware,
log,
@ -521,6 +531,13 @@ def main():
dest="gc_flag",
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(
"cases",
metavar="path_to__case",
@ -563,6 +580,7 @@ def main():
options.clean_up_flag,
options.verbose_flag,
options.gc_flag,
options.memory64_flag,
options.parl_flag,
options.qemu_flag,
options.qemu_firmware,
@ -589,6 +607,7 @@ def main():
options.clean_up_flag,
options.verbose_flag,
options.gc_flag,
options.memory64_flag,
options.qemu_flag,
options.qemu_firmware,
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',
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',
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)
# default arguments
if opts.gc:
if opts.gc or opts.memory64:
cmd = [opts.wast2wasm, "-u", "-d", wast_tempfile, "-o", wasm_tempfile]
elif opts.eh:
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-tail-call")
if opts.memory64:
cmd.append("--enable-memory64")
if output == 'object':
cmd.append("--format=object")
elif output == 'ir':