From a2a8b324563c18e6e4c46e9a170bab5b0cef31f0 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 30 May 2024 14:08:18 +0800 Subject: [PATCH 01/23] Fix test-wamr-ide CI failure (#3485) Set `moduleResolution` as `node16` in tsconfig.json. ps. https://github.com/bytecodealliance/wasm-micro-runtime/actions/runs/9296272681/job/25586420457 ``` node_modules/@vscode/test-electron/out/util.d.ts(1,23): error TS1452: 'resolution-mode' assertions are only supported when `moduleResolution` is `node16` or `nodenext`. ``` --- test-tools/wamr-ide/VSCode-Extension/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/test-tools/wamr-ide/VSCode-Extension/tsconfig.json b/test-tools/wamr-ide/VSCode-Extension/tsconfig.json index c75039eee..9ecb219db 100644 --- a/test-tools/wamr-ide/VSCode-Extension/tsconfig.json +++ b/test-tools/wamr-ide/VSCode-Extension/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "module": "commonjs", + "moduleResolution": "node16", "target": "es6", "outDir": "out", "lib": ["es6"], From d29802c451a3bdc6d9b5defe1317fc61e4e0d1ff Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Thu, 30 May 2024 14:55:21 +0800 Subject: [PATCH 02/23] Fix two issues to make fuzzing test quit earlier (#3471) - Add a marco to limit the maxi allocable memory size of fuzz test to 2GB to avoid libFuzzer out-of-memory - Check global type in load_global_import and load_global_section --- core/config.h | 13 +++++++++++++ core/iwasm/interpreter/wasm_loader.c | 13 ++++++++++++- tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt | 2 +- .../fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt | 2 +- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/core/config.h b/core/config.h index b2a34b590..2f3e401dd 100644 --- a/core/config.h +++ b/core/config.h @@ -663,4 +663,17 @@ #define WASM_MEM_ALLOC_WITH_USAGE 0 #endif +#ifndef WASM_ENABLE_FUZZ_TEST +#define WASM_ENABLE_FUZZ_TEST 0 +#endif + +#ifndef WASM_MEM_ALLOC_MAX_SIZE +#if WASM_ENABLE_FUZZ_TEST != 0 +/* In oss-fuzz, the maximum RAM is ~2.5G */ +#define WASM_MEM_ALLOC_MAX_SIZE (2U * 1024 * 1024 * 1024) +#else +#define WASM_MEM_ALLOC_MAX_SIZE UINT32_MAX +#endif +#endif + #endif /* end of _CONFIG_H_ */ diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 40bf135b6..86854ab25 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -379,7 +379,8 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) { void *mem; - if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) { + if (size >= WASM_MEM_ALLOC_MAX_SIZE + || !(mem = wasm_runtime_malloc((uint32)size))) { set_error_buf(error_buf, error_buf_size, "allocate memory failed"); return NULL; } @@ -3052,7 +3053,12 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, #if WASM_ENABLE_GC == 0 CHECK_BUF(p, p_end, 2); + /* global type */ declare_type = read_uint8(p); + if (!is_value_type(declare_type)) { + set_error_buf(error_buf, error_buf_size, "type mismatch"); + return false; + } declare_mutable = read_uint8(p); #else if (!resolve_value_type(&p, p_end, parent_module, parent_module->type_count, @@ -4034,7 +4040,12 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, for (i = 0; i < global_count; i++, global++) { #if WASM_ENABLE_GC == 0 CHECK_BUF(p, p_end, 2); + /* global type */ global->type.val_type = read_uint8(p); + if (!is_value_type(global->type.val_type)) { + set_error_buf(error_buf, error_buf_size, "type mismatch"); + return false; + } mutable = read_uint8(p); #else if (!resolve_value_type(&p, p_end, module, module->type_count, diff --git a/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt index 2b6ddae76..805848fd9 100644 --- a/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt @@ -113,7 +113,7 @@ message([ceith]:REPO_ROOT_DIR, ${REPO_ROOT_DIR}) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") -add_definitions(-DWAMR_USE_MEM_POOL=0) +add_definitions(-DWAMR_USE_MEM_POOL=0 -DWASM_ENABLE_FUZZ_TEST=1) # Enable fuzzer add_compile_options(-fsanitize=fuzzer) diff --git a/tests/fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt index ec7eaff88..54bbdca11 100644 --- a/tests/fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt @@ -113,7 +113,7 @@ message([ceith]:REPO_ROOT_DIR, ${REPO_ROOT_DIR}) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") -add_definitions(-DWAMR_USE_MEM_POOL=0) +add_definitions(-DWAMR_USE_MEM_POOL=0 -DWASM_ENABLE_FUZZ_TEST=1) # Enable fuzzer add_compile_options(-fsanitize=fuzzer) From 115a4767dfd21b504d8c9826a5840e5099801b68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 15:42:37 +0800 Subject: [PATCH 03/23] Bump requests from 2.31.0 to 2.32.2 in /build-scripts (#3474) Bumps [requests](https://github.com/psf/requests) from 2.31.0 to 2.32.2. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.31.0...v2.32.2) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build-scripts/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-scripts/requirements.txt b/build-scripts/requirements.txt index 077c95d8a..6b1425c82 100644 --- a/build-scripts/requirements.txt +++ b/build-scripts/requirements.txt @@ -1 +1 @@ -requests==2.31.0 \ No newline at end of file +requests==2.32.2 \ No newline at end of file From 1f8a78d61ae5bc4f487989998180afce753d99ce Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 30 May 2024 16:55:24 +0900 Subject: [PATCH 04/23] posix iwasm: Make the timeout logic a bit more robust (#3478) Use an absolute timeout calculation to avoid being affected much by CPU scheduling. --- product-mini/platforms/posix/main.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index d951de2c9..b2f929c6a 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -535,21 +535,23 @@ void * timeout_thread(void *vp) { const struct timeout_arg *arg = vp; - uint32 left = arg->timeout_ms; + const uint64 end_time = + os_time_get_boot_us() + (uint64)arg->timeout_ms * 1000; while (!arg->cancel) { - uint32 ms; - if (left >= 100) { - ms = 100; - } - else { - ms = left; - } - os_usleep((uint64)ms * 1000); - left -= ms; - if (left == 0) { + const uint64 now = os_time_get_boot_us(); + if ((int64)(now - end_time) > 0) { wasm_runtime_terminate(arg->inst); break; } + const uint64 left_us = end_time - now; + uint32 us; + if (left_us >= 100 * 1000) { + us = 100 * 1000; + } + else { + us = left_us; + } + os_usleep(us); } return NULL; } From 5623e4d22a6e9b33e2a73acf5add439179db8ed0 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 30 May 2024 16:14:12 +0800 Subject: [PATCH 05/23] Fix memory64 handling find_block_addr and execute_main (#3480) --- core/iwasm/common/wasm_application.c | 28 ++++++++++++++++++++--- core/iwasm/interpreter/wasm_interp_fast.c | 12 +++++----- core/iwasm/interpreter/wasm_loader.c | 15 ++++++------ core/iwasm/interpreter/wasm_mini_loader.c | 3 ++- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index b7e64460a..da3b31c95 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -201,9 +201,23 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) if (func_type->param_count) { for (i = 0; i < argc; i++) total_argv_size += (uint32)(strlen(argv[i]) + 1); - total_argv_size = align_uint(total_argv_size, 4); +#if WASM_ENABLE_MEMORY64 != 0 + if (is_memory64) + /* `char **argv` is an array of 64-bit elements in memory64 */ + total_argv_size = align_uint(total_argv_size, 8); + else +#endif + total_argv_size = align_uint(total_argv_size, 4); - total_size = (uint64)total_argv_size + sizeof(int32) * (uint64)argc; +#if WASM_ENABLE_MEMORY64 != 0 + if (is_memory64) + /* `char **argv` is an array of 64-bit elements in memory64 */ + total_size = + (uint64)total_argv_size + sizeof(uint64) * (uint64)argc; + else +#endif + total_size = + (uint64)total_argv_size + sizeof(uint32) * (uint64)argc; if (total_size >= UINT32_MAX || !(argv_buf_offset = wasm_runtime_module_malloc( @@ -219,7 +233,15 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[]) for (i = 0; i < argc; i++) { bh_memcpy_s(p, (uint32)(p_end - p), argv[i], (uint32)(strlen(argv[i]) + 1)); - argv_offsets[i] = (uint32)argv_buf_offset + (uint32)(p - argv_buf); +#if WASM_ENABLE_MEMORY64 != 0 + if (is_memory64) + /* `char **argv` is an array of 64-bit elements in memory64 */ + ((uint64 *)argv_offsets)[i] = + (uint32)argv_buf_offset + (uint32)(p - argv_buf); + else +#endif + argv_offsets[i] = + (uint32)argv_buf_offset + (uint32)(p - argv_buf); p += strlen(argv[i]) + 1; } diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index df6aa73a2..825079249 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -3446,10 +3446,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { /* clang-format off */ #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 - local_offset = *frame_ip++; + local_offset = *frame_ip++; #else - local_offset = *frame_ip; - frame_ip += 2; + local_offset = *frame_ip; + frame_ip += 2; #endif /* clang-format on */ *(uint32 *)(frame_lp + local_offset) = @@ -3463,10 +3463,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { /* clang-format off */ #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 - local_offset = *frame_ip++; + local_offset = *frame_ip++; #else - local_offset = *frame_ip; - frame_ip += 2; + local_offset = *frame_ip; + frame_ip += 2; #endif /* clang-format on */ PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset), diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 86854ab25..f4911d6ee 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -6414,7 +6414,7 @@ create_sections(const uint8 *buf, uint32 size, WASMSection **p_section_list, char *error_buf, uint32 error_buf_size) { WASMSection *section_list_end = NULL, *section; - const uint8 *p = buf, *p_end = buf + size /*, *section_body*/; + const uint8 *p = buf, *p_end = buf + size; uint8 section_type, section_index, last_section_index = (uint8)-1; uint32 section_size; @@ -7658,7 +7658,6 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) case WASM_OP_SIMD_PREFIX: { - /* TODO: memory64 offset type changes */ uint32 opcode1; read_leb_uint32(p, p_end, opcode1); @@ -7683,8 +7682,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case SIMD_v128_store: /* memarg align */ skip_leb_uint32(p, p_end); - /* memarg offset*/ - skip_leb_uint32(p, p_end); + /* memarg offset */ + skip_leb_mem_offset(p, p_end); break; case SIMD_v128_const: @@ -7723,8 +7722,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case SIMD_v128_store64_lane: /* memarg align */ skip_leb_uint32(p, p_end); - /* memarg offset*/ - skip_leb_uint32(p, p_end); + /* memarg offset */ + skip_leb_mem_offset(p, p_end); /* ImmLaneId */ CHECK_BUF(p, p_end, 1); p++; @@ -7734,8 +7733,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case SIMD_v128_load64_zero: /* memarg align */ skip_leb_uint32(p, p_end); - /* memarg offset*/ - skip_leb_uint32(p, p_end); + /* memarg offset */ + skip_leb_mem_offset(p, p_end); break; default: diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index c0966aad2..b9cd91fd3 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -6942,7 +6942,8 @@ re_scan: uint32 j; for (i = 0; i < module->global_count; i++) { - if (module->globals[i].type == VALUE_TYPE_FUNCREF + if (module->globals[i].type.val_type + == VALUE_TYPE_FUNCREF && module->globals[i].init_expr.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST && module->globals[i].init_expr.u.u32 == func_idx) { From 67638e24f40a537b194a233a2d388f06db6d9546 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Fri, 31 May 2024 11:16:14 +0800 Subject: [PATCH 06/23] wasm-mutator-fuzz: Generate more kinds of corpus (#3487) --- tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt | 8 +- tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh | 80 +++++++++++-------- .../workspace/CMakeLists.txt | 4 +- 3 files changed, 51 insertions(+), 41 deletions(-) diff --git a/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt index 805848fd9..084b39911 100644 --- a/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt @@ -58,12 +58,12 @@ endif () if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) # Enable libc builtin support by default - set (WAMR_BUILD_LIBC_BUILTIN 1) + set (WAMR_BUILD_LIBC_BUILTIN 0) endif () if (NOT DEFINED WAMR_BUILD_LIBC_WASI) # Enable libc wasi support by default - set (WAMR_BUILD_LIBC_WASI 1) + set (WAMR_BUILD_LIBC_WASI 0) endif () if (NOT DEFINED WAMR_BUILD_FAST_INTERP) @@ -92,8 +92,8 @@ if (NOT DEFINED WAMR_BUILD_SIMD) endif () if (NOT DEFINED WAMR_BUILD_REF_TYPES) - # Disable reference types by default - set (WAMR_BUILD_REF_TYPES 0) + # Enable reference type by default + set (WAMR_BUILD_REF_TYPES 1) endif () if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP) diff --git a/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh b/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh index 6e9fa10fa..29d24dbd0 100755 --- a/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh +++ b/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh @@ -8,51 +8,61 @@ # 1.check parameter if [ ! $1 ]; then echo "Parameter is empty, please enter parameter !" - exit + exit fi +EXPECTED_NUM=$1 # 2.check dir buildPath="./build" corpusPath="$buildPath/CORPUS_DIR" -if [[ ! -d "$buildPath" ]]; then - echo "auto create the build folder !" - mkdir build -else # build Folder exists - if [[ -d "$buildPath" ]]; then # CORPUS_DIR exists - rm -rf $corpusPath - fi -fi +rm -rf "${corpusPath}" +mkdir -p "${corpusPath}" # 3.change dir -# cd build && mkdir CORPUS_DIR && cd CORPUS_DIR -cd build && mkdir CORPUS_DIR && cd CORPUS_DIR +cd "${corpusPath}" # 4.generate *.wasm file -echo "Generate $@ files according to user requirements" +echo "Generating $EXPECTED_NUM Wasm files for each kind as required" -for((i=1; i<($@+1); i++)); +# Generate wasm files with different features +# Try on and on until the generated wasm file exists +function try_generate_wasm() +{ + SMITH_OPTIONS=$1 + GENERATED_WASM_NAME=$2 + + local try_i=0 + until [[ -f $GENERATED_WASM_NAME ]]; do + head -c 100 /dev/urandom | wasm-tools smith $SMITH_OPTIONS -o $GENERATED_WASM_NAME >/dev/null 2>&1 + try_i=$((try_i+1)) + done + + printf -- "-- output ${GENERATED_WASM_NAME} in %d retries\n" $try_i +} + +# try_generate_wasm "--min-memories=1 --min-tables=1" "test_min.wasm" + +for i in $(seq 1 $EXPECTED_NUM) do -head -c 100 /dev/urandom | wasm-tools smith -o test_$i.wasm + # by default + try_generate_wasm "" test_$i.wasm + + # with different features + # mvp + try_generate_wasm "--min-memories=1 --min-tables=1" test_min_$i.wasm + try_generate_wasm "--min-memories=1 --min-tables=1 --bulk-memory-enabled true" test_bulk_$i.wasm + try_generate_wasm "--min-memories=1 --min-tables=1 --reference-types-enabled true" test_ref_$i.wasm + try_generate_wasm "--min-memories=1 --min-tables=1 --multi-value-enabled true" test_multi_$i.wasm + try_generate_wasm "--min-memories=1 --min-tables=1 --simd-enabled true" test_simd_$i.wasm + try_generate_wasm "--min-memories=1 --min-tables=1 --tail-call-enabled true " test_tail_$i.wasm + + # enable me when compiling iwasm with those features + #try_generate_wasm "--min-memories=1 --min-tables=1 --threads-enabled true" test_thread_$i.wasm + #try_generate_wasm "--min-memories=1 --min-tables=1 --memory64-enabled true" test_memory64_$i.wasm + #try_generate_wasm "--min-memories=1 --min-tables=1 --exceptions-enabled true" test_exception_$i.wasm + #try_generate_wasm "--min-memories=1 --min-tables=1 --gc-enabled true" test_gc_$i.wasm + # with custom-section + try_generate_wasm "--min-memories=1 --min-tables=1 --generate-custom-sections true" test_custom_$i.wasm done -# 5.check wasm file -dir=$(pwd) -d=$(find . ! -name "." -type d -prune -o -type f -name "*.wasm" -print) -#echo "current dir=$dir" -num=0 - -for((i=1; i<($@+1); i++)); -do - wasmFile="test_$i.wasm" - if [[ ! -f "$wasmFile" ]]; then - echo "The file $wasmFile is not exists !" - else - let "num++" - fi -done - -echo "$@ user requirements, $num actually generated !" - -if [ $num == $@ ]; then echo "Wasm file generated successfully !" -else echo "Wasm file generated faild !" -fi +printf "Done\n" diff --git a/tests/fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt index 54bbdca11..5fa171a9c 100644 --- a/tests/fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt @@ -92,8 +92,8 @@ if (NOT DEFINED WAMR_BUILD_SIMD) endif () if (NOT DEFINED WAMR_BUILD_REF_TYPES) - # Disable reference types by default - set (WAMR_BUILD_REF_TYPES 0) + # Enable reference type by default + set (WAMR_BUILD_REF_TYPES 1) endif () if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP) From 23e1d515879cc13693eb25d8472a4746e7c36ba1 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 31 May 2024 11:32:36 +0800 Subject: [PATCH 07/23] Fix loader parse block type and calculate dynamic offset for loop args (#3482) Fix several issues in wasm loader: - Parse a block's type index with leb int32 instead leb uint32 - Correct dst dynamic offset of loop block arguments for opcode br when copying the stack operands to the arguments of loop block - Free each frame_csp's param_frame_offsets when destroy loader ctx - Fix compilation error in wasm_mini_loader.c - Add test cases of failed issues This PR fixes issue #3467 and #3468. --- core/iwasm/compilation/aot_compiler.c | 8 ++- core/iwasm/fast-jit/jit_frontend.c | 4 +- core/iwasm/interpreter/wasm_loader.c | 65 ++++++++++++++---- core/iwasm/interpreter/wasm_mini_loader.c | 62 +++++++++++++---- .../issues/issue-3467/tt_unreachable.wasm | Bin 0 -> 237 bytes .../ba-issues/issues/issue-3468/i64.add.wasm | Bin 0 -> 14593 bytes .../regression/ba-issues/running_config.json | 32 +++++++++ 7 files changed, 139 insertions(+), 32 deletions(-) create mode 100644 tests/regression/ba-issues/issues/issue-3467/tt_unreachable.wasm create mode 100644 tests/regression/ba-issues/issues/issue-3468/i64.add.wasm diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 5c66e0fe8..96ed8facf 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -1028,7 +1028,9 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) } else { frame_ip--; - read_leb_uint32(frame_ip, frame_ip_end, type_index); + read_leb_int32(frame_ip, frame_ip_end, type_index); + /* type index was checked in wasm loader */ + bh_assert(type_index < comp_ctx->comp_data->type_count); func_type = (AOTFuncType *)comp_ctx->comp_data->types[type_index]; param_count = func_type->param_count; @@ -1048,7 +1050,9 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) case EXT_OP_LOOP: case EXT_OP_IF: { - read_leb_uint32(frame_ip, frame_ip_end, type_index); + read_leb_int32(frame_ip, frame_ip_end, type_index); + /* type index was checked in wasm loader */ + bh_assert(type_index < comp_ctx->comp_data->type_count); func_type = (AOTFuncType *)comp_ctx->comp_data->types[type_index]; param_count = func_type->param_count; diff --git a/core/iwasm/fast-jit/jit_frontend.c b/core/iwasm/fast-jit/jit_frontend.c index 092f9c0c7..17c33230c 100644 --- a/core/iwasm/fast-jit/jit_frontend.c +++ b/core/iwasm/fast-jit/jit_frontend.c @@ -1510,7 +1510,9 @@ jit_compile_func(JitCompContext *cc) case EXT_OP_LOOP: case EXT_OP_IF: { - read_leb_uint32(frame_ip, frame_ip_end, type_idx); + read_leb_int32(frame_ip, frame_ip_end, type_idx); + /* type index was checked in wasm loader */ + bh_assert(type_idx < cc->cur_wasm_module->type_count); func_type = cc->cur_wasm_module->types[type_idx]; param_count = func_type->param_count; param_types = func_type->types; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index f4911d6ee..b5185b928 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -7086,7 +7086,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, } else { p--; - skip_leb_uint32(p, p_end); + /* block type */ + skip_leb_int32(p, p_end); } if (block_nested_depth < sizeof(block_stack) / sizeof(BlockAddr)) { @@ -7101,7 +7102,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case EXT_OP_LOOP: case EXT_OP_IF: /* block type */ - skip_leb_uint32(p, p_end); + skip_leb_int32(p, p_end); if (block_nested_depth < sizeof(block_stack) / sizeof(BlockAddr)) { block_stack[block_nested_depth].start_addr = p; @@ -7850,7 +7851,11 @@ typedef struct BranchBlock { BranchBlockPatch *patch_list; /* This is used to save params frame_offset of of if block */ int16 *param_frame_offsets; - /* This is used to recover dynamic offset for else branch */ + /* This is used to recover the dynamic offset for else branch, + * and also to remember the start offset of dynamic space which + * stores the block arguments for loop block, so we can use it + * to copy the stack operands to the loop block's arguments in + * wasm_loader_emit_br_info for opcode br. */ uint16 start_dynamic_offset; #endif @@ -8001,13 +8006,26 @@ static void free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num) { BranchBlock *tmp_csp = frame_csp; + uint32 i; - for (uint32 i = 0; i < csp_num; i++) { + for (i = 0; i < csp_num; i++) { free_label_patch_list(tmp_csp); tmp_csp++; } } +static void +free_all_label_param_frame_offsets(BranchBlock *frame_csp, uint32 csp_num) +{ + BranchBlock *tmp_csp = frame_csp; + uint32 i; + + for (i = 0; i < csp_num; i++) { + if (tmp_csp->param_frame_offsets) + wasm_runtime_free(tmp_csp->param_frame_offsets); + tmp_csp++; + } +} #endif /* end of WASM_ENABLE_FAST_INTERP */ #if WASM_ENABLE_GC != 0 @@ -8126,6 +8144,8 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx) if (ctx->frame_csp_bottom) { #if WASM_ENABLE_FAST_INTERP != 0 free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num); + free_all_label_param_frame_offsets(ctx->frame_csp_bottom, + ctx->csp_num); #endif #if WASM_ENABLE_GC != 0 wasm_loader_clean_all_local_use_masks(ctx); @@ -9238,8 +9258,14 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, emit_operand(ctx, *(int16 *)(frame_offset)); } /* Part e */ - dynamic_offset = - frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); + if (frame_csp->label_type == LABEL_TYPE_LOOP) + /* Use start_dynamic_offset which was set in + copy_params_to_dynamic_space */ + dynamic_offset = frame_csp->start_dynamic_offset + + wasm_get_cell_num(types, arity); + else + dynamic_offset = + frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); if (is_br) ctx->dynamic_offset = dynamic_offset; for (i = (int32)arity - 1; i >= 0; i--) { @@ -10623,8 +10649,8 @@ fail: * Part e: each param's dst offset */ static bool -copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, - char *error_buf, uint32 error_buf_size) +copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, char *error_buf, + uint32 error_buf_size) { bool ret = false; int16 *frame_offset = NULL; @@ -10638,6 +10664,7 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, uint32 param_count = block_type->u.type->param_count; int16 condition_offset = 0; bool disable_emit = false; + bool is_if_block = (block->label_type == LABEL_TYPE_IF ? true : false); int16 operand_offset = 0; uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets)); @@ -10690,6 +10717,14 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, if (is_if_block) emit_operand(loader_ctx, condition_offset); + /* Since the start offset to save the block's params and + * the start offset to save the block's results may be + * different, we remember the dynamic offset for loop block + * so that we can use it to copy the stack operands to the + * loop block's params in wasm_loader_emit_br_info. */ + if (block->label_type == LABEL_TYPE_LOOP) + block->start_dynamic_offset = loader_ctx->dynamic_offset; + /* Part e) */ /* Push to dynamic space. The push will emit the dst offset. */ for (i = 0; i < param_count; i++) @@ -11062,12 +11097,12 @@ re_scan: #endif /* end of WASM_ENABLE_GC != 0 */ } else { - uint32 type_index; + int32 type_index; /* Resolve the leb128 encoded type index as block type */ p--; p_org = p - 1; - read_leb_uint32(p, p_end, type_index); - if (type_index >= module->type_count) { + read_leb_int32(p, p_end, type_index); + if ((uint32)type_index >= module->type_count) { set_error_buf(error_buf, error_buf_size, "unknown type"); goto fail; @@ -11171,8 +11206,8 @@ re_scan: if (BLOCK_HAS_PARAM(block_type)) { /* Make sure params are in dynamic space */ - if (!copy_params_to_dynamic_space( - loader_ctx, false, error_buf, error_buf_size)) + if (!copy_params_to_dynamic_space(loader_ctx, error_buf, + error_buf_size)) goto fail; } @@ -11218,8 +11253,8 @@ re_scan: /* skip the if label */ skip_label(); /* Emit a copy instruction */ - if (!copy_params_to_dynamic_space( - loader_ctx, true, error_buf, error_buf_size)) + if (!copy_params_to_dynamic_space(loader_ctx, error_buf, + error_buf_size)) goto fail; /* Emit the if instruction */ diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index b9cd91fd3..15e559250 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -3451,7 +3451,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case EXT_OP_LOOP: case EXT_OP_IF: /* block type */ - skip_leb_uint32(p, p_end); + skip_leb_int32(p, p_end); if (block_nested_depth < sizeof(block_stack) / sizeof(BlockAddr)) { block_stack[block_nested_depth].start_addr = p; @@ -3921,7 +3921,11 @@ typedef struct BranchBlock { /* This is used to store available param num for if/else branch, so the else * opcode can know how many parameters should be copied to the stack */ uint32 available_param_num; - /* This is used to recover dynamic offset for else branch */ + /* This is used to recover the dynamic offset for else branch, + * and also to remember the start offset of dynamic space which + * stores the block arguments for loop block, so we can use it + * to copy the stack operands to the loop block's arguments in + * wasm_loader_emit_br_info for opcode br. */ uint16 start_dynamic_offset; #endif @@ -4050,13 +4054,26 @@ static void free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num) { BranchBlock *tmp_csp = frame_csp; + uint32 i; - for (uint32 i = 0; i < csp_num; i++) { + for (i = 0; i < csp_num; i++) { free_label_patch_list(tmp_csp); tmp_csp++; } } +static void +free_all_label_param_frame_offsets(BranchBlock *frame_csp, uint32 csp_num) +{ + BranchBlock *tmp_csp = frame_csp; + uint32 i; + + for (i = 0; i < csp_num; i++) { + if (tmp_csp->param_frame_offsets) + wasm_runtime_free(tmp_csp->param_frame_offsets); + tmp_csp++; + } +} #endif static bool @@ -4120,6 +4137,8 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx) if (ctx->frame_csp_bottom) { #if WASM_ENABLE_FAST_INTERP != 0 free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num); + free_all_label_param_frame_offsets(ctx->frame_csp_bottom, + ctx->csp_num); #endif wasm_runtime_free(ctx->frame_csp_bottom); } @@ -4798,8 +4817,14 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, emit_operand(ctx, *(int16 *)(frame_offset)); } /* Part e */ - dynamic_offset = - frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); + if (frame_csp->label_type == LABEL_TYPE_LOOP) + /* Use start_dynamic_offset which was set in + copy_params_to_dynamic_space */ + dynamic_offset = frame_csp->start_dynamic_offset + + wasm_get_cell_num(types, arity); + else + dynamic_offset = + frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); if (is_br) ctx->dynamic_offset = dynamic_offset; for (i = (int32)arity - 1; i >= 0; i--) { @@ -5778,8 +5803,8 @@ fail: * Part e: each param's dst offset */ static bool -copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, - char *error_buf, uint32 error_buf_size) +copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, char *error_buf, + uint32 error_buf_size) { bool ret = false; int16 *frame_offset = NULL; @@ -5793,6 +5818,7 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, uint32 param_count = block_type->u.type->param_count; int16 condition_offset = 0; bool disable_emit = false; + bool is_if_block = (block->label_type == LABEL_TYPE_IF ? true : false); int16 operand_offset = 0; uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets)); @@ -5845,6 +5871,14 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, if (is_if_block) emit_operand(loader_ctx, condition_offset); + /* Since the start offset to save the block's params and + * the start offset to save the block's results may be + * different, we remember the dynamic offset for loop block + * so that we can use it to copy the stack operands to the + * loop block's params in wasm_loader_emit_br_info. */ + if (block->label_type == LABEL_TYPE_LOOP) + block->start_dynamic_offset = loader_ctx->dynamic_offset; + /* Part e) */ /* Push to dynamic space. The push will emit the dst offset. */ for (i = 0; i < param_count; i++) @@ -6043,11 +6077,11 @@ re_scan: block_type.u.value_type.type = value_type; } else { - uint32 type_index; + int32 type_index; /* Resolve the leb128 encoded type index as block type */ p--; - read_leb_uint32(p, p_end, type_index); - bh_assert(type_index < module->type_count); + read_leb_int32(p, p_end, type_index); + bh_assert((uint32)type_index < module->type_count); block_type.is_value_type = false; block_type.u.type = module->types[type_index]; #if WASM_ENABLE_FAST_INTERP == 0 @@ -6134,8 +6168,8 @@ re_scan: skip_label(); if (BLOCK_HAS_PARAM(block_type)) { /* Make sure params are in dynamic space */ - if (!copy_params_to_dynamic_space( - loader_ctx, false, error_buf, error_buf_size)) + if (!copy_params_to_dynamic_space(loader_ctx, error_buf, + error_buf_size)) goto fail; } if (opcode == WASM_OP_LOOP) { @@ -6175,8 +6209,8 @@ re_scan: /* skip the if label */ skip_label(); /* Emit a copy instruction */ - if (!copy_params_to_dynamic_space( - loader_ctx, true, error_buf, error_buf_size)) + if (!copy_params_to_dynamic_space(loader_ctx, error_buf, + error_buf_size)) goto fail; /* Emit the if instruction */ diff --git a/tests/regression/ba-issues/issues/issue-3467/tt_unreachable.wasm b/tests/regression/ba-issues/issues/issue-3467/tt_unreachable.wasm new file mode 100644 index 0000000000000000000000000000000000000000..9f56fb5e546cc8a7cb41ff9c032e510705ac0c4e GIT binary patch literal 237 zcmYL?F-pWx6h-gNdr8n|VVx@Qf8`#8`DWaLofr$5LUaa`M(`(C46_Lvi^0ai(n1Sc zE13<5JD3fK22||s;T*U)Zq5jRJ6X*>i?gd3r*+bG>}vcWd&a@aU~4dniZIQJwBsJE zXMp{$0o8J2-cFC&lcq(ok&}?&WV4qGIQ6S^PBPuY=39`dBV*&3;Ao>aX8T0Lu`# G4f_V?oj1Y& literal 0 HcmV?d00001 diff --git a/tests/regression/ba-issues/issues/issue-3468/i64.add.wasm b/tests/regression/ba-issues/issues/issue-3468/i64.add.wasm new file mode 100644 index 0000000000000000000000000000000000000000..ea40df17140ab7f012644f48d47bb76472d4ab02 GIT binary patch literal 14593 zcmaib349bq_J4OxcTbX@B$I^PcWS~Zr-~pVsqR+6d+`EAj3_9m+={Z31Q0<{kwXy? zH6U`x71UKgfpDs;+^D#MvY-MUhzNob;rD%2JxTWS+yC$H;7oPZyX)0^uc|uQ-6I~- zHBHlBHhPw8TDhiImb0oVy`nr&RaK>x>+*ke>QTL_T(7_YTG4VAt)M|xh386EK^+7c z1qBS1v&srqAt|9naQN2fi&aMPk7!hs8&%OLMyh}-@z6qlC2__xz_fA`P5Dp(c8ppW zB+l|t$rdd)qE(e78DyaEO7!E4GZY4 zD|>nUU-OP;l@aXe0Kv|ebgwRbRML7YK+yTqUt32MYRmrU)yuLZv`rmDf0?n>ZE~=i zWGfkd5+sCG6={->OmHD~#H! zOrkz!RJRMBUI=VJ{Utg}foAG7{7=Dnrtg`QBlpV>R$TG*IvW2_ zBPuUSEvMc&p_axsU3}5A!+ug)&XWdTDDm1237Tux{Lqak&Of4VyVediVb)zEM&3Pqq^1Q&4!LV&{}E^Ocf5*?W ztUAl)+0jV0^Vf>$-;F>0*cqmxY-)u8a3AF)<*{n&K-aKGBCr5Tnf7HQ}BsBQuL?!_4b% zA2Ihmn1|-vFynf4m_>A(1(?B1qtY8X=CO7+EIhRifZDJVwI7yhAUwYw(0R+?x_flU zI`9{NSVlZIriJy0!A+uLiWQ7ogCdsmP0)GM8pngtNKi~P97{|x4ci$LSHa_=kvMKG zmA~$({!D~*u5(SiZj9pbgCg-J4^C7-n)qHb%A8FmD~o-&$<2EW`RK(zyKmp_^i1f% zL&Q8}+osdP(Z=z_Xe5!F;*=%k>qf{(^vAtD4^8X8H6sfO`8{SG<4J=eN$%;p3!spD z_S_3F?+cJ9nY2pgfk>QfN)R8zd7klfo@7KAeM*g{tQl*@12^%4L6HJ4?&g(!PJf&S z2DZ)9oZncK7e*t6ZuRhAyM=Xg6&M$hs6}G3g-Pl4UB)#Xr{n_MoASo78=skZK;0s3I8!NFJFH)_=sDw2>h#SJul0}Avp%6OtPKX5C4 zbsm}r&u9uIq>L-1M7C`k5S%spyL{v(Y_~}^#S%;g6f|J@KbVtH#RFq`#w3Mhieox2 z;TpUp0NU~5)j)UNbWo%zPb1x$k#5awR_3N zUIg`}AW8DKSQTToX`-#>@WfNZfd_9CX6TDw3nc|z(`9!Jjl^yB0w|}S8ShcX1Zy*uj zO?eCPyea11j(HPx0dd@5A8W=xHRBVFHToy!8rSj;gCZT+r&w@2|1o}HG;*Ok>!Xx) zVV!Nz_(e2{7m4Q(B;d9+rwZ@*YT;=(Vh!&YjdbL##iD?b#qfEPUot3iiSup{rdh+< zu(qtN0?~4uHX$9Wf)Jejmg>zByDhGHlRG>#>Z;uww&O{>lpLf}H9V=4k>$PFy+why zu>?ct@w=Uxpt(X4aAy=-5OJa8igg)3Nb%poY+iV)Y}5K@i9Tj1j2Tn3;m1&w!7HQ+ zB}?Ql%_wQ$1Bs)C>W3v;kqcu{Yz{cTTa`Smrv$W3MCI}=-(%Ie(V2gTFcdvHlf627 z1x4HAnyw>^e=hY}UmnWI^?L20XeDk1ni&U$jU9xU1{1Ky({c4g~)%09%3l|A1_6%&cd_Io9KL zja}rd3O>azi$*SkWIS_vJ%D$0ivj174-{jf#8C#7c4+D!SN5>BIQobd=tiVFDRXanWQDB%q!zc#$$?BDb|+#NF8b>%$(va|DO4^2n^vLQ;?znoZkTABa=3I+-gJpXayMv`NjAmJoj5HM zmX9fx+MtMS)`~^UFva`E5NRssGmQe9YERLXDUnWP2cq`kK;mWgM#%#!I`cZl(Fq_jr+#-3fArq%f-fEDP+nv4jD$s|@%A(F8 zL$Vj|7~-74(~Tn7zl=A3w%*EORS@xV=I3ws9#fPIR=jn8Ny%Gyc0gRqUs9;cSEe{d zbZ5YM+Uh02kfh7JdHF3iJ@jNefhOD|yPa=!=Y8XLMX7Av!@Y0G`W=yfg_;mvz;k=Z zF}KT&>k(pNgqNGnYV&agWIik*c*@iD<2>N358foZZCfn#U4g6+<;l+hOa(QR3b8Q! zt?9>1Sftp!;qsj@P9GJ3zX{M%belc21Jf|M9$7qRQtnff>eGSFb9s{31E+E3n$EP~ z&Abgy7wZ_?ifqKHxTRvSSkG)RRexA=a67Gi0_>2SNCRIq-Bt<7MyXNe4vbDB?bVpg zHfo|^s0!}PkMj5P6e>{^#CkQBfE7m>!A;n-46;KtHH;FOCO5Bv9j1ZjibaO8O*4?^ zVwomFDT-}upd4^^u+g%|Imb4}5{}G^%TzWJb1iPL!Ve@gd_XK_ zN;)^ZITb?rB84(}wzFTGq-KFPr&!=yBF$DD5GvG1Okl$lIm{^H-S53^3I@du*@~xO z7jl~qqjBBl7gr9`N3|(dTI4%^ zDKa+T>ri}7D0Rc;z-?lw1`t{H5xPw^g-u;VSjK-Hx zih&Jno;pAlW_>2~dg{IIN$B;agyuEtT%w~%`w3-aaT=nc&bV?=9XU}kvbW7yAEV0q zykO@wV|JAQ`sD`bAA+Vg^i<0)gU?e|_nx0GR(^j;0${Lhq~sBE5Bt8Dgtn=gSo;+M zTdSr+

oqhEm;xkIa9iS@nfGL!jAc{$U_eL97mnrvjrCT4_w~x~({t}ZMQ8iMKrnICWQOyJ z#uF#V`d$?*Uit*Pxkjhrq|(*sSmSJRCzb-8=M2iXepdGrPLa{ z8}YLmwBPgcaJk=qQ4v~l;nQzPf!2=ca69=CN_@yF;fX`7{bkZUwVa#{&xJdMZQ zBr$1uT0LZwro^e!ob_67e+cRD=KwEI!{TdAd~A)9LtK{9h^8G%o1oTN#@j_B?bJ6f zxR2+tLid--MbPxcdiE5E%D9bfE5XXJM7{$i5$8#T)!^UP! zWM8A2iC)dn)p2*6%!l3j$u5&OyH_^E?jR2jl}%elsG#$Q8I??V7K>wX-t60c?y#gK z?Q9jQcjk+6pY00L0tYvp>a6zFNC53o9!feq1yd!ZMoc0}jV&7OuKXvH=M0eD-n8Yx zSs!1PR;!#UMnut2PvSZ23a|Xe_hw~Jvj9em&mTA#=uW$EAIbj>F;ig^SHCaz6F*Q6 zIrB}Yqd%9jW5^N-nR~w6n`}HV4NjgULbwOR&{LN{?*Xx%fK59h%V2#(yMd0M}0c&K%FK zwP76JygWqtN%=5sI+2VoxJ{}4Nl?i>AubTpy$>;a{CpcgG*&t)6Zq!jY`k5sm^bvX!v34uQB;q~vM=2G?aIq=I2r3vAtyFdsWAylc!3e+`8>au z5+KXuS=^-DuY^MtNAh~3GefET7^Rn(x*-H;@nX=AE~vM~q~KC1CU0dU@P2Hn8I<_s zDly&-`Zu(EX8%Wr9P+{b7jy&O|HH;Snd)zUkh$A(?tx3ssP7WTH5IFD-tD+omB}CLG3smadG<+5&i|6<`m1o(02KF;J5BVdQ&(4^2TBQbH%{{Rkd_(PhP4ry|`G?zz$I1 z`+PN?K@mg2@ML71&bNfIa8*eoD3=OB^+O>d#u|z1&e$6VUTk^|?5ot0PkXB-Jl?kW#9V2AVlXHS$aK;J%m6z~4sISm|sx8stD?R%yAIcF>AFr9K%Y;>EMUArOU9krQ!Qt}k9C=%p4O`4G9}xT4qpCXr#rg5n1;?*zdaN6zQ@RU4!sh8C)i{oa zK(d%Bl4Ab?fTw%_CkQ;I&fMR#c!Ky<6FV%Ug^|w^DL@sG)r(|45%U7H^-%<91*$Pc zJj;I)N3iMTmRMj7Rs(tB1=A>W4~Ry+pi2p5ZEpA~d1b@;+W!omf&#D` z0g&mziRlPS48!cH&Bx&stUNR_B;_MCD&U82%k4CuI78J9C zbUNbS00im&M{GisPq1K7D?YGLlF_E&j44h8c|o3DMYS%CqxcKmD_idDz5mAQ#N3cF z5wd2)=IK|($jIL%;#rG_;VZ0_(VQk*EH#!&Ip7@4WFr*d3D}rP;^{p7O4$1hir zqGR(=KiLVVpz0=#=Z}}7@Lce)9uO~BVzJKSv2&d;d_IU!E>#MOvl^m$0lR=cNNz=| z_PQr8JBV50IsE`1xtQVrPwtC-M$9HQ&zK;|!yi~9Qh!=kh*l$%AT+nQ!@-;=>tI^~ z=n$r!6vauA<-B3uE@4skVdp|q5u)8;Dfwk7bV{fTI(zk7{qi-7hXyF9G-c%kT)y$7 z>tpP2ie&Mm>*S-?^USiz->#tJFS`**W$r5!6@yzOlJk?n169gchOeNrJRmzDLmnMb zD@!>CRIj_HLl#WpjXRb-{O4?xJPbi1&6#68p^$t9aL2V?a$unfrz@PJY+ zkq+Q(=Nq$9>1BFvuAFx1ECYL2c8@YpyT5kan6T?4yo*ACFGxCOD4!SJ27N-_%$wP= zYugh-o}kT)bMWI3t{4Dc`bY#I>bW(a{r(r!vT z(QRy%eU)TTP+Gcqrb#Q&XJ(1R0i39Bu!bqFL34>BQsLgR|L%1NW3(mpfrB`$BT`;X z^y`lgPNhk;eN~Vqc>vcgvvuXZZnG&!!}@<1q>&UFZi}g=PNAa1H$Qv;5eJv*5{`KX zRyiwACem@YSZ5j+H#nF(>7#6Tak-S(ojBnH7&SPC>C^Lt7Kc^X1G7{dnG$VUI00u; z@K!}&<#T69Qre*-pWF6AWr>h?|L%LW9~Pd2mUkn5s|dl1#B)JgK`6Pg(N+;zt`?re zib*fGGCdt;ri&*(9nzw3>Vj1=XL(x7edRBH_y>H6=Ty^~xV(QiR?_u8w&Obw--|`i z2;1iIh{$%MgiFrjjk)&r#mA54z($DflmXpmZ=-uFEZhCoJN3+YGS!~3yo^ba$x>$5 zq=t-5XM8-J0>8@JVqCze!qwtH({1|&9gwTrBSi+G>KUV_B*ZEm9Dd~AEFYYS$b3Xu z9Ij zr~sjoW1aE^3WigaBzigGzU^JQ0U^$8JnYWB?pM%9YLGDQnjq-ne3hPjI5EM3(nu*p z&dKG$vFgnX=6ndbBo8Hovqc*%pZ)U`9Jss@@b+frK78mMI*-7+94i7W-N<10@Ftko zNR!x)#nT5xP=A^@E^}4{ct$i51EIB(?3J&+de8c#GvpCIW+s^^QIr0+{ zPduk%rsSQ7g5em7q5|;|C2h)))R1mzx*ccEftS;+M4^a97G6^E5lA#|=y`YD`!CaZ zx8H5EOt+}{6igVmA&QUa%nPDowv8$T_u664Cf+jZN1*hhcL`*ijhBl0z?8g*IQHyG zjr+YFhrQ&QKk1A(CIc?A6oiyMo?Bj<`8}tWwk)VcX3UnWB$5MDd1E?%_+z)rX#=sC z=MIYG@@%iVWtToBx%)s(jI)d!mg9rF2fJR3$>(`w$vk34i!G9a6`&eCKN`vBxTTlB z$>K5|?=J833~hPqpVcKmHhX;BqT%@cQ@H&V@ z%-{j+{p-2gMgfW%U%*6l7XeR>Q~Y6Du0{u z;7>WA9b=j7gCa24v_mYdQJaHS&pO;C?^ef@wO05(N}gO)f6j1o$Z(Dt+r*5pjo)K&eNk< zP4QQ#!Gskze}3poIujoN1MGQ+Lhy3Qn5T-@b)M}`JB~D~vl7bn{(QteE+IUvYsT9v zyRC$K$4n3>2gC+wgmbf`D{&hcQ%XUIKHU zhc{)AU3c>XXB*MR4!A;@q}Nl!DJ$FV+nwnQK9m%*PAC*>+3x&RgE4leq>bAG+;f7v zKNs$ks}dlDJ4ze?p*wIl2ZxZeMJzu(-08qmo`SX6XbrQamVD z>FhFkN6%>El#Jsoqmh;-3?Li0hFNEd!zT8L3$Q1_zN@QrvQqEr2gj!V@>>8i+8>wx zkydyEK#aqB?IEAsdlT^X9XyoI9{2?m`!3*g^_b_*e5f}@C{Czu(wr`AN(M_zZ{(i7 zrN<_QFk!UcXB>=wVk7S2iw`!$8;Og0sKE`r6E z{X!5Ixr-1uUN9mDmF~?;vDjsAiu>rg-IxmsrZKNlBXan^e7Vgxp9Mk=UJIxTD5s}o z!7ewtv2KuNN`SX`QVEeHDY-vq_rQvck@q(7@0>d-=#=hWIgV{>fESLVg(}&pIfOyw zQy$h%0jt%F^_sCk`#^OTneJE1UIWp-ib5G)9ZOU*XgeGG^5E^V->bcG)*fpc6)G{} z{+wBKlHs@IW(H-yl2!%)it&_xyrHv>Y&rhyp9pf4HkD*La{6>PQHElJ0;KnbUEF z581DmK^t)dx>3~d@m@#u1 z3l(9!k(fc77D=>NCUbu_>GFTdj5{9v;ovWrH9x{)Ynt6#0=wf|(|fu|O|Q48h8y3Z z=s`?(ejU9_woI9$1Y$O=RrFhomVFfGobTBJg@GJG70IjmG9)P1SaBZ28b$093FTQ` zE0=7GG>SvENd>9z;z4J(t^yv`58my8pZY@%T%yIqjY^hW#LYO4a)Z_{&+)W1Clj6x z)2vdaQ?#5NmMK0l@h;e-O6X)N2mDEWGbo+ZnTJJSdwG^=X z{y%1PsYg{K643ZSJtVs6b8Tuq|>r!xM-v$bs{>(u9iu;)n@~;YPuH7ITFqkRU;tr;}d~_x-^~VMY zL_0yY#cn3Yyy(Mr)3?Iu;Jrc()Swnnc<#iB32;ezP0Giltz3li?P>X*hK0X^@OEuI z^!l8unv_9Q)Hl@SED6xvCN(j62I0j1b^-@;c)wmV5@WZ+A5TM;;?p=#B%4Y zrPqUTDycx~OlJ+UI{l#q*WAw!48p{#8xxId4=I$?l%KE!usJ8TKA!j_I8Z)2pRw48 zBJx%}dvDUzoWc3eWWxZ+19H?PGnvj4!N2oBrR<`p921x5yDN^32Dea*5teUGt2y0t zxBaL^=%*Tqk=l5PX?@grY(4D)ye-Xl?XTWd1Vas=ziDw!;B`>^bX?YzCq{?(&6DG4-a?djDJR1c9~s0b+bn~88K z%#hoxPuzMC$~*oA1fs(rC6F`5#OrjoNW!?$soAb?ZGF#SgevdAk;Kx{(jO26X#1&1 ztCv;1PJhdY-+Wa*1ZWr%wN$DK{fc3V7Ue74lmD$WjF}S)^+asxr3u9Lpx9`-6K_n! zfII!y&CrjwO={FIMDuGT1!NCrsScBqHR$r#dt%#XDcwJkudjxGxno~Vb9#}ZK>~MZ zHtu*4F$u#R@%wuC6h$3H7{bY1ikZgTslLbTRILb~K1PM~IkN~;kRiMJ8BzbQmCjVj G?*9P~{yIhg literal 0 HcmV?d00001 diff --git a/tests/regression/ba-issues/running_config.json b/tests/regression/ba-issues/running_config.json index 7ec213e4d..b7e35cad0 100644 --- a/tests/regression/ba-issues/running_config.json +++ b/tests/regression/ba-issues/running_config.json @@ -1674,6 +1674,38 @@ "stdout content": "Hello from Kotlin via WASI\nCurrent 'realtime' timestamp is:", "description": "no 'type mismatch: expect (ref null ht) but got other1 unknown type'" } + }, + { + "deprecated": false, + "ids": [ + 3467 + ], + "runtime": "iwasm-default-wasi-disabled", + "file": "tt_unreachable.wasm", + "mode": "fast-interp", + "options": "--heap-size=0 -f to_test", + "argument": "", + "expected return": { + "ret code": 1, + "stdout content": "Exception: unreachable", + "description": "no '-1.861157e+19:f32'" + } + }, + { + "deprecated": false, + "ids": [ + 3468 + ], + "runtime": "iwasm-default-wasi-disabled", + "file": "i64.add.wasm", + "mode": "fast-interp", + "options": "--heap-size=0 -f to_test", + "argument": "", + "expected return": { + "ret code": 255, + "stdout content": "WASM module load failed: unknown type", + "description": "no '0x0:i64'" + } } ] } From f635ab96556227670232a980e9a9b1b9df6a5842 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 31 May 2024 12:11:11 +0800 Subject: [PATCH 08/23] Enable building static library on Android platform (#3488) ps. https://github.com/bytecodealliance/wasm-micro-runtime/issues/3486 --- product-mini/platforms/android/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/product-mini/platforms/android/CMakeLists.txt b/product-mini/platforms/android/CMakeLists.txt index db60e8649..5c0525917 100644 --- a/product-mini/platforms/android/CMakeLists.txt +++ b/product-mini/platforms/android/CMakeLists.txt @@ -105,6 +105,8 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") From ab4e17b701e1a449492704d771902a4a48a1c181 Mon Sep 17 00:00:00 2001 From: TianlongLiang <111852609+TianlongLiang@users.noreply.github.com> Date: Fri, 31 May 2024 13:07:56 +0800 Subject: [PATCH 09/23] Modify logging for windows exception handler and remove unused function (#3489) ps. https://github.com/bytecodealliance/wasm-micro-runtime/issues/3416 https://github.com/bytecodealliance/wasm-micro-runtime/issues/3400 --- core/iwasm/common/gc/gc_type.c | 6 ------ core/iwasm/common/wasm_runtime_common.c | 10 ++++++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/core/iwasm/common/gc/gc_type.c b/core/iwasm/common/gc/gc_type.c index 5ade1cb27..c9e6d206e 100644 --- a/core/iwasm/common/gc/gc_type.c +++ b/core/iwasm/common/gc/gc_type.c @@ -846,12 +846,6 @@ wasm_is_reftype_supers_of_func(uint8 type) return (type == REF_TYPE_FUNCREF) ? true : false; } -inline static bool -wasm_is_reftype_supers_of_extern(uint8 type) -{ - return (type == REF_TYPE_EXTERNREF) ? true : false; -} - #if WASM_ENABLE_STRINGREF != 0 inline static bool wasm_is_reftype_supers_of_string(uint8 type) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 6f2508618..3b08d3ec0 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -384,12 +384,14 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info) return ret; } #endif + else { + LOG_WARNING("Unhandled exception thrown: exception code: 0x%lx, " + "exception address: %p, exception information: %p\n", + ExceptionRecord->ExceptionCode, + ExceptionRecord->ExceptionAddress, sig_addr); + } } - LOG_ERROR("Unhandled exception thrown: exception code: 0x%lx, " - "exception address: %p, exception information: %p\n", - ExceptionRecord->ExceptionCode, ExceptionRecord->ExceptionAddress, - sig_addr); return EXCEPTION_CONTINUE_SEARCH; } #endif /* end of BH_PLATFORM_WINDOWS */ From 082cfa1c4f8b826f7e22f8e81b2fe76224a3d7bf Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 31 May 2024 15:39:23 +0800 Subject: [PATCH 10/23] Correct nuttx repo names (#3484) The nuttx repo had changed from https://github.com/apache/incubator-nuttx to https://github.com/apache/nuttx. --- .github/workflows/compilation_on_nuttx.yml | 4 ++-- .github/workflows/spec_test_on_nuttx.yml | 4 ++-- ATTRIBUTIONS.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/compilation_on_nuttx.yml b/.github/workflows/compilation_on_nuttx.yml index 5ff2d181c..09bdfd324 100644 --- a/.github/workflows/compilation_on_nuttx.yml +++ b/.github/workflows/compilation_on_nuttx.yml @@ -85,14 +85,14 @@ jobs: - name: Checkout NuttX uses: actions/checkout@v4 with: - repository: apache/incubator-nuttx + repository: apache/nuttx ref: releases/12.4 path: nuttx - name: Checkout NuttX Apps uses: actions/checkout@v4 with: - repository: apache/incubator-nuttx-apps + repository: apache/nuttx-apps ref: releases/12.4 path: apps diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 1dbeb8348..4976cab86 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -112,14 +112,14 @@ jobs: - name: Checkout NuttX uses: actions/checkout@v4 with: - repository: apache/incubator-nuttx + repository: apache/nuttx ref: releases/12.4 path: nuttx - name: Checkout NuttX Apps uses: actions/checkout@v4 with: - repository: apache/incubator-nuttx-apps + repository: apache/nuttx-apps ref: releases/12.4 path: apps diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index 2c83d6674..3a4afa0d2 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -35,7 +35,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the | uvwasi | unspecified | v0.0.12 | https://github.com/nodejs/uvwasi | | | asmjit | unspecified | unspecified | https://github.com/asmjit/asmjit | | | zydis | unspecified | e14a07895136182a5b53e181eec3b1c6e0b434de | https://github.com/zyantific/zydis | | -| NuttX ELF headers | 72313301e23f9c2de969fb64b9a0f67bb4c284df | 10.3.0 | https://github.com/apache/incubator-nuttx | | +| NuttX ELF headers | 72313301e23f9c2de969fb64b9a0f67bb4c284df | 10.3.0 | https://github.com/apache/nuttx | | | Dhrystone | 2.1 | 2.1 | https://fossies.org/linux/privat/old/ | | ## Licenses From 0a80cc4e94de6b4c11242a8e49e31a8167550460 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 3 Jun 2024 19:48:11 +0800 Subject: [PATCH 11/23] Fix wasm loader check data segment count (#3492) When datacount section exists, loader will check whether the data count read from data segment section is same with the data count read from datacount section, but the value of latter can be 0, loader should not skip the check when the latter is 0. This fixes #3491. And fix handle_name_section return value not checked issue and early return true issue after handle_name_section. And also add the failed case in #3491 to ba-issues. --- core/iwasm/interpreter/wasm_loader.c | 25 +++++++++++++----- core/iwasm/interpreter/wasm_mini_loader.c | 23 ++++++++++++---- .../nop_0LM_592_17171016522810388.wasm | Bin 0 -> 514 bytes .../regression/ba-issues/running_config.json | 18 ++++++++++++- 4 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 tests/regression/ba-issues/issues/issue-3491/nop_0LM_592_17171016522810388.wasm diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index b5185b928..d61907e43 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -4716,8 +4716,12 @@ fail: static bool load_data_segment_section(const uint8 *buf, const uint8 *buf_end, - WASMModule *module, bool clone_data_seg, - char *error_buf, uint32 error_buf_size) + WASMModule *module, +#if WASM_ENABLE_BULK_MEMORY != 0 + bool has_datacount_section, +#endif + bool clone_data_seg, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; uint32 data_seg_count, i, mem_index, data_seg_len; @@ -4733,8 +4737,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, read_leb_uint32(p, p_end, data_seg_count); #if WASM_ENABLE_BULK_MEMORY != 0 - if ((module->data_seg_count1 != 0) - && (data_seg_count != module->data_seg_count1)) { + if (has_datacount_section && data_seg_count != module->data_seg_count1) { set_error_buf(error_buf, error_buf_size, "data count and data section have inconsistent lengths"); return false; @@ -5242,10 +5245,11 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module->name_section_buf = buf; module->name_section_buf_end = buf_end; p += name_len; - handle_name_section(p, p_end, module, is_load_from_file_buf, error_buf, - error_buf_size); + if (!handle_name_section(p, p_end, module, is_load_from_file_buf, + error_buf, error_buf_size)) { + return false; + } LOG_VERBOSE("Load custom name section success."); - return true; } #endif @@ -5789,6 +5793,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, uint8 malloc_free_io_type = VALUE_TYPE_I32; bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable; bool clone_data_seg = is_load_from_file_buf && wasm_binary_freeable; +#if WASM_ENABLE_BULK_MEMORY != 0 + bool has_datacount_section = false; +#endif /* Find code and function sections if have */ while (section) { @@ -5881,6 +5888,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, break; case SECTION_TYPE_DATA: if (!load_data_segment_section(buf, buf_end, module, +#if WASM_ENABLE_BULK_MEMORY != 0 + has_datacount_section, +#endif clone_data_seg, error_buf, error_buf_size)) return false; @@ -5890,6 +5900,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (!load_datacount_section(buf, buf_end, module, error_buf, error_buf_size)) return false; + has_datacount_section = true; break; #endif #if WASM_ENABLE_STRINGREF != 0 diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 15e559250..96d7b5ed0 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -1740,8 +1740,12 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, static bool load_data_segment_section(const uint8 *buf, const uint8 *buf_end, - WASMModule *module, bool clone_data_seg, - char *error_buf, uint32 error_buf_size) + WASMModule *module, +#if WASM_ENABLE_BULK_MEMORY != 0 + bool has_datacount_section, +#endif + bool clone_data_seg, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; uint32 data_seg_count, i, mem_index, data_seg_len; @@ -1757,7 +1761,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, read_leb_uint32(p, p_end, data_seg_count); #if WASM_ENABLE_BULK_MEMORY != 0 - bh_assert(module->data_seg_count1 == 0 + bh_assert(!has_datacount_section || data_seg_count == module->data_seg_count1); #endif @@ -2029,8 +2033,10 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 if (name_len == 4 && memcmp(p, "name", 4) == 0) { p += name_len; - handle_name_section(p, p_end, module, is_load_from_file_buf, error_buf, - error_buf_size); + if (!handle_name_section(p, p_end, module, is_load_from_file_buf, + error_buf, error_buf_size)) { + return false; + } } #endif LOG_VERBOSE("Load custom section success.\n"); @@ -2579,6 +2585,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, uint8 malloc_free_io_type = VALUE_TYPE_I32; bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable; bool clone_data_seg = is_load_from_file_buf && wasm_binary_freeable; +#if WASM_ENABLE_BULK_MEMORY != 0 + bool has_datacount_section = false; +#endif /* Find code and function sections if have */ while (section) { @@ -2660,6 +2669,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, break; case SECTION_TYPE_DATA: if (!load_data_segment_section(buf, buf_end, module, +#if WASM_ENABLE_BULK_MEMORY != 0 + has_datacount_section, +#endif clone_data_seg, error_buf, error_buf_size)) return false; @@ -2669,6 +2681,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (!load_datacount_section(buf, buf_end, module, error_buf, error_buf_size)) return false; + has_datacount_section = true; break; #endif default: diff --git a/tests/regression/ba-issues/issues/issue-3491/nop_0LM_592_17171016522810388.wasm b/tests/regression/ba-issues/issues/issue-3491/nop_0LM_592_17171016522810388.wasm new file mode 100644 index 0000000000000000000000000000000000000000..5de7a3ce55eed41ae8f41d832d70aa3be93781aa GIT binary patch literal 514 zcmWN@yRMU9007|sFFifUsTvm(V;oMR4^W^`IvGl750sW(xD|&}3jF2L0xgtVtga5u zCMFIpzJjhkgKyyA=0kXfFZqC#9v}b!KEXBsY~Tf6HlXq0J=TDYW)mi$b%jBIwI0KF zaQIaH`6Ipk_ojXQve~*%GwYNAaGk~XnVUWg8V@c2Jc8in1$++R@C*6p@9($Ietmrf zzP$$QXKe8Os@?vCLHH5Fg<{z2vPL;Y`l% zW-(>SP8aogLSUpxhg7DJ?w+Taowjvr zX^clRt;gHLu@judea6cEfijX+!gQxcs^aGgw@971e{$7wu^p&&N7zmBQ;*`ep5%6D zt}NE19GZm^3c4P|KAU*^*obgO%Z_L{QxswxpCZ1($&uhWca*nABW|qCmyunCxrJnW zXJ{Ei)a5CX{Zc@MAy!=pdCXK=@5n)Yc5PZi_IbHj1jNE}H8!?zx3VXU!kI)&tyqKW zpUVVa*#+TlBU?wK%+%&+lCo1rk7&{AQ-_GB20rfjoOc|VW+5bX&ihEA#Gu<*>4`d@ NlzKW~5HBrr^*^^qps4@= literal 0 HcmV?d00001 diff --git a/tests/regression/ba-issues/running_config.json b/tests/regression/ba-issues/running_config.json index b7e35cad0..e50b108bd 100644 --- a/tests/regression/ba-issues/running_config.json +++ b/tests/regression/ba-issues/running_config.json @@ -912,7 +912,7 @@ "options": "", "argument": "", "expected return": { - "ret code": 57, + "ret code": 8, "stdout content": "", "description": "sock_shutdown on a non-socket file descriptor should fail with 57 notsock" } @@ -1706,6 +1706,22 @@ "stdout content": "WASM module load failed: unknown type", "description": "no '0x0:i64'" } + }, + { + "deprecated": false, + "ids": [ + 3491 + ], + "runtime": "iwasm-default-wasi-disabled", + "file": "nop_0LM_592_17171016522810388.wasm", + "mode": "fast-interp", + "options": "", + "argument": "", + "expected return": { + "ret code": 255, + "stdout content": "WASM module load failed: data count and data section have inconsistent lengths", + "description": "Check data segment count" + } } ] } From 380cd7b0e79ab239cfba3fff2180f4868a101164 Mon Sep 17 00:00:00 2001 From: "Zhang, Yi" Date: Tue, 4 Jun 2024 11:24:27 +0800 Subject: [PATCH 12/23] Add unit test suites (#3490) --- tests/unit/CMakeLists.txt | 69 +- tests/unit/aot-stack-frame/CMakeLists.txt | 55 + .../aot-stack-frame/aot_stack_frame_test.cc | 288 ++++ .../aot-stack-frame/wasm-apps/CMakeLists.txt | 27 + .../unit/aot-stack-frame/wasm-apps/test.wast | 36 + tests/unit/aot/CMakeLists.txt | 59 + tests/unit/aot/aot_test.cc | 1190 ++++++++++++++ tests/unit/common/mock_allocator.h | 89 ++ tests/unit/common/test_helper.h | 325 ++++ tests/unit/compilation/CMakeLists.txt | 72 + tests/unit/compilation/aot_compiler_test.cc | 203 +++ .../compilation/aot_emit_aot_file_test.cc | 104 ++ .../unit/compilation/aot_emit_compare_test.cc | 112 ++ .../unit/compilation/aot_emit_control_test.cc | 196 +++ .../compilation/aot_emit_function_test.cc | 101 ++ .../unit/compilation/aot_emit_memory_test.cc | 335 ++++ .../compilation/aot_emit_numberic_test.cc | 119 ++ .../compilation/aot_emit_parametric_test.cc | 143 ++ tests/unit/compilation/aot_emit_table_test.cc | 105 ++ .../compilation/aot_emit_variable_test.cc | 97 ++ tests/unit/compilation/aot_llvm_test.cc | 305 ++++ tests/unit/compilation/wasm-apps/main.wasm | Bin 0 -> 1217 bytes tests/unit/custom-section/CMakeLists.txt | 65 + .../custom-section/custom_section_test.cc | 161 ++ .../custom-section/wasm-apps/CMakeLists.txt | 14 + tests/unit/custom-section/wasm-apps/app.c | 10 + tests/unit/gc/CMakeLists.txt | 51 + tests/unit/gc/gc_test.cc | 102 ++ tests/unit/gc/wasm-apps/func1.wasm | Bin 0 -> 106 bytes tests/unit/gc/wasm-apps/func1.wast | 35 + tests/unit/gc/wasm-apps/func2.wasm | Bin 0 -> 470 bytes tests/unit/gc/wasm-apps/func2.wast | 78 + tests/unit/gc/wasm-apps/global1.wasm | Bin 0 -> 554 bytes tests/unit/gc/wasm-apps/global1.wast | 91 ++ tests/unit/gc/wasm-apps/struct1.wasm | Bin 0 -> 85 bytes tests/unit/gc/wasm-apps/struct1.wast | 10 + tests/unit/gc/wasm-apps/struct2.wasm | Bin 0 -> 234 bytes tests/unit/gc/wasm-apps/struct2.wast | 33 + tests/unit/gc/wasm-apps/struct3.wasm | Bin 0 -> 118 bytes tests/unit/gc/wasm-apps/struct3.wast | 9 + tests/unit/gc/wasm-apps/table1.wasm | Bin 0 -> 560 bytes tests/unit/gc/wasm-apps/table1.wast | 108 ++ tests/unit/gc/wasm-apps/test1.wasm | Bin 0 -> 647 bytes tests/unit/gc/wasm-apps/test1.wast | 117 ++ tests/unit/gc/wasm-apps/test2.wasm | Bin 0 -> 626 bytes tests/unit/gc/wasm-apps/test2.wast | 104 ++ tests/unit/gc/wasm-apps/test3.wasm | Bin 0 -> 976 bytes tests/unit/gc/wasm-apps/test3.wast | 146 ++ tests/unit/gc/wasm-apps/test4.wasm | Bin 0 -> 299 bytes tests/unit/gc/wasm-apps/test4.wast | 46 + tests/unit/gc/wasm-apps/test5.wasm | Bin 0 -> 512 bytes tests/unit/gc/wasm-apps/test5.wast | 85 + tests/unit/gc/wasm-apps/test6.wasm | Bin 0 -> 197 bytes tests/unit/gc/wasm-apps/test6.wast | 27 + tests/unit/interpreter/.gitignore | 1 + tests/unit/interpreter/CMakeLists.txt | 42 + tests/unit/interpreter/interpreter_test.cc | 50 + tests/unit/libc-builtin/CMakeLists.txt | 32 + tests/unit/libc-builtin/func_types.h | 170 ++ tests/unit/libc-builtin/libc_builtin_test.cc | 1412 +++++++++++++++++ tests/unit/linear-memory-aot/CMakeLists.txt | 78 + tests/unit/linear-memory-aot/build_aot.sh | 45 + .../linear_memory_aot_test.cc | 361 +++++ .../mem_grow_out_of_bounds_01.wast | 16 + .../mem_grow_out_of_bounds_02.wast | 16 + tests/unit/linear-memory-aot/mem_page_01.wast | 1 + tests/unit/linear-memory-aot/mem_page_02.wast | 1 + tests/unit/linear-memory-aot/mem_page_03.wast | 1 + tests/unit/linear-memory-aot/mem_page_05.wast | 1 + tests/unit/linear-memory-aot/mem_page_07.wast | 1 + tests/unit/linear-memory-aot/mem_page_08.wast | 1 + tests/unit/linear-memory-aot/mem_page_09.wast | 1 + tests/unit/linear-memory-aot/mem_page_10.wast | 1 + tests/unit/linear-memory-aot/mem_page_12.wast | 1 + tests/unit/linear-memory-aot/mem_page_14.wast | 1 + tests/unit/linear-memory-aot/mem_page_16.wast | 1 + tests/unit/linear-memory-aot/mem_page_20.wast | 1 + .../unit/linear-memory-aot/out_of_bounds.wast | 10 + tests/unit/linear-memory-aot/readme | 2 + tests/unit/linear-memory-wasm/CMakeLists.txt | 59 + .../linear_memory_wasm_test.cc | 327 ++++ .../mem_grow_out_of_bounds_01.wast | 16 + .../mem_grow_out_of_bounds_02.wast | 16 + .../unit/linear-memory-wasm/mem_page_01.wast | 1 + .../unit/linear-memory-wasm/mem_page_02.wast | 1 + .../unit/linear-memory-wasm/mem_page_03.wast | 1 + .../unit/linear-memory-wasm/mem_page_04.wast | 1 + .../unit/linear-memory-wasm/mem_page_05.wast | 1 + .../unit/linear-memory-wasm/mem_page_06.wast | 1 + .../unit/linear-memory-wasm/mem_page_07.wast | 1 + .../unit/linear-memory-wasm/mem_page_08.wast | 1 + .../unit/linear-memory-wasm/mem_page_09.wast | 1 + .../unit/linear-memory-wasm/mem_page_10.wast | 1 + .../unit/linear-memory-wasm/mem_page_11.wast | 1 + .../unit/linear-memory-wasm/mem_page_12.wast | 1 + .../unit/linear-memory-wasm/mem_page_13.wast | 1 + .../unit/linear-memory-wasm/mem_page_14.wast | 1 + .../unit/linear-memory-wasm/mem_page_15.wast | 1 + .../unit/linear-memory-wasm/mem_page_16.wast | 1 + .../unit/linear-memory-wasm/mem_page_17.wast | 1 + .../unit/linear-memory-wasm/mem_page_18.wast | 1 + .../unit/linear-memory-wasm/mem_page_19.wast | 1 + .../unit/linear-memory-wasm/mem_page_20.wast | 1 + .../linear-memory-wasm/out_of_bounds.wast | 10 + tests/unit/linear-memory-wasm/readme | 2 + .../wasm_files/mem_grow_out_of_bounds_01.wasm | Bin 0 -> 70 bytes .../wasm_files/mem_grow_out_of_bounds_02.wasm | Bin 0 -> 70 bytes .../wasm_files/out_of_bounds.wasm | Bin 0 -> 46 bytes .../wasm_files/wasm_app_heap_02.wasm | Bin 0 -> 15 bytes .../wasm_files/wasm_mem_page_01.wasm | Bin 0 -> 13 bytes .../wasm_files/wasm_mem_page_02.wasm | Bin 0 -> 13 bytes .../wasm_files/wasm_mem_page_03.wasm | Bin 0 -> 15 bytes .../wasm_files/wasm_mem_page_04.wasm | Bin 0 -> 15 bytes .../wasm_files/wasm_mem_page_05.wasm | Bin 0 -> 14 bytes .../wasm_files/wasm_mem_page_06.wasm | Bin 0 -> 14 bytes .../wasm_files/wasm_mem_page_07.wasm | Bin 0 -> 14 bytes .../wasm_files/wasm_mem_page_08.wasm | Bin 0 -> 14 bytes .../wasm_files/wasm_mem_page_09.wasm | Bin 0 -> 15 bytes .../wasm_files/wasm_mem_page_10.wasm | Bin 0 -> 16 bytes .../wasm_files/wasm_mem_page_11.wasm | Bin 0 -> 16 bytes .../wasm_files/wasm_mem_page_12.wasm | Bin 0 -> 16 bytes .../wasm_files/wasm_mem_page_13.wasm | Bin 0 -> 16 bytes .../wasm_files/wasm_mem_page_14.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_15.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_16.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_17.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_18.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_19.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_20.wasm | Bin 0 -> 15 bytes tests/unit/linux-perf/CMakeLists.txt | 46 + tests/unit/linux-perf/test_sort_func_ptrs.cc | 110 ++ tests/unit/memory64/CMakeLists.txt | 67 + tests/unit/memory64/memory64_atomic_test.cc | 355 +++++ tests/unit/memory64/memory64_common.h | 63 + tests/unit/memory64/memory64_test.cc | 235 +++ tests/unit/memory64/wasm-apps/8GB_memory.wasm | Bin 0 -> 249 bytes tests/unit/memory64/wasm-apps/8GB_memory.wat | 53 + .../memory64/wasm-apps/atomic_opcodes.wasm | Bin 0 -> 820 bytes .../memory64/wasm-apps/atomic_opcodes.wat | 120 ++ tests/unit/memory64/wasm-apps/mem64.c | 56 + tests/unit/memory64/wasm-apps/mem64.wasm | Bin 0 -> 1992 bytes .../memory64/wasm-apps/page_exceed_u32.wasm | Bin 0 -> 22 bytes .../memory64/wasm-apps/page_exceed_u32.wat | 4 + .../memory64/wasm-apps/page_exceed_u32_2.wasm | Bin 0 -> 21 bytes .../memory64/wasm-apps/page_exceed_u32_2.wat | 4 + .../unit/memory64/wasm-apps/page_u32_max.wasm | Bin 0 -> 22 bytes .../unit/memory64/wasm-apps/page_u32_max.wat | 4 + tests/unit/running-modes/CMakeLists.txt | 56 + .../running-modes/wasm-apps/CMakeLists.txt | 49 + tests/unit/running-modes/wasm-apps/hello.c | 31 + tests/unit/running-modes/wasm-apps/mytest.c | 53 + .../running-modes/wasm_running_modes_test.cc | 308 ++++ tests/unit/runtime-common/CMakeLists.txt | 73 + tests/unit/runtime-common/build_aot.sh | 31 + tests/unit/runtime-common/wasm-apps/main.aot | Bin 0 -> 1164 bytes tests/unit/runtime-common/wasm-apps/main.wasm | Bin 0 -> 1217 bytes .../unit/runtime-common/wasm_exec_env_test.cc | 45 + .../wasm_runtime_common_test.cc | 682 ++++++++ .../runtime-common/wasm_runtime_init_test.cc | 162 ++ tests/unit/shared-utils/CMakeLists.txt | 30 + tests/unit/shared-utils/bh_assert_test.cc | 38 + tests/unit/shared-utils/bh_common_test.cc | 96 ++ tests/unit/shared-utils/bh_hashmap_test.cc | 362 +++++ tests/unit/shared-utils/bh_list_test.cc | 137 ++ tests/unit/shared-utils/bh_log_test.cc | 95 ++ tests/unit/shared-utils/bh_queue_test.cc | 278 ++++ tests/unit/shared-utils/bh_vector_test.cc | 268 ++++ tests/unit/shared-utils/shared_utils_test.cc | 33 + tests/unit/tid-allocator/CMakeLists.txt | 39 + tests/unit/{ => tid-allocator}/main.cpp | 1 + tests/unit/unit_common.cmake | 105 ++ tests/unit/wasm-c-api/CMakeLists.txt | 62 + tests/unit/wasm-c-api/basic.cc | 191 +++ tests/unit/wasm-c-api/run.sh | 21 + tests/unit/wasm-vm/.gitignore | 2 + tests/unit/wasm-vm/CMakeLists.txt | 53 + tests/unit/wasm-vm/wasm-apps/app1.wast | 106 ++ tests/unit/wasm-vm/wasm-apps/app1/main.c | 56 + tests/unit/wasm-vm/wasm-apps/app1_wasm.h | 54 + tests/unit/wasm-vm/wasm-apps/app2.wast | 311 ++++ tests/unit/wasm-vm/wasm-apps/app2/main.c | 140 ++ tests/unit/wasm-vm/wasm-apps/app2_wasm.h | 104 ++ tests/unit/wasm-vm/wasm-apps/app3.wast | 63 + tests/unit/wasm-vm/wasm-apps/app3/main.c | 32 + tests/unit/wasm-vm/wasm-apps/app3_wasm.h | 42 + tests/unit/wasm-vm/wasm-apps/app4/m1.wasm | Bin 0 -> 103 bytes tests/unit/wasm-vm/wasm-apps/app4/m1.wat | 14 + tests/unit/wasm-vm/wasm-apps/app4/m2.wasm | Bin 0 -> 122 bytes tests/unit/wasm-vm/wasm-apps/app4/m2.wat | 24 + tests/unit/wasm-vm/wasm-apps/app4/m3.wasm | Bin 0 -> 86 bytes tests/unit/wasm-vm/wasm-apps/app4/m3.wat | 7 + tests/unit/wasm-vm/wasm-apps/binarydump | Bin 0 -> 13448 bytes tests/unit/wasm-vm/wasm-apps/build.sh | 32 + tests/unit/wasm-vm/wasm_vm.cc | 716 +++++++++ 194 files changed, 14104 insertions(+), 34 deletions(-) create mode 100644 tests/unit/aot-stack-frame/CMakeLists.txt create mode 100644 tests/unit/aot-stack-frame/aot_stack_frame_test.cc create mode 100644 tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt create mode 100644 tests/unit/aot-stack-frame/wasm-apps/test.wast create mode 100644 tests/unit/aot/CMakeLists.txt create mode 100644 tests/unit/aot/aot_test.cc create mode 100644 tests/unit/common/mock_allocator.h create mode 100644 tests/unit/common/test_helper.h create mode 100644 tests/unit/compilation/CMakeLists.txt create mode 100644 tests/unit/compilation/aot_compiler_test.cc create mode 100644 tests/unit/compilation/aot_emit_aot_file_test.cc create mode 100644 tests/unit/compilation/aot_emit_compare_test.cc create mode 100644 tests/unit/compilation/aot_emit_control_test.cc create mode 100644 tests/unit/compilation/aot_emit_function_test.cc create mode 100644 tests/unit/compilation/aot_emit_memory_test.cc create mode 100644 tests/unit/compilation/aot_emit_numberic_test.cc create mode 100644 tests/unit/compilation/aot_emit_parametric_test.cc create mode 100644 tests/unit/compilation/aot_emit_table_test.cc create mode 100644 tests/unit/compilation/aot_emit_variable_test.cc create mode 100644 tests/unit/compilation/aot_llvm_test.cc create mode 100644 tests/unit/compilation/wasm-apps/main.wasm create mode 100644 tests/unit/custom-section/CMakeLists.txt create mode 100644 tests/unit/custom-section/custom_section_test.cc create mode 100644 tests/unit/custom-section/wasm-apps/CMakeLists.txt create mode 100644 tests/unit/custom-section/wasm-apps/app.c create mode 100644 tests/unit/gc/CMakeLists.txt create mode 100644 tests/unit/gc/gc_test.cc create mode 100644 tests/unit/gc/wasm-apps/func1.wasm create mode 100644 tests/unit/gc/wasm-apps/func1.wast create mode 100644 tests/unit/gc/wasm-apps/func2.wasm create mode 100644 tests/unit/gc/wasm-apps/func2.wast create mode 100644 tests/unit/gc/wasm-apps/global1.wasm create mode 100644 tests/unit/gc/wasm-apps/global1.wast create mode 100644 tests/unit/gc/wasm-apps/struct1.wasm create mode 100644 tests/unit/gc/wasm-apps/struct1.wast create mode 100644 tests/unit/gc/wasm-apps/struct2.wasm create mode 100644 tests/unit/gc/wasm-apps/struct2.wast create mode 100644 tests/unit/gc/wasm-apps/struct3.wasm create mode 100644 tests/unit/gc/wasm-apps/struct3.wast create mode 100644 tests/unit/gc/wasm-apps/table1.wasm create mode 100644 tests/unit/gc/wasm-apps/table1.wast create mode 100644 tests/unit/gc/wasm-apps/test1.wasm create mode 100644 tests/unit/gc/wasm-apps/test1.wast create mode 100644 tests/unit/gc/wasm-apps/test2.wasm create mode 100644 tests/unit/gc/wasm-apps/test2.wast create mode 100644 tests/unit/gc/wasm-apps/test3.wasm create mode 100644 tests/unit/gc/wasm-apps/test3.wast create mode 100644 tests/unit/gc/wasm-apps/test4.wasm create mode 100644 tests/unit/gc/wasm-apps/test4.wast create mode 100644 tests/unit/gc/wasm-apps/test5.wasm create mode 100644 tests/unit/gc/wasm-apps/test5.wast create mode 100644 tests/unit/gc/wasm-apps/test6.wasm create mode 100644 tests/unit/gc/wasm-apps/test6.wast create mode 100644 tests/unit/interpreter/.gitignore create mode 100644 tests/unit/interpreter/CMakeLists.txt create mode 100644 tests/unit/interpreter/interpreter_test.cc create mode 100644 tests/unit/libc-builtin/CMakeLists.txt create mode 100644 tests/unit/libc-builtin/func_types.h create mode 100644 tests/unit/libc-builtin/libc_builtin_test.cc create mode 100644 tests/unit/linear-memory-aot/CMakeLists.txt create mode 100755 tests/unit/linear-memory-aot/build_aot.sh create mode 100644 tests/unit/linear-memory-aot/linear_memory_aot_test.cc create mode 100644 tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast create mode 100644 tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_01.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_02.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_03.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_05.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_07.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_08.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_09.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_10.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_12.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_14.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_16.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_20.wast create mode 100644 tests/unit/linear-memory-aot/out_of_bounds.wast create mode 100644 tests/unit/linear-memory-aot/readme create mode 100644 tests/unit/linear-memory-wasm/CMakeLists.txt create mode 100644 tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc create mode 100644 tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast create mode 100644 tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_01.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_02.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_03.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_04.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_05.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_06.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_07.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_08.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_09.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_10.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_11.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_12.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_13.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_14.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_15.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_16.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_17.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_18.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_19.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_20.wast create mode 100644 tests/unit/linear-memory-wasm/out_of_bounds.wast create mode 100644 tests/unit/linear-memory-wasm/readme create mode 100644 tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_01.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_02.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/out_of_bounds.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_app_heap_02.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_01.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_02.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_03.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_04.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_05.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_06.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_07.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_08.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_09.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_10.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_11.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_12.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_13.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_14.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_15.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_16.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_17.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_18.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_19.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_20.wasm create mode 100644 tests/unit/linux-perf/CMakeLists.txt create mode 100644 tests/unit/linux-perf/test_sort_func_ptrs.cc create mode 100644 tests/unit/memory64/CMakeLists.txt create mode 100644 tests/unit/memory64/memory64_atomic_test.cc create mode 100644 tests/unit/memory64/memory64_common.h create mode 100644 tests/unit/memory64/memory64_test.cc create mode 100644 tests/unit/memory64/wasm-apps/8GB_memory.wasm create mode 100644 tests/unit/memory64/wasm-apps/8GB_memory.wat create mode 100644 tests/unit/memory64/wasm-apps/atomic_opcodes.wasm create mode 100644 tests/unit/memory64/wasm-apps/atomic_opcodes.wat create mode 100644 tests/unit/memory64/wasm-apps/mem64.c create mode 100755 tests/unit/memory64/wasm-apps/mem64.wasm create mode 100644 tests/unit/memory64/wasm-apps/page_exceed_u32.wasm create mode 100644 tests/unit/memory64/wasm-apps/page_exceed_u32.wat create mode 100644 tests/unit/memory64/wasm-apps/page_exceed_u32_2.wasm create mode 100644 tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat create mode 100644 tests/unit/memory64/wasm-apps/page_u32_max.wasm create mode 100644 tests/unit/memory64/wasm-apps/page_u32_max.wat create mode 100644 tests/unit/running-modes/CMakeLists.txt create mode 100644 tests/unit/running-modes/wasm-apps/CMakeLists.txt create mode 100644 tests/unit/running-modes/wasm-apps/hello.c create mode 100644 tests/unit/running-modes/wasm-apps/mytest.c create mode 100644 tests/unit/running-modes/wasm_running_modes_test.cc create mode 100644 tests/unit/runtime-common/CMakeLists.txt create mode 100755 tests/unit/runtime-common/build_aot.sh create mode 100644 tests/unit/runtime-common/wasm-apps/main.aot create mode 100644 tests/unit/runtime-common/wasm-apps/main.wasm create mode 100644 tests/unit/runtime-common/wasm_exec_env_test.cc create mode 100644 tests/unit/runtime-common/wasm_runtime_common_test.cc create mode 100644 tests/unit/runtime-common/wasm_runtime_init_test.cc create mode 100644 tests/unit/shared-utils/CMakeLists.txt create mode 100644 tests/unit/shared-utils/bh_assert_test.cc create mode 100644 tests/unit/shared-utils/bh_common_test.cc create mode 100644 tests/unit/shared-utils/bh_hashmap_test.cc create mode 100644 tests/unit/shared-utils/bh_list_test.cc create mode 100644 tests/unit/shared-utils/bh_log_test.cc create mode 100644 tests/unit/shared-utils/bh_queue_test.cc create mode 100644 tests/unit/shared-utils/bh_vector_test.cc create mode 100644 tests/unit/shared-utils/shared_utils_test.cc create mode 100644 tests/unit/tid-allocator/CMakeLists.txt rename tests/unit/{ => tid-allocator}/main.cpp (99%) create mode 100644 tests/unit/unit_common.cmake create mode 100644 tests/unit/wasm-c-api/CMakeLists.txt create mode 100644 tests/unit/wasm-c-api/basic.cc create mode 100755 tests/unit/wasm-c-api/run.sh create mode 100644 tests/unit/wasm-vm/.gitignore create mode 100644 tests/unit/wasm-vm/CMakeLists.txt create mode 100644 tests/unit/wasm-vm/wasm-apps/app1.wast create mode 100644 tests/unit/wasm-vm/wasm-apps/app1/main.c create mode 100644 tests/unit/wasm-vm/wasm-apps/app1_wasm.h create mode 100644 tests/unit/wasm-vm/wasm-apps/app2.wast create mode 100644 tests/unit/wasm-vm/wasm-apps/app2/main.c create mode 100644 tests/unit/wasm-vm/wasm-apps/app2_wasm.h create mode 100644 tests/unit/wasm-vm/wasm-apps/app3.wast create mode 100644 tests/unit/wasm-vm/wasm-apps/app3/main.c create mode 100644 tests/unit/wasm-vm/wasm-apps/app3_wasm.h create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m1.wasm create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m1.wat create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m2.wasm create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m2.wat create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m3.wasm create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m3.wat create mode 100755 tests/unit/wasm-vm/wasm-apps/binarydump create mode 100755 tests/unit/wasm-vm/wasm-apps/build.sh create mode 100644 tests/unit/wasm-vm/wasm_vm.cc diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index a9a7b8776..40c9bb6ae 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,51 +1,52 @@ -# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.14) +cmake_minimum_required(VERSION 2.9) -project (wamr_unit_tests) +project(unit-test) -include (CTest) +SET(CMAKE_BUILD_TYPE Debug) -if (NOT DEFINED WAMR_BUILD_INTERP) - # Enable Interpreter by default - set (WAMR_BUILD_INTERP 1) -endif () +# add_definitions (-m32) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") -if (NOT DEFINED WAMR_BUILD_PLATFORM) - string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) -endif () +if(WAMR_BUILD_TARGET STREQUAL "X86_32") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") +endif() -set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) -include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) -add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Fetch Google test include (FetchContent) FetchContent_Declare ( googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip ) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable (googletest) -include (GoogleTest) +SET(GOOGLETEST_INCLUDED 1) -add_library (wamr_gtest_main main.cpp) -target_link_libraries (wamr_gtest_main PUBLIC gtest vmlib) +include(GoogleTest) +enable_testing() -function (create_wamr_unit_test test_name) - set (sources ${ARGN}) - add_executable (${test_name} ${sources}) - target_link_libraries ( - ${test_name} - wamr_gtest_main - vmlib - ${LLVM_AVAILABLE_LIBS} - ) - gtest_discover_tests (${test_name}) - endfunction () - -if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1) - include (${IWASM_DIR}/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake) -endif () +add_subdirectory(wasm-vm) +add_subdirectory(interpreter) +add_subdirectory(aot) +add_subdirectory(wasm-c-api) +add_subdirectory(libc-builtin) +add_subdirectory(shared-utils) +add_subdirectory(running-modes) +add_subdirectory(runtime-common) +add_subdirectory(custom-section) +add_subdirectory(compilation) +add_subdirectory(linear-memory-wasm) +add_subdirectory(linear-memory-aot) +add_subdirectory(aot-stack-frame) +add_subdirectory(linux-perf) +add_subdirectory(gc) +add_subdirectory(memory64) +add_subdirectory(tid-allocator) diff --git a/tests/unit/aot-stack-frame/CMakeLists.txt b/tests/unit/aot-stack-frame/CMakeLists.txt new file mode 100644 index 000000000..9ff066f08 --- /dev/null +++ b/tests/unit/aot-stack-frame/CMakeLists.txt @@ -0,0 +1,55 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-aot-stack-frame) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_INTERP 0) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_SIMD 1) +set (WAMR_BUILD_REF_TYPES 1) +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_MULTI_MODULE 0) +set (WAMR_DISABLE_HW_BOUND_CHECK 1) +set (WAMR_DISABLE_WRITE_GS_BASE 1) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) +add_definitions (-DAOT_STACK_FRAME_DEBUG) +#add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ) + +# Automatically build wasm-apps for this test +add_subdirectory(wasm-apps) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (aot_stack_frame_test ${unit_test_sources}) + +add_dependencies (aot_stack_frame_test aot-stack-frame-test-wasm) + +target_link_libraries (aot_stack_frame_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +#gtest_discover_tests(aot_stack_frame_test) \ No newline at end of file diff --git a/tests/unit/aot-stack-frame/aot_stack_frame_test.cc b/tests/unit/aot-stack-frame/aot_stack_frame_test.cc new file mode 100644 index 000000000..9bea2b2a0 --- /dev/null +++ b/tests/unit/aot-stack-frame/aot_stack_frame_test.cc @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "wasm_runtime_common.h" +#include "aot_runtime.h" +#include "test_helper.h" + +#ifndef __aligned +#define __aligned(n) +#endif +#include "wasm-apps/test_aot.h" + +typedef struct MyAOTFrame { + uintptr_t func_index; + + /* Instruction pointer: offset to the bytecode array */ + uintptr_t ip_offset; + + /* Operand stack top pointer of the current frame */ + uint32 *sp; + +#if WASM_ENABLE_GC != 0 + /* Frame ref flags (GC only) */ + uint8 *frame_ref; +#endif + + uint32 lp[1]; +} MyAOTFrame; + +class AOTStackFrameTest : public testing::Test +{ + protected: + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + } + + virtual void TearDown() + { + DestroyFrames(); + wasm_runtime_destroy(); + } + + public: + static void DestroyFrames() + { + if (my_frames) { + for (uint32 i = 0; i < my_frame_num; i++) { + if (my_frames[i]) + wasm_runtime_free(my_frames[i]); + } + wasm_runtime_free(my_frames); + my_frames = NULL; + my_frame_num = 0; + } + } + + public: + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_function_inst_t func_inst = NULL; + wasm_exec_env_t exec_env = NULL; + static MyAOTFrame **my_frames; + static uint32 my_frame_num; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + unsigned char test_aot_buf[16 * 1024]; + unsigned argv[8]; +}; + +MyAOTFrame **AOTStackFrameTest::my_frames = NULL; +uint32 AOTStackFrameTest::my_frame_num = 0; + +extern "C" { + +typedef void (*stack_frame_callback_t)(struct WASMExecEnv *exec_env); + +void +aot_set_stack_frame_callback(stack_frame_callback_t callback); + +void +aot_stack_frame_cb(struct WASMExecEnv *exec_env) +{ + AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; + AOTModule *module = (AOTModule *)module_inst->module; + AOTFrame *frame = (AOTFrame *)exec_env->cur_frame; + MyAOTFrame *my_frame, **my_frames; + uint32 all_cell_num, max_local_cell_num, max_stack_cell_num; + uint32 frame_size_old, frame_size, i, frame_num = 0, aot_func_idx; + + AOTStackFrameTest::DestroyFrames(); + + while (frame) { + frame_num++; + frame = frame->prev_frame; + } + + my_frames = + (MyAOTFrame **)wasm_runtime_malloc(sizeof(MyAOTFrame *) * frame_num); + bh_assert(my_frames); + + frame = (AOTFrame *)exec_env->cur_frame; + for (i = 0; i < frame_num; i++) { + aot_func_idx = frame->func_index; + max_local_cell_num = module->max_local_cell_nums[aot_func_idx]; + max_stack_cell_num = module->max_stack_cell_nums[aot_func_idx]; + all_cell_num = max_local_cell_num + max_stack_cell_num; + + frame_size_old = (uint32)offsetof(AOTFrame, lp) + all_cell_num * 4; + frame_size = (uint32)offsetof(MyAOTFrame, lp) + all_cell_num * 4; + + my_frames[frame_num - 1 - i] = my_frame = + (MyAOTFrame *)wasm_runtime_malloc(frame_size); + + my_frame->func_index = aot_func_idx; + my_frame->ip_offset = frame->ip_offset; + my_frame->sp = my_frame->lp + (frame->sp - frame->lp); +#if WASM_ENABLE_GC != 0 + my_frame->frame_ref = + (uint8 *)my_frame->lp + (frame->frame_ref - (uint8 *)frame->lp); +#endif + + bh_memcpy_s(my_frame->lp, all_cell_num * 4, frame->lp, + all_cell_num * 4); + + frame = frame->prev_frame; + } + + AOTStackFrameTest::my_frames = my_frames; + AOTStackFrameTest::my_frame_num = frame_num; +} +} + +TEST_F(AOTStackFrameTest, test1) +{ + MyAOTFrame *frame, **frames; + uint32 frame_num; + + aot_set_stack_frame_callback(aot_stack_frame_cb); + + bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot)); + + module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "test1"); + ASSERT_TRUE(func_inst != NULL); + + argv[0] = 33; + argv[1] = 44; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst)); + + frames = AOTStackFrameTest::my_frames; + frame_num = AOTStackFrameTest::my_frame_num; + + ASSERT_TRUE(frames != NULL); + ASSERT_TRUE(frame_num == 1); + + ASSERT_TRUE(frames[0]->lp[0] == 33); + ASSERT_TRUE(frames[0]->lp[1] == 44); + ASSERT_TRUE(frames[0]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL); + ASSERT_TRUE(*(float *)(frames[0]->lp + 5) == 5566.7788f); + ASSERT_TRUE(*(double *)(frames[0]->lp + 6) == 99887766.55443322); + + wasm_runtime_destroy_exec_env(exec_env); + exec_env = NULL; + + wasm_runtime_deinstantiate(module_inst); + module_inst = NULL; + + wasm_runtime_unload(module); + module = NULL; +} + +TEST_F(AOTStackFrameTest, test2) +{ + MyAOTFrame *frame, **frames; + uint32 frame_num; + + aot_set_stack_frame_callback(aot_stack_frame_cb); + + bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot)); + + module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "test2"); + ASSERT_TRUE(func_inst != NULL); + + argv[0] = 1234; + argv[1] = 5678; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst)); + + frames = AOTStackFrameTest::my_frames; + frame_num = AOTStackFrameTest::my_frame_num; + + ASSERT_TRUE(frames != NULL); + ASSERT_TRUE(frame_num == 1); + + ASSERT_TRUE(frames[0]->lp[0] == 1234); + ASSERT_TRUE(frames[0]->lp[1] == 5678); + ASSERT_TRUE(frames[0]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL); + ASSERT_TRUE(*(float *)(frames[0]->lp + 5) == 5566.7788f); + ASSERT_TRUE(*(double *)(frames[0]->lp + 6) == 99887766.55443322); + ASSERT_TRUE(frames[0]->lp[8] == 0x1234); + ASSERT_TRUE(frames[0]->lp[9] == 0x5678); +} + +TEST_F(AOTStackFrameTest, test3) +{ + MyAOTFrame *frame, **frames; + uint32 frame_num; + + aot_set_stack_frame_callback(aot_stack_frame_cb); + + bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot)); + + module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "test3"); + ASSERT_TRUE(func_inst != NULL); + + argv[0] = 1234; + argv[1] = 5678; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst)); + + frames = AOTStackFrameTest::my_frames; + frame_num = AOTStackFrameTest::my_frame_num; + + ASSERT_TRUE(frames != NULL); + ASSERT_TRUE(frame_num == 2); + + ASSERT_TRUE(frames[0]->sp - frames[0]->lp == 5); + ASSERT_TRUE(frames[0]->ip_offset == 24); + + ASSERT_TRUE(frames[0]->lp[0] == 1234); + ASSERT_TRUE(frames[0]->lp[1] == 5678); + ASSERT_TRUE(frames[0]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL); + + ASSERT_TRUE(frames[1]->lp[0] == 0x1234); + ASSERT_TRUE(frames[1]->lp[1] == 0x5678); + ASSERT_TRUE(frames[1]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[1]->lp + 3) == 0x12345678ABCDEF99LL); + ASSERT_TRUE(*(float *)(frames[1]->lp + 5) == 5566.7788f); + ASSERT_TRUE(*(double *)(frames[1]->lp + 6) == 99887766.55443322); +} diff --git a/tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt b/tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt new file mode 100644 index 000000000..9dd9565a5 --- /dev/null +++ b/tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project(wasm-apps-aot-stack-frame) + +add_custom_target(aot-stack-frame-test-wasm ALL + COMMAND cmake -B ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc + -S ${WAMR_ROOT_DIR}/wamr-compiler + && cmake --build ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc + && /opt/wabt/bin/wat2wasm + -o ${CMAKE_CURRENT_BINARY_DIR}/test.wasm + ${CMAKE_CURRENT_LIST_DIR}/test.wast + && ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc/wamrc + --enable-dump-call-stack --bounds-checks=1 + -o ${CMAKE_CURRENT_BINARY_DIR}/test.aot + ${CMAKE_CURRENT_BINARY_DIR}/test.wasm + && cmake -B ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump + -S ${WAMR_ROOT_DIR}/test-tools/binarydump-tool + && cmake --build ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump + && ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump/binarydump + -o ${CMAKE_CURRENT_LIST_DIR}/test_aot.h -n test_aot + ${CMAKE_CURRENT_BINARY_DIR}/test.aot + +) + diff --git a/tests/unit/aot-stack-frame/wasm-apps/test.wast b/tests/unit/aot-stack-frame/wasm-apps/test.wast new file mode 100644 index 000000000..1ef866efc --- /dev/null +++ b/tests/unit/aot-stack-frame/wasm-apps/test.wast @@ -0,0 +1,36 @@ +(module + (func $test1 (export "test1") (param i32 i32) (result i32) + i32.const 0x11223344 + i64.const 0x1234_5678_ABCD_EF99 + f32.const 5566.7788 + f64.const 99887766.55443322 + unreachable + ) + + (func $test2 (export "test2") (param f32 f32) (result i32) + i32.const 0x11223344 + i64.const 0x1234_5678_ABCD_EF99 + f32.const 5566.7788 + f64.const 99887766.55443322 + + loop + i32.const 0x1234 + i32.const 0x5678 + unreachable + end + + unreachable + ) + + (func $test3 (export "test3") (param i32 i32) (result i32) + i32.const 0x11223344 + i64.const 0x1234_5678_ABCD_EF99 + + i32.const 0x1234 + i32.const 0x5678 + call $test1 + + drop + drop + ) +) diff --git a/tests/unit/aot/CMakeLists.txt b/tests/unit/aot/CMakeLists.txt new file mode 100644 index 000000000..6b9c70c88 --- /dev/null +++ b/tests/unit/aot/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-aot) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) +add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1) +add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 1) + +include (../unit_common.cmake) + +set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (aot_test ${unit_test_sources}) + +target_link_libraries (aot_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +gtest_discover_tests(aot_test) + diff --git a/tests/unit/aot/aot_test.cc b/tests/unit/aot/aot_test.cc new file mode 100644 index 000000000..261b378e4 --- /dev/null +++ b/tests/unit/aot/aot_test.cc @@ -0,0 +1,1190 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include "gtest/gtest.h" +#include "wasm_export.h" +#include "bh_platform.h" +#include "aot_llvm.h" +#include "aot_intrinsic.h" +#include "aot.h" + +#define G_INTRINSIC_COUNT (50u) +#define CONS(num) ("f##num##.const") + +const char *llvm_intrinsic_tmp[G_INTRINSIC_COUNT] = { + "llvm.experimental.constrained.fadd.f32", + "llvm.experimental.constrained.fadd.f64", + "llvm.experimental.constrained.fsub.f32", + "llvm.experimental.constrained.fsub.f64", + "llvm.experimental.constrained.fmul.f32", + "llvm.experimental.constrained.fmul.f64", + "llvm.experimental.constrained.fdiv.f32", + "llvm.experimental.constrained.fdiv.f64", + "llvm.fabs.f32", + "llvm.fabs.f64", + "llvm.ceil.f32", + "llvm.ceil.f64", + "llvm.floor.f32", + "llvm.floor.f64", + "llvm.trunc.f32", + "llvm.trunc.f64", + "llvm.rint.f32", + "llvm.rint.f64", + "llvm.sqrt.f32", + "llvm.sqrt.f64", + "llvm.copysign.f32", + "llvm.copysign.f64", + "llvm.minnum.f32", + "llvm.minnum.f64", + "llvm.maxnum.f32", + "llvm.maxnum.f64", + "llvm.ctlz.i32", + "llvm.ctlz.i64", + "llvm.cttz.i32", + "llvm.cttz.i64", + "llvm.ctpop.i32", + "llvm.ctpop.i64", + "f64_convert_i32_s", + "f64_convert_i32_u", + "f32_convert_i32_s", + "f32_convert_i32_u", + "f64_convert_i64_s", + "f64_convert_i64_u", + "f32_convert_i64_s", + "f32_convert_i64_u", + "i32_trunc_f32_u", + "i32_trunc_f32_s", + "i32_trunc_f64_u", + "i32_trunc_f64_s", + "f32_demote_f64", + "f64_promote_f32", + "f32_cmp", + "f64_cmp", + "f32.const", + "f64.const", +}; + +uint64 g_intrinsic_flag[G_INTRINSIC_COUNT] = { + AOT_INTRINSIC_FLAG_F32_FADD, AOT_INTRINSIC_FLAG_F64_FADD, + AOT_INTRINSIC_FLAG_F32_FSUB, AOT_INTRINSIC_FLAG_F64_FSUB, + AOT_INTRINSIC_FLAG_F32_FMUL, AOT_INTRINSIC_FLAG_F64_FMUL, + AOT_INTRINSIC_FLAG_F32_FDIV, AOT_INTRINSIC_FLAG_F64_FDIV, + AOT_INTRINSIC_FLAG_F32_FABS, AOT_INTRINSIC_FLAG_F64_FABS, + AOT_INTRINSIC_FLAG_F32_CEIL, AOT_INTRINSIC_FLAG_F64_CEIL, + AOT_INTRINSIC_FLAG_F32_FLOOR, AOT_INTRINSIC_FLAG_F64_FLOOR, + AOT_INTRINSIC_FLAG_F32_TRUNC, AOT_INTRINSIC_FLAG_F64_TRUNC, + AOT_INTRINSIC_FLAG_F32_RINT, AOT_INTRINSIC_FLAG_F64_RINT, + AOT_INTRINSIC_FLAG_F32_SQRT, AOT_INTRINSIC_FLAG_F64_SQRT, + AOT_INTRINSIC_FLAG_F32_COPYSIGN, AOT_INTRINSIC_FLAG_F64_COPYSIGN, + AOT_INTRINSIC_FLAG_F32_MIN, AOT_INTRINSIC_FLAG_F64_MIN, + AOT_INTRINSIC_FLAG_F32_MAX, AOT_INTRINSIC_FLAG_F64_MAX, + AOT_INTRINSIC_FLAG_I32_CLZ, AOT_INTRINSIC_FLAG_I64_CLZ, + AOT_INTRINSIC_FLAG_I32_CTZ, AOT_INTRINSIC_FLAG_I64_CTZ, + AOT_INTRINSIC_FLAG_I32_POPCNT, AOT_INTRINSIC_FLAG_I64_POPCNT, + AOT_INTRINSIC_FLAG_I32_TO_F64, AOT_INTRINSIC_FLAG_U32_TO_F64, + AOT_INTRINSIC_FLAG_I32_TO_F32, AOT_INTRINSIC_FLAG_U32_TO_F32, + AOT_INTRINSIC_FLAG_I32_TO_F64, AOT_INTRINSIC_FLAG_U64_TO_F64, + AOT_INTRINSIC_FLAG_I64_TO_F32, AOT_INTRINSIC_FLAG_U64_TO_F32, + AOT_INTRINSIC_FLAG_F32_TO_U32, AOT_INTRINSIC_FLAG_F32_TO_I32, + AOT_INTRINSIC_FLAG_F64_TO_U32, AOT_INTRINSIC_FLAG_F64_TO_I32, + AOT_INTRINSIC_FLAG_F64_TO_F32, AOT_INTRINSIC_FLAG_F32_TO_F64, + AOT_INTRINSIC_FLAG_F32_CMP, AOT_INTRINSIC_FLAG_F64_CMP, + AOT_INTRINSIC_FLAG_F32_CONST, AOT_INTRINSIC_FLAG_F64_CONST, +}; + +// To use a test fixture, derive a class from testing::Test. +class AOTTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() { wasm_runtime_destroy(); } + + public: + char global_heap_buf[512 * 1024]; + RuntimeInitArgs init_args; +}; + +TEST_F(AOTTest, aot_value_stack_push_pop) +{ + AOTValueStack *stack; + AOTValue *value1, *value2, *value3; + AOTCompContext comp_ctx = { 0 }; + + stack = (AOTValueStack *)wasm_runtime_malloc(sizeof(AOTValueStack)); + EXPECT_TRUE(stack != NULL); + + memset(stack, 0, sizeof(AOTValueStack)); + + value1 = (AOTValue *)wasm_runtime_malloc(sizeof(AOTValue)); + EXPECT_TRUE(value1 != NULL); + + memset(value1, 0, sizeof(AOTValue)); + value1->type = VALUE_TYPE_I32; + + aot_value_stack_push(&comp_ctx, stack, value1); + EXPECT_EQ(stack->value_list_head, value1); + EXPECT_EQ(stack->value_list_end, value1); + + value2 = (AOTValue *)wasm_runtime_malloc(sizeof(AOTValue)); + EXPECT_TRUE(value2 != NULL); + + memset(value2, 0, sizeof(AOTValue)); + value2->type = VALUE_TYPE_I64; + + aot_value_stack_push(&comp_ctx, stack, value2); + EXPECT_EQ(stack->value_list_head, value1); + EXPECT_EQ(stack->value_list_end, value2); + EXPECT_EQ(value2->prev, value1); + + value3 = aot_value_stack_pop(&comp_ctx, stack); + EXPECT_EQ(value3, value2); + EXPECT_EQ(stack->value_list_head, value1); + EXPECT_EQ(stack->value_list_end, value1); + EXPECT_TRUE(value3->prev == NULL); + + aot_value_stack_destroy(&comp_ctx, stack); + wasm_runtime_free(value3); + wasm_runtime_free(stack); +} + +TEST_F(AOTTest, aot_block_stack_push_pop) +{ + AOTBlockStack *stack; + AOTBlock *block1, *block2, *block3; + AOTCompContext comp_ctx = { 0 }; + + stack = (AOTBlockStack *)wasm_runtime_malloc(sizeof(AOTBlockStack)); + EXPECT_TRUE(stack != NULL); + + memset(stack, 0, sizeof(AOTBlockStack)); + + block1 = (AOTBlock *)wasm_runtime_malloc(sizeof(AOTBlock)); + EXPECT_TRUE(block1 != NULL); + + memset(block1, 0, sizeof(AOTBlock)); + block1->label_type = LABEL_TYPE_LOOP; + + aot_block_stack_push(stack, block1); + EXPECT_EQ(stack->block_list_head, block1); + EXPECT_EQ(stack->block_list_end, block1); + + block2 = (AOTBlock *)wasm_runtime_malloc(sizeof(AOTBlock)); + EXPECT_TRUE(block2 != NULL); + + memset(block2, 0, sizeof(AOTBlock)); + block2->label_type = LABEL_TYPE_IF; + + aot_block_stack_push(stack, block2); + EXPECT_EQ(stack->block_list_head, block1); + EXPECT_EQ(stack->block_list_end, block2); + EXPECT_EQ(block2->prev, block1); + + block3 = aot_block_stack_pop(stack); + EXPECT_EQ(block3, block2); + EXPECT_EQ(stack->block_list_head, block1); + EXPECT_EQ(stack->block_list_end, block1); + EXPECT_TRUE(block3->prev == NULL); + + aot_block_stack_destroy(&comp_ctx, stack); + wasm_runtime_free(block3); + wasm_runtime_free(stack); +} + +TEST_F(AOTTest, aot_intrinsic_fadd_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fadd_f32(a, b), (a + b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fadd_f32(a, b), (a + b)); +} + +TEST_F(AOTTest, aot_intrinsic_fadd_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fadd_f64(a, b), (a + b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fadd_f64(a, b), (a + b)); +} + +TEST_F(AOTTest, aot_intrinsic_fsub_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fsub_f32(a, b), (a - b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fsub_f32(a, b), (a - b)); +} + +TEST_F(AOTTest, aot_intrinsic_fsub_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fsub_f64(a, b), (a - b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fsub_f64(a, b), (a - b)); +} + +TEST_F(AOTTest, aot_intrinsic_fmul_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fmul_f32(a, b), (a * b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fmul_f32(a, b), (a * b)); +} + +TEST_F(AOTTest, aot_intrinsic_fmul_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fmul_f64(a, b), (a * b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fmul_f64(a, b), (a * b)); +} + +TEST_F(AOTTest, aot_intrinsic_fdiv_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b)); + + a = -1.0; + b = 0.0; + EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b)); +} + +TEST_F(AOTTest, aot_intrinsic_fdiv_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b)); + + a = -1.0; + b = 0.0; + EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b)); +} + +TEST_F(AOTTest, aot_intrinsic_fabs_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a)); + + a = -1.0; + EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a)); + + a = -1.5; + EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_fabs_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a)); + + a = -1.0; + EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a)); + + a = -1.5; + EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_ceil_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), ceilf(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), 2); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_ceil_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), ceil(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), 2); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_floor_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_floor_f32(a), floorf(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_floor_f32(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_floor_f32(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_floor_f32(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_floor_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_floor_f64(a), floor(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_floor_f64(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_floor_f64(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_floor_f64(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_trunc_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), trunc(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_trunc_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), trunc(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_rint_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_rint_f32(a), rint(a)); + EXPECT_EQ(aot_intrinsic_rint_f32(a), 1); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_rint_f32(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_rint_f32(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_rint_f32(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_rint_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_rint_f64(a), rint(a)); + EXPECT_EQ(aot_intrinsic_rint_f64(a), 1); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_rint_f64(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_rint_f64(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_rint_f64(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_sqrt_f32) +{ + float32 a = 2.0; + EXPECT_EQ(aot_intrinsic_sqrt_f32(a), sqrt(a)); + + a = 2; + EXPECT_EQ(aot_intrinsic_sqrt_f32(a), sqrt(a)); +} + +TEST_F(AOTTest, aot_intrinsic_sqrt_f64) +{ + float64 a = 2.0; + EXPECT_EQ(aot_intrinsic_sqrt_f64(a), sqrt(a)); + + a = 2; + EXPECT_EQ(aot_intrinsic_sqrt_f64(a), sqrt(a)); +} + +TEST_F(AOTTest, aot_intrinsic_copysign_f32) +{ + float32 a = 20.0; + float32 b = 2.0; + + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), fabs(a)); + + b = 1.5; + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), fabs(a)); + + b = -2.0; + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), -fabs(a)); + + a = -20.0; + b = -1.5; + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), -fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_copysign_f64) +{ + float64 a = 20.0; + float64 b = 2.0; + + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), fabs(a)); + + b = 1.5; + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), fabs(a)); + + b = -2.0; + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), -fabs(a)); + + a = -20.0; + b = -1.5; + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), -fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_fmin_f32) +{ + float32 a = 1.2; + float32 b = 2.5; + + EXPECT_EQ(aot_intrinsic_fmin_f32(a, b), a); + + a = -3; + b = -1; + EXPECT_EQ(aot_intrinsic_fmin_f32(a, b), a); + + b = 1; + EXPECT_EQ(aot_intrinsic_fmin_f32('a', b), b); + + a = 3; + EXPECT_EQ(aot_intrinsic_fmin_f32(a, 'b'), a); + + EXPECT_EQ(aot_intrinsic_fmin_f32('a', 'b'), 'a'); + + EXPECT_EQ(aot_intrinsic_fmin_f32('b', 'c'), 'b'); + EXPECT_EQ(aot_intrinsic_fmin_f32('c', 'b'), 'b'); + + EXPECT_EQ(aot_intrinsic_fmin_f32(true, 2.5), 1); + EXPECT_EQ(aot_intrinsic_fmin_f32(1.0, false), 0); + + EXPECT_NE(aot_intrinsic_fmin_f32(sqrt(-1), 3), 3); + EXPECT_NE(aot_intrinsic_fmin_f32(3, sqrt(-1)), 3); +} + +TEST_F(AOTTest, aot_intrinsic_fmin_f64) +{ + float64 a = 1.00000000; + float64 b = 3.00000000; + + EXPECT_EQ(aot_intrinsic_fmin_f64(a, b), a); + + EXPECT_EQ(aot_intrinsic_fmin_f64(-a, b), -a); + + EXPECT_EQ(aot_intrinsic_fmin_f64(-a, -b), -b); + + EXPECT_EQ(aot_intrinsic_fmin_f64(a, -b), -b); + + EXPECT_EQ(aot_intrinsic_fmin_f64(a, a), a); + + a = 0.0000; + EXPECT_EQ(aot_intrinsic_fmin_f64(-a, -a), -a); +} + +TEST_F(AOTTest, aot_intrinsic_fmax_f32) +{ + float32 a = 1.2; + float32 b = 2.5; + + EXPECT_EQ(aot_intrinsic_fmax_f32(a, b), b); + + a = -3; + b = -1; + EXPECT_EQ(aot_intrinsic_fmax_f32(a, b), b); + + b = 1; + EXPECT_EQ(aot_intrinsic_fmax_f32('a', b), 'a'); + + a = 3; + EXPECT_EQ(aot_intrinsic_fmax_f32(a, 'b'), 'b'); + + EXPECT_EQ(aot_intrinsic_fmax_f32('a', 'b'), 'b'); + + EXPECT_EQ(aot_intrinsic_fmax_f32(' ', 'b'), 'b'); + EXPECT_EQ(aot_intrinsic_fmax_f32('a', ' '), 'a'); + + EXPECT_NE(aot_intrinsic_fmax_f32(sqrt(-1), 3), 3); + EXPECT_NE(aot_intrinsic_fmax_f32(3, sqrt(-1)), 3); +} + +TEST_F(AOTTest, aot_intrinsic_fmax_f64) +{ + float64 a = 1.00000000; + float64 b = 3.00000000; + + EXPECT_EQ(aot_intrinsic_fmax_f64(a, b), b); + + EXPECT_EQ(aot_intrinsic_fmax_f64(-a, b), b); + + EXPECT_EQ(aot_intrinsic_fmax_f64(-a, -b), -a); + + EXPECT_EQ(aot_intrinsic_fmax_f64(a, -b), a); + + EXPECT_EQ(aot_intrinsic_fmax_f64(a, a), a); + + a = 0.0000; + EXPECT_EQ(aot_intrinsic_fmax_f64(-a, -a), -a); + + EXPECT_EQ(aot_intrinsic_fmax_f64(-0, -0), -0); +} + +TEST_F(AOTTest, aot_intrinsic_clz_i32) +{ + uint32 type = 0; + uint32 data = 0; + uint32 num = 0; + + EXPECT_EQ(aot_intrinsic_clz_i32(0), 32); + + for (uint32 i = 0; i < 0xFFFF; i++) { + /* Generate random numbers [1,0xFFFFFFFF] */ + type = 1 + (rand() % (0xFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 0x80000000)) { + num++; + type <<= 1; + } + EXPECT_EQ(aot_intrinsic_clz_i32(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_clz_i32(0xFFFFFFFF), 0); +} + +TEST_F(AOTTest, aot_intrinsic_clz_i64) +{ + uint64 type = 0; + uint64 data = 0; + uint64 num = 0; + + EXPECT_EQ(aot_intrinsic_clz_i64(0), 64); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + /* Generate random numbers [1,0xFFFFFFFFFFFFFFFF] */ + type = 1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 0x8000000000000000LL)) { + num++; + type <<= 1; + } + EXPECT_EQ(aot_intrinsic_clz_i64(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_clz_i64(0xFFFFFFFFFFFFFFFF), 0); +} + +TEST_F(AOTTest, ast_intrinsic_ctz_i32) +{ + uint32 type = 0; + uint32 data = 0; + uint32 num = 0; + + EXPECT_EQ(aot_intrinsic_ctz_i32(0), 32); + + for (uint32 i = 0; i < 0xFFFF; i++) { + type = 1 + (rand() % (0xFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 1)) { + num++; + type >>= 1; + } + EXPECT_EQ(aot_intrinsic_ctz_i32(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_ctz_i32(0xFFFFFFFF), 0); +} + +TEST_F(AOTTest, ast_intrinsic_ctz_i64) +{ + uint64 type = 0; + uint64 data = 0; + uint64 num = 0; + + EXPECT_EQ(aot_intrinsic_ctz_i64(0), 64); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + type = 1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 1)) { + num++; + type >>= 1; + } + EXPECT_EQ(aot_intrinsic_ctz_i64(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_ctz_i64(0xFFFFFFFFFFFFFFFF), 0); +} + +TEST_F(AOTTest, aot_intrinsic_popcnt_i32) +{ + uint32 data = 0; + uint32 num = 0; + uint32 temp = 0; + + EXPECT_EQ(aot_intrinsic_popcnt_i32(0), 0); + + for (uint32 i = 0; i < 0xFFFF; i++) { + temp = 1 + (rand() % (0x100000000 - 1 + 1)); + data = temp; + + while (temp) { + if (temp & 0x01) + num++; + temp >>= 1; + } + EXPECT_EQ(aot_intrinsic_popcnt_i32(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_popcnt_i32(0xFFFFFFFF), 32); +} + +TEST_F(AOTTest, aot_intrinsic_popcnt_i64) +{ + uint64 data = 0; + uint64 num = 0; + uint64 temp = 0; + + EXPECT_EQ(aot_intrinsic_popcnt_i64(0x00), 0); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + temp = 1 + (rand() % (0xFFFFFFFFFFFFFFFFLL - 1 + 1)); + data = temp; + + while (temp) { + if (temp & 0x01) + num++; + temp >>= 1; + } + EXPECT_EQ(aot_intrinsic_popcnt_i64(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_popcnt_i64(0xFFFFFFFFFFFFFFFF), 64); +} + +TEST_F(AOTTest, aot_intrinsic_i32_to_f32) +{ + int32 idata = 0; + + EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata); + + for (uint32 i = 0; i < 0xFFFF; i++) { + idata = (int32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata); + } + + idata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u32_to_f32) +{ + uint32 udata = 0; + + EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata); + + for (uint32 i = 0; i < 0xFFFF; i++) { + udata = (uint32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata); + } + + udata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata); +} + +TEST_F(AOTTest, aot_intrinsic_i32_to_f64) +{ + int32 idata = 0; + + EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata); + + for (uint32 i = 0; i < 0xFFFF; i++) { + idata = (int32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata); + } + + idata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u32_to_f64) +{ + uint32 udata = 0; + + EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + udata = (uint32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata); + } + + udata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata); +} + +TEST_F(AOTTest, aot_intrinsic_i64_to_f32) +{ + int64 idata = 0LL; + + EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + idata = (int64)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata); + } + + idata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u64_to_f32) +{ + uint64 udata = 0LL; + + EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + udata = (uint64)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata); + } + + udata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata); +} + +TEST_F(AOTTest, aot_intrinsic_i64_to_f64) +{ + int64 idata = 0LL; + + EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), float64(idata)); + + for (uint32_t i = 0; i < 0xFFFFF; i++) { + idata = (int64)(1 + (rand() % (0xFFFFFFFFFFFFFFFLL - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), (float64)idata); + } + + idata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), (float64)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u64_to_f64) +{ + uint64 udata = 0LL; + + EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), float64(udata)); + + for (uint32_t i = 0; i < 0xFFFFF; i++) { + udata = (uint64)(1 + (rand() % (0xFFFFFFFFFFFFFFFLL - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), (float64)udata); + } + + udata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), (float64)udata); +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_i32) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_i32(data), (int32)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (100 - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_i32(data), (int32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_u32) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_u32(data), (uint32)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_u32(data), (uint32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_i64) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_i64(data), (int64)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_i64(data), (int64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_u64) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_u64(data), (uint64)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_u64(data), (uint64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_i32) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_i32(data), (int32)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_i32(data), (int32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_u32) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_u32(data), (uint32)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_u32(data), (uint32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_i64) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_i64(data), (int64)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_i64(data), (int64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_u64) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_u64(data), (uint64)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_u64(data), (uint64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_f64) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float64)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_f32) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_f32(data), (float32)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.06); + EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_cmp) +{ + float32 lhs = 0.0; + float32 rhs = 0.0; + AOTFloatCond index = FLOAT_EQ; + uint32 res = 0; + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + index = (AOTFloatCond)(1 + (rand() % (6 - 1 + 1))); + lhs = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + rhs = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + + /* cond : 0 */ + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_EQ, lhs, rhs), + lhs == rhs ? 1 : 0); + + /* cond : 1-6 */ + switch (index) { + case FLOAT_LT: // 2 + res = (lhs < rhs ? 1 : 0); + break; + case FLOAT_GT: // 3 + res = (lhs > rhs ? 1 : 0); + break; + case FLOAT_LE: // 4 + res = (lhs <= rhs ? 1 : 0); + break; + case FLOAT_GE: // 5 + res = (lhs >= rhs ? 1 : 0); + break; + case FLOAT_NE: // 1 + res = (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0; + break; + case FLOAT_UNO: // 6 + res = (isnan(lhs) || isnan(rhs)) ? 1 : 0; + break; + + default: + break; + } + + EXPECT_EQ(aot_intrinsic_f32_cmp(index, lhs, rhs), res); + index = FLOAT_EQ; + + /* cond : > 6 */ + EXPECT_EQ(aot_intrinsic_f32_cmp((AOTFloatCond)(i + 7), lhs, rhs), 0); + } + + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_NE, true, false), 1); + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_NE, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, true, false), 0); + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, 'a', 'b'), 0); +} + +TEST_F(AOTTest, aot_intrinsic_f64_cmp) +{ + float64 lhs = 0.0; + float64 rhs = 0.0; + AOTFloatCond index = FLOAT_EQ; + uint32 res = 0; + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + index = (AOTFloatCond)(1 + (rand() % (6 - 1 + 1))); + lhs = (float32)((1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1))) - 0.05); + rhs = (float32)((1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1))) - 0.05); + + /* cond : 0 */ + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_EQ, lhs, rhs), + lhs == rhs ? 1 : 0); + + /* cond : 1-6 */ + switch (index) { + case FLOAT_LT: // 2 + res = (lhs < rhs ? 1 : 0); + break; + case FLOAT_GT: // 3 + res = (lhs > rhs ? 1 : 0); + break; + case FLOAT_LE: // 4 + res = (lhs <= rhs ? 1 : 0); + break; + case FLOAT_GE: // 5 + res = (lhs >= rhs ? 1 : 0); + break; + case FLOAT_NE: // 1 + res = (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0; + break; + case FLOAT_UNO: // 6 + res = (isnan(lhs) || isnan(rhs)) ? 1 : 0; + break; + + default: + break; + } + + EXPECT_EQ(aot_intrinsic_f64_cmp(index, lhs, rhs), res); + index = FLOAT_EQ; + + /* cond : > 6 */ + EXPECT_EQ(aot_intrinsic_f64_cmp((AOTFloatCond)(i + 7), lhs, rhs), 0); + } + + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_NE, true, false), 1); + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_NE, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, true, false), 0); + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, 'a', 'b'), 0); +} + +TEST_F(AOTTest, aot_intrinsic_get_symbol) +{ + const char *llvm_intrinsic_t = NULL; + + for (int i = 0; i < 2; i++) { + if (i == 0) + llvm_intrinsic_t = CONS(32); + else + llvm_intrinsic_t = CONS(64); + + EXPECT_EQ((const char *)aot_intrinsic_get_symbol(llvm_intrinsic_t), + (const char *)NULL); + } + + for (int i = 0; i < G_INTRINSIC_COUNT - 2; i++) { + EXPECT_NE((const char *)aot_intrinsic_get_symbol(llvm_intrinsic_tmp[i]), + (const char *)NULL); + } +} + +TEST_F(AOTTest, aot_intrinsic_check_capability) +{ + AOTCompContext *comp_ctx = NULL; + AOTCompContext scomp_ctx = { 0 }; + const char *llvm_intrinsic_t = "f64_cmp"; + bool res = false; + uint64 flag = 0; + uint64 group = 0; + + comp_ctx = &scomp_ctx; + memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags)); + + /* + EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, (const char + *)NULL)); EXPECT_FALSE(aot_intrinsic_check_capability((const + AOTCompContext *)NULL, llvm_intrinsic_t)); + */ + + EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_t)); + for (int i = 0; i < G_INTRINSIC_COUNT; i++) { + EXPECT_FALSE( + aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_tmp[i])); + } + + memset(comp_ctx->flags, 1, sizeof(comp_ctx->flags)); + EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_t)); + for (int i = 0; i < G_INTRINSIC_COUNT; i++) { + flag = g_intrinsic_flag[i]; + group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag); + flag &= AOT_INTRINSIC_FLAG_MASK; + + res = aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_tmp[i]); + if ((flag & 0x01) || (flag & 0x100) || (flag & 0x10000) + || (flag & 0x1000000)) + EXPECT_TRUE(res); + else + EXPECT_FALSE(res); + } +} + +TEST_F(AOTTest, aot_intrinsic_fill_capability_flags) +{ + // AOTCompContext *comp_ctx = NULL; + AOTCompContext scomp_ctx = { 0 }; + + // comp_ctx = &scomp_ctx; + aot_intrinsic_fill_capability_flags(&scomp_ctx); + + AOTCompContext scomp_ctx_1{ + .target_cpu = (char *)"cortex-m7", + }; + strncpy(scomp_ctx_1.target_arch, "thumb", strlen("thumb")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_1); + + AOTCompContext scomp_ctx_2{ + .target_cpu = (char *)"cortex-m4", + }; + strncpy(scomp_ctx_2.target_arch, "thumb", strlen("thumb")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_2); + + AOTCompContext scomp_ctx_3{ + .target_cpu = (char *)"cortex-m4", + }; + strncpy(scomp_ctx_3.target_arch, "riscv", strlen("riscv")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_3); + + AOTCompContext scomp_ctx_4{ + .target_cpu = (char *)"cortex-m4", + }; + strncpy(scomp_ctx_4.target_arch, "intrinsic", strlen("intrinsic")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_4); +} diff --git a/tests/unit/common/mock_allocator.h b/tests/unit/common/mock_allocator.h new file mode 100644 index 000000000..a57e2dea3 --- /dev/null +++ b/tests/unit/common/mock_allocator.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#pragma once + +#include "wasm_export.h" +#include + +template +class MockAllocator +{ + private: + RuntimeInitArgs init_args; + + public: + MockAllocator() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *)my_malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *)realloc; + init_args.mem_alloc_option.allocator.free_func = (void *)free; + + /* Set count to INT32_MIN so the initialization will not fail */ + alloc_count = INT32_MIN; + + wasm_runtime_full_init(&init_args); + reset_count(); + } + + ~MockAllocator() { wasm_runtime_destroy(); } + + void reset_count() { alloc_count = 0; } + + protected: + static int32_t alloc_count; + static void *my_malloc(int32_t size) + { + if (alloc_count >= MaxAllocCount) { + return nullptr; + } + + alloc_count++; + + return malloc(size); + } +}; + +template +int32_t MockAllocator::alloc_count = 0; + +class DumpAllocUsage : public MockAllocator +{ + public: + DumpAllocUsage() + : MockAllocator() + {} + + ~DumpAllocUsage() + { + std::cout << "Alloc usage count: " << alloc_count << std::endl; + } +}; + +template +void +LIMIT_MALLOC_COUNT(std::function func) +{ + { + MockAllocator allocator; + func(); + } + + if (AllocRequired > 1) + LIMIT_MALLOC_COUNT(func); +} + +template<> +void +LIMIT_MALLOC_COUNT<0>(std::function func) +{ + { + MockAllocator<0> allocator; + func(); + } +} diff --git a/tests/unit/common/test_helper.h b/tests/unit/common/test_helper.h new file mode 100644 index 000000000..4db465fc8 --- /dev/null +++ b/tests/unit/common/test_helper.h @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#pragma once + +#include "wasm_export.h" +#include "gtest/gtest.h" + +#include +#include +#include + +template +class WAMRRuntimeRAII +{ + private: + char global_heap_buf[Size]; + RuntimeInitArgs init_args; + + public: + WAMRRuntimeRAII() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + wasm_runtime_full_init(&init_args); + } + + ~WAMRRuntimeRAII() { wasm_runtime_destroy(); } +}; + +class WAMRModule +{ + private: + wasm_module_t module_; + + public: + WAMRModule(uint8_t *buffer, uint32_t size) + { + module_ = wasm_runtime_load(buffer, size, NULL, 0); + } + + ~WAMRModule() { wasm_runtime_unload(module_); } + + wasm_module_t get() const { return module_; } +}; + +class WAMRInstance +{ + private: + wasm_module_inst_t module_inst_; + + public: + WAMRInstance(WAMRModule &module, uint32_t stack_size = 8192, + uint32_t heap_size = 8192) + { + module_inst_ = wasm_runtime_instantiate(module.get(), stack_size, + heap_size, NULL, 0); + } + + ~WAMRInstance() { wasm_runtime_deinstantiate(module_inst_); } + + wasm_module_inst_t get() const { return module_inst_; } +}; + +class WAMRExecEnv +{ + private: + wasm_exec_env_t exec_env_; + + public: + WAMRExecEnv(WAMRInstance &instance, uint32_t stack_size = 8192) + { + exec_env_ = wasm_runtime_create_exec_env(instance.get(), stack_size); + } + + ~WAMRExecEnv() { wasm_runtime_destroy_exec_env(exec_env_); } + + wasm_exec_env_t get() const { return exec_env_; } + wasm_module_inst_t get_inst() const + { + return wasm_runtime_get_module_inst(exec_env_); + } +}; + +static uint8_t dummy_wasm_buffer[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00, + 0x02, 0x06, 0x08, 0x01, 0x7F, 0x01, 0x41, 0x80, 0x88, 0x04, 0x0B, 0x07, + 0x0A, 0x01, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x00, + 0x19, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x07, 0x12, 0x01, 0x00, 0x0F, 0x5F, + 0x5F, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, + 0x65, 0x72, 0x00, 0x76, 0x09, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, + 0x72, 0x73, 0x01, 0x0C, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, + 0x64, 0x2D, 0x62, 0x79, 0x01, 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, + 0x31, 0x33, 0x2E, 0x30, 0x2E, 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, + 0x73, 0x3A, 0x2F, 0x2F, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, + 0x6F, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, + 0x2D, 0x70, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x66, 0x64, 0x31, + 0x64, 0x38, 0x63, 0x32, 0x66, 0x30, 0x34, 0x64, 0x64, 0x65, 0x32, 0x33, + 0x62, 0x65, 0x65, 0x30, 0x66, 0x62, 0x33, 0x61, 0x37, 0x64, 0x30, 0x36, + 0x39, 0x61, 0x39, 0x62, 0x31, 0x30, 0x34, 0x36, 0x64, 0x61, 0x39, 0x37, + 0x39, 0x29 +}; + +class DummyExecEnv +{ + private: + std::shared_ptr dummy_exec_env_; + std::shared_ptr inst_; + std::shared_ptr mod_; + std::vector my_wasm_buffer; + + private: + void construct(uint8_t *buf, uint32_t len) + { + std::vector buffer(buf, buf + len); + my_wasm_buffer = buffer; + + mod_ = std::make_shared(my_wasm_buffer.data(), + my_wasm_buffer.size()); + EXPECT_NE(mod_.get(), nullptr); + inst_ = std::make_shared(*mod_); + EXPECT_NE(inst_.get(), nullptr); + dummy_exec_env_ = std::make_shared(*inst_); + EXPECT_NE(dummy_exec_env_.get(), nullptr); + } + + public: + DummyExecEnv() { construct(dummy_wasm_buffer, sizeof(dummy_wasm_buffer)); } + + DummyExecEnv(uint8_t *buf, uint32_t len) { construct(buf, len); } + + DummyExecEnv(std::string filename) + { + std::ifstream wasm_file(filename, std::ios::binary); + std::vector buffer(std::istreambuf_iterator(wasm_file), + {}); + + construct(buffer.data(), buffer.size()); + } + + ~DummyExecEnv() {} + + wasm_exec_env_t get() const { return dummy_exec_env_->get(); } + + void *app_to_native(uint32_t app_addr) const + { + return wasm_runtime_addr_app_to_native(inst_->get(), app_addr); + } + + uint32_t native_to_app(void *ptr) const + { + return wasm_runtime_addr_native_to_app(inst_->get(), ptr); + } + + const char *get_exception() const + { + return wasm_runtime_get_exception(inst_->get()); + } + + void set_exception(std::string str) const + { + wasm_runtime_set_exception(inst_->get(), str.c_str()); + } + + void clear_exception() const { wasm_runtime_clear_exception(inst_->get()); } + + bool execute(const char *func_name, uint32_t argc, uint32_t argv[]) + { + wasm_function_inst_t func; + + if (!(func = wasm_runtime_lookup_function(inst_->get(), func_name))) { + return false; + } + + return wasm_runtime_call_wasm(dummy_exec_env_->get(), func, argc, argv); + } +}; + +class WAMRVaList +{ + private: + void *buffer_; + uint32_t current_loc_; + uint32_t capacity_; + wasm_exec_env_t exec_env_; + + void _append(void *ptr, uint32_t size) + { + if (current_loc_ + size >= capacity_) { + capacity_ *= 2; + buffer_ = realloc(buffer_, capacity_); + ASSERT_NE(buffer_, nullptr); + } + + memcpy((void *)((uintptr_t)buffer_ + current_loc_), ptr, size); + current_loc_ += size; + } + + public: + explicit WAMRVaList(wasm_exec_env_t exec_env) + : exec_env_(exec_env) + { + capacity_ = 64; + buffer_ = malloc(capacity_); + EXPECT_NE(buffer_, nullptr); + current_loc_ = 0; + } + + ~WAMRVaList() + { + current_loc_ = 0; + free(buffer_); + } + + template + void add(T arg) + { + if (std::is_floating_point::value) { + /* float data should be 8 bytes aligned */ + current_loc_ = ((current_loc_ + 7) & ~7); + _append(&arg, sizeof(T)); + } + else if (std::is_integral::value) { + if (sizeof(T) > 4) { + current_loc_ = ((current_loc_ + 7) & ~7); + } + _append(&arg, sizeof(T)); + } + } + + void add(std::string arg) + { + void *native_addr; + auto inst = wasm_runtime_get_module_inst(exec_env_); + uint32_t addr = + wasm_runtime_module_malloc(inst, arg.size() + 1, &native_addr); + ASSERT_NE(addr, 0); + memcpy(native_addr, arg.data(), arg.size()); + *(char *)((uintptr_t)native_addr + arg.size()) = 0; + _append(&addr, sizeof(uint32_t)); + } + + void add(const char *arg) { add(std::string(arg)); } + + char *get() const + { + auto inst = wasm_runtime_get_module_inst(exec_env_); + uint32_t addr = wasm_runtime_module_dup_data( + inst, (const char *)buffer_, current_loc_); + EXPECT_NE(addr, 0); + return (char *)wasm_runtime_addr_app_to_native(inst, addr); + } +}; + +/* Get memory space in app */ +class AppMemory +{ + private: + wasm_exec_env_t exec_env_; + void *native_addr_; + uint32_t app_addr_; + + public: + AppMemory(wasm_exec_env_t exec_env, uint32_t size) + : exec_env_(exec_env) + { + app_addr_ = wasm_runtime_module_malloc(get_module_inst(exec_env_), size, + &native_addr_); + } + + ~AppMemory() + { + wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_); + } + + void *get_native_addr() const + { + return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_), + app_addr_); + } + uint32_t get_app_addr() const { return app_addr_; } +}; + +/* Put the data to app */ +class AppData +{ + private: + wasm_exec_env_t exec_env_; + void *native_addr_; + uint32_t app_addr_; + + public: + AppData(wasm_exec_env_t exec_env, void *data, uint32_t size) + : exec_env_(exec_env) + { + app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_), + (const char *)data, size); + } + + AppData(wasm_exec_env_t exec_env, std::string str) + : exec_env_(exec_env) + { + app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_), + (const char *)str.c_str(), + str.size() + 1); + } + + ~AppData() + { + wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_); + } + + void *get_native_addr() const + { + return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_), + app_addr_); + } + uint32_t get_app_addr() const { return app_addr_; } +}; \ No newline at end of file diff --git a/tests/unit/compilation/CMakeLists.txt b/tests/unit/compilation/CMakeLists.txt new file mode 100644 index 000000000..0941a39cc --- /dev/null +++ b/tests/unit/compilation/CMakeLists.txt @@ -0,0 +1,72 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-compilation) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) +add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1) +add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_THREAD_MGR 1) +set (WAMR_BUILD_AOT 1) + +include (../unit_common.cmake) + +set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (compilation_test ${unit_test_sources}) + +target_link_libraries (compilation_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +add_custom_command(TARGET compilation_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.wasm + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy main.wasm to the directory: build/compilation." +) + +gtest_discover_tests(compilation_test) diff --git a/tests/unit/compilation/aot_compiler_test.cc b/tests/unit/compilation/aot_compiler_test.cc new file mode 100644 index 000000000..8592a4b61 --- /dev/null +++ b/tests/unit/compilation/aot_compiler_test.cc @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "wasm_export.h" +#include "aot_export.h" +#include "bh_read_file.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +extern "C" { +char * +aot_generate_tempfile_name(const char *prefix, const char *extension, + char *buffer, uint32 len); +} + +class aot_compiler_test_suit : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +void +test_aot_emit_object_file_with_option(AOTCompOption *option_ptr) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + aot_comp_data_t comp_data = nullptr; + aot_comp_context_t comp_ctx = nullptr; + char out_file_name[] = "test.aot"; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + + comp_ctx = aot_create_comp_context(comp_data, option_ptr); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_STREQ(aot_get_last_error(), ""); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_TRUE(aot_emit_object_file(comp_ctx, out_file_name)); +} + +TEST_F(aot_compiler_test_suit, aot_emit_object_file) +{ + AOTCompOption option = { 0 }; + uint32_t i = 0; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + // Test opt_level in range from 0 to 3. + for (i = 0; i <= 3; i++) { + option.opt_level = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test size_level in range from 0 to 3. + option.opt_level = 3; + for (i = 0; i <= 3; i++) { + option.size_level = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test output_format in range from AOT_FORMAT_FILE to AOT_LLVMIR_OPT_FILE. + option.size_level = 3; + for (i = AOT_FORMAT_FILE; i <= AOT_LLVMIR_OPT_FILE; i++) { + option.output_format = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test bounds_checks in range 0 to 2. + option.output_format = AOT_FORMAT_FILE; + for (i = 0; i <= 2; i++) { + option.bounds_checks = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test all enable option is false. + option.bounds_checks = 2; + option.enable_simd = false; + option.enable_aux_stack_check = false; + option.enable_bulk_memory = false; + option.enable_ref_types = false; + test_aot_emit_object_file_with_option(&option); +} + +TEST_F(aot_compiler_test_suit, aot_emit_llvm_file) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + aot_comp_data_t comp_data = nullptr; + aot_comp_context_t comp_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_STREQ(aot_get_last_error(), ""); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_EQ(true, aot_emit_llvm_file(comp_ctx, out_file_name)); +} + +TEST_F(aot_compiler_test_suit, aot_generate_tempfile_name) +{ + char obj_file_name[64]; + + // Test common case. + aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name, + sizeof(obj_file_name)); + EXPECT_NE(nullptr, strstr(obj_file_name, ".o")); + + // Test abnormal cases. + EXPECT_EQ(nullptr, + aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name, 0)); + char obj_file_name_1[20]; + EXPECT_EQ(nullptr, aot_generate_tempfile_name( + "wamrc-obj", "12345678901234567890", obj_file_name_1, + sizeof(obj_file_name_1))); +} diff --git a/tests/unit/compilation/aot_emit_aot_file_test.cc b/tests/unit/compilation/aot_emit_aot_file_test.cc new file mode 100644 index 000000000..64c5533bb --- /dev/null +++ b/tests/unit/compilation/aot_emit_aot_file_test.cc @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "wasm_export.h" +#include "aot_export.h" +#include "bh_read_file.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +extern "C" { +uint8 * +aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data, + uint32 *p_aot_file_size); +} + +class aot_emit_aot_file_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_aot_file_test_suite, aot_emit_aot_file) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + aot_comp_data_t comp_data = nullptr; + aot_comp_context_t comp_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "test.aot"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = false; + option.enable_aux_stack_check = false; + option.enable_bulk_memory = false; + option.enable_ref_types = false; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_EQ(false, aot_emit_aot_file(comp_ctx, comp_data, nullptr)); +} diff --git a/tests/unit/compilation/aot_emit_compare_test.cc b/tests/unit/compilation/aot_emit_compare_test.cc new file mode 100644 index 000000000..dfd125f9a --- /dev/null +++ b/tests/unit/compilation/aot_emit_compare_test.cc @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "aot_emit_compare.h" + +class compilation_aot_emit_compare_test : public testing::Test +{ + protected: + virtual void SetUp() {} + virtual void TearDown() {} + + public: +}; + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_i32_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + IntCond cond = INT_EQZ; + IntCond cond1 = INT_EQZ; + + /* false cond = 0 */ + EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_i32_compare(&comp_ctx, &func_ctx, (IntCond)(-1))); + + /* false cond = [1:10] || [11:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (IntCond)(1 + (rand() % (INT_GE_U - 1 + 1))); + cond1 = (IntCond)((INT_GE_U + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond1)); + } +} + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_i64_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + IntCond cond = INT_EQZ; + IntCond cond1 = INT_EQZ; + + /* false cond = 0 */ + // EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_i64_compare(&comp_ctx, &func_ctx, (IntCond)(-1))); + + /* false cond = [1:10] || [11:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (IntCond)(1 + (rand() % (INT_GE_U - 1 + 1))); + cond1 = (IntCond)((INT_GE_U + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond1)); + } +} + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_f32_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + FloatCond cond = FLOAT_EQ; + FloatCond cond1 = FLOAT_EQ; + + /* false cond = 0 */ + EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_f32_compare(&comp_ctx, &func_ctx, (FloatCond)(-1))); + + /* false cond = [1:10] || [7:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (FloatCond)(1 + (rand() % (FLOAT_UNO - 1 + 1))); + cond1 = (FloatCond)((FLOAT_UNO + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond1)); + } +} + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_f64_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + FloatCond cond = FLOAT_EQ; + FloatCond cond1 = FLOAT_EQ; + + /* false cond = 0 */ + EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_f64_compare(&comp_ctx, &func_ctx, (FloatCond)(-1))); + + /* false cond = [1:10] || [7:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (FloatCond)(1 + (rand() % (FLOAT_UNO - 1 + 1))); + cond1 = (FloatCond)((FLOAT_UNO + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond1)); + } +} diff --git a/tests/unit/compilation/aot_emit_control_test.cc b/tests/unit/compilation/aot_emit_control_test.cc new file mode 100644 index 000000000..a269f51eb --- /dev/null +++ b/tests/unit/compilation/aot_emit_control_test.cc @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot.h" +#include "aot_llvm.h" +#include "aot_emit_control.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_control_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_control_test_suite, check_suspend_flags) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + EXPECT_EQ(true, check_suspend_flags(comp_ctx, func_ctx, false)); +} + +TEST_F(aot_emit_control_test_suite, aot_compile_op_block) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + func_ctx->block_stack.block_list_end = nullptr; + EXPECT_EQ(false, aot_compile_op_block(comp_ctx, func_ctx, nullptr, nullptr, + 0, 0, nullptr, 0, nullptr)); +} + +TEST_F(aot_emit_control_test_suite, aot_compile_op_else) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + func_ctx->block_stack.block_list_end = nullptr; + EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr)); + + AOTBlock block_list_end_test; + block_list_end_test.label_type = LABEL_TYPE_FUNCTION; + func_ctx->block_stack.block_list_end = &block_list_end_test; + EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr)); + + block_list_end_test.label_type = LABEL_TYPE_IF; + block_list_end_test.llvm_else_block = nullptr; + EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr)); +} diff --git a/tests/unit/compilation/aot_emit_function_test.cc b/tests/unit/compilation/aot_emit_function_test.cc new file mode 100644 index 000000000..8c4c93fce --- /dev/null +++ b/tests/unit/compilation/aot_emit_function_test.cc @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_emit_control.h" +#include "aot_emit_function.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_function_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_function_test_suite, aot_compile_op_call) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + EXPECT_EQ(false, aot_compile_op_call(comp_ctx, func_ctx, 9999, true)); +} diff --git a/tests/unit/compilation/aot_emit_memory_test.cc b/tests/unit/compilation/aot_emit_memory_test.cc new file mode 100644 index 000000000..26a6a79ba --- /dev/null +++ b/tests/unit/compilation/aot_emit_memory_test.cc @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "aot_emit_memory.h" +#include "test_helper.h" + +#define DEFAULT_CYCLE_TIMES 0xFFFF +#define DEFAULT_MAX_RAND_NUM 0xFFFFFFFF + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class compilation_aot_emit_memory_test : public testing::Test +{ + protected: + void SetUp() override + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + /* default value, enable or disable depends on the platform */ + option.stack_bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = reinterpret_cast(wasm_runtime_load( + wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf))); + EXPECT_NE(wasm_module, nullptr); + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(comp_data, nullptr); + + // properly init compilation and function context, to do that, + // use as a dummy module(instead of compile the function in it, simply + // test the APIs) + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + func_ctx = comp_ctx->func_ctxes[0]; + EXPECT_NE(func_ctx, nullptr); + } + + void TearDown() override + { + aot_destroy_comp_context(comp_ctx); + aot_destroy_comp_data(comp_data); + wasm_runtime_unload(reinterpret_cast(wasm_module)); + } + + public: + WASMModule *wasm_module = nullptr; + AOTCompData *comp_data = nullptr; + AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(compilation_aot_emit_memory_test, aot_check_memory_overflow) +{ + uint32 offset = 64; + uint32 bytes = 4; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes, false); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i32_load) +{ + uint32 align = 0; + uint32 offset = 1024; + uint32 bytes = 0; + bool sign = false; + bool atomic = false; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + bytes = (1 + (rand() % (4 - 1 + 1))); + printf("---%d", aot_compile_op_i32_load(comp_ctx, func_ctx, align, + offset, bytes, sign, atomic)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i64_load) +{ + uint32 align = 0; + uint32 offset = 1024; + uint32 bytes = 0; + bool sign = false; + bool atomic = false; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + bytes = (1 + (rand() % (4 - 1 + 1))); + sign = !sign; + atomic = !atomic; + aot_compile_op_i64_load(comp_ctx, func_ctx, align, offset, bytes, sign, + atomic); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f32_load) +{ + uint32 align = 10; + uint32 offset = 10; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + aot_compile_op_f32_load(comp_ctx, func_ctx, align, offset); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f64_load) +{ + uint32 align = 10; + uint32 offset = 10; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + aot_compile_op_f64_load(comp_ctx, func_ctx, align, offset); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i32_store) +{ + uint32 align = 0; + uint32 offset = 0; + uint32 bytes = 0; + bool atomic = false; + + EXPECT_FALSE(aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + bytes = (1 + (rand() % (4 - 1 + 1))); + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + atomic = !atomic; + + EXPECT_FALSE(aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i64_store) +{ + uint32 align = 0; + uint32 offset = 0; + uint32 bytes = 0; + bool atomic = false; + + EXPECT_FALSE(aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + bytes = (1 + (rand() % (8 - 1 + 1))); + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + atomic = !atomic; + + EXPECT_FALSE(aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f32_store) +{ + uint32 align = 0; + uint32 offset = 0; + + EXPECT_FALSE(aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + + EXPECT_FALSE( + aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f64_store) +{ + uint32 align = 0; + uint32 offset = 0; + + EXPECT_FALSE(aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + + EXPECT_FALSE( + aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_size) +{ + aot_compile_op_memory_size(comp_ctx, func_ctx); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_grow) +{ + aot_compile_op_memory_grow(comp_ctx, func_ctx); +} + +#if WASM_ENABLE_BULK_MEMORY != 0 +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_init) +{ + uint32 seg_index = 0; + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + seg_index = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + aot_compile_op_memory_init(comp_ctx, func_ctx, seg_index); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_data_drop) +{ + uint32 seg_index = 0; + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + seg_index = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + aot_compile_op_data_drop(comp_ctx, func_ctx, seg_index); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_copy) +{ + aot_compile_op_memory_copy(comp_ctx, func_ctx); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_fill) +{ + aot_compile_op_memory_fill(comp_ctx, func_ctx); +} +#endif + +#if WASM_ENABLE_SHARED_MEMORY != 0 +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_rmw) +{ + uint8 atomic_op = LLVMAtomicRMWBinOpAdd; + uint8 op_type = VALUE_TYPE_I32; + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compile_op_atomic_rmw(comp_ctx, func_ctx, atomic_op, op_type, align, + offset, bytes); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_cmpxchg) +{ + + uint8 op_type = VALUE_TYPE_I32; + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compile_op_atomic_cmpxchg(comp_ctx, func_ctx, op_type, align, offset, + bytes); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_wait) +{ + + uint8 op_type = VALUE_TYPE_I32; + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compile_op_atomic_wait(comp_ctx, func_ctx, op_type, align, offset, + bytes); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compiler_op_atomic_notify) +{ + + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compiler_op_atomic_notify(comp_ctx, func_ctx, align, offset, bytes); +} +#endif diff --git a/tests/unit/compilation/aot_emit_numberic_test.cc b/tests/unit/compilation/aot_emit_numberic_test.cc new file mode 100644 index 000000000..f7e6e8ee7 --- /dev/null +++ b/tests/unit/compilation/aot_emit_numberic_test.cc @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_emit_numberic.h" +#include "aot_compiler.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_numberic_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_numberic_test_suite, aot_compile_op_functions) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + EXPECT_EQ(false, + aot_compile_op_f32_arithmetic(comp_ctx, func_ctx, FLOAT_SUB)); + EXPECT_EQ(false, aot_compile_op_f32_copysign(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_f32_math(comp_ctx, func_ctx, FLOAT_NEG)); + EXPECT_EQ(false, + aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, FLOAT_SUB)); + EXPECT_EQ(false, aot_compile_op_f64_copysign(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_f64_math(comp_ctx, func_ctx, FLOAT_NEG)); + EXPECT_EQ(false, aot_compile_op_i32_clz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i32_ctz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i32_popcnt(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i32_shift(comp_ctx, func_ctx, INT_SHR_S)); + EXPECT_EQ(false, aot_compile_op_i64_arithmetic(comp_ctx, func_ctx, INT_SUB, + nullptr)); + EXPECT_EQ(false, aot_compile_op_i64_bitwise(comp_ctx, func_ctx, INT_OR)); + EXPECT_EQ(false, aot_compile_op_i64_clz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i64_ctz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i64_popcnt(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i64_shift(comp_ctx, func_ctx, INT_SHR_S)); +} diff --git a/tests/unit/compilation/aot_emit_parametric_test.cc b/tests/unit/compilation/aot_emit_parametric_test.cc new file mode 100644 index 000000000..f9dabe1c8 --- /dev/null +++ b/tests/unit/compilation/aot_emit_parametric_test.cc @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_emit_parametric.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_parametric_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_parametric_test_suite, aot_compile_op_select) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + EXPECT_FALSE(aot_compile_op_select(comp_ctx, func_ctx, true)); + EXPECT_FALSE(aot_compile_op_select(comp_ctx, func_ctx, false)); +} + +TEST_F(aot_emit_parametric_test_suite, aot_compile_op_drop) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + func_ctx->block_stack.block_list_end = nullptr; + + EXPECT_FALSE(aot_compile_op_drop(comp_ctx, func_ctx, true)); + EXPECT_FALSE(aot_compile_op_drop(comp_ctx, func_ctx, false)); +} diff --git a/tests/unit/compilation/aot_emit_table_test.cc b/tests/unit/compilation/aot_emit_table_test.cc new file mode 100644 index 000000000..fc4bfe2f1 --- /dev/null +++ b/tests/unit/compilation/aot_emit_table_test.cc @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_emit_table.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_table_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_table_test_suite, get_tbl_inst_offset) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 6)); + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 1)); + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 0)); + ((AOTCompData *)comp_ctx->comp_data)->import_table_count = 1; + AOTImportTable import_tables_test; + ((AOTCompData *)comp_ctx->comp_data)->import_tables = &import_tables_test; + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 6)); +} diff --git a/tests/unit/compilation/aot_emit_variable_test.cc b/tests/unit/compilation/aot_emit_variable_test.cc new file mode 100644 index 000000000..11cc238f0 --- /dev/null +++ b/tests/unit/compilation/aot_emit_variable_test.cc @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "aot_emit_variable.h" + +#define DEFAULT_CYCLE_TIMES 0xFFFF +#define DEFAULT_MAX_RAND_NUM 0xFFFFFFFF + +class compilation_aot_emit_variable_test : public testing::Test +{ + protected: + virtual void SetUp() {} + virtual void TearDown() {} + + public: + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; +}; + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_get_local) +{ + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 local_idx = 0; + + // aot_compile_op_get_local(NULL, pfunc_ctx, local_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_get_local(pcomp_ctx, pfunc_ctx, local_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_set_local) +{ + + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 local_idx = 0; + + // aot_compile_op_set_local(pcomp_ctx, pfunc_ctx, local_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_set_local(pcomp_ctx, pfunc_ctx, local_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_tee_local) +{ + + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 local_idx = 0; + + // aot_compile_op_tee_local(pcomp_ctx, pfunc_ctx, local_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_tee_local(pcomp_ctx, pfunc_ctx, local_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_get_global) +{ + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 global_idx = 0; + + // aot_compile_op_get_global(pcomp_ctx, pfunc_ctx, global_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_get_global(pcomp_ctx, pfunc_ctx, global_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_set_global) +{ + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 global_idx = 0; + bool is_aux_stack = false; + + // aot_compile_op_set_global(pcomp_ctx, pfunc_ctx, global_idx, + // is_aux_stack); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // is_aux_stack = is_aux_stack ? false : ture; + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_set_global(pcomp_ctx, pfunc_ctx, + // global_idx,is_aux_stack); + // } +} \ No newline at end of file diff --git a/tests/unit/compilation/aot_llvm_test.cc b/tests/unit/compilation/aot_llvm_test.cc new file mode 100644 index 000000000..dcebe04b4 --- /dev/null +++ b/tests/unit/compilation/aot_llvm_test.cc @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_compiler.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_llvm_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_llvm_test_suite, aot_functions) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + AOTFuncContext *func_ctx = nullptr; + WASMValue wasm_value; + LLVMTypeRef param_types[1]; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + param_types[0] = F64_TYPE; + EXPECT_TRUE(aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f32_demote_f64", + F32_TYPE, param_types, 0)); + + /* Test function aot_get_native_symbol_index. */ + AOTNativeSymbol elem_insert_1; + elem_insert_1.index = -1; + bh_list_insert(&comp_ctx->native_symbols, &elem_insert_1); + + AOTNativeSymbol elem_insert_2; + strcpy(elem_insert_2.symbol, "f64#_test"); + elem_insert_2.index = -1; + bh_list_insert(&comp_ctx->native_symbols, &elem_insert_2); + comp_ctx->pointer_size = sizeof(uint32); + strcpy(comp_ctx->target_arch, "i386"); + EXPECT_NE(-1, aot_get_native_symbol_index(comp_ctx, "f64#_test")); +} + +TEST_F(aot_llvm_test_suite, wasm_type_to_llvm_type) {} + +TEST_F(aot_llvm_test_suite, aot_build_zero_function_ret) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + AOTFuncContext *func_ctx = nullptr; + AOTFuncType func_type; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = false; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + func_type.result_count = 1; + func_type.param_count = 0; + func_type.types[func_type.param_count] = VALUE_TYPE_I32; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_I64; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_F32; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_F64; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_V128; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + /* THe current optimization, if not actually use ref_types in wasm module, + * it will set to false, so test false condition */ + func_type.types[func_type.param_count] = VALUE_TYPE_FUNCREF; + EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type), + ".*"); + func_type.types[func_type.param_count] = VALUE_TYPE_EXTERNREF; + EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type), + ".*"); + func_type.types[func_type.param_count] = 0xFF; + EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type), + ".*"); +} + +TEST_F(aot_llvm_test_suite, aot_destroy_comp_context) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + AOTFuncContext *func_ctx = nullptr; + AOTFuncType func_type; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + AOTNativeSymbol elem_insert_1; + elem_insert_1.index = -1; + bh_list_insert(&comp_ctx->native_symbols, &elem_insert_1); + aot_destroy_comp_context(comp_ctx); + + aot_destroy_comp_context(nullptr); +} + +TEST_F(aot_llvm_test_suite, aot_create_comp_context) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + + option.enable_thread_mgr = true; + option.enable_tail_call = true; + option.is_indirect_mode = true; + option.disable_llvm_intrinsics = true; + option.disable_llvm_lto = true; + option.is_jit_mode = true; + + option.target_arch = (char *)"arm"; + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + option.output_format = 100; + comp_ctx = aot_create_comp_context(comp_data, &option); + + // Test every target_arch. + option.is_jit_mode = false; + option.target_arch = (char *)"arm"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"armeb"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"thumb"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"thumbeb"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"aarch64"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"aarch64_be"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"help"; + comp_ctx = aot_create_comp_context(comp_data, &option); + + // Test every target_abi. + option.target_arch = (char *)"arm"; + option.target_abi = (char *)"test"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_abi = (char *)"help"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_abi = (char *)"msvc"; + option.target_arch = (char *)"i386"; + comp_ctx = aot_create_comp_context(comp_data, &option); + + option.cpu_features = (char *)"test"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.is_sgx_platform = true; + comp_ctx = aot_create_comp_context(comp_data, &option); + comp_data->func_count = 0; + comp_ctx = aot_create_comp_context(comp_data, &option); +} diff --git a/tests/unit/compilation/wasm-apps/main.wasm b/tests/unit/compilation/wasm-apps/main.wasm new file mode 100644 index 0000000000000000000000000000000000000000..28af80e4052ce6e62666bfaccdc27e7275eaf542 GIT binary patch literal 1217 zcmcIjOK;Oa5T4n!orl}>5g{l&uz`ZwLzA?rQc|QsS}q8|0U<6ea{bsOZelywPEbzn z1&RN_0sa-gf+Hs`%qFQQ9H190@9fO(%(vg{&VZc+2mrXIpRp{%>a; zG8`Mj*bmbV05^1GoN1blLqyayM8=FV&#?Vv)6Ag#DX%2yxwknZkUCiMyg)_e7HSj}8)kM6WlSITHrA0MOtC1Ft4^Cf9tf%z$ zrz)q@_f)CYT#IK~Es0%#!1k%MRN5}6V9=+D+|czR+bZX~Y@J}?D;DSEsl=#|r(tlN zL!6O6@UG=abZS@GxC1-vim{9nKMKW8qgt=l#bz%}hsi;$*7eig$f>$fP#X-!GqF94 zqjTw|qT}s&58d5Peb4jcZo`qX-fy^+S7LDL(9v=HtKjo_3}6^vll6ts)RklG<+H8b)+uGA)pZtFUm;ft$ literal 0 HcmV?d00001 diff --git a/tests/unit/custom-section/CMakeLists.txt b/tests/unit/custom-section/CMakeLists.txt new file mode 100644 index 000000000..1529d0ea6 --- /dev/null +++ b/tests/unit/custom-section/CMakeLists.txt @@ -0,0 +1,65 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-custom-section) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LAZY_JIT 0) +set (WAMR_BUILD_AOT 1) + +add_definitions(-DWASM_ENABLE_WAMR_COMPILER=1) +add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) + +# Feature to test +set (WAMR_BUILD_LOAD_CUSTOM_SECTION 1) + +include (../unit_common.cmake) + +set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ) + +# Automatically build wasm-apps for this test +add_subdirectory(wasm-apps) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (custom_section_test ${unit_test_sources}) + +target_link_libraries (custom_section_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +gtest_discover_tests(custom_section_test) diff --git a/tests/unit/custom-section/custom_section_test.cc b/tests/unit/custom-section/custom_section_test.cc new file mode 100644 index 000000000..9bf04664a --- /dev/null +++ b/tests/unit/custom-section/custom_section_test.cc @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include +#include "test_helper.h" +#include "aot_export.h" + +class CustomSectionTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<1 * 1024 * 1024> runtime; +}; + +TEST_F(CustomSectionTest, get_custom_section_from_wasm_module_t) +{ + uint32_t length, len_from_aot; + const uint8_t *content, *content_from_aot; + std::ifstream wasm_file("wasm-apps/app.wasm", std::ios::binary); + std::vector buffer(std::istreambuf_iterator(wasm_file), + {}); + { + WAMRModule module(buffer.data(), buffer.size()); + aot_comp_data_t comp_data = NULL; + aot_comp_context_t comp_ctx = NULL; + std::vector sections_to_emit{ + "name", + ".debug_info", + ".debug_abbrev", + /* skip ".debug_line" section in AoT module */ + ".debug_str", + "producers", + }; + + AOTCompOption option = { 0 }; + option.custom_sections = (char **)sections_to_emit.data(); + option.custom_sections_count = 5; + + { + /* Compile an AoT module */ + comp_data = aot_create_comp_data(module.get(), NULL, false); + EXPECT_NE(comp_data, nullptr); + + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_TRUE(aot_emit_aot_file(comp_ctx, comp_data, "temp.aot")); + } + + std::ifstream aot_file("temp.aot", std::ios::binary); + std::vector aot_buffer( + std::istreambuf_iterator(aot_file), {}); + WAMRModule aot_module(aot_buffer.data(), aot_buffer.size()); + + /* name */ + content = + wasm_runtime_get_custom_section(module.get(), "name", &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + /* TODO: aot_emit_name_section don't + EMIT_U32(AOT_CUSTOM_SECTION_RAW);* + EMIT_STR("name"); + but instead + EMIT_U32(AOT_CUSTOM_SECTION_NAME); + can't use get_custom_section to get it + */ + // content_from_aot = wasm_runtime_get_custom_section( + // aot_module.get(), "name", &len_from_aot); + // EXPECT_NE(content_from_aot, nullptr); + // EXPECT_EQ(len_from_aot, length); + // EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* .debug_info */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_info", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_info", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* .debug_abbrev */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_abbrev", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_abbrev", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* .debug_line */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_line", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_line", &len_from_aot); + EXPECT_EQ(content_from_aot, nullptr); + + /* .debug_str */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_str", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_str", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* producers */ + content = + wasm_runtime_get_custom_section(module.get(), "producers", &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), "producers", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* Not exist */ + content = wasm_runtime_get_custom_section(module.get(), "producers1", + &length); + EXPECT_EQ(content, nullptr); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), "producers1", &len_from_aot); + EXPECT_EQ(content_from_aot, nullptr); + } +} diff --git a/tests/unit/custom-section/wasm-apps/CMakeLists.txt b/tests/unit/custom-section/wasm-apps/CMakeLists.txt new file mode 100644 index 000000000..a539dd236 --- /dev/null +++ b/tests/unit/custom-section/wasm-apps/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project(wasm-apps-custom-section) + +# Add -g option so there will be debugger related custom sections +add_custom_target(app.wasm ALL + COMMAND /opt/wasi-sdk/bin/clang -g -nostdlib + -Wl,--no-entry,--export-all + -o ${CMAKE_CURRENT_BINARY_DIR}/app.wasm + ${CMAKE_CURRENT_LIST_DIR}/app.c +) diff --git a/tests/unit/custom-section/wasm-apps/app.c b/tests/unit/custom-section/wasm-apps/app.c new file mode 100644 index 000000000..3820e3c7c --- /dev/null +++ b/tests/unit/custom-section/wasm-apps/app.c @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +int +main(int argc, char const *argv[]) +{ + return 0; +} diff --git a/tests/unit/gc/CMakeLists.txt b/tests/unit/gc/CMakeLists.txt new file mode 100644 index 000000000..e0f70d142 --- /dev/null +++ b/tests/unit/gc/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-wamr-gc) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_GC 1) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} +) + +add_executable (gc_test ${unit_test_sources}) +target_link_libraries (gc_test gtest_main) + +add_custom_command(TARGET gc_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/*.was* + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy wasm files to directory ${CMAKE_CURRENT_BINARY_DIR}" +) + +#gtest_discover_tests(gc_test) \ No newline at end of file diff --git a/tests/unit/gc/gc_test.cc b/tests/unit/gc/gc_test.cc new file mode 100644 index 000000000..196ddba65 --- /dev/null +++ b/tests/unit/gc/gc_test.cc @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" + +class WasmGCTest : public testing::Test +{ + private: + std::string get_binary_path() + { + char cwd[1024] = { 0 }; + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + return NULL; + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); + } + + protected: + void SetUp() + { + CWD = get_binary_path(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + cleanup = true; + } + + void TearDown() + { + if (cleanup) { + wasm_runtime_destroy(); + } + } + + public: + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = strdup((CWD + "/" + wasm_file).c_str()); + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + return false; + + module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + if (!module) + return false; + + return true; + } + + public: + std::string CWD; + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_function_inst_t func_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + bool cleanup = true; +}; + +TEST_F(WasmGCTest, Test_app1) +{ + ASSERT_TRUE(load_wasm_file("test1.wasm")); + ASSERT_TRUE(load_wasm_file("test2.wasm")); + ASSERT_TRUE(load_wasm_file("test3.wasm")); + ASSERT_TRUE(load_wasm_file("test4.wasm")); + ASSERT_TRUE(load_wasm_file("test5.wasm")); + ASSERT_TRUE(load_wasm_file("test6.wasm")); + + ASSERT_TRUE(load_wasm_file("struct1.wasm")); + ASSERT_TRUE(load_wasm_file("struct2.wasm")); + ASSERT_TRUE(load_wasm_file("struct3.wasm")); + + ASSERT_TRUE(load_wasm_file("func1.wasm")); + ASSERT_TRUE(load_wasm_file("func2.wasm")); +} diff --git a/tests/unit/gc/wasm-apps/func1.wasm b/tests/unit/gc/wasm-apps/func1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..51b316b54edacd385cb79b8d54e8ebe886eb0c20 GIT binary patch literal 106 zcmZQbEY4+QU|?YEY-ng;U`k+MNMK6OVqk6paTyueJHRwcNosKk0|VD~FmEG>6ksl3 s&S%VH%wPq&S7B8VPq^|1kw=UEXH&NhTk4(QVNW}9kZmk0cPtN<^TWy literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/func1.wast b/tests/unit/gc/wasm-apps/func1.wast new file mode 100644 index 000000000..1b4941787 --- /dev/null +++ b/tests/unit/gc/wasm-apps/func1.wast @@ -0,0 +1,35 @@ +(module + (type $t (func)) + + (func (export "test") (param structref i31ref) + (local funcref) + (local funcref) + (local funcref) + (local externref) + (local externref) + (local externref) + (local anyref) + (local eqref) + (local structref) + (local arrayref) + (local i31ref) + (local (ref null 0)) + (local (ref null 0)) + (local (ref null 0)) + (local (ref null 1)) + (local (ref null func)) + (local (ref null 0)) + (local (ref null extern)) + (local (ref null any)) + (local (ref null eq)) + (local (ref null i31)) + (local (ref null struct)) + + local.get 0 + ref.test null array + drop + local.get 1 + ref.cast i31 + drop + ) +) diff --git a/tests/unit/gc/wasm-apps/func2.wasm b/tests/unit/gc/wasm-apps/func2.wasm new file mode 100644 index 0000000000000000000000000000000000000000..e5d852ce4664d9109bc5ae6e0c5f7da48096d746 GIT binary patch literal 470 zcmcJKO=`q23`U=l$)+dhsz>ON;iMMtn~{e0(kf z$k*e3=Y51xqA}r+RpHTk{>JMo6g)Z)`ut}Aj z8&@(bArn>-3lpA*jXmnE;+bvs@%k2s> literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/func2.wast b/tests/unit/gc/wasm-apps/func2.wast new file mode 100644 index 000000000..bfe588dd5 --- /dev/null +++ b/tests/unit/gc/wasm-apps/func2.wast @@ -0,0 +1,78 @@ +(module + (type $t0 (func)) + (type $t1 (func (param (ref null 1)))) + (type $t2 (func (param funcref externref (ref func)(ref extern) + anyref eqref structref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 1) (ref $t0) (ref null func) + (ref null extern) (ref null 2) (ref null $t0)) + (result (ref null func)))) + (type $t3 (func (param i32 i32) (result (ref null 3)))) + + (type $t4 (func)) + (type $t5 (func (param (ref null 3)))) + (type $t6 (func (param funcref externref (ref func)(ref extern) + anyref eqref structref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)) + (result (ref null func)))) + (type $t7 (func (param i32 i32) (result (ref null 4)))) + + (type $t11 (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null struct) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type $t12 (struct)) + (type $t13 (struct (field))) + (type $t14 (struct (field i8))) + (type $t15 (struct (field i8 i8 i8 i8))) + (type $t16 (struct (field $x1 i32) (field $y1 i32))) + (type $t17 (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type $t18 (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type $t19 (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) + + (type $t20 (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref structref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type $t21 (struct)) + (type $t22 (struct (field))) + (type $t23 (struct (field i8))) + (type $t24 (struct (field i8 i8 i8 i8))) + (type $t25 (struct (field $x3 i32) (field $y3 i32))) + (type $t26 (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type $t27 (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type $t28 (struct (field $x4 i32) (field f32 f64) (field $y4 i32))) + + (type $t31 (array i8)) + (type $t32 (array i16)) + (type $t33 (array i32)) + (type $t34 (array i64)) + (type $t35 (array f32)) + (type $t36 (array f64)) + (type $t37 (array anyref)) + (type $t38 (array (ref i31))) + (type $t39 (array (ref 0))) + (type $t40 (array (ref null 1))) + (type $t43 (array (mut i8))) + (type $t44 (array (mut i16))) + (type $t45 (array (mut i32))) + (type $t46 (array (mut i64))) + (type $t47 (array (mut i32))) + (type $t48 (array (mut i64))) + (type $t49 (array (mut anyref))) + (type $t50 (array (mut (ref struct)))) + (type $t51 (array (mut (ref 0)))) + (type $t52 (array (mut (ref null i31)))) +) diff --git a/tests/unit/gc/wasm-apps/global1.wasm b/tests/unit/gc/wasm-apps/global1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..706cc954c48e64ac555113486c195338e876633a GIT binary patch literal 554 zcmd6k!EM7Z3`HO9B!_r`o;pJ(qTP!Rk}L`6DTZSO?WJ3EC8Ha3lTuE*Ku-llQuz4) zlY)4DnFNrpx7&@UK?*}tRw+YsU1S*!UVIZIGz)}nY>A&!`Qb=t>1)VLf0(&P-xLb{ z+5D~F{i8XVJ_!A>VzW6$)0BO>vH#UJI-?h~peuSs7c`=Nv;?(B=q!2>Eu!mhjba2# oM4hy+H~VHeojz(mWj^T=Tk0ZP>?XFc8*6cFt~V_~Ui`xFqZ&{Tb0trK11dux-=#)eZEyj;Fj-$P?r!P(p SRyHP>1#RDEjM=pKcbx}0=@RMy literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/struct1.wast b/tests/unit/gc/wasm-apps/struct1.wast new file mode 100644 index 000000000..3ce6fde6b --- /dev/null +++ b/tests/unit/gc/wasm-apps/struct1.wast @@ -0,0 +1,10 @@ +(module + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x1 i32) (field $y1 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) +) diff --git a/tests/unit/gc/wasm-apps/struct2.wasm b/tests/unit/gc/wasm-apps/struct2.wasm new file mode 100644 index 0000000000000000000000000000000000000000..497a96441938f39943904cfb416a6bcc60893952 GIT binary patch literal 234 zcmaisF%H5o5CnI9wj*$pC-@2QqL?D0h)5G8L}AGdB6R$Lg1_;FG}x9xOS8APH@7%U zCj#Irr3BkaL}Ww&$G`!M*~OrSk_KjxxquCoXrqm-TL!TxxaM7MTE_kYm}7tLc2Jus t&*HDpKfj0FernOJX#K8L@K^+J_cd8T~Ud8Iiy p3=A-lVweac*AlSO9uUdMn8TpJ@SB-|QHr}4A>hdHn~i~y8vtg|A3y*A literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/struct3.wast b/tests/unit/gc/wasm-apps/struct3.wast new file mode 100644 index 000000000..b7678ba78 --- /dev/null +++ b/tests/unit/gc/wasm-apps/struct3.wast @@ -0,0 +1,9 @@ +(module + (type $t (struct (field i32 (mut i32)))) + (func (export "struct.get-null") + (local (ref null $t)) (drop (struct.get $t 1 (local.get 0))) + ) + (func (export "struct.set-null") + (local (ref null $t)) (struct.set $t 1 (local.get 0) (i32.const 0)) + ) +) diff --git a/tests/unit/gc/wasm-apps/table1.wasm b/tests/unit/gc/wasm-apps/table1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..f43b425398e0addf187cb0dcc315aff6fc251cbe GIT binary patch literal 560 zcmd6kJx;_h5QV=8fRxxof=mDoCj49&_^9r#SXQAXM2-L+|nR9yx_N)RK){ zBs3lTmD)Z{+@;9M!b~RNGd>X+=@|%E@dMwH!7z_C@iX@Pa3R#Rd&orFOq|hHg+hBZ zecMm{XiCNpLVMY<$rPh;%2D02|5Z0Sp?9>PE4rXF8d2Zd1hq%#BzhMuqU-M(#S&~H qI!N=m**D)Z*Th5QW#qNT4LEbvnXNA45-#G#1GdW(F;AVD>b?QRrG>5l literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/table1.wast b/tests/unit/gc/wasm-apps/table1.wast new file mode 100644 index 000000000..8e0061835 --- /dev/null +++ b/tests/unit/gc/wasm-apps/table1.wast @@ -0,0 +1,108 @@ +(module + (type $ftype0 (func (param i32))) + (type $ftype1 (func (param i32 i64) (result i32))) + (type $ftype2 (func (param f32 f64) (result f64))) + (type $t0 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2)))) + (type $t1 (func (param funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 3) (ref null $t0)) + (result (ref null func)))) + (type $t2 (func (param i32 i32) (result (ref null 4)))) + + ;; Duplicated types + (type $t3 (func)) + (type $t4 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2)))) + (type $t5 (func (param funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 3) (ref null $t0)) + (result (ref null func)))) + (type $t6 (func (param i32 i32) (result (ref null 4)))) + + (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x1 i32) (field $y1 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) + + ;; Duplicated types + (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x3 i32) (field $y3 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32))) + + (type (array i8)) + (type (array i16)) + (type (array i32)) + (type (array i64)) + (type (array f32)) + (type (array f64)) + (type (array anyref)) + (type (array (ref array))) + (type (array (ref 0))) + (type (array (ref null 1))) + (type (array (mut i8))) + (type (array (mut i16))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut anyref))) + (type (array (mut (ref array)))) + (type (array (mut (ref 0)))) + (type (array (mut (ref null i31)))) + + (table 10 funcref) + (table 20 externref) + ;; non-defaultable element type + ;; (table 30 (ref func)) + ;; (table 40 (ref extern)) + (table 50 anyref) + (table 60 eqref) + (table 100 arrayref) + (table 100 i31ref) + (table 100 (ref null 0)) + (table 100 (ref null 2)) + (table 100 (ref null func)) + (table 100 (ref null extern)) + (table 100 (ref null any)) + (table 100 (ref null eq)) + (table 100 (ref null i31)) + (table 100 (ref null array)) + ;; non-defaultable element type + ;; (table 100 (ref 0)) + ;; (table 100 (ref $t0)) + ;; (table 100 (ref 3)) + ;; (table 100 (ref $t0)) + (table 100 (ref null func)) + (table 100 (ref null extern)) + (table 100 (ref null 5)) + (table 100 (ref null $t0)) +) diff --git a/tests/unit/gc/wasm-apps/test1.wasm b/tests/unit/gc/wasm-apps/test1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..d907e457f589c37ecdb58ceac4ac65fd12e46af4 GIT binary patch literal 647 zcmd5%NlwE+5Uh3x2VTJ&P;x;$A}?s0L+r#g9$VsMEAiyOr@2vMgAgA;sMXb@nyOy# z`qmi$`*^?I@KOQQeE_kf(NH}NeeBw%KAulMFAnS(*|BBAnn#{_3J4a8FAYIs@msbT zdRkSaB-x)0Djz3|mTblq7YyjZ0qhacp+SvSry>-~Pv+W%CA2@d$(TK1tK(4SunFbe zgf+?{A)$QG4Apf;ltcck-)3%7&nQn?Hjw(?ZR8VtgeUk6zrru@2xp_L;VMF1WMyEk5-?0O0*sX!s^Kq*bEo1%#u6Jzu^o&r697nzN3 zz(A3N|9|hBe`emm-)$HG_EDB4j0ND~_5ll)(tl(}?N#wHG`;&?6w(B&3|0!u{CuR| z)?*PDV3Rxuy&~8Zp4hL~-ko3g;Nuqh;sDKV+h7a5Ta0h6VO+F}yCUB&3k=R%;^(=4 zfcfu^a4(h^p0%mEA6>S6JxFk01Ub#z9sft{(X)CF)4*W;JgL``lz=U3b5V&YTvkP- zyb4G)*OU&qE;%DJT*wKhV&Fh#u@;8=~7m*bh2{$32vo(v1c8GOajLz>FHL)zgiPt*L6YV zdbzAV>`d$3!*+MQeZCXdP~NXMPaDzZ`^_w$RwO~9%3MN|;G#M_wNVw&s2-R_EdU?2 z1d6EDT-qPRiCl!5M^y~U5?oFokw7AWL;{Hf zW9m!AzI=xsKKCHegG3J!JxKI020D2HXPKQOoFtqioFtsazzKK)XO*2KoFtqioFtsa zz=^4BN1bhzvm|9VO3D(FGRL2~aprDPoQ4kGjt-{waN@H8F2N_12^GS54ZP({R>mt* z@D&{Cf+m<@f)OTIgLbLL1ZOb88WXIsEc+Qc6Ra`8h7jkiwC^v&|CSv8+D$WVsU6j9 ZR1DU|kW9ro?vQoUHVdocneEkX_6yM(<=+4R literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/test3.wast b/tests/unit/gc/wasm-apps/test3.wast new file mode 100644 index 000000000..4df02ce8f --- /dev/null +++ b/tests/unit/gc/wasm-apps/test3.wast @@ -0,0 +1,146 @@ +(module + (type $t0 (sub (struct))) + (type $t1 (sub $t0 (struct (field i32)))) + (type $t1' (sub $t0 (struct (field i32)))) + (type $t2 (sub $t1 (struct (field i32 i32)))) + (type $t2' (sub $t1' (struct (field i32 i32)))) + (type $t3 (sub $t0 (struct (field i32 i32)))) + (type $t0' (sub $t0 (struct))) + (type $t4 (sub $t0' (struct (field i32 i32)))) + + (table 20 (ref null struct)) + + (func $init + (table.set (i32.const 0) (struct.new_canon_default $t0)) + (table.set (i32.const 10) (struct.new_canon_default $t0)) + (table.set (i32.const 1) (struct.new_canon_default $t1)) + (table.set (i32.const 11) (struct.new_canon_default $t1')) + (table.set (i32.const 2) (struct.new_canon_default $t2)) + (table.set (i32.const 12) (struct.new_canon_default $t2')) + (table.set (i32.const 3) (struct.new_canon_default $t3)) + (table.set (i32.const 4) (struct.new_canon_default $t4)) + ) + + (func (export "test-sub") + (call $init) + (block $l + ;; must hold + (br_if $l (i32.eqz (ref.test null $t0 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test null $t1 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t1 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test null $t1 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test null $t2 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t2 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test null $t3 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t3 (table.get (i32.const 3))))) + + (br_if $l (i32.eqz (ref.test null $t4 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t4 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t2 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t3 (table.get (i32.const 3))))) + + (br_if $l (i32.eqz (ref.test $t4 (table.get (i32.const 4))))) + + ;; must not hold + (br_if $l (ref.test $t0 (ref.null struct))) + (br_if $l (ref.test $t1 (ref.null struct))) + (br_if $l (ref.test $t2 (ref.null struct))) + (br_if $l (ref.test $t3 (ref.null struct))) + (br_if $l (ref.test $t4 (ref.null struct))) + + (br_if $l (ref.test $t1 (table.get (i32.const 0)))) + (br_if $l (ref.test $t1 (table.get (i32.const 3)))) + (br_if $l (ref.test $t1 (table.get (i32.const 4)))) + + (br_if $l (ref.test $t2 (table.get (i32.const 0)))) + (br_if $l (ref.test $t2 (table.get (i32.const 1)))) + (br_if $l (ref.test $t2 (table.get (i32.const 3)))) + (br_if $l (ref.test $t2 (table.get (i32.const 4)))) + + (br_if $l (ref.test $t3 (table.get (i32.const 0)))) + (br_if $l (ref.test $t3 (table.get (i32.const 1)))) + (br_if $l (ref.test $t3 (table.get (i32.const 2)))) + (br_if $l (ref.test $t3 (table.get (i32.const 4)))) + + (br_if $l (ref.test $t4 (table.get (i32.const 0)))) + (br_if $l (ref.test $t4 (table.get (i32.const 1)))) + (br_if $l (ref.test $t4 (table.get (i32.const 2)))) + (br_if $l (ref.test $t4 (table.get (i32.const 3)))) + + (return) + ) + (unreachable) + ) + + (func (export "test-canon") + (call $init) + (block $l + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 10))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 11))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 12))))) + + (br_if $l (i32.eqz (ref.test $t1' (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t1' (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 11))))) + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 12))))) + + (br_if $l (i32.eqz (ref.test $t2' (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t2 (table.get (i32.const 12))))) + + (return) + ) + (unreachable) + ) +) diff --git a/tests/unit/gc/wasm-apps/test4.wasm b/tests/unit/gc/wasm-apps/test4.wasm new file mode 100644 index 0000000000000000000000000000000000000000..b4841a82cb878091351cbe6e43bbcdef6e88341f GIT binary patch literal 299 zcmZQbEY4+QU|?YEZD?p!Z5?qq__ba>{DX^ literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/test4.wast b/tests/unit/gc/wasm-apps/test4.wast new file mode 100644 index 000000000..8bf02e430 --- /dev/null +++ b/tests/unit/gc/wasm-apps/test4.wast @@ -0,0 +1,46 @@ +(module + (type $ft (func)) + (type $st (struct)) + (type $at (array i8)) + + (table 10 anyref) + + (elem declare func $f) + (func $f) + + (func (export "init") (param $x externref) + (table.set (i32.const 0) (ref.null any)) + (table.set (i32.const 1) (i31.new (i32.const 7))) + (table.set (i32.const 2) (struct.new_canon_default $st)) + (table.set (i32.const 3) (array.new_canon_default $at (i32.const 0))) + (table.set (i32.const 4) (extern.internalize (local.get $x))) + (table.set (i32.const 5) (ref.null i31)) + (table.set (i32.const 6) (ref.null struct)) + (table.set (i32.const 7) (ref.null none)) + ) + + (func (export "ref_cast_non_null") (param $i i32) + (drop (ref.as_non_null (table.get (local.get $i)))) + (drop (ref.cast null any (table.get (local.get $i)))) + ) + (func (export "ref_cast_null") (param $i i32) + (drop (ref.cast null any (table.get (local.get $i)))) + (drop (ref.cast null struct (table.get (local.get $i)))) + (drop (ref.cast null array (table.get (local.get $i)))) + (drop (ref.cast null i31 (table.get (local.get $i)))) + (drop (ref.cast null none (table.get (local.get $i)))) + ) + (func (export "ref_cast_i31") (param $i i32) + (drop (ref.cast i31 (table.get (local.get $i)))) + (drop (ref.cast null i31 (table.get (local.get $i)))) + ) + (func (export "ref_cast_struct") (param $i i32) + (drop (ref.cast struct (table.get (local.get $i)))) + (drop (ref.cast null struct (table.get (local.get $i)))) + ) + (func (export "ref_cast_array") (param $i i32) + (drop (ref.cast array (table.get (local.get $i)))) + (drop (ref.cast null array (table.get (local.get $i)))) + ) +) + diff --git a/tests/unit/gc/wasm-apps/test5.wasm b/tests/unit/gc/wasm-apps/test5.wasm new file mode 100644 index 0000000000000000000000000000000000000000..050ead4ae9fde01db1690721be8f931206be8d43 GIT binary patch literal 512 zcmaKoF;c@o3`M`R4mREtDX6w5T@JA&U2b3k!=xe<4s}e1OK=s28Lq%#sMrQcmPsnA zr!W04t&L6pNC4<_7zSLf(P2&K=x_pce1K}63Y-dQUySM&2(P*%G)+@kMO$3eZ`$K# z|IqJO{qr5Dweo(md)k59pQA?J)r5?~SR%J0s4$6&g;~IbgJ52`5`@AtK~=b3B7VGR ze1WfRxk1XfhLN1?49;q#yUj%@n~RcnO@&EWa+b0s>+wRCOPW=xTd6*!`u^s=J5LPm n^L@Ea@!P(CA%EaJ_|M|jebG5T&#^y9XmdGi^XUPV>yY9vVfuIE literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/test5.wast b/tests/unit/gc/wasm-apps/test5.wast new file mode 100644 index 000000000..895473ce3 --- /dev/null +++ b/tests/unit/gc/wasm-apps/test5.wast @@ -0,0 +1,85 @@ +(module + (type $t0 (sub (struct))) + (type $t1 (sub $t0 (struct (field i32)))) + (type $t1' (sub $t0 (struct (field i32)))) + (type $t2 (sub $t1 (struct (field i32 i32)))) + (type $t2' (sub $t1' (struct (field i32 i32)))) + (type $t3 (sub $t0 (struct (field i32 i32)))) + (type $t0' (sub $t0 (struct))) + (type $t4 (sub $t0' (struct (field i32 i32)))) + + (table 20 (ref null struct)) + + (func $init + (table.set (i32.const 0) (struct.new_canon_default $t0)) + (table.set (i32.const 10) (struct.new_canon_default $t0)) + (table.set (i32.const 1) (struct.new_canon_default $t1)) + (table.set (i32.const 11) (struct.new_canon_default $t1')) + (table.set (i32.const 2) (struct.new_canon_default $t2)) + (table.set (i32.const 12) (struct.new_canon_default $t2')) + (table.set (i32.const 3) (struct.new_canon_default $t3)) + (table.set (i32.const 4) (struct.new_canon_default $t4)) + ) + + (func (export "test-sub") + (call $init) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t0 (table.get (i32.const 0)))) + (drop (ref.cast null $t0 (table.get (i32.const 1)))) + (drop (ref.cast null $t0 (table.get (i32.const 2)))) + (drop (ref.cast null $t0 (table.get (i32.const 3)))) + (drop (ref.cast null $t0 (table.get (i32.const 4)))) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t1 (table.get (i32.const 1)))) + (drop (ref.cast null $t1 (table.get (i32.const 2)))) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t2 (table.get (i32.const 2)))) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t3 (table.get (i32.const 3)))) + + (drop (ref.cast null $t4 (table.get (i32.const 4)))) + + (drop (ref.cast $t0 (table.get (i32.const 0)))) + (drop (ref.cast $t0 (table.get (i32.const 1)))) + (drop (ref.cast $t0 (table.get (i32.const 2)))) + (drop (ref.cast $t0 (table.get (i32.const 3)))) + (drop (ref.cast $t0 (table.get (i32.const 4)))) + + (drop (ref.cast $t1 (table.get (i32.const 1)))) + (drop (ref.cast $t1 (table.get (i32.const 2)))) + + (drop (ref.cast $t2 (table.get (i32.const 2)))) + + (drop (ref.cast $t3 (table.get (i32.const 3)))) + + (drop (ref.cast $t4 (table.get (i32.const 4)))) + ) + + (func (export "test-canon") + (call $init) + + (drop (ref.cast $t0 (table.get (i32.const 0)))) + (drop (ref.cast $t0 (table.get (i32.const 1)))) + (drop (ref.cast $t0 (table.get (i32.const 2)))) + (drop (ref.cast $t0 (table.get (i32.const 3)))) + (drop (ref.cast $t0 (table.get (i32.const 4)))) + + (drop (ref.cast $t0 (table.get (i32.const 10)))) + (drop (ref.cast $t0 (table.get (i32.const 11)))) + (drop (ref.cast $t0 (table.get (i32.const 12)))) + + (drop (ref.cast $t1' (table.get (i32.const 1)))) + (drop (ref.cast $t1' (table.get (i32.const 2)))) + + (drop (ref.cast $t1 (table.get (i32.const 11)))) + (drop (ref.cast $t1 (table.get (i32.const 12)))) + + (drop (ref.cast $t2' (table.get (i32.const 2)))) + + (drop (ref.cast $t2 (table.get (i32.const 12)))) + ) +) diff --git a/tests/unit/gc/wasm-apps/test6.wasm b/tests/unit/gc/wasm-apps/test6.wasm new file mode 100644 index 0000000000000000000000000000000000000000..b1abc14729ffe04acd72180963e77174e24912ab GIT binary patch literal 197 zcmXYpu?@m75Jmr83^t@g4B#g0;SD?ign}YSMnX{0*b;P6W?>8JG<0m@2HQz-|J{Gm z9ga6g0O%b;z{=u)G~}^=z*25gPFxlZuAud= us83E9jBW=*<2fZ88FgYcQy5kHA~KR*PLKw1!>Oxzsr&Luqk*Od-}( +#include "gtest/gtest.h" +#include "wasm_runtime_common.h" +#include "bh_platform.h" + +// To use a test fixture, derive a class from testing::Test. +class InterpreterTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() { wasm_runtime_destroy(); } + + public: + char global_heap_buf[512 * 1024]; + RuntimeInitArgs init_args; +}; + +TEST_F(InterpreterTest, wasm_runtime_is_built_in_module) +{ + bool ret = wasm_runtime_is_built_in_module("env"); + ASSERT_TRUE(ret); + + ret = ret = wasm_runtime_is_built_in_module("env1"); + ASSERT_FALSE(ret); +} \ No newline at end of file diff --git a/tests/unit/libc-builtin/CMakeLists.txt b/tests/unit/libc-builtin/CMakeLists.txt new file mode 100644 index 000000000..4d88760e7 --- /dev/null +++ b/tests/unit/libc-builtin/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-libc-builtin) + +add_definitions (-DRUN_ON_LINUX) + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ) + +add_executable (libc_builtin_test ${unit_test_sources}) + +target_link_libraries (libc_builtin_test gtest_main) + +gtest_discover_tests(libc_builtin_test) diff --git a/tests/unit/libc-builtin/func_types.h b/tests/unit/libc-builtin/func_types.h new file mode 100644 index 000000000..c653ee9c8 --- /dev/null +++ b/tests/unit/libc-builtin/func_types.h @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#pragma once + +#include "bh_platform.h" +#include "wasm_export.h" + +extern "C" { +typedef char *_va_list; + +typedef int (*printf_func_type)(wasm_exec_env_t exec_env, const char *format, + _va_list va_args); + +typedef int (*sprintf_func_type)(wasm_exec_env_t exec_env, char *str, + const char *format, _va_list va_args); + +typedef int (*snprintf_func_type)(wasm_exec_env_t exec_env, char *str, + uint32 size, const char *format, + _va_list va_args); + +typedef int (*puts_func_type)(wasm_exec_env_t exec_env, const char *str); + +typedef int (*putchar_func_type)(wasm_exec_env_t exec_env, int c); + +typedef uint32 (*strdup_func_type)(wasm_exec_env_t exec_env, const char *str); + +typedef uint32 (*_strdup_func_type)(wasm_exec_env_t exec_env, const char *str); + +typedef int32 (*memcmp_func_type)(wasm_exec_env_t exec_env, const void *s1, + const void *s2, uint32 size); + +typedef uint32 (*memcpy_func_type)(wasm_exec_env_t exec_env, void *dst, + const void *src, uint32 size); + +typedef uint32 (*memmove_func_type)(wasm_exec_env_t exec_env, void *dst, + void *src, uint32 size); + +typedef uint32 (*memset_func_type)(wasm_exec_env_t exec_env, void *s, int32 c, + uint32 size); + +typedef uint32 (*strchr_func_type)(wasm_exec_env_t exec_env, const char *s, + int32 c); + +typedef int32 (*strcmp_func_type)(wasm_exec_env_t exec_env, const char *s1, + const char *s2); + +typedef int32 (*strncmp_func_type)(wasm_exec_env_t exec_env, const char *s1, + const char *s2, uint32 size); + +typedef uint32 (*strcpy_func_type)(wasm_exec_env_t exec_env, char *dst, + const char *src); + +typedef uint32 (*strncpy_func_type)(wasm_exec_env_t exec_env, char *dst, + const char *src, uint32 size); + +typedef uint32 (*strlen_func_type)(wasm_exec_env_t exec_env, const char *s); + +typedef uint32 (*malloc_func_type)(wasm_exec_env_t exec_env, uint32 size); + +typedef uint32 (*calloc_func_type)(wasm_exec_env_t exec_env, uint32 nmemb, + uint32 size); + +typedef uint32 (*realloc_func_type)(wasm_exec_env_t exec_env, uint32 ptr, + uint32 new_size); + +typedef void (*free_func_type)(wasm_exec_env_t exec_env, void *ptr); + +typedef int32 (*atoi_func_type)(wasm_exec_env_t exec_env, const char *s); + +typedef void (*exit_func_type)(wasm_exec_env_t exec_env, int32 status); + +typedef int32 (*strtol_func_type)(wasm_exec_env_t exec_env, const char *nptr, + char **endptr, int32 base); + +typedef uint32 (*strtoul_func_type)(wasm_exec_env_t exec_env, const char *nptr, + char **endptr, int32 base); + +typedef uint32 (*memchr_func_type)(wasm_exec_env_t exec_env, const void *s, + int32 c, uint32 n); + +typedef int32 (*strncasecmp_func_type)(wasm_exec_env_t exec_env, const char *s1, + const char *s2, uint32 n); +typedef uint32 (*strspn_func_type)(wasm_exec_env_t exec_env, const char *s, + const char *accept); + +typedef uint32 (*strcspn_func_type)(wasm_exec_env_t exec_env, const char *s, + const char *reject); + +typedef uint32 (*strstr_func_type)(wasm_exec_env_t exec_env, const char *s, + const char *find); + +typedef int32 (*isupper_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isalpha_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isspace_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isgraph_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isprint_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isdigit_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isxdigit_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*tolower_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*toupper_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isalnum_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef void (*setTempRet0_func_type)(wasm_exec_env_t exec_env, + uint32 temp_ret); + +typedef uint32 (*getTempRet0_func_type)(wasm_exec_env_t exec_env); + +typedef uint32 (*llvm_bswap_i16_func_type)(wasm_exec_env_t exec_env, + uint32 data); + +typedef uint32 (*llvm_bswap_i32_func_type)(wasm_exec_env_t exec_env, + uint32 data); + +typedef uint32 (*bitshift64Lshr_func_type)(wasm_exec_env_t exec_env, + uint32 uint64_part0, + uint32 uint64_part1, uint32 bits); + +typedef uint32 (*bitshift64Shl_func_type)(wasm_exec_env_t exec_env, + uint32 int64_part0, + uint32 int64_part1, uint32 bits); + +typedef void (*llvm_stackrestore_func_type)(wasm_exec_env_t exec_env, + uint32 llvm_stack); + +typedef uint32 (*llvm_stacksave_func_type)(wasm_exec_env_t exec_env); + +typedef uint32 (*emscripten_memcpy_big_func_type)(wasm_exec_env_t exec_env, + void *dst, const void *src, + uint32 size); + +typedef void (*abort_func_type)(wasm_exec_env_t exec_env, int32 code); + +typedef void (*abortStackOverflow_func_type)(wasm_exec_env_t exec_env, + int32 code); + +typedef void (*nullFunc_X_func_type)(wasm_exec_env_t exec_env, int32 code); + +typedef uint32 (*__cxa_allocate_exception_func_type)(wasm_exec_env_t exec_env, + uint32 thrown_size); + +typedef void (*__cxa_begin_catch_func_type)(wasm_exec_env_t exec_env, + void *exception_object); + +typedef void (*__cxa_throw_func_type)(wasm_exec_env_t exec_env, + void *thrown_exception, void *tinfo, + uint32 table_elem_idx); + +struct timespec_app { + int64 tv_sec; + int32 tv_nsec; +}; + +typedef uint32 (*clock_gettime_func_type)(wasm_exec_env_t exec_env, + uint32 clk_id, + struct timespec_app *ts_app); + +typedef uint64 (*clock_func_type)(wasm_exec_env_t exec_env); +} diff --git a/tests/unit/libc-builtin/libc_builtin_test.cc b/tests/unit/libc-builtin/libc_builtin_test.cc new file mode 100644 index 000000000..6598f7a8b --- /dev/null +++ b/tests/unit/libc-builtin/libc_builtin_test.cc @@ -0,0 +1,1412 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "func_types.h" +#include "test_helper.h" +#include "wasm_export.h" +#include "gtest/gtest.h" +#include + +#include "../interpreter/wasm.h" + +void *func_ptr; +#define CALL_FUNC(name, ...) \ + ((name##_func_type)get_func(#name))(dummy_exec_env.get(), ##__VA_ARGS__) + +extern "C" { +extern uint32_t +get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis); + +extern bool +wasm_native_lookup_libc_builtin_global(const char *module_name, + const char *global_name, + WASMGlobalImport *global); +} + +class LibcBuiltinTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + n_native_symbols = get_libc_builtin_export_apis(&native_symbols); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; + DummyExecEnv dummy_exec_env; + static NativeSymbol *native_symbols; + static uint32_t n_native_symbols; + + static void *get_func(const char *name) + { + int32_t i; + + for (i = 0; i < n_native_symbols; i++) { + if (strcmp(native_symbols[i].symbol, name) == 0) { + return native_symbols[i].func_ptr; + } + } + + return NULL; + } +}; + +NativeSymbol *LibcBuiltinTest::native_symbols; +uint32_t LibcBuiltinTest::n_native_symbols; + +static const char very_long_string[] = + R"(2mwa9vxDhuuvO47XePZvc4DAMdR8dzgKrmRNAM3qVoedFhG7GYyhlC4JiuSdrw8G + 7vrPoCLGlVlGwMw7ATDL3bA5Filds8krTxS7h8ioq6CY4UmKl1zjHlmnOYRO3Wmp + ylp21RrG8LzfHFerFyKFxA1GB93OuTFcasO2n9uQljCx8h5KRolbvjdHVnado4B6 + 3zNV990V7T7LIJHwZKb0RGg0fFo4GQd6Mfdl6aD3UlpKBIxjbonyeaQBY7hPZB8R + J1JV5iw2PWB2BJEGoGhTvlc0a9FxmeqWIjpnU3yNEg2lD3NjZU627pTFcoAy5GCz + wDyF5QzcvtAgWBR95kRpDtV21CRyQ6HteorX1aHemoMYWOLIvX52stUTAnOImMD8 + tIw6xwkOZx5fs3x9m540pPnRDiihLn2XuQ1PLPwA6orWOGm3dBKthqsycTqaIl0L + 0gpycKbVYFHmakfgEyP9fyMziLT11B6EPzomHQAYgTVUdDl9u63P6sQCeaPwAYsY + gus28uK9YYjpXgOOziG8ocBddvids1iLJLdbiAqKyHaVY4IBLVWU3F74tKGF7TeI + DGAfvpzHls19VM9bKReBfCmDgbib7mCpYEFAQCmu5my0C8QrJlUoOgiljIO0x3sH + ByNf4k9OfhzYi1V4cvDnMELVrk0fyZWmIxDvig7nfzI57OltT28pughPBlLxTn8X + xyMNVYn1dD6Wpp7sqOBjxWGWmdrjleyin0iQ05UbfioHazvLKHtDfm5P2WwVejm6)"; + +TEST_F(LibcBuiltinTest, puts) +{ + char ll_string[2048]; + + /* Capture the stdout */ + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, "Hello Wrold"), strlen("Hello Wrold\n")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "Hello Wrold\n"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, "c"), strlen("c\n")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "c\n"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, very_long_string), strlen(very_long_string) + 1); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + std::string(very_long_string) + "\n"); + + memset(ll_string, 0xAA, sizeof(ll_string)); + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, ll_string), strlen(ll_string) + 1); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + std::string(ll_string) + "\n"); +} + +TEST_F(LibcBuiltinTest, printf) +{ + WAMRVaList empty_va_list(dummy_exec_env.get()); + + /* Capture the stdout */ + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", empty_va_list.get()), + strlen("Hello Wrold")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "Hello Wrold"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "c", empty_va_list.get()), strlen("c")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "c"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, very_long_string, empty_va_list.get()), + strlen(very_long_string)); + EXPECT_EQ(testing::internal::GetCapturedStdout(), very_long_string); + + /* type */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); //%d 20 + va_list.add(65); //%i 65 + va_list.add(10); //%O 12 + va_list.add(10); //%u 10 + va_list.add(255); //%x ff + va_list.add(255); //%X FF + va_list.add(3.14); //%f 3.14 + va_list.add(3.14); //%F 3.14 + va_list.add(0.000001); //%e 1.000000e-06 + va_list.add(0.000001); //%E 1.000000E-06 + va_list.add(0.000001); //%g 1e-06 + va_list.add(0.000001); //%G 1E-06 + va_list.add("Hello World"); //%s Hello World + + testing::internal::CaptureStdout(); + /* clang-format off */ + EXPECT_EQ(CALL_FUNC(printf, "%d, %i, %o, %u, %x, %X, %f, %F, %e, %E, %g, %G, %s", va_list.get()), 97); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 65, 12, 10, ff, FF, 3.140000, 3.140000, 1.000000e-06, 1.000000E-06, 1e-06, 1E-06, Hello World"); + /* clang-format on */ + } + + /* %c */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add('C'); //%c C + // va_list.add("Hello"); //%p + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "%c", va_list.get()), 1); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "C"); + } + + /* %p */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add("Hello"); + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "%p", va_list.get()), 7); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "0x200a8"); + } + + { + /* clang-format off */ + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); //%td + va_list.add(20); //%zd + va_list.add(20); //%ld + + va_list.add(20L); //%jd + + testing::internal::CaptureStdout(); + + EXPECT_EQ(CALL_FUNC(printf, "%td, %zd, %ld, %jd", va_list.get()), 14); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 20, 20, 20"); + /* clang-format on */ + } + + /* %% */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + EXPECT_TRUE(CALL_FUNC(printf, "%%", va_list.get())); + } + + /* %n */ + { + /* Construct a va_list to call printf */ + WAMRVaList empty_va_list(dummy_exec_env.get()); + + /* Capture the stdout */ + testing::internal::CaptureStdout(); + CALL_FUNC(printf, "0123%n", empty_va_list.get()); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "0123"); + } + + /* flag */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + /*%-*/ + va_list.add(20); //%-d 20 + va_list.add(20); //%d 20 + + /*%+*/ + va_list.add(20); //%+d +20 + va_list.add(-20); //%+d -20 + + /*% */ + va_list.add(20); //% d 20 + va_list.add(-20); //% d -20 + + /*%#*/ + va_list.add(20); //%#o 024 + va_list.add(255); //%#x 0xff + va_list.add(255); //%#X 0xFF + va_list.add(3.14); //%#.f 3. + va_list.add(3.14); //%#.lf 3. + va_list.add(3.14); //%#.e 3.e+00 + va_list.add(3.14); //%#.E 3.E+00 + va_list.add(3.14); //%#.g 3. + va_list.add(3.14); //%#.G 3. + va_list.add(20); //%#.a %a + va_list.add(20); //%#.A %A + + /*%0*/ + va_list.add(20); //%03d 020 + + testing::internal::CaptureStdout(); + /* clang-format off */ + EXPECT_EQ(CALL_FUNC(printf, "%-d, %d, %+d, %+d, % d, % d, %#o, %#x, %#X, %#.f, %#.lf, %#.e, %#.E, %#.g, %#.G, %#.a, %#.A, %03d", va_list.get()), 88); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 20, +20, -20, 20, -20, 024, 0xff, 0XFF, 3., 3., 3.e+00, 3.E+00, 3., 3., %a, %A, 020"); + /* clang-format on */ + } + + /* precision */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); //%d 20 + va_list.add(20); //%.1d 20 + va_list.add(20); //%.2d 20 + va_list.add(20); //%.3d 020 + va_list.add(20); //%.4d 0020 + va_list.add(20); //%.5d 00020 + va_list.add(20); //%.6d 000020 + va_list.add(20); //%.7d 0000020 + va_list.add(20); //%.8d 00000020 + va_list.add(20); //%.9d 000000020 + testing::internal::CaptureStdout(); + /* clang-format off */ + EXPECT_EQ(CALL_FUNC(printf, "%d, %.1d, %.2d, %.3d, %.4d, %.5d, %.6d, %.7d, %.8d, %.9d", va_list.get()), 66); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 20, 20, 020, 0020, 00020, 000020, 0000020, 00000020, 000000020"); + /* clang-format on */ + } + + /*length*/ + { + /* clang-format off */ + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(0x7F); //%hhd 127 -char + va_list.add(0xFF); //%hhu.1d 255 -unsiged char + va_list.add(0x7FFF); //%hd 32767 -sing short int + va_list.add(0xFFFF); //%hu 65535 -unsiged short + va_list.add(0x7FFFFFFF); //%ld 2147483647 - sing long + va_list.add(0xFFFFFFFF); //%lu 4294967295 -unsigned long + va_list.add(0x7FFFFFFFFFFFFFFF); //%lld 9223372036854775807 sing long long + va_list.add(0xFFFFFFFFFFFFFFFF);//%llu 18446744073709551615 unsiged long long + + testing::internal::CaptureStdout(); + + EXPECT_EQ(CALL_FUNC(printf, "%hhd, %hhu, %hd, %hu, %ld, %lu, %lld, %llu", va_list.get()), 89); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "127, 255, 32767, 65535, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615"); + /* clang-format on */ + } + + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", 0), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", NULL), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", (char *)-1), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(printf, (char *)-1, (char *)-1), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, sprintf) +{ + const char *buf; + const char *str = "Hello Wrold"; + const char *str_sig = "c"; + const char *str_f = "20, 3.140000, Hello World"; + const char *str_long = "eqwewerwerqwer34were"; // test ok + // const char *str_long = "TDSFGAWE%#$TERFQ@$%$@!%$@!RS!$#@$%" + // "WAWAAEWAFSDNGFUTKNZDAERQWYNZREWGHAH"; + // //fail + + WAMRVaList empty_va_list(dummy_exec_env.get()); + + AppData buf_app{ dummy_exec_env.get(), buf }; + AppData str_app{ dummy_exec_env.get(), str }; + AppData str_sig_app{ dummy_exec_env.get(), str_sig }; + AppData str_long_app{ dummy_exec_env.get(), str_long }; + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), 0), + 0); + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), NULL), + 0); + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), (char *)-1), + 0); + + EXPECT_FALSE(CALL_FUNC(sprintf, (char *)-1, + (char *)str_app.get_native_addr(), + empty_va_list.get())); + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), empty_va_list.get()), + strlen(str)); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), + str_app.get_native_addr(), strlen(str)), + 0); + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_sig_app.get_native_addr(), + empty_va_list.get()), + strlen(str_sig)); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), + str_sig_app.get_native_addr(), strlen(str_sig)), + 0); + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_long_app.get_native_addr(), + empty_va_list.get()), + strlen(str_long)); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), + str_long_app.get_native_addr(), strlen(str_long)), + 0); + + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); + va_list.add(3.14); + va_list.add("Hello World"); + + /* This is like printf("%d, %f, %s", 20, 3.14, "Hello World") */ + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + "%d, %f, %s", va_list.get()), + 25); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), str_f, 25), 0); + } +} + +TEST_F(LibcBuiltinTest, snprintf) +{ + char buf[1024]; + char buf1[10]; + + WAMRVaList empty_va_list(dummy_exec_env.get()); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", 0), + 0); + EXPECT_EQ( + CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", NULL), + 0); + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", + (char *)-1), + 0); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", + empty_va_list.get()), + strlen("Hello Wrold")); + EXPECT_EQ(CALL_FUNC(memcmp, buf, "Hello Wrold", strlen("Hello Wrold")), 0); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen(very_long_string), + very_long_string, empty_va_list.get()), + strlen(very_long_string)); + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); + va_list.add(3.14); + va_list.add("Hello World"); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, 25, "%d, %f, %s", va_list.get()), + 25); + } +} + +TEST_F(LibcBuiltinTest, putchar) +{ + char ch; + + for (ch = 'a'; ch <= 'z'; ch++) + EXPECT_EQ(CALL_FUNC(putchar, ch), 1); + + for (ch = '0'; ch <= '9'; ch++) + EXPECT_EQ(CALL_FUNC(putchar, ch), 1); + + for (ch = 0; ch < 127; ch++) + EXPECT_EQ(CALL_FUNC(putchar, ch), 1); +} + +TEST_F(LibcBuiltinTest, strdup) +{ + const char *src = "Hello World!"; + + AppData src_app{ dummy_exec_env.get(), src }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(strdup, NULL), 0); + + EXPECT_GE(CALL_FUNC(strdup, (char *)src_app.get_native_addr()), 0); +} + +TEST_F(LibcBuiltinTest, _strdup) +{ + const char *src = "Hello World!"; + + AppData src_app{ dummy_exec_env.get(), src }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(_strdup, NULL), 0); + + EXPECT_GE(CALL_FUNC(_strdup, (char *)src_app.get_native_addr()), 0); +} + +TEST_F(LibcBuiltinTest, memcmp) +{ + const char *a = "aBcDeF"; + const char *b = "AbCdEf"; + const char *c = "aacdef"; + const char *d = "aBcDeF"; + + AppData a_app{ dummy_exec_env.get(), a }; + AppData b_app{ dummy_exec_env.get(), b }; + AppData c_app{ dummy_exec_env.get(), c }; + AppData d_app{ dummy_exec_env.get(), d }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(memcmp, (void *)-1, d_app.get_native_addr(), 0), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + /* size = 0 */ + EXPECT_EQ( + CALL_FUNC(memcmp, a_app.get_native_addr(), d_app.get_native_addr(), 0), + 0); + + // /* s1>s2 */ + EXPECT_GT(CALL_FUNC(memcmp, a_app.get_native_addr(), + b_app.get_native_addr(), strlen(a)), + 0); + // /* s1s2*/ + EXPECT_GT(CALL_FUNC(strcmp, (char *)b_app.get_native_addr(), + (char *)a_app.get_native_addr()), + 0); + /*s1s2*/ + EXPECT_GT(CALL_FUNC(strncmp, (char *)b_app.get_native_addr(), + (char *)a_app.get_native_addr(), strlen(a)), + 0); + /*s1s2*/ + EXPECT_GT(CALL_FUNC(strncmp, (char *)b_app.get_native_addr(), + (char *)a_app.get_native_addr(), 3), + 0); + /*s1= UINT32_MAX */ + EXPECT_EQ(CALL_FUNC(calloc, 1, 0xffffffff), 0); + + /* nmemb = 1 size=0xffffffff-1 total_size >= UINT32_MAX-1 */ + EXPECT_EQ(CALL_FUNC(calloc, 1, (0xffffffff - 1)), 0); + + /* nmemb = 1 size = 0 total_size = 0 */ + /* According to Linux man page: + If nmemb or size is 0, then calloc() returns either NULL, or a unique + pointer value that can later be successfully passed to free() */ + EXPECT_GE(CALL_FUNC(calloc, 1, 0), 0); + + /* nmemb = 10 size = 1024 total_size < UINT32_MAX */ + EXPECT_GT(CALL_FUNC(calloc, 10, 1024), 0); +} + +TEST_F(LibcBuiltinTest, realloc) +{ + unsigned int ptr = 0; + + // ptr = 0; + // EXPECT_EQ(CALL_FUNC(realloc, ptr, 1024), 0); + + // ptr = 1; + // EXPECT_GT(CALL_FUNC(realloc, ptr, 1024), 0); + + // ptr = 3; + // EXPECT_GT(CALL_FUNC(realloc, ptr, 1024), 0); + + /* If ptr is NULL, then the call is equivalent to malloc(size), for all + * values of size */ + ptr = CALL_FUNC(realloc, ptr, 1024); + EXPECT_EQ(ptr, ptr); + EXPECT_EQ(CALL_FUNC(realloc, ptr, 10), ptr); + EXPECT_EQ(CALL_FUNC(realloc, ptr, 15), ptr); + + ptr = CALL_FUNC(realloc, ptr, 2048); + EXPECT_EQ(ptr, ptr); + + /* If size is equal to zero, and ptr is not NULL, then + the call is equivalent to free(ptr) */ + CALL_FUNC(realloc, ptr, 0); +} + +TEST_F(LibcBuiltinTest, free) +{ + const char *src; + const char *s = "Hello World!"; + + AppMemory src_mem{ dummy_exec_env.get(), 15 }; + AppData s_app{ dummy_exec_env.get(), s }; + + CALL_FUNC(free, (char *)0xFFFFFFFF); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(free, (char *)-1); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(free, NULL); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + memset((char *)src_mem.get_native_addr(), '\0', 15); + strcpy((char *)src_mem.get_native_addr(), (char *)s_app.get_native_addr()); + EXPECT_EQ(CALL_FUNC(memcmp, (char *)src_mem.get_native_addr(), + s_app.get_native_addr(), 15), + 0); + + /* free */ + CALL_FUNC(free, (char *)src_mem.get_native_addr()); + EXPECT_NE(CALL_FUNC(memcmp, (char *)src_mem.get_native_addr(), + s_app.get_native_addr(), 15), + 0); +} + +TEST_F(LibcBuiltinTest, atoi) +{ + char *src = (char *)"123"; + char *src1 = (char *)"-123"; + + AppData src_app{ dummy_exec_env.get(), src }; + AppData src1_app{ dummy_exec_env.get(), src1 }; + + EXPECT_EQ(CALL_FUNC(atoi, (char *)src_app.get_native_addr()), 123); + EXPECT_EQ(CALL_FUNC(atoi, (char *)src1_app.get_native_addr()), -123); +} + +TEST_F(LibcBuiltinTest, exit) +{ + CALL_FUNC(exit, 3); + EXPECT_STREQ(dummy_exec_env.get_exception(), "Exception: env.exit(3)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, strtol) +{ + char str[20] = "20"; + char str1[20] = "-20"; + char buffer[20] = "0x31"; + char buffer1[20] = "10379cend$3"; + char *ptr; + + AppData src_app{ dummy_exec_env.get(), str }; + AppData src1_app{ dummy_exec_env.get(), str1 }; + AppData buffer_app{ dummy_exec_env.get(), buffer }; + AppData buffer1_app{ dummy_exec_env.get(), buffer1 }; + AppMemory ptr_app{ dummy_exec_env.get(), 20 }; + + CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(strtol, (char *)src_app.get_native_addr(), &ptr, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 2), 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 8), 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 10), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 16), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 32), + 0); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 2), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 8), + 16); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 20); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 32); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 32), + 64); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 2), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 8), + -16); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + -20); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + -32); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 32), + -64); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 0), + 49); + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 49); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 0); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 10379); + // EXPECT_STREQ((char *)ptr_app.get_native_addr(), "cend$3"); + + uint32_t str_app_addr = *(uint32_t *)ptr_app.get_native_addr(); + EXPECT_GT(str_app_addr, 0); + char *str_native_addr = (char *)dummy_exec_env.app_to_native(str_app_addr); + EXPECT_NE(str_native_addr, nullptr); + EXPECT_STREQ(str_native_addr, "cend$3"); +} + +TEST_F(LibcBuiltinTest, strtoul) +{ + char str[20] = "20"; + char buffer[20] = "0x31"; + char buffer1[20] = "10379cend$3"; + char *ptr; + + AppData src_app{ dummy_exec_env.get(), str }; + AppData buffer_app{ dummy_exec_env.get(), buffer }; + AppData buffer1_app{ dummy_exec_env.get(), buffer1 }; + AppMemory ptr_app{ dummy_exec_env.get(), 20 }; + + CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), &ptr, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 2), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 8), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 10), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 16), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 32), + 0); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 2), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 8), + 16); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 20); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 32); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 32), + 64); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 0), + 49); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 49); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 0); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 10379); + + uint32_t str_app_addr = *(uint32_t *)ptr_app.get_native_addr(); + EXPECT_GT(str_app_addr, 0); + char *str_native_addr = (char *)dummy_exec_env.app_to_native(str_app_addr); + EXPECT_NE(str_native_addr, nullptr); + EXPECT_STREQ(str_native_addr, "cend$3"); +} + +TEST_F(LibcBuiltinTest, memchr) +{ + const char src[] = "Hello World."; + char ch = 'o'; + + AppData src_app{ dummy_exec_env.get(), src }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(memchr, (char *)-1, ch, strlen(src)), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_GE(CALL_FUNC(memchr, src_app.get_native_addr(), ch, strlen(src)), 0); +} + +TEST_F(LibcBuiltinTest, strncasecmp) +{ + const char *src1 = "Hello World."; + const char *src2 = "hel"; + const char *src3 = "HELLO WORLD."; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + + EXPECT_GT(CALL_FUNC(strncasecmp, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr(), 4), + 0); + + EXPECT_LT(CALL_FUNC(strncasecmp, (char *)src2_app.get_native_addr(), + (char *)src1_app.get_native_addr(), 4), + 0); + + EXPECT_EQ(CALL_FUNC(strncasecmp, (char *)src1_app.get_native_addr(), + (char *)src3_app.get_native_addr(), strlen(src1)), + 0); +} + +TEST_F(LibcBuiltinTest, strspn) +{ + const char *src1 = "Hello world!"; + const char *src2 = "abcd"; + const char *src3 = "l"; + const char *src4 = "Hell"; + const char *src5 = "Helo"; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + AppData src4_app{ dummy_exec_env.get(), src4 }; + AppData src5_app{ dummy_exec_env.get(), src5 }; + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr()), + 0); + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src3_app.get_native_addr()), + 0); + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src4_app.get_native_addr()), + 4); + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src5_app.get_native_addr()), + 5); +} + +TEST_F(LibcBuiltinTest, strcspn) +{ + const char *src1 = "Hello world!"; + const char *src2 = ".?"; + const char *src3 = "llo"; + const char *src4 = "http://www.baidu.com/"; + const char *src5 = "?.,:\"\'-!"; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + AppData src4_app{ dummy_exec_env.get(), src4 }; + AppData src5_app{ dummy_exec_env.get(), src5 }; + + EXPECT_EQ(CALL_FUNC(strcspn, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr()), + 12); + + EXPECT_EQ(CALL_FUNC(strcspn, (char *)src1_app.get_native_addr(), + (char *)src3_app.get_native_addr()), + 2); + + EXPECT_EQ(CALL_FUNC(strcspn, (char *)src4_app.get_native_addr(), + (char *)src5_app.get_native_addr()), + 4); +} + +TEST_F(LibcBuiltinTest, strstr) +{ + const char *src1 = "Hello world!"; + const char *src2 = "abcd"; + const char *src3 = "Hello"; + const char *src4 = "H"; + const char *src5 = "llo"; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + AppData src4_app{ dummy_exec_env.get(), src4 }; + AppData src5_app{ dummy_exec_env.get(), src5 }; + + EXPECT_EQ(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr()), + 0); + + EXPECT_EQ(CALL_FUNC(strstr, (char *)src3_app.get_native_addr(), + (char *)src1_app.get_native_addr()), + 0); + + EXPECT_GT(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(), + (char *)src4_app.get_native_addr()), + 0); + + EXPECT_GT(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(), + (char *)src5_app.get_native_addr()), + 0); +} + +TEST_F(LibcBuiltinTest, isupper) +{ + EXPECT_FALSE(CALL_FUNC(isupper, 'a')); + + EXPECT_FALSE(CALL_FUNC(isupper, 97)); + + EXPECT_FALSE(CALL_FUNC(isupper, '0')); + + EXPECT_FALSE(CALL_FUNC(isupper, '.')); + + EXPECT_TRUE(CALL_FUNC(isupper, 'A')); + + EXPECT_TRUE(CALL_FUNC(isupper, 65)); +} + +TEST_F(LibcBuiltinTest, isalpha) +{ + EXPECT_FALSE(CALL_FUNC(isalpha, '0')); + + EXPECT_FALSE(CALL_FUNC(isalpha, 0)); + + EXPECT_FALSE(CALL_FUNC(isalpha, '?')); + + EXPECT_TRUE(CALL_FUNC(isalpha, 'A')); + + EXPECT_TRUE(CALL_FUNC(isalpha, 'a')); +} + +TEST_F(LibcBuiltinTest, isspace) +{ + EXPECT_FALSE(CALL_FUNC(isspace, '0')); + + EXPECT_FALSE(CALL_FUNC(isspace, 0)); + + EXPECT_FALSE(CALL_FUNC(isspace, '?')); + + EXPECT_TRUE(CALL_FUNC(isspace, ' ')); + EXPECT_TRUE(CALL_FUNC(isspace, '\t')); + EXPECT_TRUE(CALL_FUNC(isspace, '\n')); + EXPECT_TRUE(CALL_FUNC(isspace, '\v')); + EXPECT_TRUE(CALL_FUNC(isspace, '\f')); + EXPECT_TRUE(CALL_FUNC(isspace, '\r')); +} + +TEST_F(LibcBuiltinTest, isgraph) +{ + /* ASCII 0x00-0x20 */ + EXPECT_FALSE(CALL_FUNC(isgraph, 0x00)); + EXPECT_FALSE(CALL_FUNC(isgraph, 0x20)); + + /* ASCII 0x7F */ + EXPECT_FALSE(CALL_FUNC(isgraph, 0x7F)); + EXPECT_FALSE(CALL_FUNC(isgraph, 0x80)); + + /* ASCII 0x21-0x7E */ + EXPECT_TRUE(CALL_FUNC(isgraph, 0x21)); + EXPECT_TRUE(CALL_FUNC(isgraph, 0x7E)); +} + +TEST_F(LibcBuiltinTest, isprint) +{ + /* ASCII 0x00-0x1F */ + EXPECT_FALSE(CALL_FUNC(isprint, 0x00)); + EXPECT_FALSE(CALL_FUNC(isprint, 0x1F)); + + /* ASCII 0x7F */ + EXPECT_FALSE(CALL_FUNC(isprint, 0x7F)); + EXPECT_FALSE(CALL_FUNC(isprint, 0x80)); + + /* ASCII 0x20-0x7E */ + EXPECT_TRUE(CALL_FUNC(isprint, 0x20)); + EXPECT_TRUE(CALL_FUNC(isprint, 0x7E)); +} + +TEST_F(LibcBuiltinTest, isdigit) +{ + /* ASCII 0x00-0x2F */ + EXPECT_FALSE(CALL_FUNC(isdigit, 0x00)); + EXPECT_FALSE(CALL_FUNC(isdigit, 0x2F)); + + /* ASCII 0x3A-0x7F */ + EXPECT_FALSE(CALL_FUNC(isdigit, 0x3A)); + EXPECT_FALSE(CALL_FUNC(isdigit, 0x7F)); + + /* ASCII 0x30-0x39 */ + EXPECT_TRUE(CALL_FUNC(isdigit, 0x30)); + EXPECT_TRUE(CALL_FUNC(isdigit, 0x39)); +} + +TEST_F(LibcBuiltinTest, isxdigit) +{ + char str[] = "-FFEE"; + char str1[] = "FFEE"; + + EXPECT_FALSE(CALL_FUNC(isxdigit, str[0])); + EXPECT_TRUE(CALL_FUNC(isxdigit, str1[0])); + + /* ASCII 0x00-0x2F */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x00)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x2F)); + + /* ASCII 0x3A-0x40 */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x3A)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x40)); + + /* ASCII 0x49-0x60 */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x49)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x60)); + + /* ASCII 0x67-0x7F */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x67)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x7F)); + + /* ASCII 0x30-0x39 */ + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x30)); + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x39)); + + /* ASCII 0x41-0x46 */ + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x41)); + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x46)); + + /* ASCII 0x61-0x66 */ + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x61)); + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x66)); +} + +TEST_F(LibcBuiltinTest, tolower) +{ + char src[] = "aBcDeFgH12345;!#$"; + char dest[sizeof(src)]; + int i; + + for (i = 0; i < sizeof(src); i++) { + dest[i] = CALL_FUNC(tolower, (src[i])); + } + EXPECT_STREQ(dest, "abcdefgh12345;!#$"); +} + +TEST_F(LibcBuiltinTest, toupper) +{ + char src[] = "aBcDeFgH12345;!#$"; + char dest[sizeof(src)]; + int i; + + for (i = 0; i < sizeof(src); i++) { + dest[i] = CALL_FUNC(toupper, (src[i])); + } + EXPECT_STREQ(dest, "ABCDEFGH12345;!#$"); +} + +TEST_F(LibcBuiltinTest, isalnum) +{ + char src[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678" + "9!\"#$%&'()*+,-./:;<=>?@[^_'{|}~"; + int i; + int isalnum_cnt = 0; + + for (i = 0; i < sizeof(src); i++) { + if (CALL_FUNC(isalnum, (src[i]))) + isalnum_cnt++; + } + EXPECT_EQ(isalnum_cnt, 62); +} + +TEST_F(LibcBuiltinTest, emscripten_memcpy_big) +{ + const char *src = "Hell World"; + char *dest; + + AppData src_app{ dummy_exec_env.get(), src }; + AppData dest_app{ dummy_exec_env.get(), dest }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(emscripten_memcpy_big, (void *)-1, + src_app.get_native_addr(), 0), + 0); + + CALL_FUNC(emscripten_memcpy_big, dest_app.get_native_addr(), + src_app.get_native_addr(), strlen(src)); + EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(), + src_app.get_native_addr(), strlen(src)), + 0); +} + +TEST_F(LibcBuiltinTest, abort) +{ + CALL_FUNC(abort, 33); + EXPECT_STREQ(dummy_exec_env.get_exception(), "Exception: env.abort(33)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, abortStackOverflow) +{ + CALL_FUNC(abortStackOverflow, 33); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: env.abortStackOverflow(33)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, nullFunc_X) +{ + CALL_FUNC(nullFunc_X, 33); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: env.nullFunc_X(33)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, __cxa_allocate_exception) +{ + EXPECT_NE(CALL_FUNC(__cxa_allocate_exception, 0x0), 0x0); + EXPECT_EQ(CALL_FUNC(__cxa_allocate_exception, 0xFFFF), 0x0); +} + +TEST_F(LibcBuiltinTest, __cxa_begin_catch) +{ + /* 无函数原型 */ +} + +TEST_F(LibcBuiltinTest, __cxa_throw) +{ + void *excepton; + void *tinfo; + + CALL_FUNC(__cxa_throw, excepton, tinfo, 1); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: exception thrown by stdc++"); + dummy_exec_env.clear_exception(); +} + +struct timespec_app app; +TEST_F(LibcBuiltinTest, clock_gettime) +{ + struct timespec_app *tsapp; + tsapp = &app; + + AppMemory tsapp_app{ dummy_exec_env.get(), sizeof(struct timespec_app) }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(clock_gettime, 0, (struct timespec_app *)-1), -1); + + EXPECT_EQ(CALL_FUNC(clock_gettime, 100, NULL), -1); + + EXPECT_EQ(CALL_FUNC(clock_gettime, 100, 0), -1); + + EXPECT_EQ(CALL_FUNC(clock_gettime, 10, + (struct timespec_app *)tsapp_app.get_native_addr()), + 0); +} + +TEST_F(LibcBuiltinTest, clock) +{ + EXPECT_GE(CALL_FUNC(clock), 0); +} + +WASMGlobalImport glb; +TEST_F(LibcBuiltinTest, wasm_native_lookup_libc_builtin_global) +{ + const char *module_name = "module name"; + const char *global_name = "global name"; + + const char *module_name1 = "global"; + const char *global_name1 = "NaN"; + const char *global_name2 = "Infinity"; + WASMGlobalImport *global = &glb; + + EXPECT_FALSE( + wasm_native_lookup_libc_builtin_global(NULL, global_name, global)); + EXPECT_FALSE( + wasm_native_lookup_libc_builtin_global(module_name, NULL, global)); + EXPECT_FALSE( + wasm_native_lookup_libc_builtin_global(module_name, global_name, NULL)); + EXPECT_FALSE(wasm_native_lookup_libc_builtin_global(module_name, + global_name, global)); + EXPECT_FALSE(wasm_native_lookup_libc_builtin_global(module_name, + global_name1, global)); + + EXPECT_TRUE(wasm_native_lookup_libc_builtin_global(module_name1, + global_name1, global)); + + EXPECT_TRUE(wasm_native_lookup_libc_builtin_global(module_name1, + global_name2, global)); +} diff --git a/tests/unit/linear-memory-aot/CMakeLists.txt b/tests/unit/linear-memory-aot/CMakeLists.txt new file mode 100644 index 000000000..549b70ad6 --- /dev/null +++ b/tests/unit/linear-memory-aot/CMakeLists.txt @@ -0,0 +1,78 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-linear-memory-aot) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_MEMORY_PROFILING 1) +set (WAMR_BUILD_INTERP 0) +set (WAMR_BUILD_AOT 1) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} +) + +# Test case: .aot file with hardware bound check. +add_executable (linear_memory_test_aot ${unit_test_sources}) +target_link_libraries (linear_memory_test_aot gtest_main) +gtest_discover_tests(linear_memory_test_aot) +target_compile_definitions(linear_memory_test_aot PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=0) + +# Ensure that aot compiled is completed before linear_memory_test_aot is built +set(dummy_output "${CMAKE_CURRENT_BINARY_DIR}/dummy_output") + +add_custom_command(OUTPUT ${dummy_output} + COMMAND ./build_aot.sh + COMMAND ${CMAKE_COMMAND} -E touch ${dummy_output} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/build_aot.sh + COMMENT "Executing script to compile aot files" + VERBATIM +) + +add_custom_target( + RunBuildAot ALL + DEPENDS ${dummy_output} +) + +add_dependencies(linear_memory_test_aot RunBuildAot) + +add_custom_command(TARGET linear_memory_test_aot POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/build/*.aot + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy aot files to the directory: build/linear-memory-aot." +) + +# Test case: .aot file with no hardware bound check. +add_executable (linear_memory_test_aot_no_hw_bound ${unit_test_sources}) +target_link_libraries (linear_memory_test_aot_no_hw_bound gtest_main) +gtest_discover_tests(linear_memory_test_aot_no_hw_bound) +target_compile_definitions(linear_memory_test_aot_no_hw_bound PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=1) diff --git a/tests/unit/linear-memory-aot/build_aot.sh b/tests/unit/linear-memory-aot/build_aot.sh new file mode 100755 index 000000000..8f2b29ede --- /dev/null +++ b/tests/unit/linear-memory-aot/build_aot.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +# Define a list of .wasm files +file_names=("mem_grow_out_of_bounds_01" "mem_grow_out_of_bounds_02" + "mem_page_01" "mem_page_02" "mem_page_03" "mem_page_05" + "mem_page_07" "mem_page_08" "mem_page_09" "mem_page_10" + "mem_page_12" "mem_page_14" "mem_page_16" "mem_page_20" "out_of_bounds") + +WORKDIR="$PWD" +WAMRC_ROOT_DIR="${WORKDIR}/../../../wamr-compiler" +WAMRC="${WAMRC_ROOT_DIR}/build/wamrc" +WAST2WASM="/opt/wabt/bin/wat2wasm" + +# build wamrc if not exist +if [ ! -s "$WAMRC" ]; then + cd $WAMRC_ROOT_DIR + if [ -d "$WAMRC/build" ]; then + rm -r build + fi + cmake -B build && cmake --build build -j $(nproc) + cd $WORKDIR +fi + +# error if not exist +if [ ! -s "$WAST2WASM" ]; then + echo "please install wabt first" && exit -1 +fi + +# Iterate over the files array +rm -r build +mkdir build +for file_name in "${file_names[@]}"; do + # wast to wasm + $WAST2WASM "${file_name}.wast" -o "build/${file_name}.wasm" + # compile the aot files, x86-64, x86-32, no_hw_bounds, no_hw_bounds_x32 + $WAMRC -o "build/${file_name}.aot" "build/${file_name}.wasm" + $WAMRC --target=i386 -o "build/${file_name}_32.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 -o "build/${file_name}_no_hw_bounds.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 --target=i386 -o "build/${file_name}_no_hw_bounds_32.aot" "build/${file_name}.wasm" +done diff --git a/tests/unit/linear-memory-aot/linear_memory_aot_test.cc b/tests/unit/linear-memory-aot/linear_memory_aot_test.cc new file mode 100644 index 000000000..dafdbb791 --- /dev/null +++ b/tests/unit/linear-memory-aot/linear_memory_aot_test.cc @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "wasm_runtime_common.h" + +static std::string CWD; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +#if WASM_DISABLE_HW_BOUND_CHECK != 0 +#define TEST_SUITE_NAME linear_memory_test_suite_aot_no_hw_bound +#else +#define TEST_SUITE_NAME linear_memory_test_suite_aot +#endif + +class TEST_SUITE_NAME : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() { CWD = get_binary_path(); } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +struct ret_env { + wasm_exec_env_t exec_env; + wasm_module_t aot_module; + wasm_module_inst_t aot_module_inst; + unsigned char *aot_file_buf; + char error_buf[128]; +}; + +struct ret_env +load_aot(char *aot_file_tested, unsigned int app_heap_size) +{ + std::string aot_mem_page = aot_file_tested; + const char *aot_file = strdup((CWD + aot_mem_page).c_str()); + wasm_module_inst_t aot_module_inst = nullptr; + wasm_module_t aot_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + unsigned char *aot_file_buf = nullptr; + unsigned int aot_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = app_heap_size; + char error_buf[128] = { 0 }; + struct ret_env ret_module_env; + + memset(ret_module_env.error_buf, 0, 128); + aot_file_buf = + (unsigned char *)bh_read_file_to_buffer(aot_file, &aot_file_size); + if (!aot_file_buf) { + goto fail; + } + + aot_module = wasm_runtime_load(aot_file_buf, aot_file_size, error_buf, + sizeof(error_buf)); + if (!aot_module) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + aot_module_inst = wasm_runtime_instantiate( + aot_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + if (!aot_module_inst) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + exec_env = wasm_runtime_create_exec_env(aot_module_inst, stack_size); + +fail: + ret_module_env.exec_env = exec_env; + ret_module_env.aot_module = aot_module; + ret_module_env.aot_module_inst = aot_module_inst; + ret_module_env.aot_file_buf = aot_file_buf; + + return ret_module_env; +} + +void +destroy_module_env(struct ret_env module_env) +{ + if (module_env.exec_env) { + wasm_runtime_destroy_exec_env(module_env.exec_env); + } + + if (module_env.aot_module_inst) { + wasm_runtime_deinstantiate(module_env.aot_module_inst); + } + + if (module_env.aot_module) { + wasm_runtime_unload(module_env.aot_module); + } + + if (module_env.aot_file_buf) { + wasm_runtime_free(module_env.aot_file_buf); + } +} + +TEST_F(TEST_SUITE_NAME, test_aot_mem_page_count) +{ + struct ret_env tmp_module_env; + const unsigned int num_normal_aot = 9; + const unsigned int num_error_aot = 2; + +#if UINTPTR_MAX == UINT64_MAX + const char *aot_file_normal[num_normal_aot] = { + "/mem_page_01.aot", "/mem_page_02.aot", "/mem_page_05.aot", + "/mem_page_07.aot", "/mem_page_08.aot", "/mem_page_09.aot", + "/mem_page_10.aot", "/mem_page_12.aot", "/mem_page_14.aot" + }; + + const char *aot_file_error[num_error_aot] = { "/mem_page_03.aot", + "/mem_page_16.aot" }; +#else + const char *aot_file_normal[num_normal_aot] = { + "/mem_page_01_32.aot", "/mem_page_02_32.aot", "/mem_page_05_32.aot", + "/mem_page_07_32.aot", "/mem_page_08_32.aot", "/mem_page_09_32.aot", + "/mem_page_10_32.aot", "/mem_page_12_32.aot", "/mem_page_14_32.aot" + }; + + const char *aot_file_error[num_error_aot] = { "/mem_page_03_32.aot", + "/mem_page_16_32.aot" }; +#endif + + // Test normal wasm file. + for (int i = 0; i < num_normal_aot; i++) { +#if UINTPTR_MAX != UINT64_MAX + // 32 bit do not load this wasm. + if ((0 == strcmp("/mem_page_14_32.aot", aot_file_normal[i]))) { + continue; + } +#endif + + tmp_module_env = load_aot((char *)aot_file_normal[i], 16 * 1024); + EXPECT_NE(nullptr, tmp_module_env.aot_module); + EXPECT_NE(nullptr, tmp_module_env.aot_file_buf); + + destroy_module_env(tmp_module_env); + } + + // Test error wasm file. + for (int i = 0; i < num_error_aot; i++) { + tmp_module_env = load_aot((char *)aot_file_error[i], 16 * 1024); + if (0 != strlen(tmp_module_env.error_buf)) { + /* 3 and 16 are for legit for loader, the init and max page count + * can be 65536, but they can't allocate any host managed heap, so + * instantiating errors */ + EXPECT_EQ(0, strncmp("AOT module instantiate failed", + (const char *)tmp_module_env.error_buf, 29)); + printf("%s\n", tmp_module_env.error_buf); + } + + destroy_module_env(tmp_module_env); + } +} + +TEST_F(TEST_SUITE_NAME, test_aot_about_app_heap) +{ + struct ret_env tmp_module_env; + + // Test case: init_page_count = 65536, app heap size = 1. +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_page_03.aot", 1); +#else + tmp_module_env = load_aot((char *)"/mem_page_03_32.aot", 1); +#endif + EXPECT_EQ( + 0, strncmp("AOT module", (const char *)tmp_module_env.error_buf, 10)); + destroy_module_env(tmp_module_env); + + // Test case: init_page_count = 65535, app heap size = 65537. +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_page_20.aot", 65537); +#else + tmp_module_env = load_aot((char *)"/mem_page_20_32.aot", 65537); +#endif + EXPECT_EQ( + 0, strncmp("AOT module", (const char *)tmp_module_env.error_buf, 10)); + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_throw_exception_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func = nullptr; + bool ret = false; + uint32 argv[1] = { 9999 * 64 * 1024 }; + const char *exception = nullptr; + + /* TODO: use no_hw_bounds version when disable */ +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/out_of_bounds.aot", 16 * 1024); +#else + tmp_module_env = load_aot((char *)"/out_of_bounds_32.aot", 16 * 1024); +#endif + func = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, "load"); + if (!func) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = wasm_runtime_call_wasm(tmp_module_env.exec_env, func, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + } + + exception = wasm_runtime_get_exception(tmp_module_env.aot_module_inst); + EXPECT_EQ(0, + strncmp("Exception: out of bounds memory access", exception, 38)); + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_mem_grow_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func_mem_grow = nullptr; + WASMFunctionInstanceCommon *func_mem_size = nullptr; + bool ret = false; + uint32 argv[1] = { 65535 }; + const char *exception = nullptr; + + /* TODO: use no_hw_bounds version when disable */ + // Test case: module((memory 2)), memory.grow 65535, then memory.size. +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_01.aot", 0); +#else + tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_01_32.aot", 0); +#endif + + func_mem_grow = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(-1, argv[0]); + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(2, argv[0]); + + // Test case: wasm_runtime_instantiate(heap_size=32768), memory.grow 65534, + // memory.grow 1. + destroy_module_env(tmp_module_env); + +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_02.aot", 32768); +#else + tmp_module_env = + load_aot((char *)"/mem_grow_out_of_bounds_02_32.aot", 32768); +#endif + + func_mem_grow = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + EXPECT_EQ(2, argv[0]); + + argv[0] = 65534; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + +#if UINTPTR_MAX == UINT64_MAX + EXPECT_EQ(2, argv[0]); +#else + EXPECT_EQ(-1, argv[0]); +#endif + + argv[0] = 1; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + +#if UINTPTR_MAX == UINT64_MAX + EXPECT_EQ(-1, argv[0]); +#else + EXPECT_EQ(2, argv[0]); +#endif + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} diff --git a/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast new file mode 100644 index 000000000..296455d86 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 2) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast new file mode 100644 index 000000000..7faceae49 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 1) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-aot/mem_page_01.wast b/tests/unit/linear-memory-aot/mem_page_01.wast new file mode 100644 index 000000000..aa3aeed76 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_01.wast @@ -0,0 +1 @@ +(module (memory 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_02.wast b/tests/unit/linear-memory-aot/mem_page_02.wast new file mode 100644 index 000000000..eb1fba88e --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_02.wast @@ -0,0 +1 @@ +(module (memory 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_03.wast b/tests/unit/linear-memory-aot/mem_page_03.wast new file mode 100644 index 000000000..f3e09dcf4 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_03.wast @@ -0,0 +1 @@ +(module (memory 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_05.wast b/tests/unit/linear-memory-aot/mem_page_05.wast new file mode 100644 index 000000000..7551af514 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_05.wast @@ -0,0 +1 @@ +(module (memory 0 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_07.wast b/tests/unit/linear-memory-aot/mem_page_07.wast new file mode 100644 index 000000000..709e6ca05 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_07.wast @@ -0,0 +1 @@ +(module (memory 1 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_08.wast b/tests/unit/linear-memory-aot/mem_page_08.wast new file mode 100644 index 000000000..abf081802 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_08.wast @@ -0,0 +1 @@ +(module (memory 0 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_09.wast b/tests/unit/linear-memory-aot/mem_page_09.wast new file mode 100644 index 000000000..47b38fde5 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_09.wast @@ -0,0 +1 @@ +(module (memory 1 256)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_10.wast b/tests/unit/linear-memory-aot/mem_page_10.wast new file mode 100644 index 000000000..523f9e674 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_10.wast @@ -0,0 +1 @@ +(module (memory 0 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_12.wast b/tests/unit/linear-memory-aot/mem_page_12.wast new file mode 100644 index 000000000..d82dabb59 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_12.wast @@ -0,0 +1 @@ +(module (memory 0 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_14.wast b/tests/unit/linear-memory-aot/mem_page_14.wast new file mode 100644 index 000000000..9779bf234 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_14.wast @@ -0,0 +1 @@ +(module (memory 65535 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_16.wast b/tests/unit/linear-memory-aot/mem_page_16.wast new file mode 100644 index 000000000..94068a4e9 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_16.wast @@ -0,0 +1 @@ +(module (memory 65536 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_20.wast b/tests/unit/linear-memory-aot/mem_page_20.wast new file mode 100644 index 000000000..0d4b6ebd6 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_20.wast @@ -0,0 +1 @@ +(module (memory 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/out_of_bounds.wast b/tests/unit/linear-memory-aot/out_of_bounds.wast new file mode 100644 index 000000000..89854b924 --- /dev/null +++ b/tests/unit/linear-memory-aot/out_of_bounds.wast @@ -0,0 +1,10 @@ +(module + (type $1 (func (param i32) (result i32))) + (memory $3 0) + (export "load" (func $4)) + + (func $4 (type $1) (param $0 i32) (result i32) + local.get $0 + i32.load + ) +) diff --git a/tests/unit/linear-memory-aot/readme b/tests/unit/linear-memory-aot/readme new file mode 100644 index 000000000..a9ec33833 --- /dev/null +++ b/tests/unit/linear-memory-aot/readme @@ -0,0 +1,2 @@ +build 64 bit target: cmake .. +build 32 bit target: cmake .. -DWAMR_BUILD_TARGET=X86_32 \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/CMakeLists.txt b/tests/unit/linear-memory-wasm/CMakeLists.txt new file mode 100644 index 000000000..03e1616d7 --- /dev/null +++ b/tests/unit/linear-memory-wasm/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-linear-memory-wasm) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_MEMORY_PROFILING 1) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} +) + +# Test case: .wasm file with hardware bound check. +add_executable (linear_memory_test_wasm ${unit_test_sources}) +target_link_libraries (linear_memory_test_wasm gtest_main) +gtest_discover_tests(linear_memory_test_wasm) +target_compile_definitions(linear_memory_test_wasm PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=0) + +add_custom_command(TARGET linear_memory_test_wasm POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm_files/* + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy wasm files to the directory: build/linear-memory-wasm." +) + +# Test case: .wasm file with no hardware bound check. +add_executable (linear_memory_test_wasm_no_hw_bound ${unit_test_sources}) +target_link_libraries (linear_memory_test_wasm_no_hw_bound gtest_main) +gtest_discover_tests(linear_memory_test_wasm_no_hw_bound) +target_compile_definitions(linear_memory_test_wasm_no_hw_bound PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=1) diff --git a/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc b/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc new file mode 100644 index 000000000..77eb53d7e --- /dev/null +++ b/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "wasm_runtime_common.h" + +static std::string CWD; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +#if WASM_DISABLE_HW_BOUND_CHECK != 0 +#define TEST_SUITE_NAME linear_memory_test_suite_wasm_no_hw_bound +#else +#define TEST_SUITE_NAME linear_memory_test_suite_wasm +#endif + +class TEST_SUITE_NAME : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() { CWD = get_binary_path(); } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +struct ret_env { + wasm_exec_env_t exec_env; + wasm_module_t wasm_module; + wasm_module_inst_t wasm_module_inst; + unsigned char *wasm_file_buf; + char error_buf[128]; +}; + +struct ret_env +load_wasm(char *wasm_file_tested, unsigned int app_heap_size) +{ + std::string wasm_mem_page = wasm_file_tested; + const char *wasm_file = strdup((CWD + wasm_mem_page).c_str()); + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + unsigned char *wasm_file_buf = nullptr; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = app_heap_size; + char error_buf[128] = { 0 }; + struct ret_env ret_module_env; + + memset(ret_module_env.error_buf, 0, 128); + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + if (!wasm_file_buf) { + goto fail; + } + + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + if (!wasm_module) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + if (!wasm_module_inst) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + +fail: + ret_module_env.exec_env = exec_env; + ret_module_env.wasm_module = wasm_module; + ret_module_env.wasm_module_inst = wasm_module_inst; + ret_module_env.wasm_file_buf = wasm_file_buf; + + return ret_module_env; +} + +void +destroy_module_env(struct ret_env module_env) +{ + if (module_env.exec_env) { + wasm_runtime_destroy_exec_env(module_env.exec_env); + } + + if (module_env.wasm_module_inst) { + wasm_runtime_deinstantiate(module_env.wasm_module_inst); + } + + if (module_env.wasm_module) { + wasm_runtime_unload(module_env.wasm_module); + } + + if (module_env.wasm_file_buf) { + wasm_runtime_free(module_env.wasm_file_buf); + } +} + +TEST_F(TEST_SUITE_NAME, test_wasm_mem_page_count) +{ + struct ret_env tmp_module_env; + unsigned int num_normal_wasm = 9; + unsigned int num_error_wasm = 10; + const char *wasm_file_normal[num_normal_wasm] = { + "/wasm_mem_page_01.wasm", "/wasm_mem_page_02.wasm", + "/wasm_mem_page_05.wasm", "/wasm_mem_page_07.wasm", + "/wasm_mem_page_08.wasm", "/wasm_mem_page_09.wasm", + "/wasm_mem_page_10.wasm", "/wasm_mem_page_12.wasm", + "/wasm_mem_page_14.wasm" + }; + + const char *wasm_file_error[num_error_wasm] = { + "/wasm_mem_page_03.wasm", "/wasm_mem_page_04.wasm", + "/wasm_mem_page_06.wasm", "/wasm_mem_page_11.wasm", + "/wasm_mem_page_13.wasm", "/wasm_mem_page_15.wasm", + "/wasm_mem_page_16.wasm", "/wasm_mem_page_17.wasm", + "/wasm_mem_page_18.wasm", "/wasm_mem_page_19.wasm" + }; + + // Test normal wasm file. + for (int i = 0; i < num_normal_wasm; i++) { +#if UINTPTR_MAX != UINT64_MAX + // 32 bit do not load this wasm. + if ((0 == strcmp("/wasm_mem_page_12.wasm", wasm_file_normal[i])) + || (0 == strcmp("/wasm_mem_page_14.wasm", wasm_file_normal[i]))) { + continue; + } +#endif + tmp_module_env = load_wasm((char *)wasm_file_normal[i], 16 * 1024); + EXPECT_NE(nullptr, tmp_module_env.wasm_module); + EXPECT_NE(nullptr, tmp_module_env.wasm_file_buf); + +#if WASM_DISABLE_HW_BOUND_CHECK == 0 + EXPECT_NE(nullptr, tmp_module_env.exec_env); + EXPECT_NE(nullptr, tmp_module_env.wasm_module_inst); +#endif + destroy_module_env(tmp_module_env); + } + + // Test error wasm file. + for (int i = 0; i < num_error_wasm; i++) { + tmp_module_env = load_wasm((char *)wasm_file_error[i], 16 * 1024); + + if (0 != strlen(tmp_module_env.error_buf)) { + EXPECT_EQ(0, strncmp("WASM module", + (const char *)tmp_module_env.error_buf, 11)); + } + + destroy_module_env(tmp_module_env); + } +} + +TEST_F(TEST_SUITE_NAME, test_wasm_about_app_heap) +{ + struct ret_env tmp_module_env; + + // Test case: init_page_count = 65536, app heap size = 1. + tmp_module_env = load_wasm((char *)"/wasm_mem_page_03.wasm", 1); + EXPECT_EQ(0, strncmp("WASM module instantiate failed", + (const char *)tmp_module_env.error_buf, 30)); + destroy_module_env(tmp_module_env); + + // Test case: init_page_count = 65535, app heap size = 65537. + tmp_module_env = load_wasm((char *)"/wasm_mem_page_20.wasm", 65537); + EXPECT_EQ(0, strncmp("WASM module instantiate failed", + (const char *)tmp_module_env.error_buf, 30)); + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_throw_exception_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func = nullptr; + bool ret = false; + uint32 argv[1] = { 9999 * 64 * 1024 }; + const char *exception = nullptr; + + tmp_module_env = load_wasm((char *)"/out_of_bounds.wasm", 16 * 1024); + func = + wasm_runtime_lookup_function(tmp_module_env.wasm_module_inst, "load"); + if (!func) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = wasm_runtime_call_wasm(tmp_module_env.exec_env, func, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + } + + exception = wasm_runtime_get_exception(tmp_module_env.wasm_module_inst); + EXPECT_EQ(0, + strncmp("Exception: out of bounds memory access", exception, 38)); + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_mem_grow_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func_mem_grow = nullptr; + WASMFunctionInstanceCommon *func_mem_size = nullptr; + bool ret = false; + // after refactor, the 65536 pages to one 4G page optimization is removed + // the size can be 65536 now, so use 2 + 65535 to test OOB + uint32 argv[1] = { 65535 }; + const char *exception = nullptr; + + // Test case: module((memory 2)), memory.grow 65535, then memory.size. + tmp_module_env = load_wasm((char *)"/mem_grow_out_of_bounds_01.wasm", 0); + func_mem_grow = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(-1, argv[0]); + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(2, argv[0]); + + // Test case: wasm_runtime_instantiate(heap_size=32768), memory.grow 65535, + // memory.grow 1. + destroy_module_env(tmp_module_env); + tmp_module_env = + load_wasm((char *)"/mem_grow_out_of_bounds_02.wasm", 32768); + func_mem_grow = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + EXPECT_EQ(2, argv[0]); + + argv[0] = 65535; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_NE(2, argv[0]); + + argv[0] = 1; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(2, argv[0]); + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} diff --git a/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast new file mode 100644 index 000000000..296455d86 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 2) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast new file mode 100644 index 000000000..7faceae49 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 1) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-wasm/mem_page_01.wast b/tests/unit/linear-memory-wasm/mem_page_01.wast new file mode 100644 index 000000000..aa3aeed76 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_01.wast @@ -0,0 +1 @@ +(module (memory 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_02.wast b/tests/unit/linear-memory-wasm/mem_page_02.wast new file mode 100644 index 000000000..eb1fba88e --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_02.wast @@ -0,0 +1 @@ +(module (memory 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_03.wast b/tests/unit/linear-memory-wasm/mem_page_03.wast new file mode 100644 index 000000000..f3e09dcf4 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_03.wast @@ -0,0 +1 @@ +(module (memory 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_04.wast b/tests/unit/linear-memory-wasm/mem_page_04.wast new file mode 100644 index 000000000..b476caa2e --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_04.wast @@ -0,0 +1 @@ +(module (memory 65537)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_05.wast b/tests/unit/linear-memory-wasm/mem_page_05.wast new file mode 100644 index 000000000..7551af514 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_05.wast @@ -0,0 +1 @@ +(module (memory 0 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_06.wast b/tests/unit/linear-memory-wasm/mem_page_06.wast new file mode 100644 index 000000000..eae97baa2 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_06.wast @@ -0,0 +1 @@ +(module (memory 1 0)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_07.wast b/tests/unit/linear-memory-wasm/mem_page_07.wast new file mode 100644 index 000000000..709e6ca05 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_07.wast @@ -0,0 +1 @@ +(module (memory 1 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_08.wast b/tests/unit/linear-memory-wasm/mem_page_08.wast new file mode 100644 index 000000000..abf081802 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_08.wast @@ -0,0 +1 @@ +(module (memory 0 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_09.wast b/tests/unit/linear-memory-wasm/mem_page_09.wast new file mode 100644 index 000000000..47b38fde5 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_09.wast @@ -0,0 +1 @@ +(module (memory 1 256)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_10.wast b/tests/unit/linear-memory-wasm/mem_page_10.wast new file mode 100644 index 000000000..523f9e674 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_10.wast @@ -0,0 +1 @@ +(module (memory 0 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_11.wast b/tests/unit/linear-memory-wasm/mem_page_11.wast new file mode 100644 index 000000000..1d9cf77cf --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_11.wast @@ -0,0 +1 @@ +(module (memory 65535 0)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_12.wast b/tests/unit/linear-memory-wasm/mem_page_12.wast new file mode 100644 index 000000000..d82dabb59 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_12.wast @@ -0,0 +1 @@ +(module (memory 0 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_13.wast b/tests/unit/linear-memory-wasm/mem_page_13.wast new file mode 100644 index 000000000..e3c1f1e21 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_13.wast @@ -0,0 +1 @@ +(module (memory 65536 0)) ;; Should report an error. diff --git a/tests/unit/linear-memory-wasm/mem_page_14.wast b/tests/unit/linear-memory-wasm/mem_page_14.wast new file mode 100644 index 000000000..9779bf234 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_14.wast @@ -0,0 +1 @@ +(module (memory 65535 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_15.wast b/tests/unit/linear-memory-wasm/mem_page_15.wast new file mode 100644 index 000000000..d2862b9bb --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_15.wast @@ -0,0 +1 @@ +(module (memory 65536 65535)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_16.wast b/tests/unit/linear-memory-wasm/mem_page_16.wast new file mode 100644 index 000000000..94068a4e9 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_16.wast @@ -0,0 +1 @@ +(module (memory 65536 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_17.wast b/tests/unit/linear-memory-wasm/mem_page_17.wast new file mode 100644 index 000000000..d5a19eff2 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_17.wast @@ -0,0 +1 @@ +(module (memory 65537 65537)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_18.wast b/tests/unit/linear-memory-wasm/mem_page_18.wast new file mode 100644 index 000000000..d5793de6a --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_18.wast @@ -0,0 +1 @@ +(module (memory 65537 65535)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_19.wast b/tests/unit/linear-memory-wasm/mem_page_19.wast new file mode 100644 index 000000000..8cf0a39f6 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_19.wast @@ -0,0 +1 @@ +(module (memory 65535 65537)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_20.wast b/tests/unit/linear-memory-wasm/mem_page_20.wast new file mode 100644 index 000000000..0d4b6ebd6 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_20.wast @@ -0,0 +1 @@ +(module (memory 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/out_of_bounds.wast b/tests/unit/linear-memory-wasm/out_of_bounds.wast new file mode 100644 index 000000000..89854b924 --- /dev/null +++ b/tests/unit/linear-memory-wasm/out_of_bounds.wast @@ -0,0 +1,10 @@ +(module + (type $1 (func (param i32) (result i32))) + (memory $3 0) + (export "load" (func $4)) + + (func $4 (type $1) (param $0 i32) (result i32) + local.get $0 + i32.load + ) +) diff --git a/tests/unit/linear-memory-wasm/readme b/tests/unit/linear-memory-wasm/readme new file mode 100644 index 000000000..a9ec33833 --- /dev/null +++ b/tests/unit/linear-memory-wasm/readme @@ -0,0 +1,2 @@ +build 64 bit target: cmake .. +build 32 bit target: cmake .. -DWAMR_BUILD_TARGET=X86_32 \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_01.wasm b/tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_01.wasm new file mode 100644 index 0000000000000000000000000000000000000000..544ed91e81f24415ebe3b31d49ba258fbcd97e73 GIT binary patch literal 70 zcmZQbEY4+QU|?Y6VoG3OtWRL9XRK#tW@2PuWoBexVi#xP$W6_SPcO literal 0 HcmV?d00001 diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_02.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_02.wasm new file mode 100644 index 0000000000000000000000000000000000000000..67d6849c74838975793d0355a2fcc483d91b53ef GIT binary patch literal 13 UcmZQbEY4+QU|?WnW@KOl01f^DO#lD@ literal 0 HcmV?d00001 diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_03.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_03.wasm new file mode 100644 index 0000000000000000000000000000000000000000..5c82427261437804479ea013acb216837af33b1a GIT binary patch literal 15 WcmZQbEY4+QU|?WnWn^e*U;zLVB?3|a literal 0 HcmV?d00001 diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_04.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_04.wasm new file mode 100644 index 0000000000000000000000000000000000000000..6f2d7eb15e502576a113677b03ef203ffc7f7ec6 GIT binary patch literal 15 WcmZQbEY4+QU|?WnWn^e +#include +#include + +extern "C" { +// TODO: won't work, for non static function create_perf_map have goto statement jump to label ‘quit’ +// #include "aot_perf_map.c" + +// simply copy the function +struct func_info { + uint32 idx; + void *ptr; +}; + +static int +compare_func_ptrs(const void *f1, const void *f2) +{ + return (intptr_t)((struct func_info *)f1)->ptr + - (intptr_t)((struct func_info *)f2)->ptr; +} + +static struct func_info * +sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size) +{ + uint64 content_len; + struct func_info *sorted_func_ptrs; + unsigned i; + + content_len = (uint64)sizeof(struct func_info) * module->func_count; + sorted_func_ptrs = wasm_runtime_malloc(content_len); + if (!sorted_func_ptrs) { + snprintf(error_buf, error_buf_size, + "allocate memory failed when creating perf map"); + return NULL; + } + + for (i = 0; i < module->func_count; i++) { + sorted_func_ptrs[i].idx = i; + sorted_func_ptrs[i].ptr = module->func_ptrs[i]; + } + + qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info), + compare_func_ptrs); + + return sorted_func_ptrs; +} + +void * +wasm_runtime_malloc(unsigned int size) +{ + return malloc(size); +} + +void +wasm_runtime_free(void* ptr) +{ + return free(ptr); +} + +int +b_memcpy_s(void *s1, unsigned int s1max, const void *s2, unsigned int n) +{ + return memcpy(s1, s2, n); +} +} + +TEST(TestSortFuncPtrs, qsort) +{ + void *p = sort_func_ptrs; + ASSERT_NE(p, nullptr); + + void *funcs[5] = { + (void *)0x1024, (void *)0x10, (void *)0x24, (void *)0x102, (void *)0x4, + }; + + AOTModule module = { 0 }; + module.func_count = 5; + module.func_ptrs = &funcs[0]; + + char buf[64] = { 0 }; + + struct func_info *sorted_funcs = sort_func_ptrs(&module, buf, 64); + // sorted + ASSERT_EQ((uintptr_t)(sorted_funcs[0].ptr), 0x4); + ASSERT_EQ((uintptr_t)(sorted_funcs[1].ptr), 0x10); + ASSERT_EQ((uintptr_t)(sorted_funcs[2].ptr), 0x24); + ASSERT_EQ((uintptr_t)(sorted_funcs[3].ptr), 0x102); + ASSERT_EQ((uintptr_t)(sorted_funcs[4].ptr), 0x1024); + + ASSERT_EQ(sorted_funcs[0].idx, 4); + ASSERT_EQ(sorted_funcs[1].idx, 1); + ASSERT_EQ(sorted_funcs[2].idx, 2); + ASSERT_EQ(sorted_funcs[3].idx, 3); + ASSERT_EQ(sorted_funcs[4].idx, 0); + + // don't change input + ASSERT_EQ((uintptr_t)(funcs[0]), 0x1024); + ASSERT_EQ((uintptr_t)(funcs[1]), 0x10); + ASSERT_EQ((uintptr_t)(funcs[2]), 0x24); + ASSERT_EQ((uintptr_t)(funcs[3]), 0x102); + ASSERT_EQ((uintptr_t)(funcs[4]), 0x4); + + wasm_runtime_free(sorted_funcs); +} \ No newline at end of file diff --git a/tests/unit/memory64/CMakeLists.txt b/tests/unit/memory64/CMakeLists.txt new file mode 100644 index 000000000..f3629a7c4 --- /dev/null +++ b/tests/unit/memory64/CMakeLists.txt @@ -0,0 +1,67 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) + +project(test-memory64) + +add_definitions(-DRUN_ON_LINUX) + +set(WAMR_BUILD_LIBC_WASI 1) +set(WAMR_BUILD_APP_FRAMEWORK 0) +# TODO: Currently only support classic interpreter mode +set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_FAST_INTERP 0) +set(WAMR_BUILD_JIT 0) +set(WAMR_BUILD_FAST_JIT 0) +set(WAMR_BUILD_MEMORY64 1) +set(WAMR_BUILD_SHARED_MEMORY 1) + +# if only load this CMake other than load it as subdirectory +# include(GoogleTest) +include(../unit_common.cmake) + +set(LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") + +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message(FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () + +set(CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include(${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +file(GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set(UNIT_SOURCE ${source_all}) + +aux_source_directory(. SRC_LIST) + +set(unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable(memory64_test ${unit_test_sources}) + +target_link_libraries(memory64_test ${LLVM_AVAILABLE_LIBS} gtest_main) + +add_custom_command(TARGET memory64_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps/*.wasm + ${CMAKE_CURRENT_BINARY_DIR}/ + COMMENT "Copy test wasm files to the directory of google test" + ) + +gtest_discover_tests(memory64_test) diff --git a/tests/unit/memory64/memory64_atomic_test.cc b/tests/unit/memory64/memory64_atomic_test.cc new file mode 100644 index 000000000..2f9703890 --- /dev/null +++ b/tests/unit/memory64/memory64_atomic_test.cc @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "memory64_common.h" + +// To use a test fixture and Value Parameterized Tests, +// derive a class from testing::TestWithParam. +class memory64_atomic_test_suite : public testing::TestWithParam +{ + protected: + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = wasm_file; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + goto fail; + + if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + return true; + + fail: + if (!module) + wasm_runtime_unload(module); + + return false; + } + + bool init_exec_env() + { + if (!(module_inst = + wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + if (!(exec_env = + wasm_runtime_create_exec_env(module_inst, stack_size))) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + return true; + + fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) + wasm_runtime_unload(module); + return false; + } + + void destory_exec_env() + { + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + } + + public: + // If your test fixture defines SetUpTestSuite() or TearDownTestSuite() + // they must be declared public rather than protected in order to use + // TEST_P. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the variables. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + ASSERT_TRUE(load_wasm_file("atomic_opcodes.wasm")); + ASSERT_TRUE(init_exec_env()); + + running_mode = GetParam(); + ASSERT_TRUE(wasm_runtime_set_running_mode(module_inst, running_mode)); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + + for (auto &iter : func_map) { + iter.second = + wasm_runtime_lookup_function(module_inst, iter.first.c_str()); + ASSERT_TRUE(iter.second != NULL); + } + + cleanup = true; + } + + static void SetUpTestCase() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() + { + if (cleanup) { + destory_exec_env(); + wasm_runtime_destroy(); + cleanup = false; + } + } + + static void TearDownTestCase() {} + + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + RunningMode running_mode; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + uint32_t stack_size = 8092, heap_size = 8092; + bool cleanup = true; + std::unordered_map func_map = { + { "i32_atomic_store", nullptr }, + { "i32_atomic_store8", nullptr }, + { "i32_atomic_store16", nullptr }, + { "i64_atomic_store", nullptr }, + { "i64_atomic_store8", nullptr }, + { "i64_atomic_store16", nullptr }, + { "i64_atomic_store32", nullptr }, + { "i32_atomic_load", nullptr }, + { "i32_atomic_load8_u", nullptr }, + { "i32_atomic_load16_u", nullptr }, + { "i64_atomic_load", nullptr }, + { "i64_atomic_load8_u", nullptr }, + { "i64_atomic_load16_u", nullptr }, + { "i64_atomic_load32_u", nullptr }, + { "i32_atomic_rmw_add", nullptr }, + { "i32_atomic_rmw8_add_u", nullptr }, + { "i32_atomic_rmw16_add_u", nullptr }, + { "i64_atomic_rmw_add", nullptr }, + { "i64_atomic_rmw8_add_u", nullptr }, + { "i64_atomic_rmw16_add_u", nullptr }, + { "i64_atomic_rmw32_add_u", nullptr }, + { "i64_atomic_rmw_cmpxchg", nullptr }, + }; + uint32_t wasm_argv[6], i32; + uint64_t i64; +}; + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_st) +{ + // store at 0x2000, with value 0xbeefdead + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafedeadbeefdead); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeadbeefdead:i64 + i64 = 0xcafedeadbeefdead; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + // store at 0x2000, with value 0xbeefbeef + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xdeadbeef); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store32"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeaddeadbeef:i64 + i64 = 0xcafedeaddeadbeef; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + // store at 0x2000, with value 0xcafe + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafe); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store16"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeaddeadcafe:i64 + i64 = 0xcafedeaddeadcafe; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + // store at 0x2000, with value 0xcafe + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xaa); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store8"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeaddeadcaaa:i64 + i64 = 0xcafedeaddeadcaaa; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i32_st) +{ + // store at 0x1000, with value 0xbeefbeef + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xaabbccdd); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0xaabbccdd:i32 + i32 = 0xaabbccdd; + ASSERT_EQ(i32, wasm_argv[0]); + + // store at 0x1000, with value 0xcafe + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafe); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store16"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0xaabbcafe:i32 + i32 = 0xaabbcafe; + ASSERT_EQ(i32, wasm_argv[0]); + + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xaa); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store8"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0xaabbcaaa:i32 + i32 = 0xaabbcaaa; + ASSERT_EQ(i32, wasm_argv[0]); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_ld) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x0); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0x0807060504030201:i64 + i64 = 0x0807060504030201; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_load32_u"], 2, wasm_argv)); + // check return value: 0x0C0B0A09:i64 + i64 = 0x0C0B0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_load16_u"], 2, wasm_argv)); + // check return value: 0x0A09:i64 + i64 = 0x0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x0A); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load8_u"], + 2, wasm_argv)); + // check return value: 0x0B:i64 + i64 = 0x0B; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i32_ld) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x0); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0x04030201:i32 + i32 = 0x04030201; + ASSERT_EQ(i32, wasm_argv[0]); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i32_atomic_load16_u"], 2, wasm_argv)); + // check return value: 0x0A09:i32 + i32 = 0x0A09; + ASSERT_EQ(i32, wasm_argv[0]); + + PUT_I64_TO_ADDR(wasm_argv, 0xA); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load8_u"], + 2, wasm_argv)); + // check return value: 0x0B:i32 + i32 = 0x0B; + ASSERT_EQ(i32, wasm_argv[0]); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_rmw_add) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x1010101020202020); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_rmw_add"], + 4, wasm_argv)); + i64 = 0x100F0E0D0C0B0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x10103030); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_rmw32_add_u"], 4, wasm_argv)); + i64 = 0x2C2B2A29; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x1020); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_rmw16_add_u"], 4, wasm_argv)); + i64 = 0x5A59; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x30); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_rmw8_add_u"], 4, wasm_argv)); + i64 = 0x79; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + i64 = 0x201F1E1D3C3B6AA9; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_rmw_cmpxchg) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x8); + // old + PUT_I64_TO_ADDR(wasm_argv + 2, 0x100F0E0D0C0B0A09); + // new + PUT_I64_TO_ADDR(wasm_argv + 4, 0xdeadcafebeefdead); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_rmw_cmpxchg"], + 6, wasm_argv)); + i64 = 0x100F0E0D0C0B0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + i64 = 0xdeadcafebeefdead; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +INSTANTIATE_TEST_CASE_P(RunningMode, memory64_atomic_test_suite, + testing::ValuesIn(running_mode_supported)); diff --git a/tests/unit/memory64/memory64_common.h b/tests/unit/memory64/memory64_common.h new file mode 100644 index 000000000..76c43a8e7 --- /dev/null +++ b/tests/unit/memory64/memory64_common.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef UNIT_TEST_MEMORY64_COMMON_H +#define UNIT_TEST_MEMORY64_COMMON_H + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" +#include +// #include "aot_runtime.h" + +namespace { + +std::vector running_mode_supported = { Mode_Interp, +#if WASM_ENABLE_FAST_JIT != 0 + Mode_Fast_JIT, +#endif +#if WASM_ENABLE_JIT != 0 + Mode_LLVM_JIT, +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + Mode_Multi_Tier_JIT +#endif +}; + +static inline uint64 +GET_U64_FROM_ADDR(uint32 *addr) +{ + union { + uint64 val; + uint32 parts[2]; + } u; + u.parts[0] = addr[0]; + u.parts[1] = addr[1]; + return u.val; +} + +static inline void +PUT_U64_TO_ADDR(uint32 *addr, uint64 value) +{ + uint32 *addr_u32 = (uint32 *)(addr); + union { + float64 val; + uint32 parts[2]; + } u; + u.val = (value); + addr_u32[0] = u.parts[0]; + addr_u32[1] = u.parts[1]; +} + +} + +#endif // UNIT_TEST_MEMORY64_COMMON_H diff --git a/tests/unit/memory64/memory64_test.cc b/tests/unit/memory64/memory64_test.cc new file mode 100644 index 000000000..67315a594 --- /dev/null +++ b/tests/unit/memory64/memory64_test.cc @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "memory64_common.h" + +// To use a test fixture and Value Parameterized Tests, +// derive a class from testing::TestWithParam. +class memory64_test_suite : public testing::TestWithParam +{ + protected: + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = wasm_file; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + goto fail; + + if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + return true; + + fail: + if (!module) + wasm_runtime_unload(module); + + return false; + } + + bool init_exec_env() + { + if (!(module_inst = + wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + if (!(exec_env = + wasm_runtime_create_exec_env(module_inst, stack_size))) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + return true; + + fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) + wasm_runtime_unload(module); + return false; + } + + void destory_exec_env() + { + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + } + + public: + // If your test fixture defines SetUpTestSuite() or TearDownTestSuite() + // they must be declared public rather than protected in order to use + // TEST_P. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + cleanup = true; + } + + static void SetUpTestCase() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() + { + if (cleanup) { + wasm_runtime_destroy(); + cleanup = false; + } + } + + static void TearDownTestCase() {} + + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + uint32_t stack_size = 8092, heap_size = 8092; + bool cleanup = true; +}; + +TEST_F(memory64_test_suite, wasm_runtime_is_running_mode_supported) +{ + // TODO: make sure the chosen running mode option is compiled, for memory64, + // currently only support classic interp mode + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported( + static_cast(Mode_Default))); + for (auto running_mode : running_mode_supported) { + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported(running_mode)); + } +} + +TEST_F(memory64_test_suite, page_exceed_u32_1) +{ + bool ret; + ret = load_wasm_file("page_exceed_u32.wasm"); + ASSERT_FALSE(ret); + ASSERT_TRUE(strcmp("WASM module load failed: integer too large", error_buf) + == 0); +} + +TEST_F(memory64_test_suite, page_exceed_u32_2) +{ + bool ret; + ret = load_wasm_file("page_exceed_u32_2.wasm"); + ASSERT_FALSE(ret); + ASSERT_TRUE(strcmp("WASM module load failed: integer too large", error_buf) + == 0); +} + +TEST_F(memory64_test_suite, page_u32_max) +{ + bool ret; + ret = load_wasm_file("page_u32_max.wasm"); + ASSERT_TRUE(ret); +} + +TEST_P(memory64_test_suite, memory_8GB) +{ + RunningMode running_mode = GetParam(); + wasm_function_inst_t touch_every_page_func, i64_store_offset_4GB, + i64_load_offset_4GB; + uint32_t wasm_argv[6], i32; + uint64_t i64; + bool ret; + + ret = load_wasm_file("8GB_memory.wasm"); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + + touch_every_page_func = + wasm_runtime_lookup_function(module_inst, "touch_every_page"); + ASSERT_TRUE(touch_every_page_func != NULL); + ret = wasm_runtime_call_wasm(exec_env, touch_every_page_func, 0, wasm_argv); + ASSERT_TRUE(ret); + // check return value: 0xfff8:i64,0x10000fff8:i64,0x1fff8:i32,0x1:i32 + i64 = 0xfff8; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + i64 = 0x10000fff8; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv + 2)); + i32 = 0x1fff8; + ASSERT_EQ(i32, wasm_argv[4]); + i32 = 0x1; + ASSERT_EQ(i32, wasm_argv[5]); + + // store at 0x100001000, with value 0xbeefdead + PUT_I64_TO_ADDR(wasm_argv, 0x1000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xbeefdead); + i64_store_offset_4GB = + wasm_runtime_lookup_function(module_inst, "i64_store_offset_4GB"); + ASSERT_TRUE(i64_store_offset_4GB != NULL); + ret = wasm_runtime_call_wasm(exec_env, i64_store_offset_4GB, 4, wasm_argv); + ASSERT_TRUE(ret); + + i64_load_offset_4GB = + wasm_runtime_lookup_function(module_inst, "i64_load_offset_4GB"); + ASSERT_TRUE(i64_load_offset_4GB != NULL); + ret = wasm_runtime_call_wasm(exec_env, i64_load_offset_4GB, 2, wasm_argv); + ASSERT_TRUE(ret); + // check return value: 0xbeefdead:i64 + i64 = 0xbeefdead; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + destory_exec_env(); +} + +TEST_P(memory64_test_suite, mem64_from_clang) +{ + RunningMode running_mode = GetParam(); + wasm_function_inst_t test_func; + uint32_t wasm_argv[1], i32; + bool ret; + + ret = load_wasm_file("mem64.wasm"); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + + test_func = + wasm_runtime_lookup_function(module_inst, "test"); + ASSERT_TRUE(test_func != NULL); + ret = wasm_runtime_call_wasm(exec_env, test_func, 0, wasm_argv); + ASSERT_TRUE(ret); + i32 = 0x109; + ASSERT_EQ(i32, wasm_argv[0]); + + destory_exec_env(); +} + +INSTANTIATE_TEST_CASE_P(RunningMode, memory64_test_suite, + testing::ValuesIn(running_mode_supported)); \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/8GB_memory.wasm b/tests/unit/memory64/wasm-apps/8GB_memory.wasm new file mode 100644 index 0000000000000000000000000000000000000000..32028ff62bbbf3eb0d6196d925b2e01590fcdc83 GIT binary patch literal 249 zcmZQbEY4+QU|?XJ)X>ntz?{IqQdd`BpTJaC$B@8S$5_YQ0v2arWMb_Au^3q!8aRN6 z{UBIepd`OEIU_!`EVZaIz92C@m4QJd)668kxFo+QH9kKrtvIzL-o)LBfl(MFoRgoJ zf-K6!^#yFq8L-iebxuFz6&aWv6c`j3%$b3NQ-eZ{BA5m$P;la?4dG?rcKY$3S(BLo rNHsSIKp5=}0vb#VPJjMG82sG5AOnFK6&TH#fy@R0?rx}vCX^2Voc>7V literal 0 HcmV?d00001 diff --git a/tests/unit/memory64/wasm-apps/8GB_memory.wat b/tests/unit/memory64/wasm-apps/8GB_memory.wat new file mode 100644 index 000000000..10e355198 --- /dev/null +++ b/tests/unit/memory64/wasm-apps/8GB_memory.wat @@ -0,0 +1,53 @@ +(module + ;; Memory definition: 4 GB = 65536 + ;; 8 GB = 131072 + ;; 16 GB = 262144 + ;; 20 GB = 327680 + ;; 32 GB = 524288 + (memory (;0;) i64 131072 131072) + + ;; if touch too many pages more than physical memory can provide, + ;; the signal will kill the process + (func (export "touch_every_page") (result i64 i64 i32 i32) + (local $i i64) + i64.const 0x0000000000000ff8 + local.set $i + loop $loop + ;; a[i] = i + local.get $i + local.get $i + i64.store + local.get $i + i64.const 4096 + i64.add + local.set $i + local.get $i + ;; max boundary(exclusive) 8GB - 8 = 0x0000000200000000 - 8 + i64.const 0x0000000200000000 + i64.const 8 + i64.sub + i64.lt_u + br_if $loop + end + i64.const 0x000000000000fff8 + i64.load + i64.const 0x000000010000fff8 + i64.load + ;; lower 8 bytes of 0x000000010001fff8 -> 0x0001fff8 + i64.const 0x000000010001fff8 + i32.load + ;; higher 8 bytes of 0x000000010001fff8 -> 0x1 + i64.const 0x000000010001fffc + i32.load + return + ) + + ;; Function to test i64.atomic.store with i64 address + (func (export "i64_store_offset_4GB") (param $addr i64) (param $value i64) + (i64.store offset=0x100000000 (local.get $addr) (local.get $value)) + ) + + (func (export "i64_load_offset_4GB") (param $addr i64) (result i64) + (i64.load offset=0x100000000 (local.get $addr)) + ) +) \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/atomic_opcodes.wasm b/tests/unit/memory64/wasm-apps/atomic_opcodes.wasm new file mode 100644 index 0000000000000000000000000000000000000000..fbdc587096da88e66f9e785c4734d440e0ba3804 GIT binary patch literal 820 zcmZXR$xg#C5QfLj)+R048ke209JsbcRnFXaiZp5wR3a+sA~>b5*N5QFTU3k`=AR@`tV#j^TP;9~=$A_LY>k zMKJ?M&E+J^H_(bT+hB~e?JF^&*;O;@W-r!kqPe3}{3sjfs_Dz}BQIt%I7*asgc+x3 z_SqrFxxa-#U89~7CdwMhl!zVjW=gCT_+JybJ*|*W%lFUe>kB0AH(@TMkdl3$g7+s+ zppmDfk;g_O&!pj88ZK}`3y1B4T14m*Bu1AIAr29uSC^8y#N+~(Ql>KMT1H*TU2de| jRvPYbLPxwV@z)&g(zzT3IcOsq=6vK-4+rIHFv>BRCe zpO9k?JmeF6bZ-6xA9Hk7a!%z9L5ub^sA>+Tr(d%h@1bE;U+vqLW!V}1MAz$e`{;>9 zQ%Ahhj<#&&I<{-8NT06T{_&rdSGW9sV&>OuqT6m{e{cVXmp?1ZIox}7XxZsXWxx9U z^GfyQx8InbA1#%rRGwB3tChXyPqpn;D&Or@UsS%XzS`3&@h++V)mdGS9NBes3%MDNvFA}l8)_K65(y6s2sJUci`rfBhg(~ zVu&JEmiVqM3B-{&5D(s^qzyN(`=u)kOd=`W=x$2NSCU2w>4x;63q65kkjW`adWk=U zUYt6Vz7U!Xp{H?L`qAH%0YV2cfWd|gA&a3vhB1u3qO!uk5oQ?02u5o%#!AOnX_w`B zEF9e8i^7G4k3%qCmI=ZpF@ebgnZndb;nQK#8O%ryxu)d#?`M$5nTDLjG|mPxi&<0n zoT)Y~^I`k~7NmeeQx+M&ghebhWEt~V4rB!@CjK1eaPFBD4J;<55Vnd{S;JaW)(P9d zIyM@zi4rygIgj%wo;10|YPYe4?V6AS?6jKen}B%gYkS|6oxI3T{B=BXCR&IPBxjuQS`i~3OT0!pI`36nIQ*S~i{k~~e8^r~_H)^T^!-CfcJ(wX9I zijDj4Eow<29Z*X>lJN`D%WZE!A)S&wKP_2qvw?&X%AgPZ>9Dy09t;$fQS~5i2aBq! zrD~N^T{1**3}XnxWjWE*0W~#d#L3_-g`I0iNcrq6Y(*U?$SJ(ra3KZOF;R@Hu+Z2uf^dbaN)o$s(_1CR6lXyi~oZ3 zk@uW>-ytDtG!f%@EHKm}YUqpP^}9|;f~N_i3A*2Q+#cOts0s3(Qy)7=Nu!Bwo_7bN zHie`~+LhOTbwbiSO&d+n{h{OTp}Qy4M25GSPb@ly#a^=58YpGy;}g!3{p^8}f?=^0 z!Koqx7--6%QPL1Igfm4(NaH95G1?&OBNz)fL11VUCTfk1L$cn=(PAA_O_?@1W|$)+ zy*)3c!+DW!&kIbL-deyprkdv{n6JqKQ44L>$wqDa$fpD_F+L0SC#s zlU9l-a+H*svTDj$V}`Xr*0C-dY-JOx*lci+Y~Xw#Ti7zKY=>p+U`IGMn&R{Axj@{7 zKrZ5NB|(!ms1H+`x^d+~kXJi||{4+{SIWL-<|X z#NCG6!yViU+DZ2h*v3OVz{8q6BI?m6&GXSf9^-M!^M0}UQH*(q=6kAWn&!}4 V+UHkU}OQ34FUi(u?1uR literal 0 HcmV?d00001 diff --git a/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat b/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat new file mode 100644 index 000000000..4db1b838d --- /dev/null +++ b/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat @@ -0,0 +1,4 @@ +(module + ;; u32 max pages is 4,294,967,295 + (memory i64 4294967296) +) \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/page_u32_max.wasm b/tests/unit/memory64/wasm-apps/page_u32_max.wasm new file mode 100644 index 0000000000000000000000000000000000000000..caa8de4543ba54074d17aa8e9c1301f5d366f985 GIT binary patch literal 22 bcmZQbEY4+QU|?YFXlQ6)U}R +#include + +int +recursive(int a) +{ + if (a > 0) { + return recursive(a - 1) + 1; + } + else + return 0; +} + +int +testFunction(int *input, int length) +{ + int sum = 0; + for (int i = 0; i < length; ++i) { + sum += input[i]; + } + return sum; +} + +int +main(int argc, char **argv) +{ + + int arr[5] = { 1, 2, 3, 4, 5 }; + testFunction(arr, recursive(5)); + + char *buf; + + printf("Hello world!\n"); + + buf = malloc(1024); + if (!buf) { + printf("malloc buf failed\n"); + return -1; + } + + printf("buf ptr: %p\n", buf); + + snprintf(buf, 1024, "%s", "1234\n"); + printf("buf: %s", buf); + + free(buf); + return 0; +} diff --git a/tests/unit/running-modes/wasm_running_modes_test.cc b/tests/unit/running-modes/wasm_running_modes_test.cc new file mode 100644 index 000000000..9d6a9379c --- /dev/null +++ b/tests/unit/running-modes/wasm_running_modes_test.cc @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" +#include "aot_runtime.h" + +namespace { + +std::string CWD; +std::string TEST_WASM1 = "/hello.wasm"; +std::string TEST_WASM2 = "/mytest.wasm"; +char *WASM_FILE_1; +char *WASM_FILE_2; +std::vector running_mode_supportted = { Mode_Interp, +#if WASM_ENABLE_FAST_JIT != 0 + Mode_Fast_JIT, +#endif +#if WASM_ENABLE_JIT != 0 + Mode_LLVM_JIT, +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + Mode_Multi_Tier_JIT +#endif +}; + +// To use a test fixture and Value Parameterized Tests, +// derive a class from testing::TestWithParam. +class wasm_running_modes_test_suite : public testing::TestWithParam +{ + private: + std::string get_binary_path() + { + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); + } + + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = wasm_file; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + goto fail; + + if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + return true; + + fail: + if (!module) + wasm_runtime_unload(module); + + return false; + } + + bool init_exec_env() + { + if (!(module_inst = + wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + if (!(exec_env = + wasm_runtime_create_exec_env(module_inst, stack_size))) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + return true; + + fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) + wasm_runtime_unload(module); + return false; + } + + void destory_exec_env() + { + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + } + + protected: + void run_wasm_basic( + char *filename, bool in_default_running_mode, + RunningMode running_mode = static_cast(Mode_Default)) + { + bool ret; + uint32_t wasm_argv[2]; + ret = load_wasm_file(filename); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + if (!in_default_running_mode) { + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + } + + wasm_function_inst_t echo2xback_func = + wasm_runtime_lookup_function(module_inst, "echo"); + ASSERT_TRUE(echo2xback_func != NULL); + + wasm_argv[0] = 5; + ret = wasm_runtime_call_wasm(exec_env, echo2xback_func, 1, wasm_argv); + ASSERT_TRUE(ret); + ASSERT_EQ(10, wasm_argv[0]); + + destory_exec_env(); + } + + void run_wasm_complex(char *filename1, char *filename2, + RunningMode default_running_mode, + RunningMode running_mode) + { + bool ret; + uint32_t wasm_argv[2]; + + /* run wasm file 1 in default running mode */ + wasm_runtime_set_default_running_mode(default_running_mode); + ret = load_wasm_file(filename1); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + uint8_t *buffer, *buffer2; + wasm_function_inst_t echo2xback_func, main; + + ASSERT_EQ(default_running_mode, + wasm_runtime_get_running_mode(module_inst)); + echo2xback_func = wasm_runtime_lookup_function(module_inst, "echo"); + ASSERT_TRUE(echo2xback_func != NULL); + wasm_argv[0] = 5; + ret = wasm_runtime_call_wasm(exec_env, echo2xback_func, 1, wasm_argv); + ASSERT_TRUE(ret); + ASSERT_EQ(10, wasm_argv[0]); + + destory_exec_env(); + + /* run wasm file 2 in running_mode */ + ret = load_wasm_file(filename2); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + main = wasm_runtime_lookup_function(module_inst, "__main_argc_argv"); + ASSERT_TRUE(main != NULL); + ret = wasm_runtime_call_wasm(exec_env, main, 2, wasm_argv); + ASSERT_TRUE(ret); + + destory_exec_env(); + } + + public: + // If your test fixture defines SetUpTestSuite() or TearDownTestSuite() + // they must be declared public rather than protected in order to use + // TEST_P. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + CWD = get_binary_path(); + WASM_FILE_1 = strdup((CWD + TEST_WASM1).c_str()); + WASM_FILE_2 = strdup((CWD + TEST_WASM2).c_str()); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + cleanup = true; + } + + static void SetUpTestCase() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() + { + if (cleanup) { + wasm_runtime_destroy(); + cleanup = false; + } + free(WASM_FILE_1); + free(WASM_FILE_2); + } + + static void TearDownTestCase() {} + + std::string CWD; + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + uint32_t stack_size = 8092, heap_size = 8092; + bool cleanup = true; +}; + +TEST_F(wasm_running_modes_test_suite, wasm_runtime_is_running_mode_supported) +{ + // normal situation + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported( + static_cast(Mode_Default))); + for (auto running_mode : running_mode_supportted) { + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported(running_mode)); + } + + // abnormal situation + ASSERT_EQ(false, wasm_runtime_is_running_mode_supported( + static_cast(-1))); + ASSERT_EQ(false, wasm_runtime_is_running_mode_supported( + static_cast(5))); + ASSERT_EQ(false, wasm_runtime_is_running_mode_supported( + static_cast(0xFF))); +} + +TEST_F(wasm_running_modes_test_suite, wasm_runtime_set_default_running_mode) +{ + // normal situation: only set up + ASSERT_EQ(true, wasm_runtime_set_default_running_mode( + static_cast(Mode_Default))); + for (auto running_mode : running_mode_supportted) { + ASSERT_EQ(true, wasm_runtime_set_default_running_mode(running_mode)); + } + + // abnormal situation + ASSERT_EQ(false, wasm_runtime_set_default_running_mode( + static_cast(-1))); + ASSERT_EQ(false, wasm_runtime_set_default_running_mode( + static_cast(5))); + ASSERT_EQ(false, wasm_runtime_set_default_running_mode( + static_cast(0xFF))); +} + +TEST_P(wasm_running_modes_test_suite, + wasm_runtime_set_default_running_mode_basic) +{ + RunningMode running_mode = GetParam(); + ASSERT_EQ(true, wasm_runtime_set_default_running_mode(running_mode)); + run_wasm_basic(WASM_FILE_1, true); +} + +TEST_P(wasm_running_modes_test_suite, + wasm_runtime_set_and_get_running_mode_basic) +{ + RunningMode running_mode = GetParam(); + run_wasm_basic(WASM_FILE_1, false, running_mode); +} + +TEST_P(wasm_running_modes_test_suite, + wasm_runtime_set_and_get_running_mode_complex) +{ + RunningMode default_running_mode = GetParam(); + for (auto running_mode : running_mode_supportted) { + run_wasm_complex(WASM_FILE_1, WASM_FILE_2, default_running_mode, + running_mode); + } +} + +INSTANTIATE_TEST_CASE_P(RunningMode, wasm_running_modes_test_suite, + testing::ValuesIn(running_mode_supportted)); + +} \ No newline at end of file diff --git a/tests/unit/runtime-common/CMakeLists.txt b/tests/unit/runtime-common/CMakeLists.txt new file mode 100644 index 000000000..f73756915 --- /dev/null +++ b/tests/unit/runtime-common/CMakeLists.txt @@ -0,0 +1,73 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project(test-runtime-common) + +add_definitions(-DRUN_ON_LINUX) + +set(WAMR_BUILD_LIBC_WASI 0) +set(WAMR_BUILD_APP_FRAMEWORK 0) + +include(../unit_common.cmake) + +set(LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") + +if(NOT EXISTS "${LLVM_SRC_ROOT}/build") + message(FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif() + +set(CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +file(GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set(UNIT_SOURCE ${source_all}) + +aux_source_directory(. SRC_LIST) + +set(unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} +) + +add_executable(runtime_common_test ${unit_test_sources}) + +target_link_libraries(runtime_common_test ${LLVM_AVAILABLE_LIBS} gtest_main) + +# Ensure that aot compiled is completed before linear_memory_test_aot is built +set(dummy_output "${CMAKE_CURRENT_BINARY_DIR}/dummy_output") + +add_custom_command(OUTPUT ${dummy_output} + COMMAND ./build_aot.sh + COMMAND ${CMAKE_COMMAND} -E touch ${dummy_output} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/build_aot.sh + COMMENT "Executing script to compile aot files" + VERBATIM +) + +add_custom_target( + BuildAot ALL + DEPENDS ${dummy_output} +) + +add_dependencies(runtime_common_test BuildAot) + +add_custom_command(TARGET runtime_common_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.wasm ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.aot + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy main.wasm and main.aot to the directory: build/runtime-common." +) + +gtest_discover_tests(runtime_common_test) diff --git a/tests/unit/runtime-common/build_aot.sh b/tests/unit/runtime-common/build_aot.sh new file mode 100755 index 000000000..441d441b5 --- /dev/null +++ b/tests/unit/runtime-common/build_aot.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +# Define a list of .wasm files +file_names=("main") + +WORKDIR="$PWD" +WAMRC_ROOT_DIR="${WORKDIR}/../../../wamr-compiler" +WAMRC="${WAMRC_ROOT_DIR}/build/wamrc" +WAST2WASM="/opt/wabt/bin/wat2wasm" + +# build wamrc if not exist +if [ ! -s "$WAMRC" ]; then + cd $WAMRC_ROOT_DIR + if [ -d "$WAMRC/build" ]; then + rm -r build + fi + cmake -B build && cmake --build build -j $(nproc) + cd $WORKDIR +fi + +# Iterate over the files array +for file_name in "${file_names[@]}"; do + # compile wasm to aot + $WAMRC -o "wasm-apps/${file_name}.aot" "wasm-apps/${file_name}.wasm" +done + diff --git a/tests/unit/runtime-common/wasm-apps/main.aot b/tests/unit/runtime-common/wasm-apps/main.aot new file mode 100644 index 0000000000000000000000000000000000000000..79319145a9019df34a340da8f14f9a3f95e5175d GIT binary patch literal 1164 zcmah|L2J}d5Pq%7#&+%IP_WuVSJ;E6(gi8qixAji7E%#x^`P|;H?Q4bHwnpeyDGTF z1!)LMPu~0sp1kN`DYPQqihsbH2v+Dx1%*1_OV(0WH{#)8J(|r2EK@PZl28MwaM^oE>?xPJj#~B+ZGc@0DqaytxyBVyA;*uX0rHJI@ zP>M!vK!1PsIH6L56zg<4DGWY&K*54NQUeM@4-C6?C~c4hFQDL$6OX>%=L>SeYq1;) zLf4Z^1Y?-FPl5?Ws)1k%YWniq*V72{;0{?Zt{c~k1!MlI+1(wpl2zSI{HfXG#SQ_C zC$oFKQ-m@rZwlS#aN-|UvOLopA-`7HE<9Q%$4VZI)soBS&DbjGwd83VrSW5Qcw5!- zgkZ06u2%f5hq2{%bMg022-lLF8COf%D}*Us{#t&2kUMS0AIwCSG&8A|^nJZ|j!?$h z!v?!Ms%Tl2FVT?VGFRD+&QJr@wY+I|x5sW6H;qN(mcbXdW@EL^=Z{MpW^#!(TnEKu z4Gg=Rd$H8=TZM@=>dubJ$Mc#-m?QK5t1oYEsk?SCB$K_&>e!xSDzjHI3xm7DI|7UA zJ(*eDJDzi-$Q@SXHnKb!%I8>9H2v^iie;?8e2+`FDMBt5g{l&uz`ZwLzA?rQc|QsS}q8|0U<6ea{bsOZelywPEbzn z1&RN_0sa-gf+Hs`%qFQQ9H190@9fO(%(vg{&VZc+2mrXIpRp{%>a; zG8`Mj*bmbV05^1GoN1blLqyayM8=FV&#?Vv)6Ag#DX%2yxwknZkUCiMyg)_e7HSj}8)kM6WlSITHrA0MOtC1Ft4^Cf9tf%z$ zrz)q@_f)CYT#IK~Es0%#!1k%MRN5}6V9=+D+|czR+bZX~Y@J}?D;DSEsl=#|r(tlN zL!6O6@UG=abZS@GxC1-vim{9nKMKW8qgt=l#bz%}hsi;$*7eig$f>$fP#X-!GqF94 zqjTw|qT}s&58d5Peb4jcZo`qX-fy^+S7LDL(9v=HtKjo_3}6^vll6ts)RklG<+H8b)+uGA)pZtFUm;ft$ literal 0 HcmV?d00001 diff --git a/tests/unit/runtime-common/wasm_exec_env_test.cc b/tests/unit/runtime-common/wasm_exec_env_test.cc new file mode 100644 index 000000000..06c162b62 --- /dev/null +++ b/tests/unit/runtime-common/wasm_exec_env_test.cc @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "wasm_exec_env.h" + +class wasm_exec_env_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} +}; + +TEST_F(wasm_exec_env_test_suite, wasm_exec_env_create) +{ + EXPECT_EQ(nullptr, wasm_exec_env_create(nullptr, 0)); +} + +TEST_F(wasm_exec_env_test_suite, wasm_exec_env_create_internal) +{ + EXPECT_EQ(nullptr, wasm_exec_env_create_internal(nullptr, UINT32_MAX)); +} + +TEST_F(wasm_exec_env_test_suite, wasm_exec_env_pop_jmpbuf) +{ + WASMExecEnv exec_env; + + exec_env.jmpbuf_stack_top = nullptr; + EXPECT_EQ(nullptr, wasm_exec_env_pop_jmpbuf(&exec_env)); +} diff --git a/tests/unit/runtime-common/wasm_runtime_common_test.cc b/tests/unit/runtime-common/wasm_runtime_common_test.cc new file mode 100644 index 000000000..978b54022 --- /dev/null +++ b/tests/unit/runtime-common/wasm_runtime_common_test.cc @@ -0,0 +1,682 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" +#include "aot_runtime.h" + +using namespace std; + +extern "C" { +uint32 +wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint32 ptr, + uint32 size, void **p_native_addr); +bool +wasm_runtime_create_exec_env_and_call_wasm( + WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function, + uint32 argc, uint32 argv[]); +} + +static bh_list loading_module_list_head; +static bh_list *const loading_module_list = &loading_module_list_head; +static korp_mutex loading_module_list_lock; + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static std::string MAIN_AOT = "/main.aot"; +static char *WASM_FILE_1; +static char *AOT_FILE_1; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class wasm_runtime_common_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE_1 = strdup((CWD + MAIN_WASM).c_str()); + AOT_FILE_1 = strdup((CWD + MAIN_AOT).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() + { + free(WASM_FILE_1); + free(AOT_FILE_1); + } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_destroy) +{ + wasm_runtime_init(); + wasm_runtime_destroy(); +} + +static bool +reader_test(package_type_t module_type, const char *module_name, + uint8 **p_buffer, uint32 *p_size) +{ + return true; +} + +static void +destroyer_test(uint8 *buffer, uint32 size) +{} + +TEST_F(wasm_runtime_common_test_suite, + set_module_reader_get_module_reader_get_module_destroyer) +{ + wasm_runtime_set_module_reader(reader_test, destroyer_test); + EXPECT_EQ((module_reader)reader_test, wasm_runtime_get_module_reader()); + EXPECT_EQ((module_destroyer)destroyer_test, + wasm_runtime_get_module_destroyer()); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_register_module) +{ + const char *wasm_file = WASM_FILE_1; + wasm_module_t wasm_module = nullptr; + unsigned char *wasm_file_buf = nullptr; + unsigned int wasm_file_size = 0; + char error_buf[128] = { 0 }; + char module_name[] = "module_test"; + char module_name_1[] = "module_test_1"; + + // Normal situation. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + EXPECT_NE(false, + wasm_runtime_register_module("module_test", wasm_module, + error_buf, sizeof(error_buf))); + + // Abnormal situation. + EXPECT_EQ(false, + wasm_runtime_register_module(nullptr, nullptr, nullptr, 0)); + EXPECT_EQ(false, wasm_runtime_register_module( + "module_test", nullptr, error_buf, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module("module_test", wasm_module, + nullptr, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module("module_test", wasm_module, + error_buf, 0)); + EXPECT_EQ(false, wasm_runtime_register_module( + nullptr, wasm_module, error_buf, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module(nullptr, nullptr, error_buf, + sizeof(error_buf))); + + EXPECT_EQ(true, wasm_runtime_register_module(module_name, wasm_module, + error_buf, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module_internal(nullptr, wasm_module, + NULL, 0, error_buf, + sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module_internal( + module_name_1, wasm_module, NULL, 0, error_buf, + sizeof(error_buf))); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_unregister_module) +{ + wasm_runtime_unregister_module(nullptr); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_find_module_registered) +{ + EXPECT_EQ(nullptr, wasm_runtime_find_module_registered("module_test")); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_is_module_registered) +{ + EXPECT_EQ(nullptr, wasm_runtime_find_module_registered("")); +} + +/* TODO: add thread safety test. */ +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_add_loading_module) +{ + EXPECT_EQ(true, wasm_runtime_add_loading_module(nullptr, nullptr, 0)); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_destroy_loading_module_list) +{ + os_mutex_init(&loading_module_list_lock); + wasm_runtime_destroy_loading_module_list(); + os_mutex_destroy(&loading_module_list_lock); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_is_built_in_module) +{ + EXPECT_EQ(true, wasm_runtime_is_built_in_module("env")); + EXPECT_EQ(true, wasm_runtime_is_built_in_module("wasi_unstable")); + EXPECT_EQ(true, wasm_runtime_is_built_in_module("wasi_snapshot_preview1")); + EXPECT_EQ(true, wasm_runtime_is_built_in_module("")); + EXPECT_EQ(false, wasm_runtime_is_built_in_module("test")); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_read_v128) +{ + unsigned char buf[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + unsigned char ret1[8] = { 0 }; + unsigned char ret2[8] = { 0 }; + + wasm_runtime_read_v128((const uint8 *)buf, (uint64 *)ret1, (uint64 *)ret2); + EXPECT_EQ(0, strncmp("01234567", (const char *)ret1, 8)); + EXPECT_EQ(0, strncmp("89ABCDEF", (const char *)ret2, 8)); +} + +TEST_F(wasm_runtime_common_test_suite, + wasm_runtime_show_app_heap_corrupted_prompt) +{ + wasm_runtime_show_app_heap_corrupted_prompt(); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_is_xip_file) +{ + // WASM file. + const char *wasm_file = WASM_FILE_1; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + EXPECT_EQ(false, wasm_runtime_is_xip_file(wasm_file_buf, wasm_file_size)); + + // AoT file. + const char *aot_file = AOT_FILE_1; + unsigned int aot_file_size = 0; + unsigned char *aot_file_buf = nullptr; + + aot_file_buf = + (unsigned char *)bh_read_file_to_buffer(aot_file, &aot_file_size); + EXPECT_NE(aot_file_buf, nullptr); + EXPECT_EQ(false, wasm_runtime_is_xip_file(aot_file_buf, aot_file_size)); +} + +TEST_F(wasm_runtime_common_test_suite, get_package_type) +{ + const char *wasm_file = WASM_FILE_1; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + + // WASM file. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + EXPECT_EQ(Wasm_Module_Bytecode, + get_package_type(wasm_file_buf, wasm_file_size)); + + // WASM file. Abnormally. + wasm_file_buf[3] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[2] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[1] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[0] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + + EXPECT_EQ(Package_Type_Unknown, get_package_type(wasm_file_buf, 0)); + EXPECT_EQ(Package_Type_Unknown, get_package_type(nullptr, 0)); + + // AoT file. + const char *wasm_file_aot = AOT_FILE_1; + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file_aot, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + EXPECT_EQ(Wasm_Module_AoT, get_package_type(wasm_file_buf, wasm_file_size)); + + // AoT file. Abnormally. + wasm_file_buf[3] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[2] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[1] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[0] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + + EXPECT_EQ(Package_Type_Unknown, get_package_type(wasm_file_buf, 0)); + EXPECT_EQ(Package_Type_Unknown, get_package_type(nullptr, 0)); +} + +TEST_F(wasm_runtime_common_test_suite, functions_on_wasm_module) +{ + const char *wasm_file = WASM_FILE_1; + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_exec_env_t exec_env_1 = nullptr; + unsigned char *wasm_file_buf = nullptr; + WASMFunctionInstanceCommon *func = nullptr; + const char *user_data = "test"; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = 16 * 1024; + char error_buf[128] = { 0 }; + unsigned int argv[2] = { 0 }; + WASMType *func_type = nullptr; + wasm_val_t arguments[1]; + char str_test[] = "This is a test."; + char str_exception[] = "Exception: "; + char str_tmp[60] = { 0 }; + void *ptr_tmp = nullptr; + unsigned int offset_tmp = 0; + unsigned int tmp = 0; + unsigned char *p_native_start_addr = nullptr; + unsigned char *p_native_end_addr = nullptr; + NativeSymbol *native_symbols; + uint32 n_native_symbols; + const char *exception_test = nullptr; + + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = 0; + + // Create exec_env. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + EXPECT_NE(wasm_module_inst, nullptr); + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + EXPECT_NE(exec_env, nullptr); + + // Operations on exec_env. + EXPECT_EQ(true, wasm_runtime_register_module_internal("test", wasm_module, + nullptr, 0, error_buf, + sizeof(error_buf))); + EXPECT_NE(nullptr, wasm_runtime_find_module_registered("test")); + EXPECT_EQ(wasm_module_inst, wasm_runtime_get_module_inst(exec_env)); + EXPECT_EQ(exec_env->attachment, + wasm_runtime_get_function_attachment(exec_env)); + EXPECT_EQ(wasm_module, wasm_exec_env_get_module(exec_env)); + + wasm_runtime_set_user_data(exec_env, (void *)user_data); + EXPECT_EQ((void *)user_data, wasm_runtime_get_user_data(exec_env)); + + func = wasm_runtime_lookup_function(wasm_module_inst, "on_timer_event"); + func_type = + wasm_runtime_get_function_type(func, wasm_module_inst->module_type); + EXPECT_NE(func_type, nullptr); + EXPECT_EQ(false, wasm_runtime_call_wasm(exec_env, func, 0, argv)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + EXPECT_EQ(false, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 1, + arguments)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + WASMFunctionInstance func_test_1; + WASMFunction wasm_func_test; + WASMType wasm_type_test; + wasm_func_test.func_type = &wasm_type_test; + func_test_1.u.func = &wasm_func_test; + func_test_1.u.func->func_type->param_count = 1; + func_test_1.u.func->func_type->param_cell_num = 2; + func_test_1.u.func->func_type->types[0] = VALUE_TYPE_I64; + func_test_1.u.func->max_stack_cell_num = 10; + EXPECT_EQ(false, wasm_runtime_call_wasm_v( + exec_env, (WASMFunctionInstanceCommon *)(&func_test_1), + 0, nullptr, 1, arguments)); + func_test_1.u.func->func_type->types[0] = VALUE_TYPE_F32; + EXPECT_EQ(false, wasm_runtime_call_wasm_v( + exec_env, (WASMFunctionInstanceCommon *)(&func_test_1), + 0, nullptr, 1, arguments)); + func_test_1.u.func->func_type->types[0] = VALUE_TYPE_F64; + EXPECT_EQ(false, wasm_runtime_call_wasm_v( + exec_env, (WASMFunctionInstanceCommon *)(&func_test_1), + 0, nullptr, 1, arguments)); + +#if 0 + WASMFunctionInstance func_test; + WASMFunctionImport func_import_test; + WASMType *func_type_1 = nullptr; + func_import_test.func_type = func_type; + func_test.u.func_import = &func_import_test; + func_test.is_import_func = true; + func_type_1 = wasm_runtime_get_function_type(&func_test, + wasm_module_inst->module_type); + EXPECT_NE(func_type_1, nullptr); +#endif + + EXPECT_EQ(true, wasm_runtime_create_exec_env_singleton(wasm_module_inst)); + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + wasm_runtime_set_exception(wasm_module_inst, str_test); + sprintf(str_tmp, "%s%s", str_exception, str_test); + EXPECT_EQ(0, strcmp(str_tmp, wasm_runtime_get_exception(wasm_module_inst))); + wasm_runtime_clear_exception(wasm_module_inst); + EXPECT_EQ(nullptr, wasm_runtime_get_exception(wasm_module_inst)); + + wasm_runtime_set_custom_data(wasm_module_inst, (void *)user_data); + EXPECT_EQ((void *)user_data, + wasm_runtime_get_custom_data(wasm_module_inst)); + + offset_tmp = wasm_runtime_module_malloc(wasm_module_inst, 10, &ptr_tmp); + EXPECT_NE(0, offset_tmp); + EXPECT_EQ(true, + wasm_runtime_validate_app_addr(wasm_module_inst, offset_tmp, 10)); + EXPECT_EQ(ptr_tmp, + wasm_runtime_addr_app_to_native(wasm_module_inst, offset_tmp)); + EXPECT_EQ(true, + wasm_runtime_validate_native_addr(wasm_module_inst, ptr_tmp, 10)); + EXPECT_EQ(offset_tmp, + wasm_runtime_addr_native_to_app(wasm_module_inst, ptr_tmp)); + EXPECT_EQ(true, wasm_runtime_get_native_addr_range( + wasm_module_inst, (unsigned char *)ptr_tmp, + &p_native_start_addr, &p_native_end_addr)); + EXPECT_NE(0, wasm_runtime_module_realloc(wasm_module_inst, offset_tmp, 100, + &ptr_tmp)); + /* can't test like that since shrink size optimization will be applied */ + /* EXPECT_EQ(false, + wasm_enlarge_memory((WASMModuleInstance *)wasm_module_inst, 1)); + */ + EXPECT_EQ(offset_tmp, + wasm_runtime_addr_native_to_app(wasm_module_inst, ptr_tmp)); + EXPECT_EQ(true, wasm_runtime_get_native_addr_range( + wasm_module_inst, (unsigned char *)ptr_tmp, + &p_native_start_addr, &p_native_end_addr)); + + offset_tmp = wasm_runtime_module_dup_data(wasm_module_inst, str_test, + sizeof(str_test)); + EXPECT_EQ(0, strcmp(str_test, (char *)wasm_runtime_addr_app_to_native( + wasm_module_inst, offset_tmp))); + EXPECT_EQ(true, + wasm_runtime_validate_app_str_addr(wasm_module_inst, offset_tmp)); + + ((WASMModuleInstance *)wasm_module_inst)->exec_env_singleton = nullptr; + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + EXPECT_EQ(false, wasm_runtime_call_wasm(nullptr, func, 0, argv)); + wasm_runtime_set_exception(wasm_module_inst, str_test); + EXPECT_EQ(false, wasm_runtime_call_wasm(exec_env, func, 0, argv)); + wasm_runtime_clear_exception(wasm_module_inst); + + EXPECT_EQ(false, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 2, + arguments)); + WASMFunctionInstance *func_test_call_wasm_a_ptr = + (WASMFunctionInstance *)func; + func_test_call_wasm_a_ptr->u.func->func_type->ret_cell_num = 10; + EXPECT_EQ(true, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 1, + arguments)); + + // Destroy. + wasm_runtime_module_free(wasm_module_inst, offset_tmp); + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(wasm_module_inst); + wasm_runtime_unload(wasm_module); + if (wasm_file_buf) { + wasm_runtime_free(wasm_file_buf); + } +} + +TEST_F(wasm_runtime_common_test_suite, functions_on_aot_module) +{ + const char *wasm_file = AOT_FILE_1; + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_exec_env_t exec_env_1 = nullptr; + unsigned char *wasm_file_buf = nullptr; + WASMFunctionInstanceCommon *func = nullptr; + const char *user_data = "test"; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = 16 * 1024; + char error_buf[128] = { 0 }; + unsigned int argv[2] = { 0 }; + WASMType *func_type = nullptr; + wasm_val_t arguments[1]; + char str_test[] = "This is a test."; + char str_exception[] = "Exception: "; + char str_tmp[60] = { 0 }; + void *ptr_tmp = nullptr; + unsigned int offset_tmp = 0; + unsigned int tmp = 0; + unsigned char *p_native_start_addr = nullptr; + unsigned char *p_native_end_addr = nullptr; + NativeSymbol *native_symbols; + uint32 n_native_symbols; + const char *exception_test = nullptr; + + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = 0; + + // Create exec_env. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + EXPECT_NE(wasm_module_inst, nullptr); + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + EXPECT_NE(exec_env, nullptr); + + // Operations on exec_env. + EXPECT_EQ(true, wasm_runtime_register_module_internal("test", wasm_module, + nullptr, 0, error_buf, + sizeof(error_buf))); + EXPECT_NE(nullptr, wasm_runtime_find_module_registered("test")); + EXPECT_EQ(wasm_module_inst, wasm_runtime_get_module_inst(exec_env)); + EXPECT_EQ(exec_env->attachment, + wasm_runtime_get_function_attachment(exec_env)); + EXPECT_EQ(wasm_module, wasm_exec_env_get_module(exec_env)); + + wasm_runtime_set_user_data(exec_env, (void *)user_data); + EXPECT_EQ((void *)user_data, wasm_runtime_get_user_data(exec_env)); + + func = wasm_runtime_lookup_function(wasm_module_inst, "on_timer_event"); + func_type = + wasm_runtime_get_function_type(func, wasm_module_inst->module_type); + EXPECT_NE(func_type, nullptr); + + EXPECT_EQ(false, wasm_runtime_call_wasm(exec_env, func, 0, argv)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + EXPECT_EQ(false, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 1, + arguments)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + EXPECT_EQ(false, wasm_runtime_call_wasm_v(exec_env, func, 0, nullptr, 1, + arguments)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + AOTFunctionInstance func_test; + AOTImportFunc func_import_test; + func_test.u.func_import = &func_import_test; + func_import_test.func_type = (AOTFuncType *)func_type; + func_test.is_import_func = true; + EXPECT_NE(nullptr, wasm_runtime_get_function_type( + &func_test, wasm_module_inst->module_type)); + + EXPECT_EQ(true, wasm_runtime_create_exec_env_singleton(wasm_module_inst)); + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + wasm_runtime_set_exception(wasm_module_inst, str_test); + sprintf(str_tmp, "%s%s", str_exception, str_test); + EXPECT_EQ(0, strcmp(str_tmp, wasm_runtime_get_exception(wasm_module_inst))); + wasm_runtime_clear_exception(wasm_module_inst); + EXPECT_EQ(nullptr, wasm_runtime_get_exception(wasm_module_inst)); + + wasm_runtime_set_custom_data(wasm_module_inst, (void *)user_data); + EXPECT_EQ((void *)user_data, + wasm_runtime_get_custom_data(wasm_module_inst)); + + offset_tmp = wasm_runtime_module_malloc(wasm_module_inst, 10, &ptr_tmp); + EXPECT_NE(0, offset_tmp); + EXPECT_EQ(true, + wasm_runtime_validate_app_addr(wasm_module_inst, offset_tmp, 10)); + EXPECT_EQ(ptr_tmp, + wasm_runtime_addr_app_to_native(wasm_module_inst, offset_tmp)); + EXPECT_EQ(true, + wasm_runtime_validate_native_addr(wasm_module_inst, ptr_tmp, 10)); + EXPECT_EQ(offset_tmp, + wasm_runtime_addr_native_to_app(wasm_module_inst, ptr_tmp)); + EXPECT_EQ(true, wasm_runtime_get_native_addr_range( + wasm_module_inst, (unsigned char *)ptr_tmp, + &p_native_start_addr, &p_native_end_addr)); + EXPECT_NE(0, wasm_runtime_module_realloc(wasm_module_inst, offset_tmp, 100, + &ptr_tmp)); + + /* can't test like that since shrink size optimization will be applied */ + /* EXPECT_EQ(false, + wasm_enlarge_memory((WASMModuleInstance *)wasm_module_inst, 1)); + */ + + offset_tmp = wasm_runtime_module_dup_data(wasm_module_inst, str_test, + sizeof(str_test)); + EXPECT_EQ(0, strcmp(str_test, (char *)wasm_runtime_addr_app_to_native( + wasm_module_inst, offset_tmp))); + EXPECT_EQ(true, + wasm_runtime_validate_app_str_addr(wasm_module_inst, offset_tmp)); + + ((WASMModuleInstance *)wasm_module_inst)->exec_env_singleton = nullptr; + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + // Destroy. + wasm_runtime_module_free(wasm_module_inst, offset_tmp); + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(wasm_module_inst); + wasm_runtime_unload(wasm_module); + if (wasm_file_buf) { + wasm_runtime_free(wasm_file_buf); + } +} + +TEST_F(wasm_runtime_common_test_suite, functions_on_module_type_unknown) +{ + const char *wasm_file = AOT_FILE_1; + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_exec_env_t exec_env_1 = nullptr; + unsigned char *wasm_file_buf = nullptr; + WASMFunctionInstanceCommon *func = nullptr; + const char *user_data = "test"; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = 16 * 1024; + char error_buf[128] = { 0 }; + unsigned int argv[2] = { 0 }; + WASMType *func_type = nullptr; + wasm_val_t arguments[1]; + char str_test[] = "This is a test."; + char str_exception[] = "Exception: "; + char str_tmp[60] = { 0 }; + void *ptr_tmp = nullptr; + unsigned int offset_tmp = 0; + unsigned int tmp = 0; + unsigned char *p_native_start_addr = nullptr; + unsigned char *p_native_end_addr = nullptr; + const char *exception_test = nullptr; + + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = 0; + + // Create exec_env. + wasm_runtime_unregister_module(wasm_module); + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + EXPECT_NE(wasm_module_inst, nullptr); + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + EXPECT_NE(exec_env, nullptr); + + // wasm_module_inst->module_type = Package_Type_Unknown. + wasm_module_inst->module_type = Package_Type_Unknown; + EXPECT_DEATH(wasm_exec_env_get_module(exec_env), ""); + EXPECT_DEATH( + wasm_runtime_validate_app_str_addr(wasm_module_inst, offset_tmp), ""); + + // wasm_module->module_type = Package_Type_Unknown. + wasm_module->module_type = Package_Type_Unknown; + EXPECT_EQ(nullptr, + wasm_runtime_instantiate(wasm_module, stack_size, heap_size, + error_buf, sizeof(error_buf))); + + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + /* Reload unmodified buffer should be valid now */ + EXPECT_NE(wasm_module, nullptr); + wasm_file_buf[3] = -1; + wasm_file_buf[2] = -1; + wasm_file_buf[1] = -1; + wasm_file_buf[0] = -1; + wasm_module = + wasm_runtime_load(wasm_file_buf, 0, error_buf, sizeof(error_buf)); + EXPECT_EQ(wasm_module, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_EQ(wasm_module, nullptr); + + // Destroy. + wasm_runtime_module_free(wasm_module_inst, offset_tmp); + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(wasm_module_inst); + wasm_runtime_unload(wasm_module); + if (wasm_file_buf) { + wasm_runtime_free(wasm_file_buf); + } +} diff --git a/tests/unit/runtime-common/wasm_runtime_init_test.cc b/tests/unit/runtime-common/wasm_runtime_init_test.cc new file mode 100644 index 000000000..30e44cea3 --- /dev/null +++ b/tests/unit/runtime-common/wasm_runtime_init_test.cc @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" + +using namespace std; + +extern "C" { +uint32 +wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint32 ptr, + uint32 size, void **p_native_addr); +bool +wasm_runtime_create_exec_env_and_call_wasm( + WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function, + uint32 argc, uint32 argv[]); +} + +static char global_heap_buf[100 * 1024 * 1024] = { 0 }; + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static std::string MAIN_AOT = "/main.aot"; +static char *WASM_FILE_1; +static char *AOT_FILE_1; + +static int +foo(int a, int b); + +static int +foo_native(wasm_exec_env_t exec_env, int a, int b) +{ + return a + b; +} + +static NativeSymbol native_symbols[] = { { + "foo", // the name of WASM function name + (void *)foo_native, // the native function pointer + "(ii)i" // the function prototype signature +} }; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class wasm_runtime_init_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE_1 = strdup((CWD + MAIN_WASM).c_str()); + AOT_FILE_1 = strdup((CWD + MAIN_AOT).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() + { + free(WASM_FILE_1); + free(AOT_FILE_1); + } +}; + +TEST_F(wasm_runtime_init_test_suite, init_and_register_natives) +{ + EXPECT_EQ(true, wasm_runtime_init()); + int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + EXPECT_EQ(true, wasm_runtime_register_natives("env", native_symbols, + n_native_symbols)); + EXPECT_EQ(true, wasm_runtime_register_natives_raw("env", native_symbols, + n_native_symbols)); + wasm_runtime_destroy(); +} + +TEST_F(wasm_runtime_init_test_suite, init_thread_env_destroy_thread_env) +{ + EXPECT_EQ(true, wasm_runtime_init_thread_env()); + wasm_runtime_destroy_thread_env(); +} + +TEST_F(wasm_runtime_init_test_suite, wasm_runtime_full_init) +{ + RuntimeInitArgs init_args; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + wasm_module_t module = nullptr; + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + wasm_runtime_destroy(); + init_args.n_native_symbols = 1; + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + wasm_runtime_destroy(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *)malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *)realloc; + init_args.mem_alloc_option.allocator.free_func = (void *)free; + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + wasm_runtime_destroy(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *)os_malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *)os_realloc; + init_args.mem_alloc_option.allocator.free_func = (void *)os_free; + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + /* Use valid module, and runtime need to be proper inited */ + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(WASM_FILE_1, &wasm_file_size); + EXPECT_NE(nullptr, wasm_file_buf); + module = wasm_runtime_load(wasm_file_buf, wasm_file_size, nullptr, 0); + EXPECT_NE(nullptr, module); + EXPECT_EQ(true, wasm_runtime_register_module_internal( + "module", module, wasm_file_buf, wasm_file_size, nullptr, 0)); + wasm_runtime_destroy(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = NULL; + init_args.mem_alloc_option.pool.heap_size = 0; + EXPECT_EQ(false, wasm_runtime_full_init(&init_args)); +} diff --git a/tests/unit/shared-utils/CMakeLists.txt b/tests/unit/shared-utils/CMakeLists.txt new file mode 100644 index 000000000..c5a43dd0e --- /dev/null +++ b/tests/unit/shared-utils/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-shared-utils) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} +) + +add_executable (shared_utils_test ${unit_test_sources}) + +target_link_libraries (shared_utils_test gtest_main) + +gtest_discover_tests(shared_utils_test) diff --git a/tests/unit/shared-utils/bh_assert_test.cc b/tests/unit/shared-utils/bh_assert_test.cc new file mode 100644 index 000000000..faa7a807b --- /dev/null +++ b/tests/unit/shared-utils/bh_assert_test.cc @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_assert.h" + +class bh_assert_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} +}; + +TEST_F(bh_assert_test_suite, bh_assert_internal) +{ + bh_assert_internal(6, "file_name_test", 6, "expr_string_test"); + + // Test abnormal cases. + EXPECT_DEATH(bh_assert_internal(0, "file_name_test", 1, "expr_string_test"), + ""); + EXPECT_DEATH(bh_assert_internal(0, nullptr, 2, "expr_string_test"), ""); + EXPECT_DEATH(bh_assert_internal(0, "file_name_test", 3, nullptr), ""); +} diff --git a/tests/unit/shared-utils/bh_common_test.cc b/tests/unit/shared-utils/bh_common_test.cc new file mode 100644 index 000000000..1d1cb528d --- /dev/null +++ b/tests/unit/shared-utils/bh_common_test.cc @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_common.h" + +class bh_common_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +#define STR_TEST "test" + +TEST_F(bh_common_test_suite, wa_strdup) +{ + EXPECT_EQ(nullptr, wa_strdup(nullptr)); + EXPECT_NE(nullptr, wa_strdup(STR_TEST)); +} + +TEST_F(bh_common_test_suite, b_strcpy_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_strcpy_s(dest, sizeof(dest), STR_TEST)); + + // Test abnormal cases. + EXPECT_EQ(-1, b_strcpy_s(nullptr, 0, nullptr)); + EXPECT_EQ(-1, b_strcpy_s(dest, sizeof(dest), nullptr)); + EXPECT_EQ(-1, b_strcpy_s(dest, 0, STR_TEST)); +} + +TEST_F(bh_common_test_suite, b_strcat_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_strcat_s(dest, sizeof(dest), STR_TEST)); + + // Test abnormal cases. + EXPECT_EQ(-1, b_strcat_s(nullptr, 0, nullptr)); + EXPECT_EQ(-1, b_strcat_s(dest, sizeof(dest), nullptr)); + EXPECT_EQ(-1, b_strcat_s(dest, 0, STR_TEST)); +} + +TEST_F(bh_common_test_suite, bh_strdup) +{ + EXPECT_NE(nullptr, bh_strdup(STR_TEST)); + EXPECT_EQ(nullptr, bh_strdup(nullptr)); +} + +TEST_F(bh_common_test_suite, b_memmove_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_memmove_s(dest, sizeof(dest), STR_TEST, sizeof(STR_TEST))); + + // Test abnormal cases. + EXPECT_EQ(0, b_memmove_s(dest, sizeof(dest), STR_TEST, 0)); + EXPECT_EQ(0, b_memmove_s(nullptr, sizeof(dest), STR_TEST, 0)); + + EXPECT_EQ(0, b_memmove_s(dest, sizeof(dest), nullptr, 0)); + EXPECT_EQ(-1, b_memmove_s(dest, sizeof(dest), STR_TEST, sizeof(dest) + 1)); +} + +TEST_F(bh_common_test_suite, b_memcpy_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_memcpy_s(dest, sizeof(dest), STR_TEST, sizeof(STR_TEST))); + + // Test abnormal cases. + EXPECT_EQ(0, b_memcpy_s(dest, sizeof(dest), STR_TEST, 0)); + EXPECT_EQ(-1, + b_memcpy_s(nullptr, sizeof(dest), STR_TEST, sizeof(STR_TEST))); + EXPECT_EQ(-1, b_memcpy_s(dest, sizeof(dest), nullptr, sizeof(STR_TEST))); + EXPECT_EQ(-1, b_memcpy_s(dest, sizeof(dest), STR_TEST, sizeof(dest) + 1)); +} diff --git a/tests/unit/shared-utils/bh_hashmap_test.cc b/tests/unit/shared-utils/bh_hashmap_test.cc new file mode 100644 index 000000000..4b651ef17 --- /dev/null +++ b/tests/unit/shared-utils/bh_hashmap_test.cc @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "test_helper.h" +#include "gtest/gtest.h" +#include "bh_hashmap.h" +#include "wasm.h" +#include "wasm_export.h" + +#include + +typedef struct HashMapElem { + void *key; + void *value; + struct HashMapElem *next; +} HashMapElem; + +struct HashMap { + /* size of element array */ + uint32 size; + /* lock for elements */ + korp_mutex *lock; + /* hash function of key */ + HashFunc hash_func; + /* key equal function */ + KeyEqualFunc key_equal_func; + KeyDestroyFunc key_destroy_func; + ValueDestroyFunc value_destroy_func; + HashMapElem *elements[1]; +}; + +int DESTROY_NUM = 0; +char TRAVERSE_KEY[] = "key_1"; +char TRAVERSE_VAL[] = "val_1"; +int TRAVERSE_COMP_RES = 0; + +class bh_hashmap_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(bh_hashmap_test_suite, bh_hash_map_create) +{ + // Normally. + EXPECT_NE((HashMap *)nullptr, + bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free)); + + // Illegal parameters. + EXPECT_EQ((HashMap *)nullptr, + bh_hash_map_create(65537, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free)); + EXPECT_EQ((HashMap *)nullptr, + bh_hash_map_create(65536, true, nullptr, nullptr, nullptr, + wasm_runtime_free)); + EXPECT_EQ((HashMap *)nullptr, + bh_hash_map_create(65536, true, (HashFunc)wasm_string_hash, + nullptr, nullptr, wasm_runtime_free)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_insert) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + int num = 0; + void **p_old_key = nullptr; + void **p_old_value = nullptr; + + // Normally. + EXPECT_EQ(true, bh_hash_map_insert(test_hash_map, (void *)"key_1", + (void *)"val_1")); + num++; + // Illegal parameters. + EXPECT_EQ(false, bh_hash_map_insert(nullptr, nullptr, (void *)"val_2")); + + // Execute fail: more than 32. + for (; num <= 32; num++) { + bh_hash_map_insert(test_hash_map, (void *)&num, (void *)"val"); + } + EXPECT_EQ(false, + bh_hash_map_insert(test_hash_map, (void *)&num, (void *)"val")); + + // Remove one, insert one. + bh_hash_map_remove(test_hash_map, (void *)"key_1", p_old_key, p_old_value); + EXPECT_EQ(true, bh_hash_map_insert(test_hash_map, (void *)"key_1", + (void *)"val_1")); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_find) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + + // Normally. use_lock is false. + EXPECT_NE((void *)nullptr, + bh_hash_map_find(test_hash_map, (void *)"key_1")); + + // Execute fail. + EXPECT_EQ((void *)nullptr, + bh_hash_map_find(test_hash_map, (void *)"KEY_1")); + + // Illegal parameters. + EXPECT_EQ((void *)nullptr, bh_hash_map_find(nullptr, nullptr)); + EXPECT_EQ((void *)nullptr, bh_hash_map_find(test_hash_map, nullptr)); + + // Normally. use_lock is true. + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + EXPECT_EQ((void *)nullptr, + bh_hash_map_find(test_hash_map, (void *)"KEY_1")); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_update) +{ + char old_value[10] = { 0 }; + void **p_old_value = (void **)(&old_value); + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + + // test_hash_map->lock == nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_update(test_hash_map, (void *)"key_1", + (void *)"val_2", p_old_value)); + // test_hash_map->lock == nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_update(nullptr, nullptr, (void *)"val_2", + p_old_value)); + EXPECT_EQ(false, bh_hash_map_update(test_hash_map, nullptr, (void *)"val_2", + p_old_value)); + EXPECT_EQ(false, + bh_hash_map_update(nullptr, nullptr, (void *)"val_2", nullptr)); + + // test_hash_map->lock == nullptr. Update non-existent elements. + EXPECT_EQ(false, bh_hash_map_update(test_hash_map, (void *)"key", + (void *)"val", p_old_value)); + + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + + // test_hash_map->lock == no nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_update(test_hash_map, (void *)"key_1", + (void *)"val_2", p_old_value)); + // test_hash_map->lock == no nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_update(nullptr, nullptr, (void *)"val_2", + p_old_value)); + EXPECT_EQ(false, bh_hash_map_update(test_hash_map, nullptr, (void *)"val_2", + p_old_value)); +} + +void +trav_callback_fun(void *key, void *value, void *user_data) +{ + if (!strncmp(TRAVERSE_VAL, (const char *)value, 5)) { + TRAVERSE_COMP_RES = 1; + } + else { + TRAVERSE_COMP_RES = 0; + } +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_traverse) +{ + void **p_old_value = nullptr; + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + + // Normally: TRAVERSE_COMP_RES = 1. + bh_hash_map_insert(test_hash_map, (void *)TRAVERSE_KEY, + (void *)TRAVERSE_VAL); + EXPECT_EQ(true, + bh_hash_map_traverse(test_hash_map, trav_callback_fun, nullptr)); + EXPECT_EQ(1, TRAVERSE_COMP_RES); + + // Normally: TRAVERSE_COMP_RES = 0. + bh_hash_map_update(test_hash_map, (void *)TRAVERSE_KEY, (void *)"val", + p_old_value); + EXPECT_EQ(true, + bh_hash_map_traverse(test_hash_map, trav_callback_fun, nullptr)); + EXPECT_EQ(0, TRAVERSE_COMP_RES); + // Illegal parameters. + EXPECT_EQ(false, bh_hash_map_traverse(nullptr, trav_callback_fun, nullptr)); + EXPECT_EQ(false, bh_hash_map_traverse(test_hash_map, nullptr, nullptr)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_remove) +{ + void **p_old_key = nullptr; + void **p_old_value = nullptr; + + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + + // test_hash_map->lock == nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_remove(test_hash_map, (void *)"key_1", + p_old_key, p_old_value)); + // test_hash_map->lock == nullptr. Remove non-existent elements. + EXPECT_EQ(false, bh_hash_map_remove(test_hash_map, (void *)"key_1", + p_old_key, p_old_value)); + // test_hash_map->lock == nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_remove(nullptr, (void *)"key_2", p_old_key, + p_old_value)); + EXPECT_EQ(false, bh_hash_map_remove(test_hash_map, nullptr, p_old_key, + p_old_value)); + + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + + // test_hash_map->lock == no nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_remove(test_hash_map, (void *)"key_1", + p_old_key, p_old_value)); + // test_hash_map->lock == no nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_remove(nullptr, (void *)"key_2", p_old_key, + p_old_value)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_get_struct_size) +{ + HashMap *test_hash_map = nullptr; + uint32 size = 0; + + // No lock. + test_hash_map = bh_hash_map_create(32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + size = (size_t)(&((HashMap *)0)->elements) + + (uint32)sizeof(HashMapElem *) * test_hash_map->size; + EXPECT_EQ(size, bh_hash_map_get_struct_size(test_hash_map)); + + // Has lock. + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + size = (size_t)(&((HashMap *)0)->elements) + + (uint32)sizeof(HashMapElem *) * test_hash_map->size; + size += (uint32)sizeof(korp_mutex); + EXPECT_EQ(size, bh_hash_map_get_struct_size(test_hash_map)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_get_elem_struct_size) +{ + EXPECT_EQ((uint32)sizeof(HashMapElem), bh_hash_map_get_elem_struct_size()); +} + +void +destroy_func_test(void *key) +{ + DESTROY_NUM++; +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_destroy) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, true, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + destroy_func_test, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + + // test_hash_map->lock == no nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); + // key_destroy_func must be called 2 times. + EXPECT_EQ(2, DESTROY_NUM); + + test_hash_map = bh_hash_map_create(32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, + destroy_func_test, wasm_runtime_free); + + // test_hash_map->lock == no nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_destroy(nullptr)); + // test_hash_map->lock == nullptr. + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); + + // key_destroy_func and value_destroy_func is nullptr. + test_hash_map = + bh_hash_map_create(32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, nullptr); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); +} + +// This fun allows inserting the same keys. +bool +string_equal_test(const char *s1, const char *s2) +{ + return false; +} + +int COUNT_ELEM = 0; + +void +fun_count_elem(void *key, void *value, void *user_data) +{ + COUNT_ELEM++; +} + +TEST_F(bh_hashmap_test_suite, bh_hashmap_thread_safety) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, true, (HashFunc)wasm_string_hash, (KeyEqualFunc)string_equal_test, + destroy_func_test, wasm_runtime_free); + int32_t i = 0; + std::vector> threads; + + // Creat 8 threads. In every thread, run the codes in brackets of + // std::async. + for (i = 0; i < 8; i++) { + threads.push_back(std::async([&] { + for (int j = 0; j < 25; j++) { + bh_hash_map_insert(test_hash_map, (void *)"key_1", + (void *)"val_1"); + } + })); + } + + // Wait all 8 threads finished. + for (auto &t : threads) { + t.wait(); + } + + // Count hash map elements. + bh_hash_map_traverse(test_hash_map, fun_count_elem, nullptr); + + EXPECT_EQ(200, COUNT_ELEM); + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); +} \ No newline at end of file diff --git a/tests/unit/shared-utils/bh_list_test.cc b/tests/unit/shared-utils/bh_list_test.cc new file mode 100644 index 000000000..981c52f25 --- /dev/null +++ b/tests/unit/shared-utils/bh_list_test.cc @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" + +#include "test_helper.h" +#include "gtest/gtest.h" + +class bh_list_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(bh_list_test_suite, bh_list_init) +{ + bh_list list_test; + + // Normally. + EXPECT_EQ(BH_LIST_SUCCESS, bh_list_init(&list_test)); + + // Illegal parameters. + EXPECT_EQ(BH_LIST_ERROR, bh_list_init(nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_insert) +{ + bh_list list_test; + bh_list_link elem_insert; + + // Normally. + bh_list_init(&list_test); + EXPECT_EQ(BH_LIST_SUCCESS, bh_list_insert(&list_test, &elem_insert)); + + // Illegal parameters. + EXPECT_EQ(BH_LIST_ERROR, bh_list_insert(nullptr, nullptr)); + EXPECT_EQ(BH_LIST_ERROR, bh_list_insert(&list_test, nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_remove) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + bh_list_link elem_insert_3; + bh_list_link elem_insert_4; + + // Normally. + bh_list_init(&list_test); + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + bh_list_insert(&list_test, &elem_insert_3); + bh_list_insert(&list_test, &elem_insert_4); + EXPECT_EQ(BH_LIST_SUCCESS, bh_list_remove(&list_test, &elem_insert_1)); + + // The elem specified by prameter is not in the list. + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(&list_test, &elem_insert_1)); + + // Illegal parameters. + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(&list_test, nullptr)); + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(nullptr, nullptr)); + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(nullptr, &elem_insert_1)); +} + +TEST_F(bh_list_test_suite, bh_list_length) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + + bh_list_init(&list_test); + + // The length is 0. + EXPECT_EQ(0, bh_list_length(&list_test)); + + // The length is 2. + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + EXPECT_EQ(2, bh_list_length(&list_test)); + + // Illegal parameters. + EXPECT_EQ(0, bh_list_length(nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_first_elem) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + + bh_list_init(&list_test); + + // There is no element in the list. + EXPECT_EQ(nullptr, bh_list_first_elem(&list_test)); + + // There are 2 elements in the list. + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + EXPECT_EQ(&elem_insert_2, bh_list_first_elem(&list_test)); + + // Illegal parameters. + EXPECT_EQ(nullptr, bh_list_first_elem(nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_elem_next) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + + bh_list_init(&list_test); + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + + // Normally. + EXPECT_EQ(&elem_insert_1, bh_list_elem_next(&elem_insert_2)); + + // Illegal parameters. + EXPECT_EQ(nullptr, bh_list_elem_next(nullptr)); +} diff --git a/tests/unit/shared-utils/bh_log_test.cc b/tests/unit/shared-utils/bh_log_test.cc new file mode 100644 index 000000000..250fb7926 --- /dev/null +++ b/tests/unit/shared-utils/bh_log_test.cc @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_log.h" +#include "stdio.h" + +class bh_log_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} +}; + +#define TEST_STR "This is a test." + +TEST_F(bh_log_test_suite, bh_log_set_verbose_level) +{ + bh_log_set_verbose_level(BH_LOG_LEVEL_DEBUG); +} + +TEST_F(bh_log_test_suite, bh_print_time) +{ + std::string captured; + + bh_log_set_verbose_level(BH_LOG_LEVEL_WARNING); + bh_print_time(TEST_STR); + + bh_log_set_verbose_level(BH_LOG_LEVEL_DEBUG); + testing::internal::CaptureStdout(); + bh_print_time(TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_EQ(0, strncmp(TEST_STR, captured.c_str(), strlen(TEST_STR))); + + testing::internal::CaptureStdout(); + bh_print_time(TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_EQ(0, strncmp(TEST_STR, captured.c_str(), strlen(TEST_STR))); +} + +TEST_F(bh_log_test_suite, bh_log) +{ + std::string captured; + + bh_log_set_verbose_level(BH_LOG_LEVEL_DEBUG); + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_FATAL, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_ERROR, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_DEBUG, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + // log_verbose_level == BH_LOG_LEVEL_DEBUG, so BH_LOG_LEVEL_VERBOSE is not + // printed. + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_VERBOSE, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_EQ(nullptr, strstr(captured.c_str(), TEST_STR)); + + // After set log_verbose_level = BH_LOG_LEVEL_VERBOSE, BH_LOG_LEVEL_VERBOSE + // can be printed. + bh_log_set_verbose_level(BH_LOG_LEVEL_VERBOSE); + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_VERBOSE, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); +} diff --git a/tests/unit/shared-utils/bh_queue_test.cc b/tests/unit/shared-utils/bh_queue_test.cc new file mode 100644 index 000000000..c540d8f36 --- /dev/null +++ b/tests/unit/shared-utils/bh_queue_test.cc @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_platform.h" + +class bh_queue_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +typedef struct bh_queue_node { + struct bh_queue_node *next; + struct bh_queue_node *prev; + unsigned short tag; + unsigned int len; + void *body; + bh_msg_cleaner msg_cleaner; +} bh_queue_node; + +struct bh_queue { + bh_queue_mutex queue_lock; + bh_queue_cond queue_wait_cond; + unsigned int cnt; + unsigned int max; + unsigned int drops; + bh_queue_node *head; + bh_queue_node *tail; + + bool exit_loop_run; +}; + +typedef enum LINK_MSG_TYPE { + COAP_TCP_RAW = 0, + COAP_UDP_RAW = 1, + REQUEST_PACKET, + RESPONSE_PACKET, + INSTALL_WASM_APP, + CBOR_GENERIC = 30, + + LINK_MSG_TYPE_MAX = 50 +} LINK_MSG_TYPE; + +typedef enum QUEUE_MSG_TYPE { + COAP_PARSED = LINK_MSG_TYPE_MAX + 1, + RESTFUL_REQUEST, + RESTFUL_RESPONSE, + TIMER_EVENT = 5, + SENSOR_EVENT = 6, + GPIO_INTERRUPT_EVENT = 7, + BLE_EVENT = 8, + JDWP_REQUEST = 9, + WD_TIMEOUT = 10, + BASE_EVENT_MAX = 100 + +} QUEUE_MSG_TYPE; + +enum { + WASM_Msg_Start = BASE_EVENT_MAX, + TIMER_EVENT_WASM, + SENSOR_EVENT_WASM, + CONNECTION_EVENT_WASM, + WIDGET_EVENT_WASM, + WASM_Msg_End = WASM_Msg_Start + 100 +}; + +// If RES_CMP == 1, the function bh_queue_enter_loop_run run error. +int RES_CMP = 0; + +TEST_F(bh_queue_test_suite, bh_queue_create) +{ + EXPECT_NE(nullptr, bh_queue_create()); +} + +TEST_F(bh_queue_test_suite, bh_queue_destroy) +{ + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + // Normally. + msg_ptr = bh_new_msg(RESTFUL_REQUEST, nullptr, 0, nullptr); + bh_post_msg2(queue_ptr, msg_ptr); + bh_queue_destroy(queue_ptr); + EXPECT_EQ(nullptr, queue_ptr->head); + + // Illegal parameters. + bh_queue_destroy(nullptr); +} + +TEST_F(bh_queue_test_suite, bh_message_payload) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + EXPECT_EQ("test_msg_body", bh_message_payload(msg_ptr)); +} + +TEST_F(bh_queue_test_suite, bh_message_payload_len) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + EXPECT_EQ(sizeof("test_msg_body"), bh_message_payload_len(msg_ptr)); +} + +TEST_F(bh_queue_test_suite, bh_message_type) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + EXPECT_EQ(RESTFUL_REQUEST, bh_message_type(msg_ptr)); +} + +TEST_F(bh_queue_test_suite, bh_new_msg) +{ + EXPECT_NE(nullptr, bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr)); +} + +void +msg_cleaner_test(void *) +{ + return; +} + +TEST_F(bh_queue_test_suite, bh_free_msg) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), (void *)msg_cleaner_test); + bh_free_msg(msg_ptr); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + bh_free_msg(msg_ptr); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)(uintptr_t)100, 0, nullptr); + bh_free_msg(msg_ptr); +} + +TEST_F(bh_queue_test_suite, bh_post_msg) +{ + int i = 0; + bh_queue *queue_ptr = bh_queue_create(); + bh_message_t msg_ptr; + + EXPECT_EQ(true, bh_post_msg(queue_ptr, TIMER_EVENT_WASM, nullptr, 0)); + EXPECT_EQ(1, queue_ptr->cnt); + + // queue_ptr->cnt >= queue_ptr->max. + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + for (i = 1; i <= 50; i++) { + bh_post_msg2(queue_ptr, msg_ptr); + } + EXPECT_EQ(false, bh_post_msg(queue_ptr, TIMER_EVENT_WASM, nullptr, 0)); +} + +TEST_F(bh_queue_test_suite, bh_post_msg2) +{ + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, nullptr, 0, nullptr); + EXPECT_EQ(true, bh_post_msg2(queue_ptr, msg_ptr)); + EXPECT_EQ(1, queue_ptr->cnt); +} + +TEST_F(bh_queue_test_suite, bh_get_msg) +{ + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + + // queue->cnt == 0, timeout_us == 0. + EXPECT_EQ(nullptr, bh_get_msg(queue_ptr, 0)); + // queue->cnt == 0, timeout_us != 0. + bh_get_msg(queue_ptr, 1); + + bh_post_msg2(queue_ptr, msg_ptr); + EXPECT_EQ(1, queue_ptr->cnt); + bh_get_msg(queue_ptr, -1); + EXPECT_EQ(0, queue_ptr->cnt); +} + +TEST_F(bh_queue_test_suite, bh_queue_get_message_count) +{ + int i = 0, j = 0; + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + // Normally. + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + for (i = 1; i <= 20; i++) { + bh_post_msg2(queue_ptr, msg_ptr); + } + i = i - 1; + // The count of msg is less than queue_ptr->max. + EXPECT_EQ(i, bh_queue_get_message_count(queue_ptr)); + + // The count of msg is more than queue_ptr->max. + for (j = 1; j <= 60; j++) { + bh_post_msg2(queue_ptr, msg_ptr); + } + j = j - 1; + EXPECT_EQ(queue_ptr->max, bh_queue_get_message_count(queue_ptr)); + EXPECT_EQ(j + i - queue_ptr->max, queue_ptr->drops); + + // Illegal parameters. + EXPECT_EQ(0, bh_queue_get_message_count(nullptr)); +} + +void +bh_queue_enter_loop_run_test_fun(void *message, void *arg) +{ + static int count = 0; + RES_CMP = + strncmp("test_queue_loop", (char *)((bh_message_t)message)->body, 15); + + count++; + if (2 == count) { + bh_queue_exit_loop_run((bh_queue *)arg); + } +} + +TEST_F(bh_queue_test_suite, bh_queue_enter_loop_run) +{ + bh_queue *queue_ptr = bh_queue_create(); + bh_message_t msg_ptr1 = + bh_new_msg(RESTFUL_REQUEST, (void *)"test_queue_loop", + sizeof("test_queue_loop"), nullptr); + bh_message_t msg_ptr2 = + bh_new_msg(RESTFUL_REQUEST, (void *)"test_queue_loop", + sizeof("test_queue_loop"), nullptr); + + bh_post_msg2(queue_ptr, msg_ptr1); + bh_post_msg2(queue_ptr, msg_ptr2); + bh_queue_enter_loop_run(queue_ptr, bh_queue_enter_loop_run_test_fun, + queue_ptr); + EXPECT_EQ(0, RES_CMP); + + // Illegal parameters. + bh_queue_enter_loop_run(nullptr, bh_queue_enter_loop_run_test_fun, + queue_ptr); +} + +TEST_F(bh_queue_test_suite, bh_queue_exit_loop_run) +{ + // Illegal parameters. + bh_queue_exit_loop_run(nullptr); +} \ No newline at end of file diff --git a/tests/unit/shared-utils/bh_vector_test.cc b/tests/unit/shared-utils/bh_vector_test.cc new file mode 100644 index 000000000..3da9fba5d --- /dev/null +++ b/tests/unit/shared-utils/bh_vector_test.cc @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" +#include "bh_platform.h" + +#include + +class bh_vector_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +static inline void * +malloc_internal(uint64 size); + +TEST_F(bh_vector_test_suite, bh_vector_init) +{ + Vector *vector_ptr = nullptr; + + // Normally. use_lock is true. + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + EXPECT_EQ(true, bh_vector_init(vector_ptr, 6, sizeof(Vector *), true)); + // use_lock is false. + EXPECT_EQ(true, bh_vector_init(vector_ptr, 6, sizeof(Vector *), false)); + // init_length == 0. + EXPECT_EQ(true, bh_vector_init(vector_ptr, 0, sizeof(Vector *), false)); + // size_elem > UINT32_MAX. + EXPECT_EQ(true, bh_vector_init(vector_ptr, 6, UINT32_MAX + 1, false)); + // init_length > UINT32_MAX. + EXPECT_EQ(true, bh_vector_init(vector_ptr, UINT32_MAX + 1, sizeof(Vector *), + false)); + + // Illegal parameters. + EXPECT_EQ(false, bh_vector_init(nullptr, 6, sizeof(Vector *), true)); +} + +TEST_F(bh_vector_test_suite, bh_vector_set) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, "test"); + + // Normally. use_lock is true. + EXPECT_EQ(true, bh_vector_set(vector_ptr, 0, elem_buf)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_set(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_set(vector_ptr, 0, nullptr)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_set(vector_ptr, 1, elem_buf)); + + // Normally. use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, "test"); + EXPECT_EQ(true, bh_vector_set(vector_ptr, 0, elem_buf)); +} + +TEST_F(bh_vector_test_suite, bh_vector_get) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char get_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + + // Normally. use_lock is true. + EXPECT_EQ(true, bh_vector_get(vector_ptr, 0, get_elem)); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_get(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_get(vector_ptr, 0, nullptr)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_get(vector_ptr, 1, get_elem)); + + // Normally. use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, elem_buf); + EXPECT_EQ(true, bh_vector_get(vector_ptr, 0, get_elem)); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); +} + +TEST_F(bh_vector_test_suite, bh_vector_insert) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char get_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, "test"); + bh_vector_append(vector_ptr, "test"); + bh_vector_append(vector_ptr, "test"); + bh_vector_append(vector_ptr, "test"); + + // Normally. + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 0, elem_buf)); + bh_vector_get(vector_ptr, 1, get_elem); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); + + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 2, elem_buf)); + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 5, elem_buf)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_insert(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_insert(vector_ptr, 0, nullptr)); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 0)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_insert(vector_ptr, 10, elem_buf)); + + // "if (!extend_vector(vector, vector->num_elems + 1))" == true. + vector_ptr->num_elems = UINT32_MAX + 1; + EXPECT_EQ(false, bh_vector_insert(vector_ptr, 2, elem_buf)); + + // use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, "test"); + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 0, elem_buf)); +} + +TEST_F(bh_vector_test_suite, bh_vector_append) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char get_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + + // Normally. + EXPECT_EQ(true, bh_vector_append(vector_ptr, elem_buf)); + bh_vector_get(vector_ptr, 0, get_elem); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_append(nullptr, nullptr)); + EXPECT_EQ(false, bh_vector_append(vector_ptr, nullptr)); +} + +TEST_F(bh_vector_test_suite, bh_vector_remove) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char old_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + bh_vector_append(vector_ptr, elem_buf); + bh_vector_append(vector_ptr, elem_buf); + bh_vector_append(vector_ptr, elem_buf); + + // Normally. + // Remove the first one. + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 0, old_elem)); + // Remove the middle one. + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 2, old_elem)); + // Remove the last one. + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 1, old_elem)); + + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 0, nullptr)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_remove(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_remove(vector_ptr, 0, nullptr)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_remove(vector_ptr, 1, old_elem)); + + // use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, elem_buf); + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 0, old_elem)); +} + +TEST_F(bh_vector_test_suite, bh_vector_size) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + + EXPECT_EQ(1, bh_vector_size(vector_ptr)); + EXPECT_EQ(0, bh_vector_size(nullptr)); +} + +TEST_F(bh_vector_test_suite, bh_vector_destroy) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + + // Normally. + EXPECT_EQ(true, bh_vector_destroy(vector_ptr)); + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_destroy(nullptr)); + + // use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, elem_buf); + EXPECT_EQ(true, bh_vector_destroy(vector_ptr)); +} + +TEST_F(bh_vector_test_suite, bh_vector_thread_safety) +{ + Vector *vector_ptr = nullptr; + char elem; + int32_t i = 0; + std::vector> threads; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem), true); + + for (i = 0; i < 8; i++) { + threads.push_back(std::async([&] { + for (int j = 0; j < 25; j++) { + bh_vector_append(vector_ptr, (void *)&elem); + } + })); + } + + for (auto &t : threads) { + t.wait(); + } + + EXPECT_EQ(bh_vector_size(vector_ptr), 200); + + // Normally. + EXPECT_EQ(true, bh_vector_destroy(vector_ptr)); +} diff --git a/tests/unit/shared-utils/shared_utils_test.cc b/tests/unit/shared-utils/shared_utils_test.cc new file mode 100644 index 000000000..82bedf32f --- /dev/null +++ b/tests/unit/shared-utils/shared_utils_test.cc @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "test_helper.h" +#include "gtest/gtest.h" + +/* Test APIs under wamr/core/shared/utils */ + +class SharedUtilsTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(SharedUtilsTest, bh_list) {} diff --git a/tests/unit/tid-allocator/CMakeLists.txt b/tests/unit/tid-allocator/CMakeLists.txt new file mode 100644 index 000000000..be62340a3 --- /dev/null +++ b/tests/unit/tid-allocator/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +project (tid_allocator_tests) + +if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS) + set (WAMR_BUILD_LIB_WASI_THREADS 1) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_PLATFORM) + string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +endif () + +include (../unit_common.cmake) + +add_library (tid_allocator_vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +add_library (wamr_gtest_main main.cpp) +target_link_libraries (wamr_gtest_main PUBLIC gtest tid_allocator_vmlib) + +function (create_wamr_unit_test test_name) + set (sources ${ARGN}) + add_executable (${test_name} ${sources}) + target_link_libraries ( + ${test_name} + wamr_gtest_main + tid_allocator_vmlib + ${LLVM_AVAILABLE_LIBS} + ) + gtest_discover_tests (${test_name}) + endfunction () + +include (${IWASM_DIR}/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake) + diff --git a/tests/unit/main.cpp b/tests/unit/tid-allocator/main.cpp similarity index 99% rename from tests/unit/main.cpp rename to tests/unit/tid-allocator/main.cpp index 63695d9ee..081676a1b 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/tid-allocator/main.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ + #include #include "wasm_runtime_common.h" diff --git a/tests/unit/unit_common.cmake b/tests/unit/unit_common.cmake new file mode 100644 index 000000000..90ea2eb7c --- /dev/null +++ b/tests/unit/unit_common.cmake @@ -0,0 +1,105 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +if (NOT DEFINED WAMR_BUILD_PLATFORM) + set (WAMR_BUILD_PLATFORM "linux") +endif () + +set (UNIT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${UNIT_ROOT_DIR}) + +enable_language (ASM) + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Debug) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Enable AOT by default. + set (WAMR_BUILD_AOT 1) +endif () + +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Enable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 1) +endif () + +if (NOT DEFINED WAMR_BUILD_MULTI_MODULE) + set (WAMR_BUILD_MULTI_MODULE 1) +endif() + +if (NOT DEFINED WAMR_BUILD_APP_FRAMEWORK) + set (WAMR_BUILD_APP_FRAMEWORK 1) +endif () + +if (COLLECT_CODE_COVERAGE EQUAL 1) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") +endif () + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \ + -Wall -Wno-unused-parameter -Wno-pedantic") + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) + +# include the build config template file +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +include_directories (${SHARED_DIR}/include + ${IWASM_DIR}/include) + +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +if (NOT (GOOGLETEST_INCLUDED EQUAL 1)) +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# Fetch Google test +include (FetchContent) +FetchContent_Declare ( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +FetchContent_MakeAvailable (googletest) + +endif() + +# Add helper classes +include_directories(${CMAKE_CURRENT_LIST_DIR}/common) + +message ("unit_common.cmake included") + diff --git a/tests/unit/wasm-c-api/CMakeLists.txt b/tests/unit/wasm-c-api/CMakeLists.txt new file mode 100644 index 000000000..3b8884e11 --- /dev/null +++ b/tests/unit/wasm-c-api/CMakeLists.txt @@ -0,0 +1,62 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 2.9) +project (wasm_c_api_test) + +################ runtime settings ################ +set(CMAKE_BUILD_TYPE Debug) +set(WAMR_BUILD_PLATFORM "linux") + +# Resetdefault linker flags +set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# WAMR features switch +set(WAMR_BUILD_TARGET "X86_64") +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_JIT 0) +set(WAMR_BUILD_LIBC_BUILTIN 1) +set(WAMR_BUILD_LIBC_WASI 0) +set(WAMR_BUILD_FAST_INTERP 0) + +# compiling and linking flags +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -mindirect-branch-register") + +# build out vmlib +# hard code path here +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_library(vmlib STATIC ${WAMR_RUNTIME_LIB_SOURCE}) +################################################ + +################ unit test related ################ +# Add googletest directly to our build. This defines +# the gtest and gtest_main targets. + +if (NOT (GOOGLETEST_INCLUDED EQUAL 1)) +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# Fetch Google test +include (FetchContent) +FetchContent_Declare ( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +FetchContent_MakeAvailable (googletest) +endif() + +enable_testing() + +add_executable(wasm_c_api_test + basic.cc +) + +target_link_libraries(wasm_c_api_test vmlib gtest_main) + +gtest_discover_tests(wasm_c_api_test) diff --git a/tests/unit/wasm-c-api/basic.cc b/tests/unit/wasm-c-api/basic.cc new file mode 100644 index 000000000..34d837dd9 --- /dev/null +++ b/tests/unit/wasm-c-api/basic.cc @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "bh_platform.h" +#include "wasm_c_api.h" +#include "wasm_c_api_internal.h" + +#ifndef own +#define own +#endif + +class CApiTests : public ::testing::Test +{ + protected: + void SetUp() + { + bh_log_set_verbose_level(5); + engine = nullptr; + engine = wasm_engine_new(); + ASSERT_NE(nullptr, engine); + } + + void TearDown() { wasm_engine_delete(engine); } + + wasm_engine_t *engine; +}; + +TEST_F(CApiTests, empty) {} + +TEST_F(CApiTests, wasm_engine_t) +{ + wasm_engine_t *engine1 = wasm_engine_new(); + wasm_engine_t *engine2 = wasm_engine_new(); + EXPECT_EQ(engine1, engine2); + /* TearDown() will delete it */ +} + +TEST_F(CApiTests, wasm_store_t) +{ + wasm_engine_t *engine = wasm_engine_new(); + wasm_store_t *store1 = wasm_store_new(engine); + EXPECT_NE(nullptr, store1); + EXPECT_NE(nullptr, store1->modules->data); + + wasm_store_t *store2 = wasm_store_new(engine); + EXPECT_NE(store1, store2); + EXPECT_NE(store1->modules->data, store2->modules->data); + + wasm_store_delete(store1); + wasm_store_delete(store2); + + store1 = wasm_store_new(engine); + EXPECT_NE(nullptr, store1); + wasm_store_delete(store1); +} + +TEST_F(CApiTests, wasm_byte_vec_t) +{ + wasm_byte_vec_t byte_vec = { 0 }; + wasm_byte_vec_new_uninitialized(&byte_vec, 10); + EXPECT_NE(nullptr, byte_vec.data); + EXPECT_EQ(10, byte_vec.size); + + byte_vec.data[0] = (wasm_byte_t)'a'; + byte_vec.data[1] = (wasm_byte_t)'b'; + byte_vec.data[2] = (wasm_byte_t)'c'; + EXPECT_STREQ("abc", (char *)byte_vec.data); + + byte_vec.data[5] = (wasm_byte_t)'d'; + byte_vec.data[6] = (wasm_byte_t)'e'; + byte_vec.data[7] = (wasm_byte_t)'f'; + EXPECT_STREQ("def", (char *)(byte_vec.data + 5)); + + wasm_byte_vec_delete(&byte_vec); + EXPECT_EQ(nullptr, byte_vec.data); + EXPECT_EQ(0, byte_vec.size); +} + +TEST_F(CApiTests, wasm_valtype_vec_t) +{ + wasm_valtype_vec_t tuple1 = { 0 }; + wasm_valtype_vec_new_uninitialized(&tuple1, 128); + EXPECT_NE(nullptr, tuple1.data); + EXPECT_EQ(128, tuple1.size); + + wasm_valtype_t *val_type_1 = wasm_valtype_new_i32(); + tuple1.data[0] = val_type_1; + EXPECT_EQ(WASM_I32, wasm_valtype_kind(*(tuple1.data + 0))); + wasm_valtype_vec_delete(&tuple1); + wasm_valtype_delete(val_type_1); + + wasm_valtype_t *val_types[5] = { + wasm_valtype_new_i32(), wasm_valtype_new_i64(), wasm_valtype_new_f32(), + wasm_valtype_new_f64(), wasm_valtype_new_funcref() + }; + + wasm_valtype_vec_t tuple2 = { 0 }; + wasm_valtype_vec_new(&tuple2, 5, val_types); + EXPECT_NE(nullptr, tuple2.data); + EXPECT_EQ(WASM_F32, wasm_valtype_kind(*(tuple2.data + 2))); + EXPECT_EQ(WASM_FUNCREF, wasm_valtype_kind(*(tuple2.data + 4))); + + wasm_valtype_vec_t tuple3 = { 0 }; + wasm_valtype_vec_copy(&tuple3, &tuple2); + + wasm_valtype_vec_delete(&tuple2); + + EXPECT_EQ(WASM_I64, wasm_valtype_kind(*(tuple3.data + 1))); + EXPECT_EQ(WASM_F64, wasm_valtype_kind(*(tuple3.data + 3))); + wasm_valtype_vec_delete(&tuple3); +} + +TEST_F(CApiTests, wasm_functype_t) +{ + wasm_functype_t *callback_type = wasm_functype_new_1_1( + wasm_valtype_new(WASM_EXTERNREF), wasm_valtype_new(WASM_FUNCREF)); + EXPECT_EQ(WASM_EXTERNREF, + wasm_valtype_kind(*(wasm_functype_params(callback_type)->data))); + wasm_functype_delete(callback_type); + + callback_type = wasm_functype_new_0_0(); + wasm_functype_delete(callback_type); + + callback_type = wasm_functype_new_0_1(wasm_valtype_new(WASM_EXTERNREF)); + const wasm_valtype_vec_t *results = wasm_functype_results(callback_type); + EXPECT_EQ(WASM_EXTERNREF, wasm_valtype_kind(*(results->data))); + wasm_functype_delete(callback_type); + + callback_type = wasm_functype_new_1_0(wasm_valtype_new(WASM_EXTERNREF)); + EXPECT_EQ(WASM_EXTERNREF, + wasm_valtype_kind(*(wasm_functype_params(callback_type)->data))); + wasm_functype_delete(callback_type); + + wasm_functype_t *func_type1 = wasm_functype_new_2_2( + wasm_valtype_new(WASM_I32), wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_I32), wasm_valtype_new(WASM_I64)); + wasm_functype_t *func_type2 = wasm_functype_copy(func_type1); + wasm_functype_delete(func_type1); + + EXPECT_EQ(WASM_I64, wasm_valtype_kind( + *(wasm_functype_results(func_type2)->data + 1))); + wasm_functype_delete(func_type2); +} + +TEST_F(CApiTests, wasm_globaltype_t) +{ + wasm_globaltype_t *const_f32_type = + wasm_globaltype_new(wasm_valtype_new(WASM_F32), WASM_CONST); + EXPECT_EQ(WASM_F32, + wasm_valtype_kind(wasm_globaltype_content(const_f32_type))); + + wasm_globaltype_t *cloned = wasm_globaltype_copy(const_f32_type); + wasm_globaltype_delete(const_f32_type); + + EXPECT_EQ(WASM_F32, wasm_valtype_kind(wasm_globaltype_content(cloned))); + + wasm_globaltype_delete(cloned); +} + +static wasm_trap_t * +test_func(const wasm_val_vec_t *args, own wasm_val_vec_t *results) +{ + return NULL; +} + +TEST_F(CApiTests, wasm_func_t) +{ + wasm_valtype_t *types[4] = { wasm_valtype_new_i32(), wasm_valtype_new_i64(), + wasm_valtype_new_i64(), + wasm_valtype_new_i32() }; + wasm_valtype_vec_t tuple1 = { 0 }, tuple2 = { 0 }; + wasm_valtype_vec_new(&tuple1, 4, types); + wasm_valtype_vec_copy(&tuple2, &tuple1); + wasm_functype_t *callback_type = wasm_functype_new(&tuple1, &tuple2); + + wasm_store_t *store = wasm_store_new(engine); + wasm_func_t *callback_func = wasm_func_new(store, callback_type, test_func); + wasm_functype_delete(callback_type); + + callback_type = callback_func->type; + EXPECT_EQ(WASM_I32, wasm_valtype_kind( + *(wasm_functype_params(callback_type)->data + 0))); + EXPECT_EQ(WASM_I32, wasm_valtype_kind( + *(wasm_functype_results(callback_type)->data + 3))); + wasm_func_delete(callback_func); + wasm_store_delete(store); +} diff --git a/tests/unit/wasm-c-api/run.sh b/tests/unit/wasm-c-api/run.sh new file mode 100755 index 000000000..1b0d88e36 --- /dev/null +++ b/tests/unit/wasm-c-api/run.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# ./c_api_unit_test --gtest_list_tests + +function run_one() +{ + local case=$1 + valgrind --tool=memcheck --leak-check=yes -v \ + ./c_api_unit_test --gtest_filter=CApiTests.${case} +} + +function run() +{ + valgrind --tool=memcheck --leak-check=yes -v \ + ./c_api_unit_test +} + +[[ $# -gt 0 ]] && $@ || run diff --git a/tests/unit/wasm-vm/.gitignore b/tests/unit/wasm-vm/.gitignore new file mode 100644 index 000000000..aa3883989 --- /dev/null +++ b/tests/unit/wasm-vm/.gitignore @@ -0,0 +1,2 @@ +wasm-apps/app[123]/*.wat +wasm-apps/app[123]/*.wasm \ No newline at end of file diff --git a/tests/unit/wasm-vm/CMakeLists.txt b/tests/unit/wasm-vm/CMakeLists.txt new file mode 100644 index 000000000..d13d65aac --- /dev/null +++ b/tests/unit/wasm-vm/CMakeLists.txt @@ -0,0 +1,53 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-wasm-vm) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) + +set (WAMR_BUILD_APP_FRAMEWORK 1) +set (CMAKE_BUILD_TYPE Release) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${LIBC_WASI_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ${UNCOMMON_SHARED_SOURCE} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable(wasm_vm_test ${unit_test_sources}) + +target_link_libraries(wasm_vm_test ${LLVM_AVAILABLE_LIBS} gtest_main) + +add_custom_command(TARGET wasm_vm_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps/app4/*.wasm + ${PROJECT_BINARY_DIR}/ + COMMENT "Copy wasm files to the output directory" +) + +gtest_discover_tests(wasm_vm_test) diff --git a/tests/unit/wasm-vm/wasm-apps/app1.wast b/tests/unit/wasm-vm/wasm-apps/app1.wast new file mode 100644 index 000000000..aea3a8792 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app1.wast @@ -0,0 +1,106 @@ +(module + (type $0 (func (param i32) (result i32))) + (type $1 (func (param i32 i32) (result i32))) + (type $2 (func (param i32))) + (type $3 (func (param i32 i32 i32) (result i32))) + (type $4 (func)) + (type $5 (func (result i32))) + (import "env" "malloc" (func $13 (param i32) (result i32))) + (import "env" "calloc" (func $14 (param i32 i32) (result i32))) + (import "env" "free" (func $15 (param i32))) + (import "env" "memcpy" (func $16 (param i32 i32 i32) (result i32))) + (import "env" "strdup" (func $17 (param i32) (result i32))) + (memory $6 1) + (global $7 i32 (i32.const 1024)) + (global $8 i32 (i32.const 1024)) + (global $9 i32 (i32.const 1024)) + (global $10 i32 (i32.const 5120)) + (global $11 i32 (i32.const 0)) + (global $12 i32 (i32.const 1)) + (export "memory" (memory $6)) + (export "__wasm_call_ctors" (func $18)) + (export "on_init" (func $18)) + (export "my_sqrt" (func $19)) + (export "null_pointer" (func $20)) + (export "my_malloc" (func $21)) + (export "my_calloc" (func $22)) + (export "my_free" (func $23)) + (export "my_memcpy" (func $24)) + (export "my_strdup" (func $25)) + (export "__dso_handle" (global $7)) + (export "__data_end" (global $8)) + (export "__global_base" (global $9)) + (export "__heap_base" (global $10)) + (export "__memory_base" (global $11)) + (export "__table_base" (global $12)) + + (func $18 (type $4) + nop + ) + + (func $19 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $1 + local.get $1 + i32.mul + local.get $0 + local.get $0 + i32.mul + i32.add + ) + + (func $20 (type $5) + (result i32) + i32.const 0 + ) + + (func $21 (type $0) + (param $0 i32) + (result i32) + local.get $0 + call $13 + ) + + (func $22 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $14 + ) + + (func $23 (type $2) + (param $0 i32) + local.get $0 + call $15 + ) + + (func $24 (type $3) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $16 + ) + + (func $25 (type $0) + (param $0 i32) + (result i32) + local.get $0 + call $17 + ) + + ;;(custom_section "producers" + ;; (after code) + ;; "\01\0cprocessed-by\01\05clangV11.0.0 (ht" + ;; "tps://github.com/llvm/llvm-proje" + ;; "ct 176249bd6732a8044d457092ed932" + ;; "768724a6f06)") + + ) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app1/main.c b/tests/unit/wasm-vm/wasm-apps/app1/main.c new file mode 100644 index 000000000..0090d105f --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app1/main.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +void +on_init() +{} + +int +my_sqrt(int x, int y) +{ + return x * x + y * y; +} + +void * +null_pointer() +{ + void *ptr = NULL; + return ptr; +} + +void * +my_malloc(int size) +{ + return malloc(size); +} + +void * +my_calloc(int nmemb, int size) +{ + return calloc(nmemb, size); +} + +void +my_free(void *ptr) +{ + return free(ptr); +} + +void * +my_memcpy(void *dst, void *src, int size) +{ + return memcpy(dst, src, size); +} + +char * +my_strdup(const char *s) +{ + return strdup(s); +} diff --git a/tests/unit/wasm-vm/wasm-apps/app1_wasm.h b/tests/unit/wasm-vm/wasm-apps/app1_wasm.h new file mode 100644 index 000000000..2b20b39f9 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app1_wasm.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +unsigned char app1_wasm[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1E, 0x06, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x01, + 0x7F, 0x00, 0x60, 0x03, 0x7F, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x01, 0x7F, 0x02, 0x40, 0x05, 0x03, 0x65, 0x6E, 0x76, 0x06, + 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x01, 0x03, 0x65, 0x6E, + 0x76, 0x04, 0x66, 0x72, 0x65, 0x65, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x6D, 0x65, 0x6D, 0x63, 0x70, 0x79, 0x00, 0x03, 0x03, 0x65, 0x6E, + 0x76, 0x06, 0x73, 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x00, 0x03, 0x09, + 0x08, 0x04, 0x01, 0x05, 0x00, 0x01, 0x02, 0x03, 0x00, 0x05, 0x03, 0x01, + 0x00, 0x01, 0x06, 0x23, 0x06, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0x00, 0x0B, 0x7F, 0x00, + 0x41, 0x01, 0x0B, 0x07, 0xD4, 0x01, 0x10, 0x06, 0x6D, 0x65, 0x6D, 0x6F, + 0x72, 0x79, 0x02, 0x00, 0x11, 0x5F, 0x5F, 0x77, 0x61, 0x73, 0x6D, 0x5F, + 0x63, 0x61, 0x6C, 0x6C, 0x5F, 0x63, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x05, + 0x07, 0x6F, 0x6E, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x05, 0x07, 0x6D, + 0x79, 0x5F, 0x73, 0x71, 0x72, 0x74, 0x00, 0x06, 0x0C, 0x6E, 0x75, 0x6C, + 0x6C, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x00, 0x07, 0x09, + 0x6D, 0x79, 0x5F, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x08, 0x09, + 0x6D, 0x79, 0x5F, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x09, 0x07, + 0x6D, 0x79, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x00, 0x0A, 0x09, 0x6D, 0x79, + 0x5F, 0x6D, 0x65, 0x6D, 0x63, 0x70, 0x79, 0x00, 0x0B, 0x09, 0x6D, 0x79, + 0x5F, 0x73, 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x0C, 0x0C, 0x5F, 0x5F, + 0x64, 0x73, 0x6F, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x03, 0x00, + 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x65, 0x6E, 0x64, 0x03, + 0x01, 0x0D, 0x5F, 0x5F, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x5F, 0x62, + 0x61, 0x73, 0x65, 0x03, 0x02, 0x0B, 0x5F, 0x5F, 0x68, 0x65, 0x61, 0x70, + 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x03, 0x0D, 0x5F, 0x5F, 0x6D, 0x65, + 0x6D, 0x6F, 0x72, 0x79, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x04, 0x0C, + 0x5F, 0x5F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x62, 0x61, 0x73, 0x65, + 0x03, 0x05, 0x0A, 0x41, 0x08, 0x03, 0x00, 0x01, 0x0B, 0x0D, 0x00, 0x20, + 0x01, 0x20, 0x01, 0x6C, 0x20, 0x00, 0x20, 0x00, 0x6C, 0x6A, 0x0B, 0x04, + 0x00, 0x41, 0x00, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x00, 0x0B, 0x08, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x01, 0x0B, 0x06, 0x00, 0x20, 0x00, + 0x10, 0x02, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, + 0x03, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x04, 0x0B, 0x00, 0x76, 0x09, + 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x01, 0x0C, 0x70, + 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2D, 0x62, 0x79, 0x01, + 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, 0x31, 0x31, 0x2E, 0x30, 0x2E, + 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x6C, 0x6C, + 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2D, 0x70, 0x72, 0x6F, 0x6A, + 0x65, 0x63, 0x74, 0x20, 0x31, 0x37, 0x36, 0x32, 0x34, 0x39, 0x62, 0x64, + 0x36, 0x37, 0x33, 0x32, 0x61, 0x38, 0x30, 0x34, 0x34, 0x64, 0x34, 0x35, + 0x37, 0x30, 0x39, 0x32, 0x65, 0x64, 0x39, 0x33, 0x32, 0x37, 0x36, 0x38, + 0x37, 0x32, 0x34, 0x61, 0x36, 0x66, 0x30, 0x36, 0x29 +}; diff --git a/tests/unit/wasm-vm/wasm-apps/app2.wast b/tests/unit/wasm-vm/wasm-apps/app2.wast new file mode 100644 index 000000000..c5ea06eaa --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app2.wast @@ -0,0 +1,311 @@ +(module + (type $0 (func (param i32 i32 i32) (result i32))) + (type $1 (func (param i32 i32) (result i32))) + (type $2 (func (param i32) (result i32))) + (type $3 (func (param i32))) + (type $4 (func (param i32 i32 i32 i32) (result i32))) + (type $5 (func)) + (type $6 (func (result i32))) + (import "env" "malloc" (func $15 (param i32) (result i32))) + (import "env" "calloc" (func $16 (param i32 i32) (result i32))) + (import "env" "free" (func $17 (param i32))) + (import "env" "memcpy" (func $18 (param i32 i32 i32) (result i32))) + (import "env" "strdup" (func $19 (param i32) (result i32))) + (import "env" "memcmp" (func $20 (param i32 i32 i32) (result i32))) + (import "env" "printf" (func $21 (param i32 i32) (result i32))) + (import "env" "sprintf" (func $22 (param i32 i32 i32) (result i32))) + (import "env" "snprintf" (func $23 (param i32 i32 i32 i32) (result i32))) + (import "env" "puts" (func $24 (param i32) (result i32))) + (import "env" "putchar" (func $25 (param i32) (result i32))) + (import "env" "memmove" (func $26 (param i32 i32 i32) (result i32))) + (import "env" "memset" (func $27 (param i32 i32 i32) (result i32))) + (import "env" "strchr" (func $28 (param i32 i32) (result i32))) + (import "env" "strcmp" (func $29 (param i32 i32) (result i32))) + (import "env" "strcpy" (func $30 (param i32 i32) (result i32))) + (import "env" "strlen" (func $31 (param i32) (result i32))) + (import "env" "strncmp" (func $32 (param i32 i32 i32) (result i32))) + (import "env" "strncpy" (func $33 (param i32 i32 i32) (result i32))) + (memory $7 1) + (global $8 (mut i32) (i32.const 5120)) + (global $9 i32 (i32.const 1024)) + (global $10 i32 (i32.const 1024)) + (global $11 i32 (i32.const 1024)) + (global $12 i32 (i32.const 5120)) + (global $13 i32 (i32.const 0)) + (global $14 i32 (i32.const 1)) + (export "memory" (memory $7)) + (export "__wasm_call_ctors" (func $34)) + (export "on_init" (func $34)) + (export "my_sqrt" (func $35)) + (export "null_pointer" (func $36)) + (export "my_malloc" (func $37)) + (export "my_calloc" (func $38)) + (export "my_free" (func $39)) + (export "my_memcpy" (func $40)) + (export "my_strdup" (func $41)) + (export "my_memcmp" (func $42)) + (export "my_printf" (func $43)) + (export "my_sprintf" (func $44)) + (export "my_snprintf" (func $45)) + (export "my_puts" (func $46)) + (export "my_putchar" (func $47)) + (export "my_memmove" (func $48)) + (export "my_memset" (func $49)) + (export "my_strchr" (func $50)) + (export "my_strcmp" (func $51)) + (export "my_strcpy" (func $52)) + (export "my_strlen" (func $53)) + (export "my_strncmp" (func $54)) + (export "my_strncpy" (func $55)) + (export "__dso_handle" (global $9)) + (export "__data_end" (global $10)) + (export "__global_base" (global $11)) + (export "__heap_base" (global $12)) + (export "__memory_base" (global $13)) + (export "__table_base" (global $14)) + + (func $34 (type $5) + nop + ) + + (func $35 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $1 + local.get $1 + i32.mul + local.get $0 + local.get $0 + i32.mul + i32.add + ) + + (func $36 (type $6) + (result i32) + i32.const 0 + ) + + (func $37 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $15 + ) + + (func $38 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $16 + ) + + (func $39 (type $3) + (param $0 i32) + local.get $0 + call $17 + ) + + (func $40 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $18 + ) + + (func $41 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $19 + ) + + (func $42 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $20 + ) + + (func $43 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + (local $2 i32) + global.get $8 + i32.const 16 + i32.sub + local.tee $2 + global.set $8 + local.get $2 + local.get $1 + i32.store + local.get $0 + local.get $2 + call $21 + local.get $2 + i32.const 16 + i32.add + global.set $8 + ) + + (func $44 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + (local $3 i32) + global.get $8 + i32.const 16 + i32.sub + local.tee $3 + global.set $8 + local.get $3 + local.get $2 + i32.store + local.get $0 + local.get $1 + local.get $3 + call $22 + local.get $3 + i32.const 16 + i32.add + global.set $8 + ) + + (func $45 (type $4) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (param $3 i32) + (result i32) + (local $4 i32) + global.get $8 + i32.const 16 + i32.sub + local.tee $4 + global.set $8 + local.get $4 + local.get $3 + i32.store + local.get $0 + local.get $1 + local.get $2 + local.get $4 + call $23 + local.get $4 + i32.const 16 + i32.add + global.set $8 + ) + + (func $46 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $24 + ) + + (func $47 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $25 + ) + + (func $48 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $26 + ) + + (func $49 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $27 + ) + + (func $50 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $28 + ) + + (func $51 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $29 + ) + + (func $52 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $30 + ) + + (func $53 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $31 + ) + + (func $54 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $32 + ) + + (func $55 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $33 + ) + + ;;(custom_section "producers" + ;; (after code) + ;; "\01\0cprocessed-by\01\05clangV11.0.0 (ht" + ;; "tps://github.com/llvm/llvm-proje" + ;; "ct 176249bd6732a8044d457092ed932" + ;; "768724a6f06)") + + ) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app2/main.c b/tests/unit/wasm-vm/wasm-apps/app2/main.c new file mode 100644 index 000000000..160d834a5 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app2/main.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +void +on_init() +{} + +int +my_sqrt(int x, int y) +{ + return x * x + y * y; +} + +void * +null_pointer() +{ + void *ptr = NULL; + return ptr; +} + +void * +my_malloc(int size) +{ + return malloc(size); +} + +void * +my_calloc(int nmemb, int size) +{ + return calloc(nmemb, size); +} + +void +my_free(void *ptr) +{ + free(ptr); +} + +void * +my_memcpy(void *dst, void *src, int size) +{ + return memcpy(dst, src, size); +} + +char * +my_strdup(const char *s) +{ + return strdup(s); +} + +int +my_memcmp(const void *buf1, const void *buf2, int size) +{ + return memcmp(buf1, buf2, size); +} + +int +my_printf(const char *format, char *s) +{ + return printf(format, s); +} + +int +my_sprintf(char *buf1, const char *format, char *buf2) +{ + return sprintf(buf1, format, buf2); +} + +int +my_snprintf(char *buf1, int size, const char *format, char *buf2) +{ + return snprintf(buf1, size, format, buf2); +} + +int +my_puts(const char *s) +{ + return puts(s); +} + +int +my_putchar(int s) +{ + return putchar(s); +} + +void * +my_memmove(void *buf1, const void *buf2, int size) +{ + return memmove(buf1, buf2, size); +} + +void * +my_memset(void *buf, int c, int size) +{ + return memset(buf, c, size); +} + +char * +my_strchr(const char *s, int c) +{ + return strchr(s, c); +} + +int +my_strcmp(const char *buf1, const char *buf2) +{ + return strcmp(buf1, buf2); +} + +char * +my_strcpy(char *buf1, const char *buf2) +{ + return strcpy(buf1, buf2); +} + +int +my_strlen(const char *s) +{ + return (int)strlen(s); +} + +int +my_strncmp(const char *buf1, const char *buf2, int n) +{ + return strncmp(buf1, buf2, n); +} + +char * +my_strncpy(char *buf1, const char *buf2, int n) +{ + return strncpy(buf1, buf2, n); +} diff --git a/tests/unit/wasm-vm/wasm-apps/app2_wasm.h b/tests/unit/wasm-vm/wasm-apps/app2_wasm.h new file mode 100644 index 000000000..d89f7e57d --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app2_wasm.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +unsigned char app2_wasm[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x26, 0x07, 0x60, + 0x03, 0x7F, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, + 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x00, 0x60, 0x04, 0x7F, + 0x7F, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, 0x60, 0x00, 0x01, 0x7F, + 0x02, 0xFB, 0x01, 0x13, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x61, 0x6C, + 0x6C, 0x6F, 0x63, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x63, 0x61, + 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x66, + 0x72, 0x65, 0x65, 0x00, 0x03, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x65, + 0x6D, 0x63, 0x70, 0x79, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x73, + 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, 0x06, + 0x6D, 0x65, 0x6D, 0x63, 0x6D, 0x70, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x01, 0x03, 0x65, 0x6E, + 0x76, 0x07, 0x73, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x00, 0x03, + 0x65, 0x6E, 0x76, 0x08, 0x73, 0x6E, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, + 0x00, 0x04, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x70, 0x75, 0x74, 0x73, 0x00, + 0x02, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x70, 0x75, 0x74, 0x63, 0x68, 0x61, + 0x72, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x6D, 0x65, 0x6D, 0x6D, + 0x6F, 0x76, 0x65, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x65, + 0x6D, 0x73, 0x65, 0x74, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x73, + 0x74, 0x72, 0x63, 0x68, 0x72, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x06, + 0x73, 0x74, 0x72, 0x63, 0x6D, 0x70, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x73, 0x74, 0x72, 0x63, 0x70, 0x79, 0x00, 0x01, 0x03, 0x65, 0x6E, + 0x76, 0x06, 0x73, 0x74, 0x72, 0x6C, 0x65, 0x6E, 0x00, 0x02, 0x03, 0x65, + 0x6E, 0x76, 0x07, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x6D, 0x70, 0x00, 0x00, + 0x03, 0x65, 0x6E, 0x76, 0x07, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x70, 0x79, + 0x00, 0x00, 0x03, 0x17, 0x16, 0x05, 0x01, 0x06, 0x02, 0x01, 0x03, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x04, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x02, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x29, 0x07, 0x7F, + 0x01, 0x41, 0x80, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0x00, 0x0B, 0x7F, 0x00, + 0x41, 0x01, 0x0B, 0x07, 0x81, 0x03, 0x1E, 0x06, 0x6D, 0x65, 0x6D, 0x6F, + 0x72, 0x79, 0x02, 0x00, 0x11, 0x5F, 0x5F, 0x77, 0x61, 0x73, 0x6D, 0x5F, + 0x63, 0x61, 0x6C, 0x6C, 0x5F, 0x63, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x13, + 0x07, 0x6F, 0x6E, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x13, 0x07, 0x6D, + 0x79, 0x5F, 0x73, 0x71, 0x72, 0x74, 0x00, 0x14, 0x0C, 0x6E, 0x75, 0x6C, + 0x6C, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x00, 0x15, 0x09, + 0x6D, 0x79, 0x5F, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x16, 0x09, + 0x6D, 0x79, 0x5F, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x17, 0x07, + 0x6D, 0x79, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x00, 0x18, 0x09, 0x6D, 0x79, + 0x5F, 0x6D, 0x65, 0x6D, 0x63, 0x70, 0x79, 0x00, 0x19, 0x09, 0x6D, 0x79, + 0x5F, 0x73, 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x1A, 0x09, 0x6D, 0x79, + 0x5F, 0x6D, 0x65, 0x6D, 0x63, 0x6D, 0x70, 0x00, 0x1B, 0x09, 0x6D, 0x79, + 0x5F, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x1C, 0x0A, 0x6D, 0x79, + 0x5F, 0x73, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x1D, 0x0B, 0x6D, + 0x79, 0x5F, 0x73, 0x6E, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x1E, + 0x07, 0x6D, 0x79, 0x5F, 0x70, 0x75, 0x74, 0x73, 0x00, 0x1F, 0x0A, 0x6D, + 0x79, 0x5F, 0x70, 0x75, 0x74, 0x63, 0x68, 0x61, 0x72, 0x00, 0x20, 0x0A, + 0x6D, 0x79, 0x5F, 0x6D, 0x65, 0x6D, 0x6D, 0x6F, 0x76, 0x65, 0x00, 0x21, + 0x09, 0x6D, 0x79, 0x5F, 0x6D, 0x65, 0x6D, 0x73, 0x65, 0x74, 0x00, 0x22, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x63, 0x68, 0x72, 0x00, 0x23, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x63, 0x6D, 0x70, 0x00, 0x24, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x63, 0x70, 0x79, 0x00, 0x25, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x6C, 0x65, 0x6E, 0x00, 0x26, + 0x0A, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x6D, 0x70, 0x00, + 0x27, 0x0A, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x70, 0x79, + 0x00, 0x28, 0x0C, 0x5F, 0x5F, 0x64, 0x73, 0x6F, 0x5F, 0x68, 0x61, 0x6E, + 0x64, 0x6C, 0x65, 0x03, 0x01, 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, 0x61, + 0x5F, 0x65, 0x6E, 0x64, 0x03, 0x02, 0x0D, 0x5F, 0x5F, 0x67, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x03, 0x0B, 0x5F, + 0x5F, 0x68, 0x65, 0x61, 0x70, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x04, + 0x0D, 0x5F, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x5F, 0x62, 0x61, + 0x73, 0x65, 0x03, 0x05, 0x0C, 0x5F, 0x5F, 0x74, 0x61, 0x62, 0x6C, 0x65, + 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x06, 0x0A, 0x94, 0x02, 0x16, 0x03, + 0x00, 0x01, 0x0B, 0x0D, 0x00, 0x20, 0x01, 0x20, 0x01, 0x6C, 0x20, 0x00, + 0x20, 0x00, 0x6C, 0x6A, 0x0B, 0x04, 0x00, 0x41, 0x00, 0x0B, 0x06, 0x00, + 0x20, 0x00, 0x10, 0x00, 0x0B, 0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, + 0x01, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x02, 0x0B, 0x0A, 0x00, 0x20, + 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x03, 0x0B, 0x06, 0x00, 0x20, 0x00, + 0x10, 0x04, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, + 0x05, 0x0B, 0x21, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x10, 0x6B, 0x22, + 0x02, 0x24, 0x00, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 0x00, + 0x20, 0x02, 0x10, 0x06, 0x20, 0x02, 0x41, 0x10, 0x6A, 0x24, 0x00, 0x0B, + 0x23, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x10, 0x6B, 0x22, 0x03, 0x24, + 0x00, 0x20, 0x03, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, + 0x20, 0x03, 0x10, 0x07, 0x20, 0x03, 0x41, 0x10, 0x6A, 0x24, 0x00, 0x0B, + 0x25, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x10, 0x6B, 0x22, 0x04, 0x24, + 0x00, 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, + 0x20, 0x02, 0x20, 0x04, 0x10, 0x08, 0x20, 0x04, 0x41, 0x10, 0x6A, 0x24, + 0x00, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x09, 0x0B, 0x06, 0x00, 0x20, + 0x00, 0x10, 0x0A, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x10, 0x0B, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, + 0x0C, 0x0B, 0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x0D, 0x0B, 0x08, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x0E, 0x0B, 0x08, 0x00, 0x20, 0x00, + 0x20, 0x01, 0x10, 0x0F, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x10, 0x0B, + 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x11, 0x0B, 0x0A, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x12, 0x0B, 0x00, 0x76, + 0x09, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x01, 0x0C, + 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2D, 0x62, 0x79, + 0x01, 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, 0x31, 0x31, 0x2E, 0x30, + 0x2E, 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x6C, + 0x6C, 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2D, 0x70, 0x72, 0x6F, + 0x6A, 0x65, 0x63, 0x74, 0x20, 0x31, 0x37, 0x36, 0x32, 0x34, 0x39, 0x62, + 0x64, 0x36, 0x37, 0x33, 0x32, 0x61, 0x38, 0x30, 0x34, 0x34, 0x64, 0x34, + 0x35, 0x37, 0x30, 0x39, 0x32, 0x65, 0x64, 0x39, 0x33, 0x32, 0x37, 0x36, + 0x38, 0x37, 0x32, 0x34, 0x61, 0x36, 0x66, 0x30, 0x36, 0x29 +}; diff --git a/tests/unit/wasm-vm/wasm-apps/app3.wast b/tests/unit/wasm-vm/wasm-apps/app3.wast new file mode 100644 index 000000000..7c29ca518 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app3.wast @@ -0,0 +1,63 @@ +(module + (type $0 (func (param i32) (result i32))) + (type $1 (func)) + (type $2 (func (result i32))) + (type $3 (func (param i32 i32) (result i32))) + (import "env" "malloc" (func $11 (param i32) (result i32))) + (memory $4 1) + (global $5 i32 (i32.const 1024)) + (global $6 i32 (i32.const 1024)) + (global $7 i32 (i32.const 1024)) + (global $8 i32 (i32.const 5120)) + (global $9 i32 (i32.const 0)) + (global $10 i32 (i32.const 1)) + (export "memory" (memory $4)) + (export "__wasm_call_ctors" (func $12)) + (export "on_init" (func $12)) + (export "my_sqrt" (func $13)) + (export "null_pointer" (func $14)) + (export "my_malloc" (func $15)) + (export "__dso_handle" (global $5)) + (export "__data_end" (global $6)) + (export "__global_base" (global $7)) + (export "__heap_base" (global $8)) + (export "__memory_base" (global $9)) + (export "__table_base" (global $10)) + + (func $12 (type $1) + nop + ) + + (func $13 (type $3) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $1 + local.get $1 + i32.mul + local.get $0 + local.get $0 + i32.mul + i32.add + ) + + (func $14 (type $2) + (result i32) + i32.const 0 + ) + + (func $15 (type $0) + (param $0 i32) + (result i32) + local.get $0 + call $11 + ) + + ;;(custom_section "producers" + ;; (after code) + ;; "\01\0cprocessed-by\01\05clangV11.0.0 (ht" + ;; "tps://github.com/llvm/llvm-proje" + ;; "ct 176249bd6732a8044d457092ed932" + ;; "768724a6f06)") + + ) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app3/main.c b/tests/unit/wasm-vm/wasm-apps/app3/main.c new file mode 100644 index 000000000..000331ee9 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app3/main.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +void +on_init() +{} + +int +my_sqrt(int x, int y) +{ + return x * x + y * y; +} + +void * +null_pointer() +{ + void *ptr = NULL; + return ptr; +} + +void * +my_malloc(int size) +{ + return malloc(size); +} diff --git a/tests/unit/wasm-vm/wasm-apps/app3_wasm.h b/tests/unit/wasm-vm/wasm-apps/app3_wasm.h new file mode 100644 index 000000000..5c2ee5236 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app3_wasm.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +unsigned char app3_wasm[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x13, 0x04, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, 0x60, 0x00, 0x01, 0x7F, 0x60, + 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x02, 0x0E, 0x01, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x05, 0x04, + 0x01, 0x03, 0x02, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x23, 0x06, + 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, + 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x28, 0x0B, + 0x7F, 0x00, 0x41, 0x00, 0x0B, 0x7F, 0x00, 0x41, 0x01, 0x0B, 0x07, 0xA6, + 0x01, 0x0C, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x11, + 0x5F, 0x5F, 0x77, 0x61, 0x73, 0x6D, 0x5F, 0x63, 0x61, 0x6C, 0x6C, 0x5F, + 0x63, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x01, 0x07, 0x6F, 0x6E, 0x5F, 0x69, + 0x6E, 0x69, 0x74, 0x00, 0x01, 0x07, 0x6D, 0x79, 0x5F, 0x73, 0x71, 0x72, + 0x74, 0x00, 0x02, 0x0C, 0x6E, 0x75, 0x6C, 0x6C, 0x5F, 0x70, 0x6F, 0x69, + 0x6E, 0x74, 0x65, 0x72, 0x00, 0x03, 0x09, 0x6D, 0x79, 0x5F, 0x6D, 0x61, + 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x04, 0x0C, 0x5F, 0x5F, 0x64, 0x73, 0x6F, + 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x03, 0x00, 0x0A, 0x5F, 0x5F, + 0x64, 0x61, 0x74, 0x61, 0x5F, 0x65, 0x6E, 0x64, 0x03, 0x01, 0x0D, 0x5F, + 0x5F, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x5F, 0x62, 0x61, 0x73, 0x65, + 0x03, 0x02, 0x0B, 0x5F, 0x5F, 0x68, 0x65, 0x61, 0x70, 0x5F, 0x62, 0x61, + 0x73, 0x65, 0x03, 0x03, 0x0D, 0x5F, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72, + 0x79, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x04, 0x0C, 0x5F, 0x5F, 0x74, + 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x05, 0x0A, + 0x1F, 0x04, 0x03, 0x00, 0x01, 0x0B, 0x0D, 0x00, 0x20, 0x01, 0x20, 0x01, + 0x6C, 0x20, 0x00, 0x20, 0x00, 0x6C, 0x6A, 0x0B, 0x04, 0x00, 0x41, 0x00, + 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x00, 0x0B, 0x00, 0x76, 0x09, 0x70, + 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x01, 0x0C, 0x70, 0x72, + 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2D, 0x62, 0x79, 0x01, 0x05, + 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, 0x31, 0x31, 0x2E, 0x30, 0x2E, 0x30, + 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, + 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2D, 0x70, 0x72, 0x6F, 0x6A, 0x65, + 0x63, 0x74, 0x20, 0x31, 0x37, 0x36, 0x32, 0x34, 0x39, 0x62, 0x64, 0x36, + 0x37, 0x33, 0x32, 0x61, 0x38, 0x30, 0x34, 0x34, 0x64, 0x34, 0x35, 0x37, + 0x30, 0x39, 0x32, 0x65, 0x64, 0x39, 0x33, 0x32, 0x37, 0x36, 0x38, 0x37, + 0x32, 0x34, 0x61, 0x36, 0x66, 0x30, 0x36, 0x29 +}; diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m1.wasm b/tests/unit/wasm-vm/wasm-apps/app4/m1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..6979e1801e59855a6572e7ef1f8ce6ac836c2733 GIT binary patch literal 103 zcmXZTF$#b%5JkcFH!%r%nr-YoiKbBm1A_KmT?ET1hI%yt>a?IIn21p)bWxI}q=!jE h9T50ve9pihe5e*w7~W%s!G2`|V9*UL8%u?h zO8Gd+CeeV$HKaVcjpu(mObgU0A?=_|w(t9nGbnL^cB8fkn2@}~s=lu!$b`U@{12na B5XArh literal 0 HcmV?d00001 diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m2.wat b/tests/unit/wasm-vm/wasm-apps/app4/m2.wat new file mode 100644 index 000000000..340a3436b --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app4/m2.wat @@ -0,0 +1,24 @@ +(module + (import "m1" "f1" (func $m1-f1 (result i32))) + (export "m1-f1" (func $m1-f1)) + + (import "m1" "m1" (memory $m1-m1 1 2)) + (import "m1" "t1" (table $m1-t1 0 funcref)) + (import "m1" "g1" (global $m1-g1 i32)) + + (func $f2 (export "f2") (param i32) (result i32) + (i32.add (call $m1-f1) (local.get 0)) + ) + + (func $f4 (result i32) (i32.const 3)) + + (func $f3 (export "f3") (param i32 i32) (result i32) + (i32.add + (call $m1-f1) + (i32.add + (call $f4) + (call $f2 (local.get 0)) + ) + ) + ) +) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m3.wasm b/tests/unit/wasm-vm/wasm-apps/app4/m3.wasm new file mode 100644 index 0000000000000000000000000000000000000000..ecbff3d7b62d573e3d1e527d8f433865b2462d2e GIT binary patch literal 86 zcmZQbEY4+QU|?Y6VoG3OtWRL9XRK#(U}efRWJ)t+U;xq_xrXtHIhl#YOpJ_7Abtsy V&sYGFPlxiE>w(IRn9__G7y;)b5>o&G literal 0 HcmV?d00001 diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m3.wat b/tests/unit/wasm-vm/wasm-apps/app4/m3.wat new file mode 100644 index 000000000..e300121ef --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app4/m3.wat @@ -0,0 +1,7 @@ +(module + (import "m1" "f1" (func $m1-f1 (result i32))) + (import "m1" "m1_alias" (memory $m1-m1 1 2)) + (import "m1" "t1_alias" (table $m1-t1 0 funcref)) + (import "m1" "g1_alias" (global $m1-g1 i32)) + (import "m2" "f2" (func $m2-f2 (param i32) (result i32))) +) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/binarydump b/tests/unit/wasm-vm/wasm-apps/binarydump new file mode 100755 index 0000000000000000000000000000000000000000..e7c4d2a1da6bff79857d7b3047ccc86ef25f3a1e GIT binary patch literal 13448 zcmeHOeQ+DcbzcyYNKq0<$sduWjI~j$gpx&wlqH$^hz*d0bWll3B|(2oM4v$5NTLP- z6gY^aJ93p!R)k@la+21g>6g_s?X=VWA$J;&>UJcu%1Bm6ozjh+(X^e8;@TO|v{R-@ z6gG*4{@&g$csK$b_n*#mhO5E7eZTjyZ{O}6Z*Nz>9_Tn+<#I7qs@M~ZxJ%VO0a;hZ z-rOlziM6oR%*VE{PqS4(R^sOq5~5a3(FN&R(Hg1e23>()OO*w*RQW_j(N9}2TCj?W zkSMjcSbVZ-(GwdiR#C>d0LYGFt$$dspeIE|(epBnNlBF*v1HdE?HZ(=qBAluMOFW( zZ}baEf1xTLIO2UoSi86`QqrYz{CzV@^~?2w1@(!Fq8%2@6jgS=3_FVRlNRZob<6fD zPf^LTUGZ4|zCF9*(Z+ZzksWOuZQ0kjZ;v;V^zIh@CjX>+q^nnir1HqYQOx(_ zM{|JWpI_OqDgI8|_r9|IAOAf(^t&Hl{QTM-WUGFte&UjarknyLHlM11cU8dmSHNjL zmh=Bu1w2v#KT!b>RlwI*z+V8)@pBd*fO2s*R>0R(z>ieG8OA?C!@Z9UBvVF$4VXqe z&Qe)3!*o4kh9l4Gk)h}Hfp9F&1~P{6JR5*8!UiJoWX52_;dnd=ZX_Ku4K|QA!ci!s zV+nJBWz2MBI0ZM<2Kh>x`fxagHqwRxcyKtGkg(2{^ z5TXVf?pDg6O*UNJ(`*zh_Vu8n_KqfM;rdx$gbr73e|{^t;C;6-WvD42WeIW70DHvZoH@lf!_RMR>i({4;pttE0}?;0P= zAA#YI2kN%8-(;fpl}DuXNCX1Yn0Uiui~$e zyjT0u4}^p1du}+;a`W1B{z=VsU3=@E`9RUz8s)8S3+uaPwSVRd&4{06*Z0COpFm)J z*H=Ca$n_)9(p8Q>sM`3GEW2{<>#!?2`ym+=X8LAdfDP3#Gn%yA>DyW^JEKhmZeP); z-~ zE|AtC%lQJFFR<)=%J^F!7Yd@Gxo%R8AfnEB2p6u<%p=2bXygJPDuc6NCjuWH4CGIf zlLb=o6`iaDG&9kg&()Lc<~8c?)#K=2ekXLUeu-*ZsWwTqjZ~YVnuk2lEa?*_NRf|H zl*_)Y<$B-La-CB*0`F1h;1-Dsjc$$sZ&AiQXv^U-=5&RM0DtmHhj^C=_O2u^P^6FCTXyo_yWwtnPIh zyM-%%Xji@rWuSTOU|`-ft+uXT-3jabFht{l_goX5@4fL4w{G3az4_C3r$1Pco0+~- z<)X{>>D=GH^iQVD>Gi9etR9Ee+-A$s^c!wKR?vTnR`b7OYpw3fCy=~3*QC;==YXaA z7o?l8bj4`>-OrJ08eMC6DA&2uw=f&0qT0lYZ4Ho6?wY5x8-d$ka5o0-5FH=B<+hFrr?z=R-k5KZ8_hq%1r*r!!FgGVU?_k>8hOW31{cv4M z=Ja>aoM>lmm9WGRbuL7;$JUBW;}1hC)NWq$Kka|YpDXx#{h^MRw>`0*<6-r3Bhj8< z?rt#mPRDk7a@1(kAG`Cf{ud&8=_8Xj|BHIQb>u$i$lYy+hr<2;s*PWBY5V80AJ8A1 zFZTIQ`1}0N`Soj)i_gO!UBeKPKlvw#-Xo}_#g(z%OnA^Z!24r~aC$779ZvDaBtJ9| ziyKey#soi<2oIwcOW<8dCzKsanXzOdb3od2n?7Gsj>p3hgPTJJPi9THfFo16w;aH} z*vb-f9)cxBz>@SG#<=I5kNQ;pDsc;1COUX|Dl#$NB z58v%=;tkZNtx~jg`$2Lsmdx^DgqTR0Je#3z$1-hBEzs2yXhhV~sy7igGL(T|&BoH`asL<(rw~;n+>cn};Srup^Y9?vU85YMg)r!) zHY7Pcbv@y<<~tAHJ4iv6^7@QD0y*hFgP7(?*HeGk zv+-!%nvt3_?8!|BcRcpUR)R^V9ly^ZR-xzj)Ss(rTeqre4lP^qDCBn`r?n+h@`Mlz z`?G*oqmOawgOa-kU8F(&zlmQj`aV%2KPTkW_P6nyLQV`&*6OMM&8k+<#;>{q9{%!* zR!_rktkgVB=T>Q+mhtLNk1y?M@q3#5o`zNrhaU7>JvAb4YvDf+Kh~3woGq8-3@m40 zIRncXSkAz529`6hoPp&GEN9^VLk7;&_(Yf|B~>xYWm0jEW33cSuCnyiH~&5OEJ@`d zai#s%lcKg+^0Z!~vdJQBqmZ|j%L)y=Oo=H>0wEql5{}Q zQ<9#O^c6{+?H_4tJHQ)y`?Co%%lCTsdYc-XcV`9L{9^MyZ_}Rb7EE8K9&c`HZgP59 z%DXXpTdI6Z1hhjKDvP_BSr%VWoR@ZIZp_llW%XAvHE&Dxt6916cH=Hk^Q2UNHBzKOVOYwTlV4(hp4ia)?;JIPtx>_MF0D2IQFseN6$jho@FmCuDz{2_L} zEWU}+_L#G{nR@CiO6Y!H!G2g+M64P;PhD(j{PY~HLjLbK#)Ui+&K=Kbuf(0t?{?vT zF;4Z|=@IzSeA2lB@~{3LfEDE&uC6lU^2fl-_3JNzlb=74af)wUz^+UDmDN7f7!%*P zK;OcT^lwUBeA@z6DR1uz*#`E^1|MpRh1w~XPtqtC=P!imeM{yQ?S8q+%%2BE0+-Iu z?E+sq&kqSdOXpQL@D1oM?c!2Ve~0=7E})W&37nT87Qwu1f%fiHay%v8|-umWDFfIp0WQ9RCmJqmn7nLIpM0jG0V<@5)Em&+&Zbgr*@ zh)p`~>v6&nk$S$ZkTHBs`1i0WY{OGA#Fepc2wXBYQiJ~1<1Of-!~Y}Fk2-(1L)yGv z!Ouq&^r=_J`wo)J&!` zdN@1E#3qn|eG~8Fd-v}vuY}FEL`)ZZUb>Mm(_=VHgpDvATXe%?FtKquG|dv##oata zNk^5$)}3x9^?pQdq?tIlqz@VK6ti?K1=|0E@59~x&VU~1YDc%MKB{_2OHrn`KilQ+ z47NebCJ_gq0O6>d9?+yWt-YJ+M>>wR`aASvhY$AzLVC#G+7X}@#IdPJCM)_Z4o&%d z>X;NAj?#mnPJJ=Iq0TnSZiu$4!~w2SZE-fM6w-}o*bK{~Tn>@r?AM}nk97cS5fGs` z&v-e-)R1-7OCAd=Rgg!<93UM7 zNwrdU;y_y|r0e~ejEvMetVYM;96Co&>D_Wxx5dMm45qYo0?whQV@%Y9p}|tOLdj4u zZ)R-R4EKYYX^Rf28uo>abc%VgcWQY3t-(e!JSe%rMAqA%jp5{GEXusZ4TUp9%o`m` zz@J6Uv?al|9_{6oFgj#uBOWFLSxd!D<`v2EqUs$?f;Ej%Tq-p?N_9D*lxMU0i2NmUW>*htib&+?#kN%>)TJN;T zK-Ib&Dxx^^_Z(1K6RY;sy6CpF=ayOVJAl$t^m)i>jjedKep-H z>O^z++3nT(?vk`u@7>C#URD(SEr-2Y2VRsPI#j&M-pT*I!(P3=T$1)*R*7@8tNi_u z!(Oc`_s9=R>U)aPm&2-9_Gi*wjh}iy^GW*=nw+-cjQ=&rD1XXcowrx#@ae39y*S&y z3ZdOzt!HcK;5JH#gtp>r|0ZM}{8X6gyO}zd@6>nl@4&XsX0O)A8y^OU;?#HY--8Z? zsM=TSX#NT9zYklQYRX=%x7Gifp!EP1IUS4fsQGsRGJE@KUB0kIm=*OcZm~bAAOGR7 zFRtIYWpQ2^N~-J>T>x%xU#&OJbIU-*Db1I}a}NUYrTVYli!X4?LbYRYR$Ho0ln(h( z`%QKbb!D&C$4X4PR1~FYrrH()dHI`1tqPsduonj_{HVEa*PG!Mr|x5#4!iMF{ZY?9 Sxw;vk- literal 0 HcmV?d00001 diff --git a/tests/unit/wasm-vm/wasm-apps/build.sh b/tests/unit/wasm-vm/wasm-apps/build.sh new file mode 100755 index 000000000..dbf062ae7 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/build.sh @@ -0,0 +1,32 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +## build app1 +/opt/wasi-sdk/bin/clang -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -o app1/app1.wasm app1/main.c -Wl,--export-all \ + -Wl,--export=__heap_base,--export=__data_end \ + -Wl,--no-entry -nostdlib -Wl,--allow-undefined +./binarydump -o app1_wasm.h -n app1_wasm app1/app1.wasm +wavm disassemble app1/app1.wasm app1.wast +rm -f app1/app1.wasm + +## build app2 +/opt/wasi-sdk/bin/clang -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -o app2/app2.wasm app2/main.c -Wl,--export-all \ + -Wl,--export=__heap_base,--export=__data_end \ + -Wl,--no-entry -nostdlib -Wl,--allow-undefined +./binarydump -o app2_wasm.h -n app2_wasm app2/app2.wasm +wavm disassemble app2/app2.wasm app2.wast +rm -f app2/app2.wasm + +## build app3 +/opt/wasi-sdk/bin/clang -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -o app3/app3.wasm app3/main.c -Wl,--export-all \ + -Wl,--export=__heap_base,--export=__data_end \ + -Wl,--no-entry -nostdlib -Wl,--allow-undefined +./binarydump -o app3_wasm.h -n app3_wasm app3/app3.wasm +wavm disassemble app3/app3.wasm app3.wast +rm -f app3/app3.wasm diff --git a/tests/unit/wasm-vm/wasm_vm.cc b/tests/unit/wasm-vm/wasm_vm.cc new file mode 100644 index 000000000..f4f5a834d --- /dev/null +++ b/tests/unit/wasm-vm/wasm_vm.cc @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" +#if WASM_ENABLE_MULTI_MODULE != 0 +#include "wasm.h" +#include "wasm_runtime.h" +#endif +#include "wasm-apps/app1_wasm.h" +#include "wasm-apps/app2_wasm.h" +#include "wasm-apps/app3_wasm.h" + +#define EightK (8 * 1024) +// To use a test fixture, derive a class from testing::Test. +class WasmVMTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + // bh_log_set_verbose_level(5); + + clean = true; + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + void TearDown() + { + if (clean) { + wasm_runtime_destroy(); + } + } + + public: + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_function_inst_t func_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + RuntimeInitArgs init_args; + bool clean = true; +}; + +TEST_F(WasmVMTest, Test_app1) +{ + unsigned argv[10]; + + ASSERT_TRUE(app1_wasm != NULL); + + /* Load module */ + module = wasm_runtime_load(app1_wasm, sizeof(app1_wasm), error_buf, + sizeof(error_buf)); + if (module == nullptr) { + printf("error: %s\n", error_buf); + } + + ASSERT_TRUE(module != NULL); + + /* Initiate module */ + module_inst = wasm_runtime_instantiate(module, 8 * 1024, 8 * 1024, + error_buf, sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + /* _on_init() function doesn't exist */ + func_inst = wasm_runtime_lookup_function(module_inst, "_on_init"); + ASSERT_TRUE(func_inst == NULL); + + /* on_init() function exists */ + func_inst = wasm_runtime_lookup_function(module_inst, "on_init"); + ASSERT_TRUE(func_inst != NULL); + + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_inst, 0, NULL) == true); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc with very large size */ + argv[0] = 10 * 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + wasm_runtime_clear_exception(module_inst); + ASSERT_EQ(argv[0], 0); + + /* malloc 1K, should success */ + argv[0] = 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf), argv[0]); + int32 buf_offset = argv[0]; + + /* call memcpy */ + char *buf1 = buf + 100; + memcpy(buf1, "123456", 7); + func_inst = wasm_runtime_lookup_function(module_inst, "my_memcpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 100; + argv[2] = 7; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + ASSERT_TRUE(strcmp(buf, buf1) == 0); + + /* call strdup */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strdup"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + int32 buf_offset1 = argv[0]; + ASSERT_NE(buf_offset, buf_offset1); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, buf_offset1); + ASSERT_TRUE(strcmp(buf, buf1) == 0); + + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy_exec_env(exec_env); +} + +TEST_F(WasmVMTest, Test_app2) +{ + unsigned argv[10]; + + /* Load module */ + module = wasm_runtime_load(app2_wasm, sizeof(app2_wasm), error_buf, + sizeof(error_buf)); + + ASSERT_TRUE(module != NULL); + + /* Initiate module */ + module_inst = wasm_runtime_instantiate(module, 8 * 1024, 8 * 1024, + error_buf, sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + /* _on_init() function doesn't exist */ + func_inst = wasm_runtime_lookup_function(module_inst, "_on_init"); + ASSERT_TRUE(func_inst == NULL); + + /* on_init() function exists */ + func_inst = wasm_runtime_lookup_function(module_inst, "on_init"); + ASSERT_TRUE(func_inst != NULL); + + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_inst, 0, NULL) == true); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc 1K, should success */ + argv[0] = 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf), argv[0]); + int32 buf_offset = argv[0]; + + /* call memcpy */ + char *buf1 = buf + 100; + memcpy(buf1, "123456", 7); + func_inst = wasm_runtime_lookup_function(module_inst, "my_memcpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 100; + argv[2] = 7; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + ASSERT_TRUE(strcmp(buf, buf1) == 0); + + /* call memcmp */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memcmp"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 100; + argv[2] = 7; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE(argv[0] == 0); + + /* call printf */ + char *format = buf + 200; + memcpy(format, "string0 is %s", 13); + func_inst = wasm_runtime_lookup_function(module_inst, "my_printf"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = wasm_runtime_addr_native_to_app(module_inst, format); + argv[1] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(argv[0] == 17); + + /* call sprintf */ + memcpy(format, "string1 is %s", 13); + func_inst = wasm_runtime_lookup_function(module_inst, "my_sprintf"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 300; + int32 argv0_tmp = argv[0]; + argv[1] = wasm_runtime_addr_native_to_app(module_inst, format); + argv[2] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE( + memcmp((char *)wasm_runtime_addr_app_to_native(module_inst, argv0_tmp), + "string1 is 123456", 17) + == 0); + ASSERT_TRUE(argv[0] == 17); + + /* call snprintf */ + memcpy(format, "string2 is %s", 13); + func_inst = wasm_runtime_lookup_function(module_inst, "my_snprintf"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 400; + argv0_tmp = argv[0]; + argv[1] = 3; + argv[2] = wasm_runtime_addr_native_to_app(module_inst, format); + argv[3] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 4, argv); + + ASSERT_TRUE( + memcmp((char *)wasm_runtime_addr_app_to_native(module_inst, argv0_tmp), + "st\0", 3) + == 0); + ASSERT_TRUE(argv[0] == 17); + + /* call puts */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_puts"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(argv[0] != EOF); + + /* call putchar */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_putchar"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(argv[0] != EOF); + + /* call memmove without memory coverage*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memmove"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 10; + argv[1] = buf_offset + 100; + argv[2] = 6; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(strcmp(buf + 100, buf1) == 0); + ASSERT_TRUE(memcmp(buf1, "123456", 6) == 0); + + /* call memmove with memory coverage*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memmove"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 95; + argv[1] = buf_offset + 100; + argv[2] = 6; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(strcmp(buf + 100, buf1) != 0); + ASSERT_TRUE(memcmp(buf1, "123456", 6) == 0); + ASSERT_TRUE(memcmp(buf + 100, "623456", 6) == 0); + + /* call memset*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memset"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 100; + argv[1] = 48; + argv[2] = 4; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + ASSERT_TRUE(memcmp(buf + 100, "000056", 6) == 0); + + /* call strchr*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strchr"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = 49; // asc2 for char "1" + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf1 - buf == 0); + + /* call strcmp */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strcmp"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + + ASSERT_TRUE(argv[0] == 0); + + argv[0] = buf_offset; + argv[1] = buf_offset + 1; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + + ASSERT_TRUE(argv[0] != 0); + + /* call strcpy */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strcpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 110; + argv[1] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(memcmp(buf + 110, "123456", 6) == 0); + + /* call strlen */ + buf1 = buf + 110; + memcpy(buf1, "123456\0", 7); + func_inst = wasm_runtime_lookup_function(module_inst, "my_strlen"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 110; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(argv[0] == 6); + + /* call strncmp */ + buf1 = buf + 110; + memcpy(buf1, "123457", 6); + func_inst = wasm_runtime_lookup_function(module_inst, "my_strncmp"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 110; + argv[2] = 5; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE(argv[0] == 0); + + argv[0] = buf_offset; + argv[1] = buf_offset + 110; + argv[2] = 6; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE(argv[0] != 0); + + /* call strncpy */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strncpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 130; + argv[1] = buf_offset; + argv[2] = 5; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(memcmp(buf, buf1, 5) == 0); + ASSERT_TRUE(memcmp(buf, buf1, 6) != 0); + + /* call _my_calloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_calloc"); + ASSERT_TRUE(func_inst != NULL); + /* calloc, should success */ + argv[0] = 10; + argv[1] = 4; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 40)); + char *buf2 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf2 != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf2), argv[0]); + int32 buf_offset1 = argv[0]; + + /* call _my_free */ + memcpy(buf2, "123456", 6); + func_inst = wasm_runtime_lookup_function(module_inst, "my_free"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset1; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(memcmp(buf2, "123456", 6) != 0); + + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy_exec_env(exec_env); +} + +TEST_F(WasmVMTest, Test_app3) +{ + unsigned argv[10]; + + /* Load module */ + module = wasm_runtime_load(app3_wasm, sizeof(app3_wasm), error_buf, + sizeof(error_buf)); + + ASSERT_TRUE(module != NULL); + + /* Initiate module */ + module_inst = wasm_runtime_instantiate(module, 8 * 1024, 8 * 1024, + error_buf, sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + /* _on_init() function doesn't exist */ + func_inst = wasm_runtime_lookup_function(module_inst, "_on_init"); + ASSERT_TRUE(func_inst == NULL); + + /* on_init() function exists */ + func_inst = wasm_runtime_lookup_function(module_inst, "on_init"); + ASSERT_TRUE(func_inst != NULL); + + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_inst, 0, NULL) == true); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc with very large size */ + argv[0] = 10 * 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + wasm_runtime_clear_exception(module_inst); + ASSERT_EQ(argv[0], 0); + + /* malloc 1K, should success */ + argv[0] = 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf), argv[0]); + int32 buf_offset = argv[0]; + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc, should success */ + argv[0] = 10; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf1 != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf1), argv[0]); + int32 buf_offset1 = argv[0]; + + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy_exec_env(exec_env); +} + +#if WASM_ENABLE_MULTI_MODULE != 0 +static const char *module_search_path = "."; +static bool call_destroyer = false; +static bool +module_reader_callback(package_type_t module_type, const char *module_name, + uint8 **p_buffer, uint32 *p_size) +{ + const char *format = "%s/%s.wasm"; + int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + + strlen(".wasm") + 1; + char *wasm_file_name = (char *)BH_MALLOC(sz); + if (!wasm_file_name) { + return false; + } + + snprintf(wasm_file_name, sz, format, module_search_path, module_name); + printf("going to open %s\n", wasm_file_name); + + call_destroyer = false; + *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); + + BH_FREE(wasm_file_name); + return *p_buffer != NULL; +} + +static void +module_destroyer_callback(uint8 *buffer, uint32 size) +{ + wasm_runtime_free(buffer); + call_destroyer = true; +} + +TEST_F(WasmVMTest, Test_app4_single) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + unsigned argv[10]; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m1 only */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m1", &buffer, + &buffer_size); + ASSERT_TRUE(ret); + ASSERT_TRUE(buffer_size > 0); + ASSERT_TRUE(buffer != NULL); + + module = + wasm_runtime_load(buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + ASSERT_FALSE(wasm_runtime_find_module_registered("m1")); + + wasm_runtime_register_module("m1", module, error_buf, sizeof(error_buf)); + + ASSERT_TRUE(wasm_runtime_find_module_registered("m1")); + + module_inst = wasm_runtime_instantiate(module, EightK, EightK, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, EightK); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "f1"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_FALSE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 0); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + wasm_runtime_call_wasm(exec_env, func_inst, 0, argv); + printf("exception is %s", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 1); + + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + + // call destroyer and without exception + ASSERT_FALSE(call_destroyer); + module_destroyer_callback(buffer, buffer_size); + + clean = false; + wasm_runtime_destroy(); +} + +TEST_F(WasmVMTest, Test_app4_plus_one) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + uint32_t argv[10] = { 0 }; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m2 -> m1 */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m2", &buffer, + &buffer_size); + ASSERT_TRUE(ret); + ASSERT_TRUE(buffer_size > 0); + ASSERT_TRUE(buffer != NULL); + + module = + wasm_runtime_load(buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, EightK, EightK, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, EightK); + ASSERT_TRUE(exec_env != NULL); + + printf("------------------- m1-f1 ---------------------\n"); + func_inst = wasm_runtime_lookup_function(module_inst, "m1-f1"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 0); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + wasm_runtime_call_wasm(exec_env, func_inst, 0, argv); + printf("exception is %s\n", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 1); + + printf("------------------- f2 ---------------------\n"); + func_inst = wasm_runtime_lookup_function(module_inst, "f2"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_FALSE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 1); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + argv[0] = 2; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + printf("exception is %s\n", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 3); + + printf("------------------- f3 ---------------------\n"); + func_inst = wasm_runtime_lookup_function(module_inst, "f3"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_FALSE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 2); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + argv[0] = 4; + argv[1] = 9; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + printf("exception is %s\n", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 9); + + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + + wasm_runtime_unload(module); + ASSERT_FALSE(call_destroyer); +} + +TEST_F(WasmVMTest, Test_app4_family) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m3 -> m2[->m1], m1 */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m3", &buffer, + &buffer_size); + ASSERT_TRUE(ret); + ASSERT_TRUE(buffer_size > 0); + ASSERT_TRUE(buffer != NULL); + module = + wasm_runtime_load(buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + wasm_runtime_unload(module); + ASSERT_FALSE(call_destroyer); +} + +static const WASMModule * +search_sub_module(const WASMModule *parent_module, const char *sub_module_name) +{ + WASMRegisteredModule *node = (WASMRegisteredModule *)bh_list_first_elem( + parent_module->import_module_list); + while (node && strcmp(node->module_name, sub_module_name)) { + node = (WASMRegisteredModule *)bh_list_elem_next(node); + } + return node ? (WASMModule *)node->module : NULL; +} + +TEST_F(WasmVMTest, Test_app4_reuse) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m3 -> m2[->m1], m1 */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m3", &buffer, + &buffer_size); + ASSERT_TRUE(buffer != NULL); + + WASMModule *m3 = (WASMModule *)wasm_runtime_load( + buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(m3 != NULL); + + const WASMModule *m2 = search_sub_module(m3, "m2"); + const WASMModule *m1_in_m2 = search_sub_module(m2, "m1"); + const WASMModule *m1_in_m3 = search_sub_module(m3, "m1"); + ASSERT_EQ(m1_in_m2, m1_in_m3); +} +#endif /* WASM_ENABLE_MULTI_MODULE */ From 56b42908a85fbbc19a0346f8eb4106ecc1f96fec Mon Sep 17 00:00:00 2001 From: Benbuck Nason Date: Mon, 3 Jun 2024 20:29:31 -0700 Subject: [PATCH 13/23] Fix internal global getter types (#3495) --- core/iwasm/common/wasm_runtime_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 3b08d3ec0..794897cbc 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -4170,7 +4170,7 @@ wasm_func_type_get_result_valkind(WASMFuncType *const func_type, } wasm_valkind_t -wasm_global_type_get_valkind(const wasm_global_type_t global_type) +wasm_global_type_get_valkind(WASMGlobalType *const global_type) { bh_assert(global_type); @@ -4178,7 +4178,7 @@ wasm_global_type_get_valkind(const wasm_global_type_t global_type) } bool -wasm_global_type_get_mutable(const wasm_global_type_t global_type) +wasm_global_type_get_mutable(WASMGlobalType *const global_type) { bh_assert(global_type); From 0712c7f3612bb542893016846c6c297eb89cd8f5 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 4 Jun 2024 14:47:42 +0800 Subject: [PATCH 14/23] Fix CI build and run unit tests (#3499) --- .../compilation_on_android_ubuntu.yml | 69 ++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index c1c31f5f5..934e839c9 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -19,6 +19,7 @@ on: - "samples/**" - "!samples/workload/**" - "tests/wamr-test-suites/**" + - "tests/unit/**" - "wamr-compiler/**" - "test-tools/wamr-ide/**" # will be triggered on push events @@ -36,6 +37,7 @@ on: - "samples/**" - "!samples/workload/**" - "tests/wamr-test-suites/**" + - "tests/unit/**" - "wamr-compiler/**" - "test-tools/wamr-ide/**" # allow to be triggered manually @@ -272,10 +274,73 @@ jobs: cmake --build . --config Release --parallel 4 working-directory: product-mini/platforms/${{ matrix.platform }} + build_unit_tests: + needs: + [ + build_llvm_libraries_on_ubuntu_2204, + build_wamrc + ] + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-22.04] + wasi_sdk_release: + [ + "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz", + ] + wabt_release: + [ + "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz", + ] + include: + - os: ubuntu-22.04 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: Get LLVM libraries + id: retrieve_llvm_libs + uses: actions/cache@v4 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: ${{ matrix.llvm_cache_key }} + + - name: Quit if cache miss + if: (steps.retrieve_llvm_libs.outputs.cache-hit != 'true') + run: echo "::error::can not get prebuilt llvm libraries" && exit 1 + + - name: download and install wasi-sdk + run: | + cd /opt + sudo wget ${{ matrix.wasi_sdk_release }} + sudo tar -xzf wasi-sdk-*.tar.gz + sudo ln -sf wasi-sdk-20.0 wasi-sdk + + - name: download and install wabt + run: | + cd /opt + sudo wget ${{ matrix.wabt_release }} + sudo tar -xzf wabt-1.0.31-*.tar.gz + sudo mv wabt-1.0.31 wabt + + - name: Build wamrc + run: | + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + working-directory: wamr-compiler + - name: Build and run unit tests run: | - mkdir build-unittests && cd build-unittests - cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} + mkdir build && cd build + cmake .. cmake --build . --config Release --parallel 4 ctest working-directory: tests/unit From 3fbb7fca25334d526ff47db9f2eb2f1b716899a7 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Tue, 4 Jun 2024 09:27:06 +0100 Subject: [PATCH 15/23] Update version to 2.1.0 and update release notes (#3481) There was quite a few enhancements since 2.0.0 release and it'd be good to have another release now. --- RELEASE_NOTES.md | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ core/version.h | 2 +- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 0721fc638..7e74ff0dc 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,97 @@ +## WAMR-2.1.0 + +### Breaking Changes + +### New Features + - Add api to get export global instance (#3452) + - Add wasm-mutator-fuzz test (#3420) + - Implement Memory64 support for AOT (#3362) + - Add wasm module global type information APIs (#3406) + - Add aot binary analysis tool aot-analyzer (#3379) + - Expose API to get import/export function's param/result valkind (#3363) + - Add WASI support for esp-idf platform (#3348) + +### Bug Fixes + - Fix wasm loader check data segment count (#3492) + - Fix loader parse block type and calculate dynamic offset for loop args (#3482) + - Fix memory64 handling find_block_addr and execute_main (#3480) + - Fix two issues to make fuzzing test quit earlier (#3471) + - Fix test-wamr-ide CI failure (#3485) + - NuttX: Fix a dbus-related crash on esp32s3 (#3470) + - Clone data segments when specified with load args (#3463) + - Fix codeql compilation error (#3461) + - Fix several typos and fix bh_log calculate mills (#3441) + - ssp_config.h: Fix ifdef for android random api (#3444) + - libc-wasi: Fix a locking botch (#3437) + - Fix fast interp RECOVER_BR_INFO and local set/tee (#3434) + - aot compiler: Fix a type mismatch in compile_op_float_min_max (#3423) + - Correct Exception Handling tag type when GC is enabled (#3413) + - wasm loader: Fix handling if block without op else (#3404) + - ref-types: Correct default value for function local variables (#3397) + - aot compiler: Fix the length type passed to aot_memmove/aot_memset (#3378) + - Fix loader and mini-loader select potiential error (#3374) + - Fix aot debugger compilation error on windows (#3370) + - A few native stack detection fixes for macOS/arm64 (#3368) + - Fix ESP32-S3 compiling error (#3359) + - Fix a few native stack address calculations (#3351) + +### Enhancements + - Modify logging for windows exception handler and remove unused function (#3489) + - posix iwasm: Make the timeout logic a bit more robust (#3478) + - libc-builtin: Enhance buffered print for printf_wrapper (#3460) + - Enhance GC const initializer expression to support nested struct/array new (#3447) + - wasi: Tweak the configuration for nuttx and explain why (#3451) + - NuttX: Replace esp32s3 bits with the OS-provided APIs (#3439) + - Allow not copying the wasm binary in wasm-c-api and not referring to the binary in wasm/aot loader (#3389) + - aot: Make precheck functions use short-call for xtensa (#3418) + - Add wasm_runtime_detect_native_stack_overflow_size (#3355) + - Enhance wasm loader checks for opcode br_table (#3352) + +### Others + - Enable building static library on Android platform (#3488) + - wasm-mutator-fuzz: Generate more kinds of corpus (#3487) + - Correct nuttx repo names (#3484) + - Bump requests from 2.31.0 to 2.32.2 in /build-scripts (#3474) + - wasm-mutator-fuzz: Adapt to oss-fuzz compilation (#3464) + - Add regression tests of BA issue cases (#3462) + - Add malformed test cases (#3459) + - NuttX: Rename a few recently-added nuttx options (#3449) + - wamr-test-suites: Enable AOT multi-module spec tests (#3450) + - Remove install_wasi_sdk from workload preparation script (#3445) + - Add cmake static/shared library build settings (#3443) + - Update spec test to latest commit (#3293) + - Fix typo of WAMR_CONFIGUABLE_BOUNDS_CHECKS (#3424) + - ci/coding_guidelines_check.py: Allow some well-known file names to contain '-' (#3428) + - product-mini/platforms/posix/main.c: Adapt to WASM_MEM_DUAL_BUS_MIRROR (#3427) + - Add comments to global type function declarations (#3431) + - nuttx/esp32s3: Apply ibus/dbus adjustment to internal ram 1 as well (#3421) + - Change WASM_ANYREF to WASM_EXTERNREF (#3426) + - Remove unused macros which were moved to wamr-app-framework (#3425) + - Add WASM_V128 in wasm_valkind_enum (#3412) + - Fix basic example, parameter missmatch between host and wasm (#3415) + - Fix workspaces path in build_wamr.sh (#3414) + - core/iwasm/compilation: Remove stale function prototypes (#3408) + - Add test cases for the requirements of "gc-aot" feature (#3399) + - append_aot_to_wasm.py: Add --ver-str option to emit more info in custom section name (#3398) + - Fix clang compile warnings (#3396) + - Fix some more spelling issues (#3393) + - Fix some spelling issues (#3385) + - samples/native-stack-overflow: Examine native functions with signature (#3382) + - Add some more comments on WASM_STACK_GUARD_SIZE (#3380) + - Fix typo for 'native' in wasm_export.h (#3376) + - CI: Use macos-13 instead of macos-latest (#3366) + - Test more samples in nightly-run CI (#3358) + - Random improvements to samples/native-stack-overflow (#3353) + - Reduce WASM_STACK_GUARD_SIZE a bit for posix-like platforms (#3350) + - doc: Add ADOPTERS.md (#3324) + - Update binary size info in README.md (#3030) + - core/config.h: Bump the default WASM_STACK_GUARD_SIZE (#3344) + - Add unit test suites (#3490) + - Fix internal global getter types (#3495) + - Fix CI build and run unit tests (#3499) + +--- + ## WAMR-2.0.0 ### Breaking Changes diff --git a/core/version.h b/core/version.h index de3f56abc..e321744e3 100644 --- a/core/version.h +++ b/core/version.h @@ -6,6 +6,6 @@ #ifndef _WAMR_VERSION_H_ #define _WAMR_VERSION_H_ #define WAMR_VERSION_MAJOR 2 -#define WAMR_VERSION_MINOR 0 +#define WAMR_VERSION_MINOR 1 #define WAMR_VERSION_PATCH 0 #endif From 8239dd4aa7bdcf4ca5047d70bd1a6a4635bef5ce Mon Sep 17 00:00:00 2001 From: Benbuck Nason Date: Wed, 5 Jun 2024 18:20:24 -0700 Subject: [PATCH 16/23] Add wasm_export.h APIs to expose memory type (#3496) Support to get `wasm_memory_type_t memory_type` from API `wasm_runtime_get_import_type` and `wasm_runtime_get_export_type`, and then get shared flag, initial page cout, maximum page count from the memory_type: ```C bool wasm_memory_type_get_shared(const wasm_memory_type_t memory_type); uint32_t wasm_memory_type_get_init_page_count(const wasm_memory_type_t memory_type); uint32_t wasm_memory_type_get_max_page_count(const wasm_memory_type_t memory_type); ``` --- core/iwasm/aot/aot_loader.c | 14 ++--- core/iwasm/aot/aot_runtime.c | 11 ++-- core/iwasm/common/wasm_c_api.c | 16 +++--- core/iwasm/common/wasm_runtime_common.c | 67 +++++++++++++++------- core/iwasm/compilation/aot.c | 24 ++++---- core/iwasm/compilation/aot.h | 18 +----- core/iwasm/compilation/aot_compiler.h | 3 +- core/iwasm/compilation/aot_emit_aot_file.c | 8 +-- core/iwasm/compilation/aot_emit_control.c | 2 +- core/iwasm/compilation/aot_emit_memory.c | 11 ++-- core/iwasm/compilation/aot_llvm.c | 2 +- core/iwasm/fast-jit/jit_frontend.c | 2 +- core/iwasm/include/wasm_export.h | 36 ++++++++++++ core/iwasm/interpreter/wasm.h | 7 +-- core/iwasm/interpreter/wasm_loader.c | 40 +++++++------ core/iwasm/interpreter/wasm_mini_loader.c | 38 ++++++------ core/iwasm/interpreter/wasm_runtime.c | 11 ++-- test-tools/aot-analyzer/src/main.cc | 12 ++-- 18 files changed, 184 insertions(+), 138 deletions(-) diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 33e74acc8..8d705248c 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -1043,16 +1043,16 @@ load_memory_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, } for (i = 0; i < module->memory_count; i++) { - read_uint32(buf, buf_end, module->memories[i].memory_flags); + read_uint32(buf, buf_end, module->memories[i].flags); - if (!wasm_memory_check_flags(module->memories[i].memory_flags, - error_buf, error_buf_size, true)) { + if (!wasm_memory_check_flags(module->memories[i].flags, error_buf, + error_buf_size, true)) { return false; } read_uint32(buf, buf_end, module->memories[i].num_bytes_per_page); - read_uint32(buf, buf_end, module->memories[i].mem_init_page_count); - read_uint32(buf, buf_end, module->memories[i].mem_max_page_count); + read_uint32(buf, buf_end, module->memories[i].init_page_count); + read_uint32(buf, buf_end, module->memories[i].max_page_count); } read_uint32(buf, buf_end, module->mem_init_data_count); @@ -3637,9 +3637,9 @@ has_module_memory64(AOTModule *module) /* TODO: multi-memories for now assuming the memory idx type is consistent * across multi-memories */ if (module->import_memory_count > 0) - return !!(module->import_memories[0].memory_flags & MEMORY64_FLAG); + return !!(module->import_memories[0].mem_type.flags & MEMORY64_FLAG); else if (module->memory_count > 0) - return !!(module->memories[0].memory_flags & MEMORY64_FLAG); + return !!(module->memories[0].flags & MEMORY64_FLAG); return false; } diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index e01b8d207..ea068378a 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -789,10 +789,9 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, { void *heap_handle; uint32 num_bytes_per_page = memory->num_bytes_per_page; - uint32 init_page_count = memory->mem_init_page_count; - uint32 max_page_count = - wasm_runtime_get_max_mem(max_memory_pages, memory->mem_init_page_count, - memory->mem_max_page_count); + uint32 init_page_count = memory->init_page_count; + uint32 max_page_count = wasm_runtime_get_max_mem( + max_memory_pages, memory->init_page_count, memory->max_page_count); uint32 default_max_pages; uint32 inc_page_count, global_idx; uint32 bytes_of_last_page, bytes_to_page_end; @@ -800,11 +799,11 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, heap_offset = (uint64)num_bytes_per_page * init_page_count; uint64 memory_data_size, max_memory_data_size; uint8 *p = NULL, *global_addr; - bool is_memory64 = memory->memory_flags & MEMORY64_FLAG; + bool is_memory64 = memory->flags & MEMORY64_FLAG; bool is_shared_memory = false; #if WASM_ENABLE_SHARED_MEMORY != 0 - is_shared_memory = memory->memory_flags & SHARED_MEMORY_FLAG ? true : false; + is_shared_memory = memory->flags & SHARED_MEMORY_FLAG ? true : false; /* Shared memory */ if (is_shared_memory && parent != NULL) { AOTMemoryInstance *shared_memory_instance; diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 190a4beff..2a8f26681 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -2580,8 +2580,8 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out) + (i - import_func_count - import_global_count); module_name_rt = import->u.names.module_name; field_name_rt = import->u.names.field_name; - min_page = import->u.memory.init_page_count; - max_page = import->u.memory.max_page_count; + min_page = import->u.memory.mem_type.init_page_count; + max_page = import->u.memory.mem_type.max_page_count; } #endif @@ -2592,8 +2592,8 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out) + (i - import_func_count - import_global_count); module_name_rt = import->module_name; field_name_rt = import->memory_name; - min_page = import->mem_init_page_count; - max_page = import->mem_max_page_count; + min_page = import->mem_type.init_page_count; + max_page = import->mem_type.max_page_count; } #endif @@ -4308,12 +4308,12 @@ wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt, AOTModule *module_aot = (AOTModule *)inst_aot->module; if (memory_idx_rt < module_aot->import_memory_count) { - min_pages = module_aot->import_memories->mem_init_page_count; - max_pages = module_aot->import_memories->mem_max_page_count; + min_pages = module_aot->import_memories->mem_type.init_page_count; + max_pages = module_aot->import_memories->mem_type.max_page_count; } else { - min_pages = module_aot->memories->mem_init_page_count; - max_pages = module_aot->memories->mem_max_page_count; + min_pages = module_aot->memories->init_page_count; + max_pages = module_aot->memories->max_page_count; } init_flag = true; } diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 794897cbc..f18cd784a 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -3873,7 +3873,8 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index, import_type->kind = WASM_IMPORT_EXPORT_KIND_FUNC; import_type->linked = aot_import_func->func_ptr_linked ? true : false; - import_type->u.func_type = aot_import_func->func_type; + import_type->u.func_type = + (WASMFuncType *)aot_import_func->func_type; return; } @@ -3909,6 +3910,8 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index, import_type->name = aot_import_memory->memory_name; import_type->kind = WASM_IMPORT_EXPORT_KIND_MEMORY; import_type->linked = false; + import_type->u.memory_type = + (WASMMemoryType *)&aot_import_memory->mem_type; return; } @@ -3933,7 +3936,8 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index, switch (import_type->kind) { case WASM_IMPORT_EXPORT_KIND_FUNC: import_type->linked = wasm_import->u.function.func_ptr_linked; - import_type->u.func_type = wasm_import->u.function.func_type; + import_type->u.func_type = + (WASMFuncType *)wasm_import->u.function.func_type; break; case WASM_IMPORT_EXPORT_KIND_GLOBAL: import_type->linked = wasm_import->u.global.is_linked; @@ -3941,12 +3945,12 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index, (WASMGlobalType *)&wasm_import->u.global.type; break; case WASM_IMPORT_EXPORT_KIND_TABLE: - /* not supported */ - import_type->linked = false; + import_type->linked = false; /* not supported */ break; case WASM_IMPORT_EXPORT_KIND_MEMORY: - /* not supported */ - import_type->linked = false; + import_type->linked = false; /* not supported */ + import_type->u.memory_type = + (WASMMemoryType *)&wasm_import->u.memory.mem_type; break; default: bh_assert(0); @@ -4026,12 +4030,11 @@ wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index, .type; break; case WASM_IMPORT_EXPORT_KIND_TABLE: - /* not supported */ - // export_type->linked = false; break; case WASM_IMPORT_EXPORT_KIND_MEMORY: - /* not supported */ - // export_type->linked = false; + export_type->u.memory_type = + &aot_module->memories[aot_export->index + - aot_module->import_memory_count]; break; default: bh_assert(0); @@ -4068,13 +4071,13 @@ wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index, .type; break; case WASM_IMPORT_EXPORT_KIND_TABLE: - /* not supported */ - // export_type->linked = false; break; case WASM_IMPORT_EXPORT_KIND_MEMORY: - /* not supported */ - // export_type->linked = false; + export_type->u.memory_type = + &wasm_module->memories[wasm_export->index + - wasm_module->import_memory_count]; break; + default: bh_assert(0); break; } @@ -4185,6 +4188,30 @@ wasm_global_type_get_mutable(WASMGlobalType *const global_type) return global_type->is_mutable; } +bool +wasm_memory_type_get_shared(WASMMemoryType *const memory_type) +{ + bh_assert(memory_type); + + return (memory_type->flags & SHARED_MEMORY_FLAG) ? true : false; +} + +uint32 +wasm_memory_type_get_init_page_count(WASMMemoryType *const memory_type) +{ + bh_assert(memory_type); + + return memory_type->init_page_count; +} + +uint32 +wasm_memory_type_get_max_page_count(WASMMemoryType *const memory_type) +{ + bh_assert(memory_type); + + return memory_type->max_page_count; +} + bool wasm_runtime_register_natives(const char *module_name, NativeSymbol *native_symbols, @@ -6519,8 +6546,8 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm, if (export->index < module->import_memory_count) { WASMMemoryImport *import_memory = &((module->import_memories + export->index)->u.memory); - *out_min_page = import_memory->init_page_count; - *out_max_page = import_memory->max_page_count; + *out_min_page = import_memory->mem_type.init_page_count; + *out_max_page = import_memory->mem_type.max_page_count; } else { WASMMemory *memory = @@ -6540,14 +6567,14 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm, if (export->index < module->import_memory_count) { AOTImportMemory *import_memory = module->import_memories + export->index; - *out_min_page = import_memory->mem_init_page_count; - *out_max_page = import_memory->mem_max_page_count; + *out_min_page = import_memory->mem_type.init_page_count; + *out_max_page = import_memory->mem_type.max_page_count; } else { AOTMemory *memory = module->memories + (export->index - module->import_memory_count); - *out_min_page = memory->mem_init_page_count; - *out_max_page = memory->mem_max_page_count; + *out_min_page = memory->init_page_count; + *out_max_page = memory->max_page_count; } return true; } diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c index 0d1b9028c..33b8c0f34 100644 --- a/core/iwasm/compilation/aot.c +++ b/core/iwasm/compilation/aot.c @@ -558,28 +558,24 @@ aot_create_comp_data(WASMModule *module, const char *target_arch, /* Set memory page count */ for (i = 0; i < module->import_memory_count + module->memory_count; i++) { if (i < module->import_memory_count) { - comp_data->memories[i].memory_flags = - module->import_memories[i].u.memory.flags; + comp_data->memories[i].flags = + module->import_memories[i].u.memory.mem_type.flags; comp_data->memories[i].num_bytes_per_page = - module->import_memories[i].u.memory.num_bytes_per_page; - comp_data->memories[i].mem_init_page_count = - module->import_memories[i].u.memory.init_page_count; - comp_data->memories[i].mem_max_page_count = - module->import_memories[i].u.memory.max_page_count; - comp_data->memories[i].num_bytes_per_page = - module->import_memories[i].u.memory.num_bytes_per_page; + module->import_memories[i].u.memory.mem_type.num_bytes_per_page; + comp_data->memories[i].init_page_count = + module->import_memories[i].u.memory.mem_type.init_page_count; + comp_data->memories[i].max_page_count = + module->import_memories[i].u.memory.mem_type.max_page_count; } else { j = i - module->import_memory_count; - comp_data->memories[i].memory_flags = module->memories[j].flags; + comp_data->memories[i].flags = module->memories[j].flags; comp_data->memories[i].num_bytes_per_page = module->memories[j].num_bytes_per_page; - comp_data->memories[i].mem_init_page_count = + comp_data->memories[i].init_page_count = module->memories[j].init_page_count; - comp_data->memories[i].mem_max_page_count = + comp_data->memories[i].max_page_count = module->memories[j].max_page_count; - comp_data->memories[i].num_bytes_per_page = - module->memories[j].num_bytes_per_page; } } diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index ae04dfbc7..94e34113b 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -46,6 +46,8 @@ typedef WASMStructType AOTStructType; typedef WASMArrayType AOTArrayType; #endif typedef WASMExport AOTExport; +typedef WASMMemory AOTMemory; +typedef WASMMemoryType AOTMemoryType; #if WASM_ENABLE_DEBUG_AOT != 0 typedef void *dwarf_extractor_handle_t; @@ -81,23 +83,9 @@ typedef enum AOTFloatCond { typedef struct AOTImportMemory { char *module_name; char *memory_name; - uint32 memory_flags; - uint32 num_bytes_per_page; - uint32 mem_init_page_count; - uint32 mem_max_page_count; + AOTMemoryType mem_type; } AOTImportMemory; -/** - * Memory information - */ -typedef struct AOTMemory { - /* memory info */ - uint32 memory_flags; - uint32 num_bytes_per_page; - uint32 mem_init_page_count; - uint32 mem_max_page_count; -} AOTMemory; - /** * A segment of memory init data */ diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h index f9016ac6b..06dc77212 100644 --- a/core/iwasm/compilation/aot_compiler.h +++ b/core/iwasm/compilation/aot_compiler.h @@ -520,8 +520,7 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type) } while (0) #if WASM_ENABLE_MEMORY64 != 0 -#define IS_MEMORY64 \ - (comp_ctx->comp_data->memories[0].memory_flags & MEMORY64_FLAG) +#define IS_MEMORY64 (comp_ctx->comp_data->memories[0].flags & MEMORY64_FLAG) #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) \ (IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED) #else diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 70fd2efac..1c5906a8e 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -189,7 +189,7 @@ get_import_memory_size(AOTCompData *comp_data) static uint32 get_memory_size(AOTCompData *comp_data) { - /* memory_count + count * (memory_flags + num_bytes_per_page + + /* memory_count + count * (flags + num_bytes_per_page + init_page_count + max_page_count) */ return (uint32)(sizeof(uint32) + comp_data->memory_count * sizeof(uint32) * 4); @@ -1762,10 +1762,10 @@ aot_emit_mem_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, EMIT_U32(comp_data->memory_count); /* Emit memory items */ for (i = 0; i < comp_data->memory_count; i++) { - EMIT_U32(comp_data->memories[i].memory_flags); + EMIT_U32(comp_data->memories[i].flags); EMIT_U32(comp_data->memories[i].num_bytes_per_page); - EMIT_U32(comp_data->memories[i].mem_init_page_count); - EMIT_U32(comp_data->memories[i].mem_max_page_count); + EMIT_U32(comp_data->memories[i].init_page_count); + EMIT_U32(comp_data->memories[i].max_page_count); } /* Emit mem init data count */ diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index 24511ffd0..7d73d8d90 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -853,7 +853,7 @@ check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMBasicBlockRef terminate_block, non_terminate_block; AOTFuncType *aot_func_type = func_ctx->aot_func->func_type; bool is_shared_memory = - comp_ctx->comp_data->memories[0].memory_flags & 0x02 ? true : false; + comp_ctx->comp_data->memories[0].flags & 0x02 ? true : false; /* Only need to check the suspend flags when memory is shared since shared memory must be enabled for multi-threading */ diff --git a/core/iwasm/compilation/aot_emit_memory.c b/core/iwasm/compilation/aot_emit_memory.c index a506f2a78..506467449 100644 --- a/core/iwasm/compilation/aot_emit_memory.c +++ b/core/iwasm/compilation/aot_emit_memory.c @@ -109,7 +109,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool is_target_64bit, is_local_of_aot_value = false; #if WASM_ENABLE_SHARED_MEMORY != 0 bool is_shared_memory = - comp_ctx->comp_data->memories[0].memory_flags & SHARED_MEMORY_FLAG; + comp_ctx->comp_data->memories[0].flags & SHARED_MEMORY_FLAG; #endif is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false; @@ -177,7 +177,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 num_bytes_per_page = comp_ctx->comp_data->memories[0].num_bytes_per_page; uint32 init_page_count = - comp_ctx->comp_data->memories[0].mem_init_page_count; + comp_ctx->comp_data->memories[0].init_page_count; uint64 mem_data_size = (uint64)num_bytes_per_page * init_page_count; if (mem_offset + bytes <= mem_data_size) { @@ -224,7 +224,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, && aot_checked_addr_list_find(func_ctx, local_idx_of_aot_value, offset, bytes))) { uint32 init_page_count = - comp_ctx->comp_data->memories[0].mem_init_page_count; + comp_ctx->comp_data->memories[0].init_page_count; if (init_page_count == 0) { LLVMValueRef mem_size; @@ -932,8 +932,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Get memory base address and memory data size */ #if WASM_ENABLE_SHARED_MEMORY != 0 - bool is_shared_memory = - comp_ctx->comp_data->memories[0].memory_flags & 0x02; + bool is_shared_memory = comp_ctx->comp_data->memories[0].flags & 0x02; if (func_ctx->mem_space_unchanged || is_shared_memory) { #else @@ -961,7 +960,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 num_bytes_per_page = comp_ctx->comp_data->memories[0].num_bytes_per_page; uint32 init_page_count = - comp_ctx->comp_data->memories[0].mem_init_page_count; + comp_ctx->comp_data->memories[0].init_page_count; uint64 mem_data_size = (uint64)num_bytes_per_page * init_page_count; if (mem_data_size > 0 && mem_offset + mem_len <= mem_data_size) { /* inside memory space */ diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index bda8ee3b7..df07c3ca6 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -1219,7 +1219,7 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Load memory base address */ #if WASM_ENABLE_SHARED_MEMORY != 0 is_shared_memory = - comp_ctx->comp_data->memories[0].memory_flags & 0x02 ? true : false; + comp_ctx->comp_data->memories[0].flags & 0x02 ? true : false; if (is_shared_memory) { LLVMValueRef shared_mem_addr; offset = I32_CONST(offsetof(AOTModuleInstance, memories)); diff --git a/core/iwasm/fast-jit/jit_frontend.c b/core/iwasm/fast-jit/jit_frontend.c index 17c33230c..a8e87c92b 100644 --- a/core/iwasm/fast-jit/jit_frontend.c +++ b/core/iwasm/fast-jit/jit_frontend.c @@ -234,7 +234,7 @@ is_shared_memory(WASMModule *module, uint32 mem_idx) if (mem_idx < module->import_memory_count) { memory_import = &(module->import_memories[mem_idx].u.memory); - is_shared = memory_import->flags & 0x02 ? true : false; + is_shared = memory_import->mem_type.flags & 0x02 ? true : false; } else { memory = &module->memories[mem_idx - module->import_memory_count]; diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 2dd1eb905..85fd522d7 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -78,6 +78,10 @@ typedef struct WASMFuncType *wasm_func_type_t; struct WASMGlobalType; typedef struct WASMGlobalType *wasm_global_type_t; +struct WASMMemory; +typedef struct WASMMemory WASMMemoryType; +typedef WASMMemoryType *wasm_memory_type_t; + typedef struct wasm_import_t { const char *module_name; const char *name; @@ -86,6 +90,7 @@ typedef struct wasm_import_t { union { wasm_func_type_t func_type; wasm_global_type_t global_type; + wasm_memory_type_t memory_type; } u; } wasm_import_t; @@ -95,6 +100,7 @@ typedef struct wasm_export_t { union { wasm_func_type_t func_type; wasm_global_type_t global_type; + wasm_memory_type_t memory_type; } u; } wasm_export_t; @@ -1350,6 +1356,36 @@ wasm_global_type_get_valkind(const wasm_global_type_t global_type); WASM_RUNTIME_API_EXTERN bool wasm_global_type_get_mutable(const wasm_global_type_t global_type); +/** + * Get the shared setting for a memory type + * + * @param memory_type the memory type + * + * @return true if shared, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_memory_type_get_shared(const wasm_memory_type_t memory_type); + +/** + * Get the initial page count for a memory type + * + * @param memory_type the memory type + * + * @return the initial memory page count + */ +WASM_RUNTIME_API_EXTERN uint32_t +wasm_memory_type_get_init_page_count(const wasm_memory_type_t memory_type); + +/** + * Get the maximum page count for a memory type + * + * @param memory_type the memory type + * + * @return the maximum memory page count + */ +WASM_RUNTIME_API_EXTERN uint32_t +wasm_memory_type_get_max_page_count(const wasm_memory_type_t memory_type); + /** * Register native functions with same module name * diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 1f6ca6deb..4bd650529 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -512,7 +512,7 @@ typedef struct WASMMemory { uint32 num_bytes_per_page; uint32 init_page_count; uint32 max_page_count; -} WASMMemory; +} WASMMemory, WASMMemoryType; typedef struct WASMTableImport { char *module_name; @@ -536,10 +536,7 @@ typedef struct WASMTableImport { typedef struct WASMMemoryImport { char *module_name; char *field_name; - uint32 flags; - uint32 num_bytes_per_page; - uint32 init_page_count; - uint32 max_page_count; + WASMMemoryType mem_type; #if WASM_ENABLE_MULTI_MODULE != 0 WASMModule *import_module; WASMMemory *import_memory_linked; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index d61907e43..bf117dd82 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -44,7 +44,8 @@ has_module_memory64(WASMModule *module) /* TODO: multi-memories for now assuming the memory idx type is consistent * across multi-memories */ if (module->import_memory_count > 0) - return !!(module->import_memories[0].u.memory.flags & MEMORY64_FLAG); + return !!(module->import_memories[0].u.memory.mem_type.flags + & MEMORY64_FLAG); else if (module->memory_count > 0) return !!(module->memories[0].flags & MEMORY64_FLAG); @@ -2935,10 +2936,10 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, } /* now we believe all declaration are ok */ - memory->flags = mem_flag; - memory->init_page_count = declare_init_page_count; - memory->max_page_count = declare_max_page_count; - memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; + memory->mem_type.flags = mem_flag; + memory->mem_type.init_page_count = declare_init_page_count; + memory->mem_type.max_page_count = declare_max_page_count; + memory->mem_type.num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; *p_buf = p; @@ -4805,8 +4806,8 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, /* 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; + memory_flag = module->import_memories[mem_index] + .u.memory.mem_type.flags; } else { memory_flag = @@ -6153,13 +6154,14 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (shrunk_memory_size <= UINT32_MAX) { if (module->import_memory_count) { memory_import = &module->import_memories[0].u.memory; - init_memory_size = (uint64)memory_import->num_bytes_per_page - * memory_import->init_page_count; + init_memory_size = + (uint64)memory_import->mem_type.num_bytes_per_page + * memory_import->mem_type.init_page_count; if (shrunk_memory_size <= init_memory_size) { /* Reset memory info to decrease memory usage */ - memory_import->num_bytes_per_page = + memory_import->mem_type.num_bytes_per_page = (uint32)shrunk_memory_size; - memory_import->init_page_count = 1; + memory_import->mem_type.init_page_count = 1; LOG_VERBOSE("Shrink import memory size to %" PRIu64, shrunk_memory_size); } @@ -6185,16 +6187,16 @@ load_from_sections(WASMModule *module, WASMSection *sections, memory_import = &module->import_memories[0].u.memory; /* Only resize the memory to one big page if num_bytes_per_page is * in valid range of uint32 */ - if (memory_import->init_page_count < DEFAULT_MAX_PAGES) { - memory_import->num_bytes_per_page *= - memory_import->init_page_count; + if (memory_import->mem_type.init_page_count < DEFAULT_MAX_PAGES) { + memory_import->mem_type.num_bytes_per_page *= + memory_import->mem_type.init_page_count; - if (memory_import->init_page_count > 0) - memory_import->init_page_count = - memory_import->max_page_count = 1; + if (memory_import->mem_type.init_page_count > 0) + memory_import->mem_type.init_page_count = + memory_import->mem_type.max_page_count = 1; else - memory_import->init_page_count = - memory_import->max_page_count = 0; + memory_import->mem_type.init_page_count = + memory_import->mem_type.max_page_count = 0; } } if (module->memory_count) { diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 96d7b5ed0..75ac876cf 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -33,7 +33,7 @@ has_module_memory64(WASMModule *module) /* TODO: multi-memories for now assuming the memory idx type is consistent * across multi-memories */ if (module->import_memory_count > 0) - return !!(module->import_memories[0].u.memory.flags & MEMORY64_FLAG); + return !!(module->import_memories[0].u.mem_type.flags & MEMORY64_FLAG); else if (module->memory_count > 0) return !!(module->memories[0].flags & MEMORY64_FLAG); @@ -761,10 +761,10 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, } /* now we believe all declaration are ok */ - memory->flags = mem_flag; - memory->init_page_count = declare_init_page_count; - memory->max_page_count = declare_max_page_count; - memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; + memory->mem_type.flags = mem_flag; + memory->mem_type.init_page_count = declare_init_page_count; + memory->mem_type.max_page_count = declare_max_page_count; + memory->mem_type.num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; *p_buf = p; return true; @@ -1812,7 +1812,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, uint8 memory_flag; if (module->import_memory_count > 0) { memory_flag = - module->import_memories[mem_index].u.memory.flags; + module->import_memories[mem_index].u.mem_type.flags; } else { memory_flag = @@ -2922,12 +2922,14 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (shrunk_memory_size <= UINT32_MAX) { if (module->import_memory_count) { memory_import = &module->import_memories[0].u.memory; - init_memory_size = (uint64)memory_import->num_bytes_per_page - * memory_import->init_page_count; + init_memory_size = + (uint64)memory_import->mem_type.num_bytes_per_page + * memory_import->mem_type.init_page_count; if (shrunk_memory_size <= init_memory_size) { /* Reset memory info to decrease memory usage */ - memory_import->num_bytes_per_page = shrunk_memory_size; - memory_import->init_page_count = 1; + memory_import->mem_type.num_bytes_per_page = + shrunk_memory_size; + memory_import->mem_type.init_page_count = 1; LOG_VERBOSE("Shrink import memory size to %" PRIu64, shrunk_memory_size); } @@ -2950,15 +2952,15 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (module->import_memory_count) { memory_import = &module->import_memories[0].u.memory; - if (memory_import->init_page_count < DEFAULT_MAX_PAGES) { - memory_import->num_bytes_per_page *= - memory_import->init_page_count; - if (memory_import->init_page_count > 0) - memory_import->init_page_count = - memory_import->max_page_count = 1; + if (memory_import->mem_type.init_page_count < DEFAULT_MAX_PAGES) { + memory_import->mem_type.num_bytes_per_page *= + memory_import->mem_type.init_page_count; + if (memory_import->mem_type.init_page_count > 0) + memory_import->mem_type.init_page_count = + memory_import->mem_type.max_page_count = 1; else - memory_import->init_page_count = - memory_import->max_page_count = 0; + memory_import->mem_type.init_page_count = + memory_import->mem_type.max_page_count = 0; } } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 635fdea6d..19455983e 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -396,12 +396,13 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, /* instantiate memories from import section */ import = module->import_memories; for (i = 0; i < module->import_memory_count; i++, import++, memory++) { - uint32 num_bytes_per_page = import->u.memory.num_bytes_per_page; - uint32 init_page_count = import->u.memory.init_page_count; + uint32 num_bytes_per_page = + import->u.memory.mem_type.num_bytes_per_page; + uint32 init_page_count = import->u.memory.mem_type.init_page_count; uint32 max_page_count = wasm_runtime_get_max_mem( - max_memory_pages, import->u.memory.init_page_count, - import->u.memory.max_page_count); - uint32 flags = import->u.memory.flags; + max_memory_pages, import->u.memory.mem_type.init_page_count, + import->u.memory.mem_type.max_page_count); + uint32 flags = import->u.memory.mem_type.flags; uint32 actual_heap_size = heap_size; #if WASM_ENABLE_MULTI_MODULE != 0 diff --git a/test-tools/aot-analyzer/src/main.cc b/test-tools/aot-analyzer/src/main.cc index fa9582cd7..7b71e3005 100644 --- a/test-tools/aot-analyzer/src/main.cc +++ b/test-tools/aot-analyzer/src/main.cc @@ -272,9 +272,9 @@ DumpDetails(AoTFile *aot) AOTImportMemory memory = import_memories[index]; printf(" -[%u] num_bytes_per_page:%5u init_page_count:%5u " "max_page_count:%5u module_name: %s memory_name: %s\n", - index, memory.num_bytes_per_page, memory.mem_init_page_count, - memory.mem_max_page_count, memory.module_name, - memory.memory_name); + index, memory.memory.num_bytes_per_page, + memory.memory.init_page_count, memory.memory.max_page_count, + memory.module_name, memory.memory_name); } printf("\n"); @@ -365,10 +365,10 @@ DumpDetails(AoTFile *aot) for (uint32_t index = 0; index < memory_count; index++) { AOTMemory memory = memories[index]; - printf(" -[%u] memory_flags:%5u bytes_per_page:%5u " + printf(" -[%u] flags:%5u bytes_per_page:%5u " "init_page_count:%5u max_page_count:%5u\n", - index, memory.memory_flags, memory.num_bytes_per_page, - memory.mem_init_page_count, memory.mem_max_page_count); + index, memory.flags, memory.num_bytes_per_page, + memory.init_page_count, memory.max_page_count); } printf("\n\n"); From 421a6c430194853948a7e5d264e2e43496175563 Mon Sep 17 00:00:00 2001 From: Benbuck Nason Date: Wed, 5 Jun 2024 18:37:28 -0700 Subject: [PATCH 17/23] Fix posix build when libc wasi is disabled and debug interp is enabled (#3503) This change supports building with `-DWAMR_BUILD_LIBC_WASI=0` and `-DWAMR_BUILD_DEBUG_INTERP=1`, otherwise the os_socket_* functions will be undefined. --- core/shared/platform/common/posix/platform_api_posix.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/shared/platform/common/posix/platform_api_posix.cmake b/core/shared/platform/common/posix/platform_api_posix.cmake index 15d6daf3f..2553a7d04 100644 --- a/core/shared/platform/common/posix/platform_api_posix.cmake +++ b/core/shared/platform/common/posix/platform_api_posix.cmake @@ -9,6 +9,11 @@ if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1) list(REMOVE_ITEM source_all ${PLATFORM_COMMON_POSIX_DIR}/posix_file.c ${PLATFORM_COMMON_POSIX_DIR}/posix_clock.c + ) +endif() + +if ((NOT WAMR_BUILD_LIBC_WASI EQUAL 1) AND (NOT WAMR_BUILD_DEBUG_INTERP EQUAL 1)) + list(REMOVE_ITEM source_all ${PLATFORM_COMMON_POSIX_DIR}/posix_socket.c ) else() From 5d1f19fc0994b6c50d9f578cf8cbbba4bb7be35c Mon Sep 17 00:00:00 2001 From: Benbuck Nason Date: Wed, 5 Jun 2024 18:53:22 -0700 Subject: [PATCH 18/23] Fix wasm_mini_loader.c build when jit or multi-module is enabled (#3502) This PR fixes compilation error when building with `-DWAMR_BUILD_MINI_LOADER=1 -DWAMR_BUILD_JIT=1` or `-DWAMR_BUILD_MINI_LOADER=1 -DWAMR_BUILD_MULTI_MODULE=1`, though normally we don't use wasm mini loader when JIT or multi-module is enabled. --- core/iwasm/interpreter/wasm_mini_loader.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 75ac876cf..41d137c25 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -2114,7 +2114,7 @@ static bool init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, uint32 error_buf_size) { - LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options(); + LLVMJITOptions *llvm_jit_options = wasm_runtime_get_llvm_jit_options(); AOTCompOption option = { 0 }; char *aot_last_error; uint64 size; @@ -3235,8 +3235,11 @@ load(const uint8 *buf, uint32 size, WASMModule *module, } WASMModule * -wasm_loader_load(uint8 *buf, uint32 size, const LoadArgs *args, char *error_buf, - uint32 error_buf_size) +wasm_loader_load(uint8 *buf, uint32 size, +#if WASM_ENABLE_MULTI_MODULE != 0 + bool main_module, +#endif + const LoadArgs *args, char *error_buf, uint32 error_buf_size) { WASMModule *module = create_module(args->name, error_buf, error_buf_size); if (!module) { @@ -3254,6 +3257,10 @@ wasm_loader_load(uint8 *buf, uint32 size, const LoadArgs *args, char *error_buf, goto fail; } +#if WASM_ENABLE_MULTI_MODULE != 0 + (void)main_module; +#endif + LOG_VERBOSE("Load module success.\n"); return module; From 53f26e436b2bbbe1b9bb47e81697cf531a5f227b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:09:19 +0800 Subject: [PATCH 19/23] Bump requests from 2.32.2 to 2.32.3 in /build-scripts (#3494) Bumps [requests](https://github.com/psf/requests) from 2.32.2 to 2.32.3. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.32.2...v2.32.3) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build-scripts/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-scripts/requirements.txt b/build-scripts/requirements.txt index 6b1425c82..ef487e06e 100644 --- a/build-scripts/requirements.txt +++ b/build-scripts/requirements.txt @@ -1 +1 @@ -requests==2.32.2 \ No newline at end of file +requests==2.32.3 \ No newline at end of file From 8f86b37616f4fe52367b6b0ab05bc869ec403058 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 6 Jun 2024 10:26:50 +0800 Subject: [PATCH 20/23] Update release notes (#3506) --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7e74ff0dc..59ce379fc 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -3,6 +3,7 @@ ### Breaking Changes ### New Features + - Add wasm_export.h APIs to expose memory type (#3496) - Add api to get export global instance (#3452) - Add wasm-mutator-fuzz test (#3420) - Implement Memory64 support for AOT (#3362) @@ -12,6 +13,8 @@ - Add WASI support for esp-idf platform (#3348) ### Bug Fixes + - Fix posix build when libc wasi is disabled and debug interp is enabled (#3503) + - Fix wasm_mini_loader.c build when jit or multi-module is enabled (#3502) - Fix wasm loader check data segment count (#3492) - Fix loader parse block type and calculate dynamic offset for loop args (#3482) - Fix memory64 handling find_block_addr and execute_main (#3480) @@ -48,6 +51,7 @@ - Enhance wasm loader checks for opcode br_table (#3352) ### Others + - Bump requests from 2.32.2 to 2.32.3 in /build-scripts (#3494) - Enable building static library on Android platform (#3488) - wasm-mutator-fuzz: Generate more kinds of corpus (#3487) - Correct nuttx repo names (#3484) From dc21c62431185f7f578c7276ac4e06f91d68e5c4 Mon Sep 17 00:00:00 2001 From: Berthelot Mewen <65554529+bmewen@users.noreply.github.com> Date: Fri, 7 Jun 2024 03:40:35 +0200 Subject: [PATCH 21/23] Add missing functions to make RIOT work with the 2.x.x version (#3508) The `os_mremap` and `os_getpagesize` were missing in the `core/shared/platform/riot` and were preventing RIOT from compiling if using WAMR v2.x.x. This PR is adding both functions and should allow RIOT to update WAMR version to v2.x.x. Signed-off-by:: mewen.berthelot --- core/shared/platform/riot/platform_internal.h | 8 ++++++++ core/shared/platform/riot/riot_platform.c | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/core/shared/platform/riot/platform_internal.h b/core/shared/platform/riot/platform_internal.h index e88b25d40..24a1d6c86 100644 --- a/core/shared/platform/riot/platform_internal.h +++ b/core/shared/platform/riot/platform_internal.h @@ -94,4 +94,12 @@ os_get_invalid_handle() return -1; } +/* There is no MMU in RIOT so the function return 1024 to make the compiler + happy */ +static inline int +os_getpagesize() +{ + return 1024; +} + #endif /* end of _BH_PLATFORM_H */ diff --git a/core/shared/platform/riot/riot_platform.c b/core/shared/platform/riot/riot_platform.c index ad5927e51..9c1fbfa45 100644 --- a/core/shared/platform/riot/riot_platform.c +++ b/core/shared/platform/riot/riot_platform.c @@ -57,6 +57,12 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) return BH_MALLOC((unsigned)size); } +void * +os_mremap(void *old_addr, size_t old_size, size_t new_size) +{ + return os_mremap_slow(old_addr, old_size, new_size); +} + void os_munmap(void *addr, size_t size) { From bd44117676fb5d12424498fc97af92ea09406baa Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Fri, 7 Jun 2024 10:26:09 +0800 Subject: [PATCH 22/23] Add wasi-nn example as smoke test case (#3501) --- core/iwasm/libraries/wasi-nn/README.md | 73 ++++++++++++++----- .../wasi-nn/test/Dockerfile.wasi-nn-example | 57 +++++++++++++++ 2 files changed, 112 insertions(+), 18 deletions(-) create mode 100644 core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-example diff --git a/core/iwasm/libraries/wasi-nn/README.md b/core/iwasm/libraries/wasi-nn/README.md index fbc99ccbb..56baf99c5 100644 --- a/core/iwasm/libraries/wasi-nn/README.md +++ b/core/iwasm/libraries/wasi-nn/README.md @@ -16,23 +16,22 @@ By only including this file in your WASM application you will bind WASI-NN into To run the tests we assume that the current directory is the root of the repository. - ### Build the runtime Build the runtime image for your execution target type. `EXECUTION_TYPE` can be: -* `cpu` -* `nvidia-gpu` -* `vx-delegate` -* `tpu` + +- `cpu` +- `nvidia-gpu` +- `vx-delegate` +- `tpu` ``` EXECUTION_TYPE=cpu docker build -t wasi-nn-${EXECUTION_TYPE} -f core/iwasm/libraries/wasi-nn/test/Dockerfile.${EXECUTION_TYPE} . ``` - ### Build wasm app ``` @@ -43,7 +42,6 @@ docker build -t wasi-nn-compile -f core/iwasm/libraries/wasi-nn/test/Dockerfile. docker run -v $PWD/core/iwasm/libraries/wasi-nn:/wasi-nn wasi-nn-compile ``` - ### Run wasm app If all the tests have run properly you will the the following message in the terminal, @@ -52,7 +50,7 @@ If all the tests have run properly you will the the following message in the ter Tests: passed! ``` -* CPU +- CPU ``` docker run \ @@ -64,9 +62,9 @@ docker run \ /assets/test_tensorflow.wasm ``` -* (NVIDIA) GPU - * Requirements: - * [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker). +- (NVIDIA) GPU + - Requirements: + - [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker). ``` docker run \ @@ -79,7 +77,7 @@ docker run \ /assets/test_tensorflow.wasm ``` -* vx-delegate for NPU (x86 simulator) +- vx-delegate for NPU (x86 simulator) ``` docker run \ @@ -90,9 +88,9 @@ docker run \ /assets/test_tensorflow_quantized.wasm ``` -* (Coral) TPU - * Requirements: - * [Coral USB](https://coral.ai/products/accelerator/). +- (Coral) TPU + - Requirements: + - [Coral USB](https://coral.ai/products/accelerator/). ``` docker run \ @@ -109,6 +107,45 @@ docker run \ Supported: -* Graph encoding: `tensorflowlite`. -* Execution target: `cpu`, `gpu` and `tpu`. -* Tensor type: `fp32`. +- Graph encoding: `tensorflowlite`. +- Execution target: `cpu`, `gpu` and `tpu`. +- Tensor type: `fp32`. + +## Smoke test + +Use [classification-example](https://github.com/bytecodealliance/wasi-nn/tree/main/rust/examples/classification-example) as a smoke test case to make sure the wasi-nn support in WAMR is working properly. + +> [!Important] +> It requires openvino. + +### Prepare the model and the wasm + +``` bash +$ pwd +/workspaces/wasm-micro-runtime/core/iwasm/libraries/wasi-nn/test + +$ docker build -t wasi-nn-example:v1.0 -f Dockerfile.wasi-nn-example . +``` + +There are model files(*mobilenet\**) and wasm files(*wasi-nn-example.wasm*) in the directory */workspaces/wasi-nn/rust/examples/classification-example/build* in the image of wasi-nn-example:v1.0. + +### build iwasm and test + +*TODO: May need alternative steps to build the iwasm and test in the container of wasi-nn-example:v1.0* + +``` bash +$ pwd +/workspaces/wasm-micro-runtime + +$ docker run --rm -it -v $(pwd):/workspaces/wasm-micro-runtime wasi-nn-example:v1.0 /bin/bash +``` + +> [!Caution] +> The following steps are executed in the container of wasi-nn-example:v1.0. + +``` bash +$ cd /workspaces/wasm-micro-runtime/product-mini/platforms/linux +$ cmake -S . -B build -DWAMR_BUILD_WASI_NN=1 -DWAMR_BUILD_WASI_EPHEMERAL_NN=1 +$ cmake --build build +$ ./build/iwasm -v=5 --map-dir=/workspaces/wasi-nn/rust/examples/classification-example/build/::fixture /workspaces/wasi-nn/rust/examples/classification-example/build/wasi-nn-example.wasm +``` \ No newline at end of file diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-example b/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-example new file mode 100644 index 000000000..020bfd20e --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-example @@ -0,0 +1,57 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +FROM mcr.microsoft.com/devcontainers/rust:1-1-bullseye + +ARG DEBIAN_FRONTEND=noninteractive +ENV TZ=Asian/Shanghai + +# hadolint ignore=DL3009 +RUN apt-get update \ + && apt-get upgrade -y + +# +# Rust targets +RUN rustup target add wasm32-wasi wasm32-unknown-unknown + +# +# Openvino +# Refer to +# - https://docs.openvino.ai/2022.3/openvino_docs_install_guides_installing_openvino_from_archive_linux.html +# - https://docs.openvino.ai/2023.3/openvino_docs_install_guides_installing_openvino_from_archive_linux.html +# - https://docs.openvino.ai/2024/get-started/install-openvino/install-openvino-archive-linux.html +# +# FIXME: upgrade to 2024.1 or latest after wasi-nn(rust binding) is ready +WORKDIR /opt/intel +RUN wget -q https://storage.openvinotoolkit.org/repositories/openvino/packages/2022.3.2/linux/l_openvino_toolkit_ubuntu20_2022.3.2.9279.e2c7e4d7b4d_x86_64.tgz +RUN tar -xf l_openvino_toolkit_ubuntu20_2022.3.2.9279.e2c7e4d7b4d_x86_64.tgz \ + && rm l_openvino_toolkit_ubuntu20_2022.3.2.9279.e2c7e4d7b4d_x86_64.tgz \ + && mv l_openvino_toolkit_ubuntu20_2022.3.2.9279.e2c7e4d7b4d_x86_64 /opt/intel/openvino + +WORKDIR /opt/intel/openvino +RUN ./install_dependencies/install_openvino_dependencies.sh -y \ + && ./setupvars.sh + +# +# wasmtime +WORKDIR /opt +RUN wget -q https://github.com/bytecodealliance/wasmtime/releases/download/v21.0.0/wasmtime-v21.0.0-x86_64-linux.tar.xz +RUN tar -xf wasmtime-v21.0.0-x86_64-linux.tar.xz \ + && rm wasmtime-v21.0.0-x86_64-linux.tar.xz \ + && ln -sf "$(realpath ./wasmtime-v21.0.0-x86_64-linux/wasmtime)" /usr/local/bin/wasmtime + +# +# wasi-nn +WORKDIR /workspaces/wasi-nn +RUN git clone --depth 1 https://github.com/bytecodealliance/wasi-nn.git . +# hadolint ignore=DL3059 +RUN ./build.sh rust + +# There are model files(mobilenet*) and wasm files(wasi-nn-example.wasm) in the directory, +# /workspaces/wasi-nn/rust/examples/classification-example/build + +RUN apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /tmp/* + +WORKDIR /workspaces From 028f43bc18494866c44666e54e9c5a2cd84152f5 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Fri, 7 Jun 2024 10:49:44 +0800 Subject: [PATCH 23/23] Fix compilation warnings of wasi-nn (#3497) --- core/iwasm/aot/aot_runtime.c | 2 +- core/iwasm/interpreter/wasm_runtime.c | 2 +- .../iwasm/libraries/wasi-nn/include/wasi_nn.h | 23 +++++----- .../libraries/wasi-nn/include/wasi_nn_types.h | 5 ++- .../wasi-nn/src/utils/wasi_nn_app_native.c | 16 +++---- .../wasi-nn/src/utils/wasi_nn_app_native.h | 8 ++-- core/iwasm/libraries/wasi-nn/src/wasi_nn.c | 44 +++++++++---------- .../wasi-nn/src/wasi_nn_tensorflowlite.cpp | 32 +++++++------- .../wasi-nn/src/wasi_nn_tensorflowlite.hpp | 12 ++--- core/iwasm/libraries/wasi-nn/test/utils.c | 14 +++--- core/iwasm/libraries/wasi-nn/test/utils.h | 10 ++--- 11 files changed, 85 insertions(+), 83 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index ea068378a..e13661303 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1945,7 +1945,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) if (!is_sub_inst) { #if WASM_ENABLE_WASI_NN != 0 - wasi_nn_destroy(module_inst); + wasi_nn_destroy((WASMModuleInstanceCommon *)module_inst); #endif wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst); } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 19455983e..122325bc2 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -3182,7 +3182,7 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) if (!is_sub_inst) { #if WASM_ENABLE_WASI_NN != 0 - wasi_nn_destroy(module_inst); + wasi_nn_destroy((WASMModuleInstanceCommon *)module_inst); #endif wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst); } diff --git a/core/iwasm/libraries/wasi-nn/include/wasi_nn.h b/core/iwasm/libraries/wasi-nn/include/wasi_nn.h index 2bf0a192c..66e2ee02a 100644 --- a/core/iwasm/libraries/wasi-nn/include/wasi_nn.h +++ b/core/iwasm/libraries/wasi-nn/include/wasi_nn.h @@ -22,9 +22,9 @@ * @param encoding Model encoding. * @param target Execution target. * @param g Graph. - * @return error Execution status. + * @return wasi_nn_error Execution status. */ -error +wasi_nn_error load(graph_builder_array *builder, graph_encoding encoding, execution_target target, graph *g) __attribute__((import_module("wasi_nn"))); @@ -34,17 +34,14 @@ load(graph_builder_array *builder, graph_encoding encoding, * */ -// Bind a `graph` to the input and output tensors for an inference. -typedef uint32_t graph_execution_context; - /** * @brief Create an execution instance of a loaded graph. * * @param g Graph. * @param ctx Execution context. - * @return error Execution status. + * @return wasi_nn_error Execution status. */ -error +wasi_nn_error init_execution_context(graph g, graph_execution_context *ctx) __attribute__((import_module("wasi_nn"))); @@ -54,9 +51,9 @@ init_execution_context(graph g, graph_execution_context *ctx) * @param ctx Execution context. * @param index Input tensor index. * @param tensor Input tensor. - * @return error Execution status. + * @return wasi_nn_error Execution status. */ -error +wasi_nn_error set_input(graph_execution_context ctx, uint32_t index, tensor *tensor) __attribute__((import_module("wasi_nn"))); @@ -64,9 +61,9 @@ set_input(graph_execution_context ctx, uint32_t index, tensor *tensor) * @brief Compute the inference on the given inputs. * * @param ctx Execution context. - * @return error Execution status. + * @return wasi_nn_error Execution status. */ -error +wasi_nn_error compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn"))); /** @@ -79,9 +76,9 @@ compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn"))); * @param output_tensor_size Pointer to `output_tensor` maximum size. * After the function call it is updated with the * copied number of bytes. - * @return error Execution status. + * @return wasi_nn_error Execution status. */ -error +wasi_nn_error get_output(graph_execution_context ctx, uint32_t index, tensor_data output_tensor, uint32_t *output_tensor_size) __attribute__((import_module("wasi_nn"))); diff --git a/core/iwasm/libraries/wasi-nn/include/wasi_nn_types.h b/core/iwasm/libraries/wasi-nn/include/wasi_nn_types.h index 7cfc70f34..d3c56cb7d 100644 --- a/core/iwasm/libraries/wasi-nn/include/wasi_nn_types.h +++ b/core/iwasm/libraries/wasi-nn/include/wasi_nn_types.h @@ -28,7 +28,7 @@ typedef enum { busy, // Runtime Error. runtime_error, -} error; +} wasi_nn_error; /** * TENSOR @@ -106,4 +106,7 @@ typedef enum { // Define where the graph should be executed. typedef enum execution_target { cpu = 0, gpu, tpu } execution_target; +// Bind a `graph` to the input and output tensors for an inference. +typedef uint32_t graph_execution_context; + #endif diff --git a/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c index 44aef5359..b1a7c327d 100644 --- a/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c +++ b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c @@ -5,7 +5,7 @@ #include "wasi_nn_app_native.h" -static error +static wasi_nn_error graph_builder_app_native(wasm_module_inst_t instance, graph_builder_wasm *builder_wasm, graph_builder *builder) @@ -27,12 +27,12 @@ graph_builder_app_native(wasm_module_inst_t instance, * builder_array_wasm is consisted of {builder_wasm, size} */ #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 -error +wasi_nn_error graph_builder_array_app_native(wasm_module_inst_t instance, graph_builder_wasm *builder_wasm, uint32_t size, graph_builder_array *builder_array) #else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ -error +wasi_nn_error graph_builder_array_app_native(wasm_module_inst_t instance, graph_builder_array_wasm *builder_array_wasm, graph_builder_array *builder_array) @@ -79,7 +79,7 @@ graph_builder_array_app_native(wasm_module_inst_t instance, return missing_memory; for (uint32_t i = 0; i < array_size; ++i) { - error res; + wasi_nn_error res; if (success != (res = graph_builder_app_native(instance, &builder_wasm[i], &builder[i]))) { @@ -97,7 +97,7 @@ graph_builder_array_app_native(wasm_module_inst_t instance, #undef array_size } -static error +static wasi_nn_error tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements, tensor_wasm *input_tensor_wasm, tensor_data *data) { @@ -119,7 +119,7 @@ tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements, #undef data_size } -static error +static wasi_nn_error tensor_dimensions_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm, tensor_dimensions **dimensions) @@ -159,7 +159,7 @@ tensor_dimensions_app_native(wasm_module_inst_t instance, return success; } -error +wasi_nn_error tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm, tensor *input_tensor) { @@ -170,7 +170,7 @@ tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm, return invalid_argument; } - error res; + wasi_nn_error res; tensor_dimensions *dimensions = NULL; if (success diff --git a/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h index f0930a883..80c22784e 100644 --- a/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h +++ b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h @@ -12,7 +12,7 @@ #include #include -#include "wasi_nn.h" +#include "wasi_nn_types.h" #include "logger.h" #include "bh_platform.h" @@ -47,18 +47,18 @@ typedef struct { } tensor_wasm; #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 -error +wasi_nn_error graph_builder_array_app_native(wasm_module_inst_t instance, graph_builder_wasm *builder_wasm, uint32_t size, graph_builder_array *builder_array); #else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ -error +wasi_nn_error graph_builder_array_app_native(wasm_module_inst_t instance, graph_builder_array_wasm *builder, graph_builder_array *builder_native); #endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ -error +wasi_nn_error tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor, tensor *input_tensor_native); diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn.c b/core/iwasm/libraries/wasi-nn/src/wasi_nn.c index 1fbb94428..6c97940a1 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn.c +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn.c @@ -11,7 +11,6 @@ #include #include -#include "wasi_nn.h" #include "wasi_nn_private.h" #include "wasi_nn_app_native.h" #include "wasi_nn_tensorflowlite.hpp" @@ -24,14 +23,15 @@ /* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */ -typedef error (*LOAD)(void *, graph_builder_array *, graph_encoding, - execution_target, graph *); -typedef error (*INIT_EXECUTION_CONTEXT)(void *, graph, - graph_execution_context *); -typedef error (*SET_INPUT)(void *, graph_execution_context, uint32_t, tensor *); -typedef error (*COMPUTE)(void *, graph_execution_context); -typedef error (*GET_OUTPUT)(void *, graph_execution_context, uint32_t, - tensor_data, uint32_t *); +typedef wasi_nn_error (*LOAD)(void *, graph_builder_array *, graph_encoding, + execution_target, graph *); +typedef wasi_nn_error (*INIT_EXECUTION_CONTEXT)(void *, graph, + graph_execution_context *); +typedef wasi_nn_error (*SET_INPUT)(void *, graph_execution_context, uint32_t, + tensor *); +typedef wasi_nn_error (*COMPUTE)(void *, graph_execution_context); +typedef wasi_nn_error (*GET_OUTPUT)(void *, graph_execution_context, uint32_t, + tensor_data, uint32_t *); typedef struct { LOAD load; @@ -177,7 +177,7 @@ is_encoding_implemented(graph_encoding encoding) && lookup[encoding].get_output; } -static error +static wasi_nn_error is_model_initialized(WASINNContext *wasi_nn_ctx) { if (!wasi_nn_ctx->is_model_loaded) { @@ -190,12 +190,12 @@ is_model_initialized(WASINNContext *wasi_nn_ctx) /* WASI-NN implementation */ #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 -error +wasi_nn_error wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_wasm *builder, uint32_t builder_wasm_size, graph_encoding encoding, execution_target target, graph *g) #else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ -error +wasi_nn_error wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder, graph_encoding encoding, execution_target target, graph *g) #endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */ @@ -211,7 +211,7 @@ wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder, wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env); bh_assert(instance); - error res; + wasi_nn_error res; graph_builder_array builder_native = { 0 }; #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 if (success @@ -249,7 +249,7 @@ fail: return res; } -error +wasi_nn_error wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g, graph_execution_context *ctx) { @@ -259,7 +259,7 @@ wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g, bh_assert(instance); WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); - error res; + wasi_nn_error res; if (success != (res = is_model_initialized(wasi_nn_ctx))) return res; @@ -278,7 +278,7 @@ wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g, return res; } -error +wasi_nn_error wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx, uint32_t index, tensor_wasm *input_tensor) { @@ -289,7 +289,7 @@ wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx, bh_assert(instance); WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); - error res; + wasi_nn_error res; if (success != (res = is_model_initialized(wasi_nn_ctx))) return res; @@ -310,7 +310,7 @@ wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx, return res; } -error +wasi_nn_error wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx) { NN_DBG_PRINTF("Running wasi_nn_compute [ctx=%d]...", ctx); @@ -319,7 +319,7 @@ wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx) bh_assert(instance); WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); - error res; + wasi_nn_error res; if (success != (res = is_model_initialized(wasi_nn_ctx))) return res; @@ -330,12 +330,12 @@ wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx) } #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 -error +wasi_nn_error wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx, uint32_t index, tensor_data output_tensor, uint32_t output_tensor_len, uint32_t *output_tensor_size) #else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ -error +wasi_nn_error wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx, uint32_t index, tensor_data output_tensor, uint32_t *output_tensor_size) @@ -348,7 +348,7 @@ wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx, bh_assert(instance); WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); - error res; + wasi_nn_error res; if (success != (res = is_model_initialized(wasi_nn_ctx))) return res; diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp index 65e38f867..08c44bb5d 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wasi_nn.h" +#include "wasi_nn_types.h" #include "wasi_nn_tensorflowlite.hpp" #include "logger.h" @@ -50,7 +50,7 @@ typedef struct { /* Utils */ -static error +static wasi_nn_error initialize_g(TFLiteContext *tfl_ctx, graph *g) { os_mutex_lock(&tfl_ctx->g_lock); @@ -63,7 +63,7 @@ initialize_g(TFLiteContext *tfl_ctx, graph *g) os_mutex_unlock(&tfl_ctx->g_lock); return success; } -static error +static wasi_nn_error initialize_graph_ctx(TFLiteContext *tfl_ctx, graph g, graph_execution_context *ctx) { @@ -78,7 +78,7 @@ initialize_graph_ctx(TFLiteContext *tfl_ctx, graph g, return success; } -static error +static wasi_nn_error is_valid_graph(TFLiteContext *tfl_ctx, graph g) { if (g >= MAX_GRAPHS_PER_INST) { @@ -96,7 +96,7 @@ is_valid_graph(TFLiteContext *tfl_ctx, graph g) return success; } -static error +static wasi_nn_error is_valid_graph_execution_context(TFLiteContext *tfl_ctx, graph_execution_context ctx) { @@ -114,7 +114,7 @@ is_valid_graph_execution_context(TFLiteContext *tfl_ctx, /* WASI-NN (tensorflow) implementation */ -error +wasi_nn_error tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder, graph_encoding encoding, execution_target target, graph *g) { @@ -135,7 +135,7 @@ tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder, return invalid_argument; } - error res; + wasi_nn_error res; if (success != (res = initialize_g(tfl_ctx, g))) return res; @@ -168,13 +168,13 @@ tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder, return success; } -error +wasi_nn_error tensorflowlite_init_execution_context(void *tflite_ctx, graph g, graph_execution_context *ctx) { TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; - error res; + wasi_nn_error res; if (success != (res = is_valid_graph(tfl_ctx, g))) return res; @@ -257,13 +257,13 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g, return success; } -error +wasi_nn_error tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx, uint32_t index, tensor *input_tensor) { TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; - error res; + wasi_nn_error res; if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx))) return res; @@ -328,12 +328,12 @@ tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx, return success; } -error +wasi_nn_error tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx) { TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; - error res; + wasi_nn_error res; if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx))) return res; @@ -341,14 +341,14 @@ tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx) return success; } -error +wasi_nn_error tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx, uint32_t index, tensor_data output_tensor, uint32_t *output_tensor_size) { TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx; - error res; + wasi_nn_error res; if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx))) return res; @@ -472,6 +472,8 @@ tensorflowlite_destroy(void *tflite_ctx) #endif break; } + default: + break; } } wasm_runtime_free(tfl_ctx->models[i].model_pointer); diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp index 9605420dd..6eea38be9 100644 --- a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp @@ -6,28 +6,28 @@ #ifndef WASI_NN_TENSORFLOWLITE_HPP #define WASI_NN_TENSORFLOWLITE_HPP -#include "wasi_nn.h" +#include "wasi_nn_types.h" #ifdef __cplusplus extern "C" { #endif -error +wasi_nn_error tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder, graph_encoding encoding, execution_target target, graph *g); -error +wasi_nn_error tensorflowlite_init_execution_context(void *tflite_ctx, graph g, graph_execution_context *ctx); -error +wasi_nn_error tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx, uint32_t index, tensor *input_tensor); -error +wasi_nn_error tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx); -error +wasi_nn_error tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx, uint32_t index, tensor_data output_tensor, uint32_t *output_tensor_size); diff --git a/core/iwasm/libraries/wasi-nn/test/utils.c b/core/iwasm/libraries/wasi-nn/test/utils.c index 7b4f65d16..f19ec0f8e 100644 --- a/core/iwasm/libraries/wasi-nn/test/utils.c +++ b/core/iwasm/libraries/wasi-nn/test/utils.c @@ -9,7 +9,7 @@ #include #include -error +wasi_nn_error wasm_load(char *model_name, graph *g, execution_target target) { FILE *pFile = fopen(model_name, "r"); @@ -46,7 +46,7 @@ wasm_load(char *model_name, graph *g, execution_target target) arr.buf[0].size = result; arr.buf[0].buf = buffer; - error res = load(&arr, tensorflowlite, target, g); + wasi_nn_error res = load(&arr, tensorflowlite, target, g); fclose(pFile); free(buffer); @@ -54,13 +54,13 @@ wasm_load(char *model_name, graph *g, execution_target target) return res; } -error +wasi_nn_error wasm_init_execution_context(graph g, graph_execution_context *ctx) { return init_execution_context(g, ctx); } -error +wasi_nn_error wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim) { tensor_dimensions dims; @@ -75,19 +75,19 @@ wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim) tensor.dimensions->buf[i] = dim[i]; tensor.type = fp32; tensor.data = (uint8_t *)input_tensor; - error err = set_input(ctx, 0, &tensor); + wasi_nn_error err = set_input(ctx, 0, &tensor); free(dims.buf); return err; } -error +wasi_nn_error wasm_compute(graph_execution_context ctx) { return compute(ctx); } -error +wasi_nn_error wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor, uint32_t *out_size) { diff --git a/core/iwasm/libraries/wasi-nn/test/utils.h b/core/iwasm/libraries/wasi-nn/test/utils.h index 0b2328406..8b139a9b1 100644 --- a/core/iwasm/libraries/wasi-nn/test/utils.h +++ b/core/iwasm/libraries/wasi-nn/test/utils.h @@ -23,19 +23,19 @@ typedef struct { /* wasi-nn wrappers */ -error +wasi_nn_error wasm_load(char *model_name, graph *g, execution_target target); -error +wasi_nn_error wasm_init_execution_context(graph g, graph_execution_context *ctx); -error +wasi_nn_error wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim); -error +wasi_nn_error wasm_compute(graph_execution_context ctx); -error +wasi_nn_error wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor, uint32_t *out_size);