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':

View File

@ -23,6 +23,7 @@ function help()
echo "-p enable multi thread feature"
echo "-S enable SIMD feature"
echo "-G enable GC feature"
echo "-W enable memory64 feature"
echo "-X enable XIP feature"
echo "-e enable exception handling"
echo "-x test SGX"
@ -50,6 +51,7 @@ ENABLE_MULTI_THREAD=0
COLLECT_CODE_COVERAGE=0
ENABLE_SIMD=0
ENABLE_GC=0
ENABLE_MEMORY64=0
ENABLE_XIP=0
ENABLE_EH=0
ENABLE_DEBUG_VERSION=0
@ -72,7 +74,7 @@ WASI_TESTSUITE_COMMIT="ee807fc551978490bf1c277059aabfa1e589a6c2"
TARGET_LIST=("AARCH64" "AARCH64_VFP" "ARMV7" "ARMV7_VFP" "THUMBV7" "THUMBV7_VFP" \
"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
OPT_PARSED="TRUE"
case $opt in
@ -131,6 +133,10 @@ do
echo "enable multi module feature"
ENABLE_MULTI_MODULE=1
;;
W)
echo "enable wasm64(memory64) feature"
ENABLE_MEMORY64=1
;;
C)
echo "enable code coverage"
COLLECT_CODE_COVERAGE=1
@ -478,6 +484,29 @@ function spec_test()
popd
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
echo $(pwd)
@ -488,7 +517,7 @@ function 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 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' ]]; then
ARGS_FOR_SPEC_TEST+="-M "
@ -537,6 +566,13 @@ function spec_test()
ARGS_FOR_SPEC_TEST+="--gc "
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
ARGS_FOR_SPEC_TEST+="--qemu "
ARGS_FOR_SPEC_TEST+="--qemu-firmware ${QEMU_FIRMWARE} "
@ -833,6 +869,12 @@ function trigger()
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MULTI_MODULE=0"
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
EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_PTHREAD=1"
fi