diff --git a/.github/workflows/build_llvm_libraries.yml b/.github/workflows/build_llvm_libraries.yml index bdfd4fcb2c..e4b7732bc3 100644 --- a/.github/workflows/build_llvm_libraries.yml +++ b/.github/workflows/build_llvm_libraries.yml @@ -65,6 +65,7 @@ jobs: shell: bash run: | echo "last_commit=$(GH_TOKEN=${{ secrets.GITHUB_TOKEN }} /usr/bin/env python3 ./build_llvm.py ${{ inputs.extra_build_llvm_options }} --llvm-ver)" >> $GITHUB_OUTPUT + working-directory: build-scripts # Bump the prefix number to evict all previous caches and # enforce a clean build, in the unlikely case that some diff --git a/.github/workflows/check_version_h.yml b/.github/workflows/check_version_h.yml new file mode 100644 index 0000000000..ab23ecf9ed --- /dev/null +++ b/.github/workflows/check_version_h.yml @@ -0,0 +1,29 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +name: confirm version.h stay in sync + +on: + workflow_call: + +permissions: + contents: read + +jobs: + confirm_version: + runs-on: ubuntu-latest + + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: cmake execute to generate version.h + run: cmake -B build_version -S . + + - name: confirm version.h + run: | + if [ -z "$(git status --porcelain | grep version.h)" ]; then + echo "version.h is in sync" + else + echo "version.h is not in sync" + exit 1 + fi diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c71f305aae..0c3a2ad15c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -53,7 +53,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3.27.4 + uses: github/codeql-action/init@v3.28.9 with: languages: ${{ matrix.language }} @@ -70,7 +70,7 @@ jobs: - run: | ./.github/scripts/codeql_buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3.27.4 + uses: github/codeql-action/analyze@v3.28.9 with: category: "/language:${{matrix.language}}" upload: false @@ -99,14 +99,14 @@ jobs: output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif - name: Upload CodeQL results to code scanning - uses: github/codeql-action/upload-sarif@v3.27.4 + uses: github/codeql-action/upload-sarif@v3.28.9 with: sarif_file: ${{ steps.step1.outputs.sarif-output }} category: "/language:${{matrix.language}}" - name: Upload CodeQL results as an artifact if: success() || failure() - uses: actions/upload-artifact@v4.4.3 + uses: actions/upload-artifact@v4.6.0 with: name: codeql-results path: ${{ steps.step1.outputs.sarif-output }} diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index 1ea36418e5..057082ebc5 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -74,6 +74,12 @@ permissions: contents: read jobs: + check_version_h: + permissions: + contents: read + actions: write + uses: ./.github/workflows/check_version_h.yml + build_llvm_libraries_on_ubuntu_2204: permissions: contents: read @@ -156,6 +162,7 @@ jobs: "-DWAMR_DISABLE_HW_BOUND_CHECK=1", "-DWAMR_BUILD_MEMORY64=1", "-DWAMR_BUILD_MULTI_MEMORY=1", + "-DWAMR_BUILD_SHARED=1", ] os: [ubuntu-22.04] platform: [android, linux] @@ -253,6 +260,9 @@ jobs: platform: android - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS platform: android + # android does not support WAMR_BUILD_SHARED in its CMakeLists.txt. + - make_options_feature: "-DWAMR_BUILD_SHARED=1" + platform: android include: - os: ubuntu-22.04 llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} @@ -671,7 +681,7 @@ jobs: test_option: $MEMORY64_TEST_OPTIONS - running_mode: "multi-tier-jit" test_option: $MEMORY64_TEST_OPTIONS - # aot, fast-interp, fast-jit, llvm-jit, multi-tier-jit don't support Multi Memory + # aot, fast-interp, fast-jit, llvm-jit, multi-tier-jit don't support Multi Memory - running_mode: "aot" test_option: $MULTI_MEMORY_TEST_OPTIONS - running_mode: "fast-interp" @@ -813,7 +823,7 @@ jobs: - name: install dependencies run: | - rustup target add wasm32-wasi + rustup target add wasm32-wasip1 sudo apt update && sudo apt-get install -y lld ninja-build npm install working-directory: test-tools/wamr-ide/VSCode-Extension diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index 5e9b4a4f29..dacdbc42d7 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -142,6 +142,7 @@ jobs: "-DWAMR_DISABLE_HW_BOUND_CHECK=1", "-DWAMR_BUILD_MEMORY64=1", "-DWAMR_BUILD_MULTI_MEMORY=1", + "-DWAMR_BUILD_SHARED=1", ] os: [ubuntu-20.04] platform: [android, linux] diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 31427d43fc..8138a86127 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -127,7 +127,8 @@ jobs: wamr_feature_option: # Empty option for default - { option: "", mode: "" } - - { option: "CONFIG_INTERPRETERS_WAMR_GC CONFIG_INTERPRETERS_WAMR_AOT_STACK_FRAME", mode: "-G" } + # need to install menhir + # - { option: "CONFIG_INTERPRETERS_WAMR_GC CONFIG_INTERPRETERS_WAMR_AOT_STACK_FRAME", mode: "-G" } exclude: # XIP is not fully supported yet on RISCV64, some relocations can not be resolved @@ -208,7 +209,7 @@ jobs: if: contains(matrix.wamr_test_option.mode, 'aot') working-directory: apps/interpreters/wamr/wamr/wamr-compiler run: | - cmake -Bbuild . + cmake -B build -DWAMR_BUILD_SHRUNK_MEMORY=0 -S . cmake --build build # the nuttx version we use for xtensa requires esptool.py newer than @@ -350,7 +351,7 @@ jobs: - name: upload the log if: always() - uses: actions/upload-artifact@v4.4.3 + uses: actions/upload-artifact@v4.6.0 with: name: spec-test-log-${{ github.run_id }}-${{ strategy.job-index }}-${{ matrix.target_config.target }} path: log diff --git a/.github/workflows/supply_chain.yml b/.github/workflows/supply_chain.yml index 1d5baa6b14..f373e1b0ba 100644 --- a/.github/workflows/supply_chain.yml +++ b/.github/workflows/supply_chain.yml @@ -52,7 +52,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@184d73b71b93c222403b2e7f1ffebe4508014249 # v3.1.0 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v3.1.0 with: name: SARIF file path: results.sarif @@ -60,6 +60,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@a1695c562bbfa68dc5ab58c9b5e9f616b52bf5be # v2.2.4 + uses: github/codeql-action/upload-sarif@0a35e8f6866a39b001e5f7ad1d0daf9836786896 # v2.2.4 with: sarif_file: results.sarif diff --git a/CMakeLists.txt b/CMakeLists.txt index 40658e9ac7..e52c86cf27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,12 +3,16 @@ cmake_minimum_required (VERSION 3.0) +option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) + if(ESP_PLATFORM) include (${COMPONENT_DIR}/build-scripts/esp-idf/wamr/CMakeLists.txt) return() endif() -project (iwasm) +project (iwasm LANGUAGES C) + +set(CMAKE_CXX_STANDARD 17) set (CMAKE_VERBOSE_MAKEFILE OFF) @@ -16,13 +20,6 @@ if (NOT DEFINED WAMR_BUILD_PLATFORM) string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) endif () -if (NOT DEFINED WAMR_BUILD_STATIC) - set (WAMR_BUILD_STATIC 1) -endif () -if (NOT DEFINED WAMR_BUILD_SHARED) - set (WAMR_BUILD_SHARED 1) -endif () - # Reset default linker flags set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") @@ -113,8 +110,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 types by default + set (WAMR_BUILD_REF_TYPES 1) endif () set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) @@ -154,52 +151,40 @@ if (MSVC) add_definitions(-DCOMPILING_WASM_RUNTIME_API=1) endif () -# STATIC LIBRARY -if (WAMR_BUILD_STATIC) - add_library(iwasm_static STATIC ${WAMR_RUNTIME_LIB_SOURCE}) - set_target_properties (iwasm_static PROPERTIES OUTPUT_NAME vmlib) - target_include_directories(iwasm_static INTERFACE ${WAMR_ROOT_DIR}/core/iwasm/include) - target_link_libraries (iwasm_static INTERFACE ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl ${CMAKE_THREAD_LIBS_INIT}) - if (WAMR_BUILD_WASM_CACHE EQUAL 1) - target_link_libraries(iwasm_static INTERFACE boringssl_crypto) - endif () +add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +set_target_properties (vmlib PROPERTIES OUTPUT_NAME iwasm) +target_include_directories(vmlib INTERFACE + $ + $ +) - if (MINGW) - target_link_libraries (iwasm_static PRIVATE ws2_32) - endif () - - if (WIN32) - target_link_libraries(iwasm_static PRIVATE ntdll) - endif() +target_link_libraries (vmlib PUBLIC ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl ${CMAKE_THREAD_LIBS_INIT}) +if (WAMR_BUILD_WASM_CACHE EQUAL 1) + target_link_libraries(vmlib INTERFACE boringssl_crypto) +endif () - install (TARGETS iwasm_static ARCHIVE DESTINATION lib) +if (MINGW) + target_link_libraries(vmlib INTERFACE -lWs2_32 -lwsock32) + target_link_libraries(vmlib PRIVATE ws2_32) endif () -# SHARED LIBRARY -if (WAMR_BUILD_SHARED) - add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE}) - set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm) - target_include_directories(iwasm_shared INTERFACE ${WAMR_ROOT_DIR}/core/iwasm/include) - target_link_libraries (iwasm_shared INTERFACE ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl ${CMAKE_THREAD_LIBS_INIT}) - if (WAMR_BUILD_WASM_CACHE EQUAL 1) - target_link_libraries(iwasm_shared INTERFACE boringssl_crypto) - endif () +if (WIN32) + target_link_libraries(vmlib PRIVATE ntdll) +endif() - if (MINGW) - target_link_libraries(iwasm_shared INTERFACE -lWs2_32 -lwsock32) - target_link_libraries(iwasm_shared PRIVATE ws2_32) - endif () +set (WAMR_PUBLIC_HEADERS + ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_c_api.h + ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h + ${WAMR_ROOT_DIR}/core/iwasm/include/lib_export.h +) +set_target_properties (vmlib PROPERTIES PUBLIC_HEADER "${WAMR_PUBLIC_HEADERS}") - if (WIN32) - target_link_libraries(iwasm_shared PRIVATE ntdll) - endif() +set_version_info (vmlib) - install (TARGETS iwasm_shared LIBRARY DESTINATION lib) -endif () +install (TARGETS vmlib + EXPORT iwasmTargets + LIBRARY DESTINATION lib + PUBLIC_HEADER DESTINATION include/iwasm +) -# HEADERS -install (FILES - ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_c_api.h - ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h - ${WAMR_ROOT_DIR}/core/iwasm/include/lib_export.h - DESTINATION include) +install_iwasm_package () diff --git a/CODEOWNERS b/CODEOWNERS index d8ec4c1b38..990dcfce2c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -22,7 +22,7 @@ # If none of the later patterns match, assign to anyone. This team is the # parent of all the other teams and automatically includes everyone on those # teams. -* @loganek @lum1n0us @no1wudi @wenyongh @xujuntwt95329 @yamt +* @loganek @lum1n0us @no1wudi @TianlongLiang @wenyongh @xujuntwt95329 @yamt # Some parts of the project require more specialized knowledge. In those areas # we designate smaller groups who are more likely to be aware of who's working diff --git a/README.md b/README.md index d89d0cd17f..05368b9295 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,8 @@ The WAMR VMcore supports the following architectures: - XTENSA, MIPS, ARC The following platforms are supported, click each link below for how to build iwasm on that platform. Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform. -- [Linux](./product-mini/README.md#linux), [Linux SGX (Intel Software Guard Extension)](./doc/linux_sgx.md), [MacOS](./product-mini/README.md#macos), [Android](./product-mini/README.md#android), [Windows](./product-mini/README.md#windows), [Windows (MinGW)](./product-mini/README.md#mingw) -- [Zephyr](./product-mini/README.md#zephyr), [AliOS-Things](./product-mini/README.md#alios-things), [VxWorks](./product-mini/README.md#vxworks), [NuttX](./product-mini/README.md#nuttx), [RT-Thread](./product-mini/README.md#RT-Thread), [ESP-IDF](./product-mini/README.md#esp-idf) +- [Linux](./product-mini/README.md#linux), [Linux SGX (Intel Software Guard Extension)](./doc/linux_sgx.md), [MacOS](./product-mini/README.md#macos), [Android](./product-mini/README.md#android), [Windows](./product-mini/README.md#windows), [Windows (MinGW, MSVC)](./product-mini/README.md#mingw) +- [Zephyr](./product-mini/README.md#zephyr), [AliOS-Things](./product-mini/README.md#alios-things), [VxWorks](./product-mini/README.md#vxworks), [NuttX](./product-mini/README.md#nuttx), [RT-Thread](./product-mini/README.md#RT-Thread), [ESP-IDF(FreeRTOS)](./product-mini/README.md#esp-idf) ## Getting started diff --git a/build-scripts/build_llvm.py b/build-scripts/build_llvm.py index ec6bb39548..eb7b703323 100755 --- a/build-scripts/build_llvm.py +++ b/build-scripts/build_llvm.py @@ -105,12 +105,23 @@ def build_llvm(llvm_dir, platform, backends, projects, use_clang=False, extra_fl experimental_backends = ["ARC", "Xtensa"] normal_backends = [s for s in backends if s not in experimental_backends] + experimental_backends = ["ARC", "Xtensa"] + normal_backends = [s for s in backends if s not in experimental_backends] + LLVM_TARGETS_TO_BUILD = [ + '-DLLVM_TARGETS_TO_BUILD:STRING="' + ";".join(normal_backends) + '"' + if normal_backends '-DLLVM_TARGETS_TO_BUILD:STRING="' + ";".join(normal_backends) + '"' if normal_backends else '-DLLVM_TARGETS_TO_BUILD:STRING="AArch64;ARM;Mips;RISCV;X86"' ] + # if not on ARC platform, but want to add expeirmental backend ARC as target + if platform != "ARC" and "ARC" in backends: + LLVM_TARGETS_TO_BUILD.extend( + LLVM_EXTRA_COMPILE_OPTIONS["arc"] + ) + # if not on ARC platform, but want to add expeirmental backend ARC as target if platform != "ARC" and "ARC" in backends: LLVM_TARGETS_TO_BUILD.extend( @@ -217,11 +228,11 @@ def repackage_llvm_windows(llvm_dir): if not packs_path: raise Exception("Didn't find any LLVM-* package") return - + llvm_package_path = f"_CPack_Packages/win64/NSIS/{packs_path[0].name}" windows_package_dir = build_dir.joinpath(llvm_package_path).resolve() - # mv package dir outside of build + # mv package dir outside of build shutil.move(str(windows_package_dir), str(llvm_dir)) # rm -r build shutil.rmtree(str(build_dir)) @@ -231,7 +242,7 @@ def repackage_llvm_windows(llvm_dir): moved_package_dir = llvm_dir.joinpath(packs_path[0].name) for sub_dir in moved_package_dir.iterdir(): shutil.move(str(sub_dir), str(build_dir)) - moved_package_dir.rmdir() + moved_package_dir.rmdir() def main(): parser = argparse.ArgumentParser(description="build necessary LLVM libraries") @@ -256,6 +267,7 @@ def main(): "Xtensa", ], default=[], + default=[], help="identify LLVM supported backends, separate by space, like '--arch ARM Mips X86'", ) parser.add_argument( diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 48c5f7be4b..614830094a 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -131,6 +131,12 @@ else () unset (LLVM_AVAILABLE_LIBS) endif () +# Version +include (${WAMR_ROOT_DIR}/build-scripts/version.cmake) + +# Package +include (${WAMR_ROOT_DIR}/build-scripts/package.cmake) + # Sanitizers if (NOT DEFINED WAMR_BUILD_SANITIZER) @@ -162,16 +168,68 @@ if (WAMR_BUILD_LINUX_PERF EQUAL 1) endif () endif () +if (NOT DEFINED WAMR_BUILD_SHRUNK_MEMORY) + # Enable shrunk memory by default + set (WAMR_BUILD_SHRUNK_MEMORY 1) +endif () + +######################################## +# Default values +######################################## +if (NOT DEFINED WAMR_BUILD_BULK_MEMORY) + set (WAMR_BUILD_BULK_MEMORY 1) +endif () + +if (NOT DEFINED WAMR_BUILD_EXCE_HANDLING) + set (WAMR_BUILD_EXCE_HANDLING 0) +endif () + +if (NOT DEFINED WAMR_BUILD_GC) + set (WAMR_BUILD_GC 0) +endif () + +if (NOT DEFINED WAMR_BUILD_MEMORY64) + set (WAMR_BUILD_MEMORY64 0) +endif () + +if (NOT DEFINED WAMR_BUILD_MULTI_MEMORY) + set (WAMR_BUILD_MULTI_MEMORY 0) +endif () + +if (NOT DEFINED WAMR_BUILD_SHARED_MEMORY) + set(WAMR_BUILD_SHARED_MEMORY 0) +endif () + +if (NOT DEFINED WAMR_BUILD_STRINGREF) + set(WAMR_BUILD_STRINGREF 0) +endif () + +if (NOT DEFINED WAMR_BUILD_TAIL_CALL) + set (WAMR_BUILD_TAIL_CALL 0) +endif () + +######################################## +# Compilation options to marco ######################################## message ("-- Build Configurations:") message (" Build as target ${WAMR_BUILD_TARGET}") +message (" Build for platform ${WAMR_BUILD_PLATFORM}") message (" CMAKE_BUILD_TYPE " ${CMAKE_BUILD_TYPE}) +message (" BUILD_SHARED_LIBS " ${BUILD_SHARED_LIBS}) +################## running mode ################## if (WAMR_BUILD_INTERP EQUAL 1) message (" WAMR Interpreter enabled") else () message (" WAMR Interpreter disabled") endif () +if ((WAMR_BUILD_FAST_INTERP EQUAL 1) AND (WAMR_BUILD_INTERP EQUAL 1)) + add_definitions (-DWASM_ENABLE_FAST_INTERP=1) + message (" Fast interpreter enabled") +else () + add_definitions (-DWASM_ENABLE_FAST_INTERP=0) + message (" Fast interpreter disabled") +endif () if (WAMR_BUILD_AOT EQUAL 1) message (" WAMR AOT enabled") else () @@ -202,6 +260,16 @@ if (WAMR_BUILD_FAST_JIT EQUAL 1 AND WAMR_BUILD_JIT EQUAL 1 AND WAMR_BUILD_LAZY_JIT EQUAL 1) message (" Multi-tier JIT enabled") endif () +################## test modes ################## +if (WAMR_BUILD_SPEC_TEST EQUAL 1) + add_definitions (-DWASM_ENABLE_SPEC_TEST=1) + message (" spec test compatible mode is on") +endif () +if (WAMR_BUILD_WASI_TEST EQUAL 1) + add_definitions (-DWASM_ENABLE_WASI_TEST=1) + message (" wasi test compatible mode is on") +endif () +################## native ################## if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) message (" Libc builtin enabled") else () @@ -214,13 +282,25 @@ elseif (WAMR_BUILD_LIBC_WASI EQUAL 1) else () message (" Libc WASI disabled") endif () -if ((WAMR_BUILD_FAST_INTERP EQUAL 1) AND (WAMR_BUILD_INTERP EQUAL 1)) - add_definitions (-DWASM_ENABLE_FAST_INTERP=1) - message (" Fast interpreter enabled") -else () - add_definitions (-DWASM_ENABLE_FAST_INTERP=0) - message (" Fast interpreter disabled") +if (WAMR_BUILD_THREAD_MGR EQUAL 1) + message (" Thread manager enabled") +endif () +if (WAMR_BUILD_LIB_PTHREAD EQUAL 1) + message (" Lib pthread enabled") +endif () +if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1) + message (" Lib pthread semaphore enabled") +endif () +if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1) + message (" Lib wasi-threads enabled") endif () +if (WAMR_BUILD_LIBC_EMCC EQUAL 1) + message (" Libc emcc enabled") +endif () +if (WAMR_BUILD_LIB_RATS EQUAL 1) + message (" Lib rats enabled") +endif() +################## WAMR features ################## if (WAMR_BUILD_MULTI_MODULE EQUAL 1) add_definitions (-DWASM_ENABLE_MULTI_MODULE=1) message (" Multiple modules enabled") @@ -228,24 +308,10 @@ else () add_definitions (-DWASM_ENABLE_MULTI_MODULE=0) message (" Multiple modules disabled") endif () -if (WAMR_BUILD_SPEC_TEST EQUAL 1) - add_definitions (-DWASM_ENABLE_SPEC_TEST=1) - message (" spec test compatible mode is on") -endif () -if (WAMR_BUILD_WASI_TEST EQUAL 1) - add_definitions (-DWASM_ENABLE_WASI_TEST=1) - message (" wasi test compatible mode is on") -endif () -if (NOT DEFINED WAMR_BUILD_BULK_MEMORY) - # Enable bulk memory by default - set (WAMR_BUILD_BULK_MEMORY 1) -endif () if (WAMR_BUILD_BULK_MEMORY EQUAL 1) add_definitions (-DWASM_ENABLE_BULK_MEMORY=1) - message (" Bulk memory feature enabled") else () add_definitions (-DWASM_ENABLE_BULK_MEMORY=0) - message (" Bulk memory feature disabled") endif () if (WAMR_BUILD_SHARED_MEMORY EQUAL 1) add_definitions (-DWASM_ENABLE_SHARED_MEMORY=1) @@ -265,31 +331,11 @@ if (WAMR_BUILD_MEMORY64 EQUAL 1) endif() add_definitions (-DWASM_ENABLE_MEMORY64=1) set (WAMR_DISABLE_HW_BOUND_CHECK 1) - message (" Memory64 memory enabled") endif () if (WAMR_BUILD_MULTI_MEMORY EQUAL 1) add_definitions (-DWASM_ENABLE_MULTI_MEMORY=1) - message (" Multi memory enabled") set (WAMR_BUILD_DEBUG_INTERP 0) endif () -if (WAMR_BUILD_THREAD_MGR EQUAL 1) - message (" Thread manager enabled") -endif () -if (WAMR_BUILD_LIB_PTHREAD EQUAL 1) - message (" Lib pthread enabled") -endif () -if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1) - message (" Lib pthread semaphore enabled") -endif () -if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1) - message (" Lib wasi-threads enabled") -endif () -if (WAMR_BUILD_LIBC_EMCC EQUAL 1) - message (" Libc emcc enabled") -endif () -if (WAMR_BUILD_LIB_RATS EQUAL 1) - message (" Lib rats enabled") -endif() if (WAMR_BUILD_MINI_LOADER EQUAL 1) add_definitions (-DWASM_ENABLE_MINI_LOADER=1) message (" WASM mini loader enabled") @@ -319,7 +365,6 @@ endif () if (WAMR_BUILD_SIMD EQUAL 1) if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*") add_definitions (-DWASM_ENABLE_SIMD=1) - message (" SIMD enabled") else () message (" SIMD disabled due to not supported on target RISCV64") endif () @@ -349,16 +394,11 @@ if (WAMR_BUILD_DUMP_CALL_STACK EQUAL 1) endif () if (WAMR_BUILD_TAIL_CALL EQUAL 1) add_definitions (-DWASM_ENABLE_TAIL_CALL=1) - message (" Tail call enabled") endif () if (WAMR_BUILD_REF_TYPES EQUAL 1) add_definitions (-DWASM_ENABLE_REF_TYPES=1) - message (" Reference types enabled") -else () - message (" Reference types disabled") endif () if (WAMR_BUILD_GC EQUAL 1) - message (" GC enabled") if (WAMR_TEST_GC EQUAL 1) message(" GC testing enabled") endif() @@ -370,7 +410,6 @@ else () message (" GC performance profiling disabled") endif () if (WAMR_BUILD_STRINGREF EQUAL 1) - message (" Stringref enabled") if (NOT DEFINED WAMR_STRINGREF_IMPL_SOURCE) message (" Using WAMR builtin implementation for stringref") else () @@ -599,3 +638,47 @@ endif() if (NOT WAMR_BUILD_SANITIZER STREQUAL "") message (" Sanitizer ${WAMR_BUILD_SANITIZER} enabled") endif () +if (WAMR_BUILD_SHRUNK_MEMORY EQUAL 1) + add_definitions (-DWASM_ENABLE_SHRUNK_MEMORY=1) + message (" Shrunk memory enabled") +else () + add_definitions (-DWASM_ENABLE_SHRUNK_MEMORY=0) + message (" Shrunk memory disabled") +endif() +if (WAMR_BUILD_AOT_VALIDATOR EQUAL 1) + message (" AOT validator enabled") + add_definitions (-DWASM_ENABLE_AOT_VALIDATOR=1) +endif () + +######################################## +# Show Phase4 Wasm proposals status. +######################################## + +message ( +"-- About Wasm Proposals:\n" +" Always-on:\n" +" \"Extended Constant Expressions\"\n" +" \"Multi-value\"\n" +" \"Non-trapping float-to-int conversions\"\n" +" \"Sign-extension operators\"\n" +" \"WebAssembly C and C++ API\"\n" +" Configurable. 0 is OFF. 1 is ON:\n" +" \"Bulk Memory Operation\" via WAMR_BUILD_BULK_MEMORY: ${WAMR_BUILD_BULK_MEMORY}\n" +" \"Fixed-width SIMD\" via WAMR_BUILD_SIMD: ${WAMR_BUILD_SIMD}\n" +" \"Garbage collection\" via WAMR_BUILD_GC: ${WAMR_BUILD_GC}\n" +" \"Legacy Exception handling\" via WAMR_BUILD_EXCE_HANDLING: ${WAMR_BUILD_EXCE_HANDLING}\n" +" \"Memory64\" via WAMR_BUILD_MEMORY64: ${WAMR_BUILD_MEMORY64}\n" +" \"Multiple memories\" via WAMR_BUILD_MULTI_MEMORY: ${WAMR_BUILD_MULTI_MEMORY}\n" +" \"Reference Types\" via WAMR_BUILD_REF_TYPES: ${WAMR_BUILD_REF_TYPES}\n" +" \"Reference-Typed Strings\" via WAMR_BUILD_STRINGREF: ${WAMR_BUILD_STRINGREF}\n" +" \"Tail call\" via WAMR_BUILD_TAIL_CALL: ${WAMR_BUILD_TAIL_CALL}\n" +" \"Threads\" via WAMR_BUILD_SHARED_MEMORY: ${WAMR_BUILD_SHARED_MEMORY}\n" +" \"Typed Function References\" via WAMR_BUILD_GC: ${WAMR_BUILD_GC}\n" +" Unsupported (>= Phase4):\n" +" \"Branch Hinting\"\n" +" \"Custom Annotation Syntax in the Text Format\"\n" +" \"Exception handling\"\n" +" \"Import/Export of Mutable Globals\"\n" +" \"JS String Builtins\"\n" +" \"Relaxed SIMD\"\n" +) diff --git a/build-scripts/iwasmConfig.cmake.in b/build-scripts/iwasmConfig.cmake.in new file mode 100644 index 0000000000..05ec5a8cda --- /dev/null +++ b/build-scripts/iwasmConfig.cmake.in @@ -0,0 +1,6 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/iwasmTargets.cmake") diff --git a/build-scripts/package.cmake b/build-scripts/package.cmake new file mode 100644 index 0000000000..4ebb1d799e --- /dev/null +++ b/build-scripts/package.cmake @@ -0,0 +1,28 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +function(install_iwasm_package) + install (EXPORT iwasmTargets + FILE iwasmTargets.cmake + NAMESPACE iwasm:: + DESTINATION lib/cmake/iwasm + ) + + include (CMakePackageConfigHelpers) + configure_package_config_file (${CMAKE_CURRENT_FUNCTION_LIST_DIR}/iwasmConfig.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/iwasmConfig.cmake" + INSTALL_DESTINATION lib/cmake/iwasm + ) + + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/iwasmConfigVersion.cmake" + VERSION ${WAMR_VERSION_MAJOR}.${WAMR_VERSION_MINOR}.${WAMR_VERSION_PATCH} + COMPATIBILITY SameMajorVersion + ) + + install (FILES + "${CMAKE_CURRENT_BINARY_DIR}/iwasmConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/iwasmConfigVersion.cmake" + DESTINATION lib/cmake/iwasm + ) +endfunction() diff --git a/build-scripts/version.cmake b/build-scripts/version.cmake new file mode 100644 index 0000000000..04c4e1ccb0 --- /dev/null +++ b/build-scripts/version.cmake @@ -0,0 +1,28 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +if(NOT WAMR_ROOT_DIR) + # if from wamr-compiler + set(WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..) +endif() + +set(WAMR_VERSION_MAJOR 2) +set(WAMR_VERSION_MINOR 2) +set(WAMR_VERSION_PATCH 0) + +message("-- WAMR version: ${WAMR_VERSION_MAJOR}.${WAMR_VERSION_MINOR}.${WAMR_VERSION_PATCH}") + +# Configure the version header file +configure_file( + ${WAMR_ROOT_DIR}/core/version.h.in + ${WAMR_ROOT_DIR}/core/version.h +) + +# Set the library version and SOVERSION +function(set_version_info target) + set_target_properties(${target} + PROPERTIES + VERSION ${WAMR_VERSION_MAJOR}.${WAMR_VERSION_MINOR}.${WAMR_VERSION_PATCH} + SOVERSION ${WAMR_VERSION_MAJOR} +) +endfunction() diff --git a/core/config.h b/core/config.h index d8cc989ebc..f71828ab95 100644 --- a/core/config.h +++ b/core/config.h @@ -699,4 +699,12 @@ #define WASM_ENABLE_SHARED_HEAP 0 #endif +#ifndef WASM_ENABLE_SHRUNK_MEMORY +#define WASM_ENABLE_SHRUNK_MEMORY 1 +#endif + +#ifndef WASM_ENABLE_AOT_VALIDATOR +#define WASM_ENABLE_AOT_VALIDATOR 0 +#endif + #endif /* end of _CONFIG_H_ */ diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 47b42e3b24..1a8b61d89e 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -10,6 +10,9 @@ #include "../common/wasm_native.h" #include "../common/wasm_loader_common.h" #include "../compilation/aot.h" +#if WASM_ENABLE_AOT_VALIDATOR != 0 +#include "aot_validator.h" +#endif #if WASM_ENABLE_DEBUG_AOT != 0 #include "debug/elf_parser.h" @@ -975,13 +978,29 @@ destroy_import_memories(AOTImportMemory *import_memories) wasm_runtime_free(import_memories); } +/** + * Free memory initialization data segments. + * + * @param module the AOT module containing the data + * @param data_list array of memory initialization data segments to free + * @param count number of segments in the data_list array + */ + static void -destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count) +destroy_mem_init_data_list(AOTModule *module, AOTMemInitData **data_list, + uint32 count) { uint32 i; + /* Free each memory initialization data segment */ for (i = 0; i < count; i++) - if (data_list[i]) + if (data_list[i]) { + /* If the module owns the binary data, free the bytes buffer */ + if (module->is_binary_freeable && data_list[i]->bytes) + wasm_runtime_free(data_list[i]->bytes); + /* Free the data segment structure itself */ wasm_runtime_free(data_list[i]); + } + /* Free the array of data segment pointers */ wasm_runtime_free(data_list); } @@ -990,6 +1009,22 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, InitializerExpression *expr, char *error_buf, uint32 error_buf_size); +/** + * Load memory initialization data segments from the AOT module. + * + * This function reads memory initialization data segments from the buffer and + * creates AOTMemInitData structures for each segment. The data can either be + * cloned into new memory or referenced directly from the buffer. + * + * @param p_buf pointer to buffer containing memory init data + * @param buf_end end of buffer + * @param module the AOT module being loaded + * @param error_buf buffer for error messages + * @param error_buf_size size of error buffer + * + * @return true if successful, false if error occurred + */ + static bool load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, char *error_buf, @@ -1020,8 +1055,8 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, return false; } read_uint32(buf, buf_end, byte_count); - size = offsetof(AOTMemInitData, bytes) + (uint64)byte_count; - if (!(data_list[i] = loader_malloc(size, error_buf, error_buf_size))) { + if (!(data_list[i] = loader_malloc(sizeof(AOTMemInitData), error_buf, + error_buf_size))) { return false; } @@ -1033,8 +1068,22 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, data_list[i]->offset.init_expr_type = init_value.init_expr_type; data_list[i]->offset.u = init_value.u; data_list[i]->byte_count = byte_count; - read_byte_array(buf, buf_end, data_list[i]->bytes, - data_list[i]->byte_count); + data_list[i]->bytes = NULL; + /* If the module owns the binary data, clone the bytes buffer */ + if (module->is_binary_freeable) { + if (byte_count > 0) { + if (!(data_list[i]->bytes = loader_malloc(byte_count, error_buf, + error_buf_size))) { + return false; + } + read_byte_array(buf, buf_end, data_list[i]->bytes, + data_list[i]->byte_count); + } + } + else { + data_list[i]->bytes = (uint8 *)buf; + buf += byte_count; + } } *p_buf = buf; @@ -1043,6 +1092,21 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, return false; } +/** + * Load memory information from the AOT module. + * + * This function reads memory-related data including import memory count, + * memory count, memory flags, page sizes, and memory initialization data. + * + * @param p_buf pointer to buffer containing memory info + * @param buf_end end of buffer + * @param module the AOT module being loaded + * @param error_buf buffer for error messages + * @param error_buf_size size of error buffer + * + * @return true if successful, false if error occurred + */ + static bool load_import_memory_list(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, bool is_load_from_file_buf, @@ -1256,6 +1320,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, } free_if_fail = true; init_values->count = field_count; + init_values->type_idx = type_idx; expr->u.data = init_values; if (type_idx >= module->type_count) { @@ -1562,7 +1627,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end, else #endif { - /* Skip 8 byte for ref type info */ + /* Skip 8 byte(2+2+4) for ref type info */ buf += 8; } @@ -4422,6 +4487,13 @@ aot_load_from_aot_file(const uint8 *buf, uint32 size, const LoadArgs *args, os_thread_jit_write_protect_np(true); /* Make memory executable */ os_icache_flush(module->code, module->code_size); +#if WASM_ENABLE_AOT_VALIDATOR != 0 + if (!aot_module_validate(module, error_buf, error_buf_size)) { + aot_unload(module); + return NULL; + } +#endif /* WASM_ENABLE_AOT_VALIDATOR != 0 */ + LOG_VERBOSE("Load module success.\n"); return module; } @@ -4436,7 +4508,7 @@ aot_unload(AOTModule *module) wasm_runtime_free(module->memories); if (module->mem_init_data_list) - destroy_mem_init_data_list(module->mem_init_data_list, + destroy_mem_init_data_list(module, module->mem_init_data_list, module->mem_init_data_count); if (module->native_symbol_list) diff --git a/core/iwasm/aot/aot_perf_map.c b/core/iwasm/aot/aot_perf_map.c index 22700dcdd6..b96bcd1bf4 100644 --- a/core/iwasm/aot/aot_perf_map.c +++ b/core/iwasm/aot/aot_perf_map.c @@ -7,7 +7,6 @@ #include "bh_log.h" #include "bh_platform.h" -#if WASM_ENABLE_LINUX_PERF != 0 struct func_info { uint32 idx; void *ptr; @@ -117,4 +116,3 @@ aot_create_perf_map(const AOTModule *module, char *error_buf, return ret; } -#endif /* WASM_ENABLE_LINUX_PERF != 0 */ \ No newline at end of file diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index e32fbbec9c..915adce2ee 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -2346,7 +2346,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, goto fail; } for (i = 0; i < module->table_init_data_count; i++) { - if (wasm_elem_is_active(module->table_init_data_list[i]->mode)) + if (wasm_elem_is_active(module->table_init_data_list[i]->mode) + || wasm_elem_is_declarative( + module->table_init_data_list[i]->mode)) bh_bitmap_set_bit(common->elem_dropped, i); } } @@ -3088,7 +3090,7 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, ret = invoke_native_internal(exec_env, func_ptr, func_type, NULL, attachment, argv, argc, argv); - if (aot_copy_exception(module_inst, NULL)) { + if (!ret) { #ifdef AOT_STACK_FRAME_DEBUG if (aot_stack_frame_callback) { aot_stack_frame_callback(exec_env); @@ -3109,7 +3111,7 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, aot_free_frame(exec_env); #endif - return ret && !aot_copy_exception(module_inst, NULL) ? true : false; + return ret; } } diff --git a/core/iwasm/aot/aot_validator.c b/core/iwasm/aot/aot_validator.c new file mode 100644 index 0000000000..58757f767f --- /dev/null +++ b/core/iwasm/aot/aot_validator.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2025 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_validator.h" + +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) { + snprintf(error_buf, error_buf_size, + "AOT module load failed: from validator. %s", string); + } +} + +static bool +aot_memory_info_validate(const AOTModule *module, char *error_buf, + uint32 error_buf_size) +{ + if (module->import_memory_count > 0) { + set_error_buf(error_buf, error_buf_size, + "import memory is not supported"); + return false; + } + + if (module->memory_count < 1) { + set_error_buf(error_buf, error_buf_size, + "there should be >=1 memory in one aot module"); + return false; + } + + return true; +} + +bool +aot_module_validate(const AOTModule *module, char *error_buf, + uint32 error_buf_size) +{ + if (!aot_memory_info_validate(module, error_buf, error_buf_size)) { + return false; + } + + return true; +} diff --git a/core/iwasm/aot/aot_validator.h b/core/iwasm/aot/aot_validator.h new file mode 100644 index 0000000000..dd8f0ecb5e --- /dev/null +++ b/core/iwasm/aot/aot_validator.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2025 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_VALIDATOR_H_ +#define _AOT_VALIDATOR_H_ + +#include "aot_runtime.h" + +bool +aot_module_validate(const AOTModule *module, char *error_buf, + uint32 error_buf_size); + +#endif /* _AOT_VALIDATOR_H_ */ diff --git a/core/iwasm/aot/iwasm_aot.cmake b/core/iwasm/aot/iwasm_aot.cmake index efff88dd07..c82501fad4 100644 --- a/core/iwasm/aot/iwasm_aot.cmake +++ b/core/iwasm/aot/iwasm_aot.cmake @@ -7,7 +7,19 @@ add_definitions (-DWASM_ENABLE_AOT=1) include_directories (${IWASM_AOT_DIR}) -file (GLOB c_source_all ${IWASM_AOT_DIR}/*.c) +list (APPEND c_source_all + ${IWASM_AOT_DIR}/aot_intrinsic.c + ${IWASM_AOT_DIR}/aot_loader.c + ${IWASM_AOT_DIR}/aot_runtime.c +) + +if (WAMR_BUILD_LINUX_PERF EQUAL 1) + list (APPEND c_source_all ${IWASM_AOT_DIR}/aot_perf_map.c) +endif () + +if (WAMR_BUILD_AOT_VALIDATOR EQUAL 1) + list (APPEND c_source_all ${IWASM_AOT_DIR}/aot_validator.c) +endif () if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_64.c) diff --git a/core/iwasm/common/SConscript b/core/iwasm/common/SConscript index 0a55f244b9..eb69744e90 100644 --- a/core/iwasm/common/SConscript +++ b/core/iwasm/common/SConscript @@ -13,13 +13,10 @@ cwd = GetCurrentDir() src = Glob('*.c') -if rtconfig.ARCH == 'arm': - if re.match('^cortex-m.*', rtconfig.CPU): - src += ['arch/invokeNative_thumb.s'] - elif re.match('^cortex-a.*', rtconfig.CPU): - src += ['arch/invokeNative_arm.s'] -elif rtconfig.ARCH == 'ia32': - src += ['arch/invokeNative_ia32.s'] +if rtconfig.ARCH == 'arm' and re.match('^cortex-m.*', rtconfig.CPU): + src += ['arch/invokeNative_thumb.s'] +else: + src.append(f"arch/invokeNative_{rtconfig.ARCH}.s") CPPPATH = [cwd, cwd + '/../include'] diff --git a/core/iwasm/common/gc/gc_type.c b/core/iwasm/common/gc/gc_type.c index c9e6d206e1..bafa3c86c8 100644 --- a/core/iwasm/common/gc/gc_type.c +++ b/core/iwasm/common/gc/gc_type.c @@ -1145,6 +1145,14 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1, return true; else { int32 heap_type = ref_type1->ref_ht_common.heap_type; + // We dont care whether type2 is nullable or not. So + // we normalize it into its related one-byte type. + if (type2 == REF_TYPE_HT_NULLABLE + || type2 == REF_TYPE_HT_NON_NULLABLE) { + bh_assert(ref_type2); + type2 = (uint8)(ref_type2->ref_ht_common.heap_type + + REF_TYPE_FUNCREF - HEAP_TYPE_FUNC); + } if (heap_type == HEAP_TYPE_ANY) { /* (ref any) <: anyref */ return type2 == REF_TYPE_ANYREF ? true : false; @@ -1188,19 +1196,15 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1, } #endif else if (heap_type == HEAP_TYPE_NONE) { - /* (ref none) */ - /* TODO */ - bh_assert(0); + return wasm_is_reftype_supers_of_none(type2, NULL, types, + type_count); } else if (heap_type == HEAP_TYPE_NOEXTERN) { - /* (ref noextern) */ - /* TODO */ - bh_assert(0); + return wasm_is_reftype_supers_of_noextern(type2); } else if (heap_type == HEAP_TYPE_NOFUNC) { - /* (ref nofunc) */ - /* TODO */ - bh_assert(0); + return wasm_is_reftype_supers_of_nofunc(type2, NULL, types, + type_count); } else { bh_assert(0); diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index dbb167fbe3..c87bc15491 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -3311,6 +3311,7 @@ argv_to_results(const uint32 *argv, const wasm_valtype_vec_t *result_defs, break; #if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0 case WASM_EXTERNREF: + case WASM_FUNCREF: result->of.ref = (struct wasm_ref_t *)(*(uintptr_t *)argv); argv += sizeof(uintptr_t) / sizeof(uint32); break; @@ -3422,6 +3423,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params, if (result_count) { if (!argv_to_results(argv, wasm_functype_results(func->type), results)) { + wasm_runtime_set_exception(func->inst_comm_rt, + "argv_to_results failed"); goto failed; } results->num_elems = result_count; diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 44f99e9c44..234df6e792 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -1367,7 +1367,7 @@ wasm_enlarge_memory_internal(WASMModuleInstanceCommon *module, if (!(memory_data_new = realloc_func(Alloc_For_LinearMemory, full_size_mmaped, #if WASM_MEM_ALLOC_WITH_USER_DATA != 0 - NULL, + allocator_user_data, #endif memory_data_old, total_size_new))) { ret = false; @@ -1389,7 +1389,7 @@ wasm_enlarge_memory_internal(WASMModuleInstanceCommon *module, if (full_size_mmaped) { #ifdef BH_PLATFORM_WINDOWS if (!os_mem_commit(memory->memory_data_end, - (mem_offset_t)(total_size_new - total_size_old), + total_size_new - total_size_old, MMAP_PROT_READ | MMAP_PROT_WRITE)) { ret = false; goto return_func; @@ -1397,12 +1397,12 @@ wasm_enlarge_memory_internal(WASMModuleInstanceCommon *module, #endif if (os_mprotect(memory->memory_data_end, - (mem_offset_t)(total_size_new - total_size_old), + total_size_new - total_size_old, MMAP_PROT_READ | MMAP_PROT_WRITE) != 0) { #ifdef BH_PLATFORM_WINDOWS os_mem_decommit(memory->memory_data_end, - (mem_offset_t)(total_size_new - total_size_old)); + total_size_new - total_size_old); #endif ret = false; goto return_func; @@ -1725,7 +1725,7 @@ wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst) (void)map_size; free_func(Alloc_For_LinearMemory, #if WASM_MEM_ALLOC_WITH_USER_DATA != 0 - NULL, + allocator_user_data, #endif memory_inst->memory_data); #else @@ -1778,7 +1778,7 @@ wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory, (void)wasm_mmap_linear_memory; if (!(*data = malloc_func(Alloc_For_LinearMemory, #if WASM_MEM_ALLOC_WITH_USER_DATA != 0 - NULL, + allocator_user_data, #endif *memory_data_size))) { return BHT_ERROR; diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 2756db88d9..d31adb5d49 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -3037,9 +3037,9 @@ static const char *exception_msgs[] = { "wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */ "failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */ /* GC related exceptions */ - "null function object", /* EXCE_NULL_FUNC_OBJ */ - "null structure object", /* EXCE_NULL_STRUCT_OBJ */ - "null array reference", /* EXCE_NULL_ARRAY_OBJ */ + "null function reference", /* EXCE_NULL_FUNC_OBJ */ + "null structure reference", /* EXCE_NULL_STRUCT_OBJ */ + "null array reference", /* EXCE_NULL_ARRAY_OBJ */ "null i31 reference", /* EXCE_NULL_I31_OBJ */ "null reference", /* EXCE_NULL_REFERENCE */ "create rtt type failed", /* EXCE_FAILED_TO_CREATE_RTT_TYPE */ @@ -3047,7 +3047,7 @@ static const char *exception_msgs[] = { "create array object failed", /* EXCE_FAILED_TO_CREATE_ARRAY_OBJ */ "create externref object failed", /* EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ */ "cast failure", /* EXCE_CAST_FAILURE */ - "out of bounds array access", /* EXCE_ARRAY_IDX_OOB */ + "out of bounds array access", /* EXCE_ARRAY_IDX_OOB */ /* stringref related exceptions */ "create string object failed", /* EXCE_FAILED_TO_CREATE_STRING */ "create stringref failed", /* EXCE_FAILED_TO_CREATE_STRINGREF */ @@ -3654,8 +3654,14 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, bh_memcpy_s(mapping_copy, max_len, map_dir_list[i], (uint32)(strlen(map_dir_list[i]) + 1)); - map_mapped = strtok(mapping_copy, "::"); - map_host = strtok(NULL, "::"); + + const char *delim = "::"; + char *delim_pos = strstr(mapping_copy, delim); + if (delim_pos) { + *delim_pos = '\0'; + map_mapped = mapping_copy; + map_host = delim_pos + strlen(delim); + } if (!map_mapped || !map_host) { if (error_buf) @@ -4460,8 +4466,9 @@ wasm_func_type_get_param_valkind(WASMFuncType *const func_type, return WASM_V128; case VALUE_TYPE_FUNCREF: return WASM_FUNCREF; - case VALUE_TYPE_EXTERNREF: + return WASM_EXTERNREF; + case VALUE_TYPE_VOID: default: { diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c index d44aa9313c..98e2c99573 100644 --- a/core/iwasm/compilation/aot.c +++ b/core/iwasm/compilation/aot.c @@ -112,8 +112,11 @@ aot_destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count) { uint32 i; for (i = 0; i < count; i++) - if (data_list[i]) + if (data_list[i]) { + if (data_list[i]->bytes) + wasm_runtime_free(data_list[i]->bytes); wasm_runtime_free(data_list[i]); + } wasm_runtime_free(data_list); } @@ -136,8 +139,7 @@ aot_create_mem_init_data_list(const WASMModule *module) /* Create each memory data segment */ for (i = 0; i < module->data_seg_count; i++) { - size = offsetof(AOTMemInitData, bytes) - + (uint64)module->data_segments[i]->data_length; + size = sizeof(AOTMemInitData); if (size >= UINT32_MAX || !(data_list[i] = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); @@ -145,18 +147,31 @@ aot_create_mem_init_data_list(const WASMModule *module) } #if WASM_ENABLE_BULK_MEMORY != 0 + /* Set bulk memory specific properties if enabled */ data_list[i]->is_passive = module->data_segments[i]->is_passive; data_list[i]->memory_index = module->data_segments[i]->memory_index; #endif data_list[i]->offset = module->data_segments[i]->base_offset; data_list[i]->byte_count = module->data_segments[i]->data_length; - memcpy(data_list[i]->bytes, module->data_segments[i]->data, - module->data_segments[i]->data_length); + data_list[i]->bytes = NULL; + /* Allocate memory for AOT compiler is OK, because the data segment + * is small and the host memory is enough */ + if (data_list[i]->byte_count > 0) { + data_list[i]->bytes = wasm_runtime_malloc(data_list[i]->byte_count); + if (!data_list[i]->bytes) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + /* Copy the actual data bytes from the WASM module */ + memcpy(data_list[i]->bytes, module->data_segments[i]->data, + module->data_segments[i]->data_length); + } } return data_list; fail: + /* Clean up allocated memory in case of failure */ aot_destroy_mem_init_data_list(data_list, module->data_seg_count); return NULL; } @@ -648,59 +663,70 @@ calculate_struct_field_sizes_offsets(AOTCompData *comp_data, bool is_target_x86, } #endif -AOTCompData * -aot_create_comp_data(WASMModule *module, const char *target_arch, - bool gc_enabled) +/** + * Checks if target architecture is 64-bit based on target_arch string. + * + * @param target_arch The target architecture string (e.g. "x86_64", "aarch64") + * @return true if target is 64-bit architecture, false otherwise + * + * If target_arch is NULL, detection is based on UINTPTR_MAX. + * Otherwise looks for "64" in target_arch string. + */ +static bool +arch_is_64bit(const char *target_arch) { - AOTCompData *comp_data; - uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0; - uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0; - bool is_64bit_target = false; -#if WASM_ENABLE_GC != 0 - bool is_target_x86 = false; -#endif - -#if WASM_ENABLE_GC != 0 if (!target_arch) { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ - || defined(BUILD_TARGET_X86_32) - is_target_x86 = true; +#if UINTPTR_MAX == UINT64_MAX + return true; +#else + return false; #endif } - else { - if (!strncmp(target_arch, "x86_64", 6) - || !strncmp(target_arch, "i386", 4)) - is_target_x86 = true; - } -#endif + /* All 64bit targets contains "64" string in their target name */ + return strstr(target_arch, "64") != NULL; +} +/** + * Checks if target architecture is x86/x64 based on target_arch string. + * + * @param target_arch The target architecture string (e.g. "x86_64", "i386") + * @return true if target is x86/x64 architecture, false otherwise + * + * If target_arch is NULL, detection is based on build-time definitions. + * Otherwise checks for x86_64 or i386 in target_arch string. + */ +static bool +arch_is_x86(const char *target_arch) +{ if (!target_arch) { -#if UINTPTR_MAX == UINT64_MAX - is_64bit_target = true; +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_X86_32) + return true; +#else + return false; #endif } - else { - /* All 64bit targets contains "64" string in their target name */ - if (strstr(target_arch, "64") != NULL) { - is_64bit_target = true; - } - } - - /* Allocate memory */ - if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) { - aot_set_last_error("create compile data failed.\n"); - return NULL; - } - - memset(comp_data, 0, sizeof(AOTCompData)); + return !strncmp(target_arch, "x86_64", 6) + || !strncmp(target_arch, "i386", 4); +} +/** + * Initialize memory information in AOT compilation data from WASM module. + * + * @param comp_data the AOT compilation data structure to initialize + * @param module the source WASM module containing memory information + * @return true if initialization succeeded, false otherwise + */ +static bool +aot_init_memories(AOTCompData *comp_data, WASMModule *module) +{ /* Create import memories */ comp_data->import_memory_count = module->import_memory_count; if (comp_data->import_memory_count) { comp_data->import_memories = aot_create_import_memories(module, comp_data->import_memory_count); if (!comp_data->import_memories) { - goto fail; + return false; } } @@ -715,7 +741,7 @@ aot_create_comp_data(WASMModule *module, const char *target_arch, comp_data->memories = aot_create_memories(module, comp_data->memory_count); if (!comp_data->memories) { - goto fail; + return false; } } @@ -724,19 +750,25 @@ aot_create_comp_data(WASMModule *module, const char *target_arch, comp_data->memories[0].num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; } - /* Create memory data segments */ - comp_data->mem_init_data_count = module->data_seg_count; - if (comp_data->mem_init_data_count > 0 - && !(comp_data->mem_init_data_list = - aot_create_mem_init_data_list(module))) - goto fail; + return true; +} +/** + * Initialize table information in AOT compilation data from WASM module. + * + * @param comp_data the AOT compilation data structure to initialize + * @param module the source WASM module containing table information + * @return true if initialization succeeded, false otherwise + */ +static bool +aot_init_tables(AOTCompData *comp_data, WASMModule *module) +{ /* Create import tables */ comp_data->import_table_count = module->import_table_count; if (comp_data->import_table_count > 0) { comp_data->import_tables = aot_create_import_tables(module); if (!comp_data->import_tables) { - goto fail; + return false; } } @@ -745,68 +777,154 @@ aot_create_comp_data(WASMModule *module, const char *target_arch, if (comp_data->table_count > 0) { comp_data->tables = aot_create_tables(module); if (!comp_data->tables) { - goto fail; + return false; } } - /* Create table data segments */ + return true; +} + +/** + * Initialize memory segment information in AOT compilation data. + * + * @param comp_data the AOT compilation data structure to initialize + * @param module the source WASM module containing memory segments + * @return true if initialization succeeded, false otherwise + */ +static bool +aot_init_memory_segments(AOTCompData *comp_data, WASMModule *module) +{ + comp_data->mem_init_data_count = module->data_seg_count; + if (comp_data->mem_init_data_count > 0 + && !(comp_data->mem_init_data_list = + aot_create_mem_init_data_list(module))) { + return false; + } + return true; +} + +/** + * Initialize table segment information in AOT compilation data. + * + * @param comp_data the AOT compilation data structure to initialize + * @param module the source WASM module containing table segments + * @return true if initialization succeeded, false otherwise + */ +static bool +aot_init_table_segments(AOTCompData *comp_data, WASMModule *module) +{ comp_data->table_init_data_count = module->table_seg_count; if (comp_data->table_init_data_count > 0 && !(comp_data->table_init_data_list = - aot_create_table_init_data_list(module))) - goto fail; + aot_create_table_init_data_list(module))) { + return false; + } + return true; +} - /* Create import globals */ +/** + * Initialize global variable information in AOT compilation data. + * + * @param comp_data the AOT compilation data structure to initialize + * @param module the source WASM module containing global information + * @param gc_enabled whether garbage collection is enabled + * @param import_global_data_size_64bit [out] size of imported global data for + * 64-bit + * @param import_global_data_size_32bit [out] size of imported global data for + * 32-bit + * @param global_data_size_64bit [out] size of global data for 64-bit + * @param global_data_size_32bit [out] size of global data for 32-bit + * @return true if initialization succeeded, false otherwise + */ +static bool +aot_init_globals(AOTCompData *comp_data, WASMModule *module, bool gc_enabled, + uint32 *import_global_data_size_64bit, + uint32 *import_global_data_size_32bit, + uint32 *global_data_size_64bit, uint32 *global_data_size_32bit) +{ comp_data->import_global_count = module->import_global_count; if (comp_data->import_global_count > 0 && !(comp_data->import_globals = aot_create_import_globals( - module, gc_enabled, &import_global_data_size_64bit, - &import_global_data_size_32bit))) - goto fail; + module, gc_enabled, import_global_data_size_64bit, + import_global_data_size_32bit))) { + return false; + } - /* Create globals */ comp_data->global_count = module->global_count; if (comp_data->global_count && !(comp_data->globals = aot_create_globals( - module, gc_enabled, import_global_data_size_64bit, - import_global_data_size_32bit, &global_data_size_64bit, - &global_data_size_32bit))) - goto fail; + module, gc_enabled, *import_global_data_size_64bit, + *import_global_data_size_32bit, global_data_size_64bit, + global_data_size_32bit))) { + return false; + } comp_data->global_data_size_64bit = - import_global_data_size_64bit + global_data_size_64bit; + *import_global_data_size_64bit + *global_data_size_64bit; comp_data->global_data_size_32bit = - import_global_data_size_32bit + global_data_size_32bit; + *import_global_data_size_32bit + *global_data_size_32bit; + + return true; +} - /* Create types, they are checked by wasm loader */ +/** + * Initialize type information in AOT compilation data. + * + * @param comp_data the AOT compilation data structure to initialize + * @param module the source WASM module containing type information + * @param is_target_x86 whether the target architecture is x86 + * @param gc_enabled whether garbage collection is enabled + * @return true if initialization succeeded, false otherwise + */ +static bool +aot_init_types(AOTCompData *comp_data, WASMModule *module, bool is_target_x86, + bool gc_enabled) +{ comp_data->type_count = module->type_count; comp_data->types = module->types; #if WASM_ENABLE_GC != 0 - /* Calculate the field sizes and field offsets for 64-bit and 32-bit - targets since they may vary in 32-bit target and 64-bit target */ calculate_struct_field_sizes_offsets(comp_data, is_target_x86, gc_enabled); #endif + return true; +} - /* Create import functions */ +/** + * Initialize function information in AOT compilation data. + * + * @param comp_data the AOT compilation data structure to initialize + * @param module the source WASM module containing function information + * @param is_64bit_target whether the target architecture is 64-bit + * @return true if initialization succeeded, false otherwise + */ +static bool +aot_init_functions(AOTCompData *comp_data, WASMModule *module, + bool is_64bit_target) +{ comp_data->import_func_count = module->import_function_count; if (comp_data->import_func_count - && !(comp_data->import_funcs = aot_create_import_funcs(module))) - goto fail; + && !(comp_data->import_funcs = aot_create_import_funcs(module))) { + return false; + } - /* Create functions */ comp_data->func_count = module->function_count; if (comp_data->func_count && !(comp_data->funcs = - aot_create_funcs(module, is_64bit_target ? 8 : 4))) - goto fail; + aot_create_funcs(module, is_64bit_target ? 8 : 4))) { + return false; + } -#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 - /* Create custom name section */ - comp_data->name_section_buf = module->name_section_buf; - comp_data->name_section_buf_end = module->name_section_buf_end; -#endif + return true; +} - /* Create aux data/heap/stack information */ +/** + * Initialize auxiliary data in AOT compilation data. + * + * @param comp_data the AOT compilation data structure to initialize + * @param module the source WASM module containing auxiliary data + */ +static void +aot_init_aux_data(AOTCompData *comp_data, WASMModule *module) +{ comp_data->aux_data_end_global_index = module->aux_data_end_global_index; comp_data->aux_data_end = module->aux_data_end; comp_data->aux_heap_base_global_index = module->aux_heap_base_global_index; @@ -825,6 +943,43 @@ aot_create_comp_data(WASMModule *module, const char *target_arch, comp_data->string_literal_ptrs_wp = module->string_literal_ptrs; comp_data->string_literal_lengths_wp = module->string_literal_lengths; #endif +} + +AOTCompData * +aot_create_comp_data(WASMModule *module, const char *target_arch, + bool gc_enabled) +{ + AOTCompData *comp_data; + uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0; + uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0; + bool is_64bit_target = arch_is_64bit(target_arch); + bool is_target_x86 = arch_is_x86(target_arch); + + if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) { + aot_set_last_error("create compile data failed.\n"); + return NULL; + } + memset(comp_data, 0, sizeof(AOTCompData)); + + if (!aot_init_memories(comp_data, module) + || !aot_init_memory_segments(comp_data, module) + || !aot_init_tables(comp_data, module) + || !aot_init_table_segments(comp_data, module) + || !aot_init_globals(comp_data, module, gc_enabled, + &import_global_data_size_64bit, + &import_global_data_size_32bit, + &global_data_size_64bit, &global_data_size_32bit) + || !aot_init_types(comp_data, module, is_target_x86, gc_enabled) + || !aot_init_functions(comp_data, module, is_64bit_target)) { + goto fail; + } + +#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 + comp_data->name_section_buf = module->name_section_buf; + comp_data->name_section_buf_end = module->name_section_buf_end; +#endif + + aot_init_aux_data(comp_data, module); comp_data->wasm_module = module; diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index 0d1a32d4dc..decc873b34 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -106,7 +106,7 @@ typedef struct AOTMemInitData { /* Byte count */ uint32 byte_count; /* Byte array */ - uint8 bytes[1]; + uint8 *bytes; } AOTMemInitData; /** diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 1d7f08652b..d0e6071f2c 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -1900,7 +1900,9 @@ aot_emit_memory_init_data_list(uint8 *buf, uint8 *buf_end, uint32 *p_offset, &init_datas[i]->offset)) return false; EMIT_U32(init_datas[i]->byte_count); - EMIT_BUF(init_datas[i]->bytes, init_datas[i]->byte_count); + if (init_datas[i]->byte_count) { + EMIT_BUF(init_datas[i]->bytes, init_datas[i]->byte_count); + } } if (offset - *p_offset diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index c2f190c867..5e7f0f0b12 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -1217,6 +1217,28 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); } + /* + * if (value_cmp > br_count) + * value_cmp = br_count; + */ + LLVMValueRef br_count_value = I32_CONST(br_count); + CHECK_LLVM_CONST(br_count_value); + + LLVMValueRef clap_value_cmp_cond = + LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, value_cmp, br_count_value, + "cmp_w_br_count"); + if (!clap_value_cmp_cond) { + aot_set_last_error("llvm build icmp failed."); + return false; + } + + value_cmp = LLVMBuildSelect(comp_ctx->builder, clap_value_cmp_cond, + br_count_value, value_cmp, "clap_value_cmp"); + if (!value_cmp) { + aot_set_last_error("llvm build select failed."); + return false; + } + if (!LLVMIsEfficientConstInt(value_cmp)) { if (comp_ctx->aot_frame) { if (comp_ctx->enable_gc diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index cf65033497..1d6c4d272c 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -1832,6 +1832,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, aot_set_last_error("llvm build load failed."); goto fail; } + LLVMSetAlignment(ext_ret, 4); PUSH(ext_ret, ext_ret_types[i]); } } @@ -2068,6 +2069,7 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, aot_set_last_error("llvm build load failed."); return false; } + LLVMSetAlignment(value_rets[i], 4); cell_num += wasm_value_type_cell_num_internal(wasm_ret_types[i], comp_ctx->pointer_size); } @@ -2690,6 +2692,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, aot_set_last_error("llvm build load failed."); goto fail; } + LLVMSetAlignment(ext_ret, 4); LLVMAddIncoming(result_phis[i], &ext_ret, &block_curr, 1); } } @@ -3121,6 +3124,7 @@ aot_compile_op_call_ref(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, aot_set_last_error("llvm build load failed."); goto fail; } + LLVMSetAlignment(ext_ret, 4); LLVMAddIncoming(result_phis[i], &ext_ret, &block_curr, 1); } } @@ -3196,6 +3200,7 @@ aot_compile_op_call_ref(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, aot_set_last_error("llvm build load failed."); goto fail; } + LLVMSetAlignment(ext_ret, 4); LLVMAddIncoming(result_phis[i], &ext_ret, &block_curr, 1); } } diff --git a/core/iwasm/compilation/aot_emit_memory.c b/core/iwasm/compilation/aot_emit_memory.c index 1c386746c3..fc35a8e74f 100644 --- a/core/iwasm/compilation/aot_emit_memory.c +++ b/core/iwasm/compilation/aot_emit_memory.c @@ -270,10 +270,24 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* offset1 = offset + addr; */ - /* TODO: check whether integer overflow occurs when memory is 64-bit - and boundary check is enabled */ BUILD_OP(Add, offset_const, addr, offset1, "offset1"); + if (is_memory64 && comp_ctx->enable_bound_check) { + /* Check whether integer overflow occurs in offset + addr */ + LLVMBasicBlockRef check_integer_overflow_end; + ADD_BASIC_BLOCK(check_integer_overflow_end, + "check_integer_overflow_end"); + LLVMMoveBasicBlockAfter(check_integer_overflow_end, block_curr); + + BUILD_ICMP(LLVMIntULT, offset1, offset_const, cmp1, "cmp1"); + if (!aot_emit_exception(comp_ctx, func_ctx, + EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp1, + check_integer_overflow_end)) { + goto fail; + } + SET_BUILD_POS(check_integer_overflow_end); + } + if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) { LLVMBasicBlockRef app_addr_in_shared_heap, app_addr_in_linear_mem; LLVMValueRef is_in_shared_heap, shared_heap_check_bound = NULL; @@ -300,7 +314,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); if (!is_target_64bit) { - /* Check whether interger overflow occurs in addr + offset */ + /* Check whether integer overflow occurs in addr + offset */ LLVMBasicBlockRef check_integer_overflow_end; ADD_BASIC_BLOCK(check_integer_overflow_end, "check_integer_overflow_end"); @@ -1209,10 +1223,24 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } - /* TODO: check whether integer overflow occurs when memory is 64-bit - and boundary check is enabled */ BUILD_OP(Add, offset, bytes, max_addr, "max_addr"); + if (is_memory64 && comp_ctx->enable_bound_check) { + /* Check whether integer overflow occurs in offset + addr */ + LLVMBasicBlockRef check_integer_overflow_end; + ADD_BASIC_BLOCK(check_integer_overflow_end, + "check_integer_overflow_end"); + LLVMMoveBasicBlockAfter(check_integer_overflow_end, block_curr); + + BUILD_ICMP(LLVMIntULT, max_addr, offset, cmp, "cmp"); + if (!aot_emit_exception(comp_ctx, func_ctx, + EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp, + check_integer_overflow_end)) { + goto fail; + } + SET_BUILD_POS(check_integer_overflow_end); + } + if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) { LLVMBasicBlockRef app_addr_in_shared_heap, app_addr_in_linear_mem; LLVMValueRef shared_heap_start_off, shared_heap_check_bound; diff --git a/core/iwasm/compilation/iwasm_compl.cmake b/core/iwasm/compilation/iwasm_compl.cmake index 4ec4603049..77925d62d8 100644 --- a/core/iwasm/compilation/iwasm_compl.cmake +++ b/core/iwasm/compilation/iwasm_compl.cmake @@ -1,6 +1,7 @@ set (IWASM_COMPL_DIR ${CMAKE_CURRENT_LIST_DIR}) include_directories(${IWASM_COMPL_DIR}) +enable_language(CXX) if (WAMR_BUILD_DEBUG_AOT EQUAL 1) file (GLOB_RECURSE source_all diff --git a/core/iwasm/fast-jit/iwasm_fast_jit.cmake b/core/iwasm/fast-jit/iwasm_fast_jit.cmake index cd880a34b2..c5012bd36c 100644 --- a/core/iwasm/fast-jit/iwasm_fast_jit.cmake +++ b/core/iwasm/fast-jit/iwasm_fast_jit.cmake @@ -9,6 +9,7 @@ if (WAMR_BUILD_FAST_JIT_DUMP EQUAL 1) endif () include_directories (${IWASM_FAST_JIT_DIR}) +enable_language(CXX) if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") include(FetchContent) diff --git a/core/iwasm/include/wasm_c_api.h b/core/iwasm/include/wasm_c_api.h index 1946fe1fce..4d68143ddd 100644 --- a/core/iwasm/include/wasm_c_api.h +++ b/core/iwasm/include/wasm_c_api.h @@ -46,7 +46,7 @@ extern "C" { // Auxiliaries // Machine types -#if (__STDC_VERSION__) > 199901L +#if defined(__STDC_VERSION__) && (__STDC_VERSION__) > 199901L inline void assertions(void) { static_assert(sizeof(float) == sizeof(uint32_t), "incompatible float type"); static_assert(sizeof(double) == sizeof(uint64_t), "incompatible double type"); diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 14e309111e..fefb1c80c3 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -23,6 +23,8 @@ #else #define WASM_RUNTIME_API_EXTERN __declspec(dllimport) #endif +#elif defined(__GNUC__) || defined(__clang__) +#define WASM_RUNTIME_API_EXTERN __attribute__((visibility("default"))) #else #define WASM_RUNTIME_API_EXTERN #endif diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index cb074e2e95..aed3e3fe1c 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -593,8 +593,8 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame) #endif #if WASM_ENABLE_MEMORY64 != 0 -#define POP_MEM_OFFSET() (is_memory64 ? POP_I64() : POP_I32()) -#define POP_TBL_ELEM_IDX() (is_table64 ? POP_I64() : POP_I32()) +#define POP_MEM_OFFSET() (is_memory64 ? POP_I64() : (uint32)POP_I32()) +#define POP_TBL_ELEM_IDX() (is_table64 ? POP_I64() : (uint32)POP_I32()) #else #define POP_MEM_OFFSET() POP_I32() #define POP_TBL_ELEM_IDX() POP_I32() @@ -2644,7 +2644,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, read_leb_uint32(frame_ip, frame_ip_end, type_index); func_obj = POP_REF(); if (!func_obj) { - wasm_set_exception(module, "null function object"); + wasm_set_exception(module, "null function reference"); goto got_exception; } @@ -2661,7 +2661,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, read_leb_uint32(frame_ip, frame_ip_end, type_index); func_obj = POP_REF(); if (!func_obj) { - wasm_set_exception(module, "null function object"); + wasm_set_exception(module, "null function reference"); goto got_exception; } @@ -2808,7 +2808,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, struct_obj = POP_REF(); if (!struct_obj) { - wasm_set_exception(module, "null structure object"); + wasm_set_exception(module, + "null structure reference"); goto got_exception; } @@ -2864,7 +2865,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, struct_obj = POP_REF(); if (!struct_obj) { - wasm_set_exception(module, "null structure object"); + wasm_set_exception(module, + "null structure reference"); goto got_exception; } diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 9b0492449e..3b896e7c3d 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1657,7 +1657,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, { uint32 ret_idx; WASMFuncType *func_type; - uint32 off, ret_offset; + int32 off; + uint32 ret_offset; uint8 *ret_types; if (cur_func->is_import_func) func_type = cur_func->u.func_import->func_type; @@ -1669,9 +1670,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, ret_offset = prev_frame->ret_offset; for (ret_idx = 0, - off = sizeof(int16) * (func_type->result_count - 1); + off = (int32)sizeof(int16) * (func_type->result_count - 1); ret_idx < func_type->result_count; - ret_idx++, off -= sizeof(int16)) { + ret_idx++, off -= (int32)sizeof(int16)) { if (ret_types[ret_idx] == VALUE_TYPE_I64 || ret_types[ret_idx] == VALUE_TYPE_F64) { PUT_I64_TO_ADDR(prev_frame->lp + ret_offset, @@ -1984,7 +1985,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #endif func_obj = POP_REF(); if (!func_obj) { - wasm_set_exception(module, "null function object"); + wasm_set_exception(module, "null function reference"); goto got_exception; } @@ -1999,7 +2000,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #endif func_obj = POP_REF(); if (!func_obj) { - wasm_set_exception(module, "null function object"); + wasm_set_exception(module, "null function reference"); goto got_exception; } @@ -2140,7 +2141,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, struct_obj = POP_REF(); if (!struct_obj) { - wasm_set_exception(module, "null structure object"); + wasm_set_exception(module, + "null structure reference"); goto got_exception; } @@ -2196,7 +2198,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, struct_obj = POP_REF(); if (!struct_obj) { - wasm_set_exception(module, "null structure object"); + wasm_set_exception(module, + "null structure reference"); goto got_exception; } diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index be14d27b31..09d9757d92 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -58,7 +58,9 @@ is_table_64bit(WASMModule *module, uint32 table_idx) return !!(module->import_tables[table_idx].u.table.table_type.flags & TABLE64_FLAG); else - return !!(module->tables[table_idx].table_type.flags & TABLE64_FLAG); + return !!(module->tables[table_idx - module->import_table_count] + .table_type.flags + & TABLE64_FLAG); return false; } @@ -195,7 +197,6 @@ check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length, res = (int32)res64; \ } while (0) -#define read_leb_memidx(p, p_end, res) read_leb_uint32(p, p_end, res) #if WASM_ENABLE_MULTI_MEMORY != 0 #define check_memidx(module, memidx) \ do { \ @@ -245,7 +246,7 @@ type2str(uint8 type) "", /* reserved */ "arrayref", "structref", - "i32ref", + "i31ref", "eqref", "anyref", "externref", @@ -354,9 +355,14 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf, { uint8 *mem_new; bh_assert(size_new > size_old); + + if ((mem_new = wasm_runtime_realloc(mem_old, size_new))) { + memset(mem_new + size_old, 0, size_new - size_old); + return mem_new; + } + if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) { bh_memcpy_s(mem_new, size_new, mem_old, size_old); - memset(mem_new + size_old, 0, size_new - size_old); wasm_runtime_free(mem_old); } return mem_new; @@ -2133,8 +2139,9 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (!wasm_type_is_subtype_of(cur_type, parent_type, module->types, module->type_count)) { - set_error_buf(error_buf, error_buf_size, - "sub type does not match super type"); + set_error_buf_v(error_buf, error_buf_size, + "sub type %u does not match super type", + processed_type_count + j); return false; } } @@ -4240,7 +4247,10 @@ check_table_index(const WASMModule *module, uint32 table_index, char *error_buf, { #if WASM_ENABLE_REF_TYPES == 0 && WASM_ENABLE_GC == 0 if (table_index != 0) { - set_error_buf(error_buf, error_buf_size, "zero byte expected"); + set_error_buf( + error_buf, error_buf_size, + "zero byte expected. The module uses reference types feature " + "which is disabled in the runtime."); return false; } #endif @@ -4285,7 +4295,8 @@ check_table_elem_type(WASMModule *module, uint32 table_index, module->import_tables[table_index].u.table.table_type.elem_type; else table_declared_elem_type = - (module->tables + table_index)->table_type.elem_type; + module->tables[table_index - module->import_table_count] + .table_type.elem_type; if (table_declared_elem_type == type_from_elem_seg) return true; @@ -4705,6 +4716,21 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, return false; } +#if WASM_ENABLE_BULK_MEMORY != 0 +static bool +check_data_count_consistency(bool has_datacount_section, int datacount_len, + int data_seg_len, char *error_buf, + uint32 error_buf_size) +{ + if (has_datacount_section && datacount_len != data_seg_len) { + set_error_buf(error_buf, error_buf_size, + "data count and data section have inconsistent lengths"); + return false; + } + return true; +} +#endif + static bool load_data_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, @@ -4728,9 +4754,9 @@ 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 (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"); + if (!check_data_count_consistency(has_datacount_section, + module->data_seg_count1, data_seg_count, + error_buf, error_buf_size)) { return false; } #endif @@ -5918,6 +5944,14 @@ load_from_sections(WASMModule *module, WASMSection *sections, section = section->next; } +#if WASM_ENABLE_BULK_MEMORY != 0 + if (!check_data_count_consistency( + has_datacount_section, module->data_seg_count1, + module->data_seg_count, error_buf, error_buf_size)) { + return false; + } +#endif + module->aux_data_end_global_index = (uint32)-1; module->aux_heap_base_global_index = (uint32)-1; module->aux_stack_top_global_index = (uint32)-1; @@ -5927,6 +5961,13 @@ load_from_sections(WASMModule *module, WASMSection *sections, for (i = 0; i < module->export_count; i++, export ++) { if (export->kind == EXPORT_KIND_GLOBAL) { if (!strcmp(export->name, "__heap_base")) { + if (export->index < module->import_global_count) { + LOG_DEBUG("Skip the process if __heap_base is imported " + "instead of being a local global"); + continue; + } + + /* only process linker-generated symbols */ global_index = export->index - module->import_global_count; global = module->globals + global_index; if (global->type.val_type == VALUE_TYPE_I32 @@ -5941,6 +5982,13 @@ load_from_sections(WASMModule *module, WASMSection *sections, } } else if (!strcmp(export->name, "__data_end")) { + if (export->index < module->import_global_count) { + LOG_DEBUG("Skip the process if __data_end is imported " + "instead of being a local global"); + continue; + } + + /* only process linker-generated symbols */ global_index = export->index - module->import_global_count; global = module->globals + global_index; if (global->type.val_type == VALUE_TYPE_I32 @@ -6139,9 +6187,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, } if (!module->possible_memory_grow) { - WASMMemoryImport *memory_import; - WASMMemory *memory; - +#if WASM_ENABLE_SHRUNK_MEMORY != 0 if (aux_data_end_global && aux_heap_base_global && aux_stack_top_global) { uint64 init_memory_size; @@ -6151,7 +6197,8 @@ load_from_sections(WASMModule *module, WASMSection *sections, * valid range of uint32 */ if (shrunk_memory_size <= UINT32_MAX) { if (module->import_memory_count) { - memory_import = &module->import_memories[0].u.memory; + WASMMemoryImport *memory_import = + &module->import_memories[0].u.memory; init_memory_size = (uint64)memory_import->mem_type.num_bytes_per_page * memory_import->mem_type.init_page_count; @@ -6166,7 +6213,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, } if (module->memory_count) { - memory = &module->memories[0]; + WASMMemory *memory = &module->memories[0]; init_memory_size = (uint64)memory->num_bytes_per_page * memory->init_page_count; if (shrunk_memory_size <= init_memory_size) { @@ -6179,10 +6226,12 @@ load_from_sections(WASMModule *module, WASMSection *sections, } } } +#endif /* WASM_ENABLE_SHRUNK_MEMORY != 0 */ #if WASM_ENABLE_MULTI_MODULE == 0 if (module->import_memory_count) { - memory_import = &module->import_memories[0].u.memory; + WASMMemoryImport *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->mem_type.init_page_count < DEFAULT_MAX_PAGES) { @@ -6198,7 +6247,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, } } if (module->memory_count) { - memory = &module->memories[0]; + WASMMemory *memory = &module->memories[0]; /* Only resize(shrunk) the memory size if num_bytes_per_page is in * valid range of uint32 */ if (memory->init_page_count < DEFAULT_MAX_PAGES) { @@ -7906,11 +7955,16 @@ typedef struct WASMLoaderContext { /* preserved local offset */ int16 preserved_local_offset; - /* const buffer */ - uint8 *const_buf; - uint16 num_const; - uint16 const_cell_num; - uint32 const_buf_size; + /* const buffer for i64 and f64 consts, note that the raw bytes + * of i64 and f64 are the same, so we read an i64 value from an + * f64 const with its raw bytes, something like `*(int64 *)&f64 */ + int64 *i64_consts; + uint32 i64_const_max_num; + uint32 i64_const_num; + /* const buffer for i32 and f32 consts */ + int32 *i32_consts; + uint32 i32_const_max_num; + uint32 i32_const_num; /* processed code */ uint8 *p_code_compiled; @@ -7923,12 +7977,6 @@ typedef struct WASMLoaderContext { #endif } WASMLoaderContext; -typedef struct Const { - WASMValue value; - uint16 slot_index; - uint8 value_type; -} Const; - #define CHECK_CSP_PUSH() \ do { \ if (ctx->frame_csp >= ctx->frame_csp_boundary) { \ @@ -8146,8 +8194,10 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx) #if WASM_ENABLE_FAST_INTERP != 0 if (ctx->frame_offset_bottom) wasm_runtime_free(ctx->frame_offset_bottom); - if (ctx->const_buf) - wasm_runtime_free(ctx->const_buf); + if (ctx->i64_consts) + wasm_runtime_free(ctx->i64_consts); + if (ctx->i32_consts) + wasm_runtime_free(ctx->i32_consts); #endif wasm_runtime_free(ctx); } @@ -8195,10 +8245,15 @@ wasm_loader_ctx_init(WASMFunction *func, char *error_buf, uint32 error_buf_size) goto fail; loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32; - loader_ctx->num_const = 0; - loader_ctx->const_buf_size = sizeof(Const) * 8; - if (!(loader_ctx->const_buf = loader_malloc(loader_ctx->const_buf_size, - error_buf, error_buf_size))) + loader_ctx->i64_const_max_num = 8; + if (!(loader_ctx->i64_consts = + loader_malloc(sizeof(int64) * loader_ctx->i64_const_max_num, + error_buf, error_buf_size))) + goto fail; + loader_ctx->i32_const_max_num = 8; + if (!(loader_ctx->i32_consts = + loader_malloc(sizeof(int32) * loader_ctx->i32_const_max_num, + error_buf, error_buf_size))) goto fail; if (func->param_cell_num >= (int32)INT16_MAX - func->local_cell_num) { @@ -9446,108 +9501,116 @@ wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt, return true; } +static int +cmp_i64_const(const void *p_i64_const1, const void *p_i64_const2) +{ + int64 i64_const1 = *(int64 *)p_i64_const1; + int64 i64_const2 = *(int64 *)p_i64_const2; + + return (i64_const1 < i64_const2) ? -1 : (i64_const1 > i64_const2) ? 1 : 0; +} + +static int +cmp_i32_const(const void *p_i32_const1, const void *p_i32_const2) +{ + int32 i32_const1 = *(int32 *)p_i32_const1; + int32 i32_const2 = *(int32 *)p_i32_const2; + + return (i32_const1 < i32_const2) ? -1 : (i32_const1 > i32_const2) ? 1 : 0; +} + static bool wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value, int16 *offset, char *error_buf, uint32 error_buf_size) { - int8 bytes_to_increase; - int16 operand_offset = 0; - Const *c; - - /* Search existing constant */ - for (c = (Const *)ctx->const_buf; - (uint8 *)c < ctx->const_buf + ctx->num_const * sizeof(Const); c++) { - /* TODO: handle v128 type? */ - if ((type == c->value_type) - && ((type == VALUE_TYPE_I64 && *(int64 *)value == c->value.i64) - || (type == VALUE_TYPE_I32 && *(int32 *)value == c->value.i32) -#if WASM_ENABLE_REF_TYPES != 0 && WASM_ENABLE_GC == 0 - || (type == VALUE_TYPE_FUNCREF - && *(int32 *)value == c->value.i32) - || (type == VALUE_TYPE_EXTERNREF - && *(int32 *)value == c->value.i32) -#endif - || (type == VALUE_TYPE_F64 - && (0 == memcmp(value, &(c->value.f64), sizeof(float64)))) - || (type == VALUE_TYPE_F32 - && (0 - == memcmp(value, &(c->value.f32), sizeof(float32)))))) { - operand_offset = c->slot_index; - break; - } - if (is_32bit_type(c->value_type)) - operand_offset += 1; - else - operand_offset += 2; - } + if (!ctx->p_code_compiled) { + /* Treat i64 and f64 as the same by reading i64 value from + the raw bytes */ + if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) { + /* No slot left, emit const instead */ + if (ctx->i64_const_num * 2 + ctx->i32_const_num > INT16_MAX - 2) { + *offset = 0; + return true; + } + + /* Traverse the list if the const num is small */ + if (ctx->i64_const_num < 10) { + for (uint32 i = 0; i < ctx->i64_const_num; i++) { + if (ctx->i64_consts[i] == *(int64 *)value) { + *offset = -1; + return true; + } + } + } - if ((uint8 *)c == ctx->const_buf + ctx->num_const * sizeof(Const)) { - /* New constant, append to the const buffer */ - if ((type == VALUE_TYPE_F64) || (type == VALUE_TYPE_I64)) { - bytes_to_increase = 2; + if (ctx->i64_const_num >= ctx->i64_const_max_num) { + MEM_REALLOC(ctx->i64_consts, + sizeof(int64) * ctx->i64_const_max_num, + sizeof(int64) * (ctx->i64_const_max_num * 2)); + ctx->i64_const_max_num *= 2; + } + ctx->i64_consts[ctx->i64_const_num++] = *(int64 *)value; } else { - bytes_to_increase = 1; - } + /* Treat i32 and f32 as the same by reading i32 value from + the raw bytes */ + bh_assert(type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32); - /* The max cell num of const buffer is 32768 since the valid index range - * is -32768 ~ -1. Return an invalid index 0 to indicate the buffer is - * full */ - if (ctx->const_cell_num > INT16_MAX - bytes_to_increase + 1) { - *offset = 0; - return true; + /* No slot left, emit const instead */ + if (ctx->i64_const_num * 2 + ctx->i32_const_num > INT16_MAX - 1) { + *offset = 0; + return true; + } + + /* Traverse the list if the const num is small */ + if (ctx->i32_const_num < 10) { + for (uint32 i = 0; i < ctx->i32_const_num; i++) { + if (ctx->i32_consts[i] == *(int32 *)value) { + *offset = -1; + return true; + } + } + } + + if (ctx->i32_const_num >= ctx->i32_const_max_num) { + MEM_REALLOC(ctx->i32_consts, + sizeof(int32) * ctx->i32_const_max_num, + sizeof(int32) * (ctx->i32_const_max_num * 2)); + ctx->i32_const_max_num *= 2; + } + ctx->i32_consts[ctx->i32_const_num++] = *(int32 *)value; } - if ((uint8 *)c == ctx->const_buf + ctx->const_buf_size) { - MEM_REALLOC(ctx->const_buf, ctx->const_buf_size, - ctx->const_buf_size + 4 * sizeof(Const)); - ctx->const_buf_size += 4 * sizeof(Const); - c = (Const *)(ctx->const_buf + ctx->num_const * sizeof(Const)); + *offset = -1; + return true; + } + else { + if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) { + int64 key = *(int64 *)value, *i64_const; + i64_const = bsearch(&key, ctx->i64_consts, ctx->i64_const_num, + sizeof(int64), cmp_i64_const); + if (!i64_const) { /* not found, emit const instead */ + *offset = 0; + return true; + } + *offset = -(uint32)(ctx->i64_const_num * 2 + ctx->i32_const_num) + + (uint32)(i64_const - ctx->i64_consts) * 2; } - c->value_type = type; - switch (type) { - case VALUE_TYPE_F64: - bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value, - sizeof(float64)); - ctx->const_cell_num += 2; - /* The const buf will be reversed, we use the second cell */ - /* of the i64/f64 const so the final offset is correct */ - operand_offset++; - break; - case VALUE_TYPE_I64: - c->value.i64 = *(int64 *)value; - ctx->const_cell_num += 2; - operand_offset++; - break; - case VALUE_TYPE_F32: - bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value, - sizeof(float32)); - ctx->const_cell_num++; - break; - case VALUE_TYPE_I32: - c->value.i32 = *(int32 *)value; - ctx->const_cell_num++; - break; -#if WASM_ENABLE_REF_TYPES != 0 && WASM_ENABLE_GC == 0 - case VALUE_TYPE_EXTERNREF: - case VALUE_TYPE_FUNCREF: - c->value.i32 = *(int32 *)value; - ctx->const_cell_num++; - break; -#endif - default: - break; + else { + int32 key = *(int32 *)value, *i32_const; + i32_const = bsearch(&key, ctx->i32_consts, ctx->i32_const_num, + sizeof(int32), cmp_i32_const); + if (!i32_const) { /* not found, emit const instead */ + *offset = 0; + return true; + } + *offset = -(uint32)(ctx->i32_const_num) + + (uint32)(i32_const - ctx->i32_consts); } - c->slot_index = operand_offset; - ctx->num_const++; - LOG_OP("#### new const [%d]: %ld\n", ctx->num_const, - (int64)c->value.i64); + + return true; } - /* use negative index for const */ - operand_offset = -(operand_offset + 1); - *offset = operand_offset; - return true; fail: return false; } @@ -9832,7 +9895,12 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 opcode, else { loader_ctx->frame_offset = frame_offset; loader_ctx->dynamic_offset = dynamic_offset; - PUSH_OFFSET_TYPE(return_types[i]); + if (!(wasm_loader_push_frame_offset( + loader_ctx, return_types[i], disable_emit, + operand_offset, error_buf, error_buf_size))) { + wasm_runtime_free(emit_data); + goto fail; + } wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); loader_ctx->frame_offset = frame_offset_org; loader_ctx->dynamic_offset = dynamic_offset_org; @@ -9973,7 +10041,8 @@ check_memory_access_align(uint8 opcode, uint32 align, char *error_buf, bh_assert(opcode >= WASM_OP_I32_LOAD && opcode <= WASM_OP_I64_STORE32); if (align > mem_access_aligns[opcode - WASM_OP_I32_LOAD]) { set_error_buf(error_buf, error_buf_size, - "alignment must not be larger than natural"); + "invalid memop flags: alignment must not be larger " + "than natural"); return false; } return true; @@ -10012,7 +10081,8 @@ check_simd_memory_access_align(uint8 opcode, uint32 align, char *error_buf, && align > mem_access_aligns_load_lane[opcode - SIMD_v128_load8_lane])) { set_error_buf(error_buf, error_buf_size, - "alignment must not be larger than natural"); + "invalid memop flags: alignment must not be larger " + "than natural"); return false; } @@ -10809,12 +10879,12 @@ get_table_elem_type(const WASMModule *module, uint32 table_idx, else { if (p_elem_type) *p_elem_type = - module->tables[module->import_table_count + table_idx] + module->tables[table_idx - module->import_table_count] .table_type.elem_type; #if WASM_ENABLE_GC != 0 if (p_ref_type) *((WASMRefType **)p_ref_type) = - module->tables[module->import_table_count + table_idx] + module->tables[table_idx - module->import_table_count] .table_type.elem_ref_type; #endif } @@ -10873,6 +10943,83 @@ DEFINE_GOTO_TABLE(const char *, op_mnemonics); #undef HANDLE_OPCODE #endif +#if WASM_ENABLE_FAST_INTERP == 0 + +#define pb_read_leb_uint32 read_leb_uint32 +#define pb_read_leb_int32 read_leb_int32 +#define pb_read_leb_int64 read_leb_int64 +#define pb_read_leb_memarg read_leb_memarg +#define pb_read_leb_mem_offset read_leb_mem_offset + +#else + +/* Read leb without malformed format check */ +static uint64 +read_leb_quick(uint8 **p_buf, uint32 maxbits, bool sign) +{ + uint8 *buf = *p_buf; + uint64 result = 0, byte = 0; + uint32 shift = 0; + + do { + byte = *buf++; + result |= ((byte & 0x7f) << shift); + shift += 7; + } while (byte & 0x80); + + if (sign && (shift < maxbits) && (byte & 0x40)) { + /* Sign extend */ + result |= (~((uint64)0)) << shift; + } + + *p_buf = buf; + return result; +} + +#define pb_read_leb_uint32(p, p_end, res) \ + do { \ + if (!loader_ctx->p_code_compiled) \ + /* Enable format check in the first scan */ \ + read_leb_uint32(p, p_end, res); \ + else \ + /* Disable format check in the second scan */ \ + res = (uint32)read_leb_quick(&p, 32, false); \ + } while (0) + +#define pb_read_leb_int32(p, p_end, res) \ + do { \ + if (!loader_ctx->p_code_compiled) \ + /* Enable format check in the first scan */ \ + read_leb_int32(p, p_end, res); \ + else \ + /* Disable format check in the second scan */ \ + res = (int32)read_leb_quick(&p, 32, true); \ + } while (0) + +#define pb_read_leb_int64(p, p_end, res) \ + do { \ + if (!loader_ctx->p_code_compiled) \ + /* Enable format check in the first scan */ \ + read_leb_int64(p, p_end, res); \ + else \ + /* Disable format check in the second scan */ \ + res = (int64)read_leb_quick(&p, 64, true); \ + } while (0) + +#if WASM_ENABLE_MULTI_MEMORY != 0 +#define pb_read_leb_memarg read_leb_memarg +#else +#define pb_read_leb_memarg pb_read_leb_uint32 +#endif + +#if WASM_ENABLE_MEMORY64 != 0 +#define pb_read_leb_mem_offset read_leb_mem_offset +#else +#define pb_read_leb_mem_offset pb_read_leb_uint32 +#endif + +#endif /* end of WASM_ENABLE_FAST_INTERP != 0 */ + static bool wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 cur_func_idx, char *error_buf, @@ -10901,7 +11048,6 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, bool need_ref_type_map; #endif #if WASM_ENABLE_FAST_INTERP != 0 - uint8 *func_const_end, *func_const = NULL; int16 operand_offset = 0; uint8 last_op = 0; bool disable_emit, preserve_local = false, if_condition_available = true; @@ -10968,6 +11114,68 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, p = func->code; func->code_compiled = loader_ctx->p_code_compiled; func->code_compiled_size = loader_ctx->code_compiled_size; + + if (loader_ctx->i64_const_num > 0) { + int64 *i64_consts_old = loader_ctx->i64_consts; + + /* Sort the i64 consts */ + qsort(i64_consts_old, loader_ctx->i64_const_num, sizeof(int64), + cmp_i64_const); + + /* Remove the duplicated i64 consts */ + uint32 k = 1; + for (i = 1; i < loader_ctx->i64_const_num; i++) { + if (i64_consts_old[i] != i64_consts_old[i - 1]) { + i64_consts_old[k++] = i64_consts_old[i]; + } + } + + if (k < loader_ctx->i64_const_num) { + int64 *i64_consts_new; + /* Try to reallocate memory with a smaller size */ + if ((i64_consts_new = + wasm_runtime_malloc((uint32)sizeof(int64) * k))) { + bh_memcpy_s(i64_consts_new, (uint32)sizeof(int64) * k, + i64_consts_old, (uint32)sizeof(int64) * k); + /* Free the old memory */ + wasm_runtime_free(i64_consts_old); + loader_ctx->i64_consts = i64_consts_new; + loader_ctx->i64_const_max_num = k; + } + loader_ctx->i64_const_num = k; + } + } + + if (loader_ctx->i32_const_num > 0) { + int32 *i32_consts_old = loader_ctx->i32_consts; + + /* Sort the i32 consts */ + qsort(i32_consts_old, loader_ctx->i32_const_num, sizeof(int32), + cmp_i32_const); + + /* Remove the duplicated i32 consts */ + uint32 k = 1; + for (i = 1; i < loader_ctx->i32_const_num; i++) { + if (i32_consts_old[i] != i32_consts_old[i - 1]) { + i32_consts_old[k++] = i32_consts_old[i]; + } + } + + if (k < loader_ctx->i32_const_num) { + int32 *i32_consts_new; + /* Try to reallocate memory with a smaller size */ + if ((i32_consts_new = + wasm_runtime_malloc((uint32)sizeof(int32) * k))) { + bh_memcpy_s(i32_consts_new, (uint32)sizeof(int32) * k, + i32_consts_old, (uint32)sizeof(int32) * k); + /* Free the old memory */ + wasm_runtime_free(i32_consts_old); + loader_ctx->i32_consts = i32_consts_new; + loader_ctx->i32_const_max_num = k; + } + loader_ctx->i32_const_num = k; + } + } } #endif @@ -11102,7 +11310,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, /* Resolve the leb128 encoded type index as block type */ p--; p_org = p - 1; - read_leb_int32(p, p_end, type_index); + pb_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"); @@ -11180,21 +11388,23 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 cell_num = wasm_value_type_cell_num(func_type->types[i]); if (i >= available_params) { + /* make sure enough space */ + if (loader_ctx->p_code_compiled == NULL) { + loader_ctx->frame_offset += cell_num; + if (!check_offset_push(loader_ctx, error_buf, + error_buf_size)) + goto fail; + /* for following dummy value assignemnt */ + loader_ctx->frame_offset -= cell_num; + } + /* If there isn't enough data on stack, push a dummy * offset to keep the stack consistent with * frame_ref. * Since the stack is already in polymorphic state, * the opcode will not be executed, so the dummy * offset won't cause any error */ - uint32 n; - - for (n = 0; n < cell_num; n++) { - if (loader_ctx->p_code_compiled == NULL) { - if (!check_offset_push(loader_ctx, - error_buf, - error_buf_size)) - goto fail; - } + for (uint32 n = 0; n < cell_num; n++) { *loader_ctx->frame_offset++ = 0; } } @@ -11309,7 +11519,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint8 label_type = cur_block->label_type; uint32 tag_index = 0; - read_leb_int32(p, p_end, tag_index); + pb_read_leb_int32(p, p_end, tag_index); /* check validity of tag_index against module->tag_count */ /* check tag index is within the tag index space */ @@ -11453,7 +11663,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint8 label_type = cur_block->label_type; uint32 tag_index = 0; - read_leb_int32(p, p_end, tag_index); + pb_read_leb_int32(p, p_end, tag_index); /* check validity of tag_index against module->tag_count */ /* check tag index is within the tag index space */ @@ -11720,7 +11930,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 j; #endif - read_leb_uint32(p, p_end, count); + pb_read_leb_uint32(p, p_end, count); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, count); #endif @@ -11729,7 +11939,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, /* Get each depth and check it */ p_org = p; for (i = 0; i <= count; i++) { - read_leb_uint32(p, p_end, depth); + pb_read_leb_uint32(p, p_end, depth); bh_assert(loader_ctx->csp_num > 0); if (loader_ctx->csp_num - 1 < depth) { set_error_buf(error_buf, error_buf_size, @@ -11751,7 +11961,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif for (i = 0; i <= count; i++) { p_org = p; - read_leb_uint32(p, p_end, depth); + pb_read_leb_uint32(p, p_end, depth); p = p_org; /* Get the target block's arity and check it */ @@ -11885,7 +12095,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #if WASM_ENABLE_GC != 0 if (opcode == WASM_OP_CALL_REF || opcode == WASM_OP_RETURN_CALL_REF) { - read_leb_uint32(p, p_end, type_idx1); + pb_read_leb_uint32(p, p_end, type_idx1); if (!check_type_index(module, module->type_count, type_idx1, error_buf, error_buf_size)) { goto fail; @@ -11924,7 +12134,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, else #endif { - read_leb_uint32(p, p_end, func_idx); + pb_read_leb_uint32(p, p_end, func_idx); #if WASM_ENABLE_FAST_INTERP != 0 /* we need to emit func_idx before arguments */ emit_uint32(loader_ctx, func_idx); @@ -12055,8 +12265,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { int32 idx; WASMFuncType *func_type; + uint32 tbl_elem_type; +#if WASM_ENABLE_GC != 0 + WASMRefType *elem_ref_type = NULL; +#endif - read_leb_uint32(p, p_end, type_idx); + pb_read_leb_uint32(p, p_end, type_idx); #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 #if WASM_ENABLE_WAMR_COMPILER != 0 if (p + 1 < p_end && *p != 0x00) { @@ -12068,7 +12282,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, module->is_ref_types_used = true; } #endif - read_leb_uint32(p, p_end, table_idx); + pb_read_leb_uint32(p, p_end, table_idx); #else CHECK_BUF(p, p_end, 1); table_idx = read_uint8(p); @@ -12077,6 +12291,43 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, error_buf_size)) { goto fail; } + tbl_elem_type = + table_idx < module->import_table_count + ? module->import_tables[table_idx] + .u.table.table_type.elem_type + : module->tables[table_idx - module->import_table_count] + .table_type.elem_type; + +#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0 + if (tbl_elem_type != VALUE_TYPE_FUNCREF) { + set_error_buf_v(error_buf, error_buf_size, + "type mismatch: instruction requires table " + "of functions but table %u has externref", + table_idx); + goto fail; + } +#elif WASM_ENABLE_GC != 0 + /* Table element must match type ref null func */ + elem_ref_type = + table_idx < module->import_table_count + ? module->import_tables[table_idx] + .u.table.table_type.elem_ref_type + : module->tables[table_idx - module->import_table_count] + .table_type.elem_ref_type; + + if (!wasm_reftype_is_subtype_of( + tbl_elem_type, elem_ref_type, REF_TYPE_FUNCREF, NULL, + module->types, module->type_count)) { + set_error_buf_v(error_buf, error_buf_size, + "type mismatch: instruction requires " + "reference type t match type ref null func" + "in table %u", + table_idx); + goto fail; + } +#else + (void)tbl_elem_type; +#endif #if WASM_ENABLE_FAST_INTERP != 0 /* we need to emit before arguments */ @@ -12350,7 +12601,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled; #endif - read_leb_uint32(p, p_end, vec_len); + pb_read_leb_uint32(p, p_end, vec_len); if (vec_len != 1) { /* typed select must have exactly one result */ set_error_buf(error_buf, error_buf_size, @@ -12480,7 +12731,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, WASMRefType *ref_type; #endif - read_leb_uint32(p, p_end, table_idx); + pb_read_leb_uint32(p, p_end, table_idx); if (!get_table_elem_type(module, table_idx, &decl_ref_type, #if WASM_ENABLE_GC != 0 (void **)&ref_type, @@ -12541,7 +12792,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, goto fail; } #else - read_leb_int32(p, p_end, heap_type); + pb_read_leb_int32(p, p_end, heap_type); if (heap_type >= 0) { if (!check_type_index(module, module->type_count, heap_type, error_buf, error_buf_size)) { @@ -12628,7 +12879,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } case WASM_OP_REF_FUNC: { - read_leb_uint32(p, p_end, func_idx); + pb_read_leb_uint32(p, p_end, func_idx); if (!check_function_index(module, func_idx, error_buf, error_buf_size)) { @@ -13024,7 +13275,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif p_org = p - 1; - read_leb_uint32(p, p_end, global_idx); + pb_read_leb_uint32(p, p_end, global_idx); if (global_idx >= global_count) { set_error_buf(error_buf, error_buf_size, "unknown global"); goto fail; @@ -13084,7 +13335,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif p_org = p - 1; - read_leb_uint32(p, p_end, global_idx); + pb_read_leb_uint32(p, p_end, global_idx); if (global_idx >= global_count) { set_error_buf(error_buf, error_buf_size, "unknown global"); goto fail; @@ -13219,8 +13470,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } #endif CHECK_MEMORY(); - read_leb_memarg(p, p_end, align); /* align */ - read_leb_mem_offset(p, p_end, mem_offset); /* offset */ + pb_read_leb_memarg(p, p_end, align); /* align */ + pb_read_leb_mem_offset(p, p_end, mem_offset); /* offset */ if (!check_memory_access_align(opcode, align, error_buf, error_buf_size)) { goto fail; @@ -13285,7 +13536,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_MEMORY_SIZE: CHECK_MEMORY(); - read_leb_uint32(p, p_end, memidx); + pb_read_leb_uint32(p, p_end, memidx); check_memidx(module, memidx); PUSH_PAGE_COUNT(); @@ -13297,7 +13548,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_MEMORY_GROW: CHECK_MEMORY(); - read_leb_uint32(p, p_end, memidx); + pb_read_leb_uint32(p, p_end, memidx); check_memidx(module, memidx); POP_AND_PUSH(mem_offset_type, mem_offset_type); @@ -13312,7 +13563,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, break; case WASM_OP_I32_CONST: - read_leb_int32(p, p_end, i32_const); + pb_read_leb_int32(p, p_end, i32_const); #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); disable_emit = true; @@ -13330,7 +13581,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, break; case WASM_OP_I64_CONST: - read_leb_int64(p, p_end, i64_const); + pb_read_leb_int64(p, p_end, i64_const); #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); disable_emit = true; @@ -13613,7 +13864,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { uint32 opcode1; - read_leb_uint32(p, p_end, opcode1); + pb_read_leb_uint32(p, p_end, opcode1); #if WASM_ENABLE_FAST_INTERP != 0 emit_byte(loader_ctx, ((uint8)opcode1)); #endif @@ -13622,7 +13873,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_STRUCT_NEW: case WASM_OP_STRUCT_NEW_DEFAULT: { - read_leb_uint32(p, p_end, type_idx); + pb_read_leb_uint32(p, p_end, type_idx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, type_idx); #endif @@ -13709,7 +13960,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 field_idx; uint8 field_type; - read_leb_uint32(p, p_end, type_idx); + pb_read_leb_uint32(p, p_end, type_idx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, type_idx); #endif @@ -13726,7 +13977,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } struct_type = (WASMStructType *)module->types[type_idx]; - read_leb_uint32(p, p_end, field_idx); + pb_read_leb_uint32(p, p_end, field_idx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, field_idx); #endif @@ -13802,14 +14053,14 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint8 elem_type; uint32 u32 = 0; - read_leb_uint32(p, p_end, type_idx); + pb_read_leb_uint32(p, p_end, type_idx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, type_idx); #endif if (opcode1 == WASM_OP_ARRAY_NEW_FIXED || opcode1 == WASM_OP_ARRAY_NEW_DATA || opcode1 == WASM_OP_ARRAY_NEW_ELEM) { - read_leb_uint32(p, p_end, u32); + pb_read_leb_uint32(p, p_end, u32); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, u32); #endif @@ -13912,7 +14163,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, WASMArrayType *array_type; WASMRefType *ref_type = NULL; - read_leb_uint32(p, p_end, type_idx); + pb_read_leb_uint32(p, p_end, type_idx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, type_idx); #endif @@ -13984,7 +14235,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, WASMArrayType *array_type; uint8 elem_type; /* typeidx */ - read_leb_uint32(p, p_end, type_idx); + pb_read_leb_uint32(p, p_end, type_idx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, type_idx); #endif @@ -14030,12 +14281,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, WASMArrayType *array_type; /* typeidx1 */ - read_leb_uint32(p, p_end, type_idx); + pb_read_leb_uint32(p, p_end, type_idx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, type_idx); #endif /* typeidx2 */ - read_leb_uint32(p, p_end, src_type_idx); + pb_read_leb_uint32(p, p_end, src_type_idx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, src_type_idx); #endif @@ -14122,7 +14373,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { uint8 type; - read_leb_int32(p, p_end, heap_type); + pb_read_leb_int32(p, p_end, heap_type); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, (uint32)heap_type); #endif @@ -14183,13 +14434,13 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif p_org = p; - read_leb_uint32(p, p_end, depth); - read_leb_int32(p, p_end, heap_type); + pb_read_leb_uint32(p, p_end, depth); + pb_read_leb_int32(p, p_end, heap_type); #if WASM_ENABLE_FAST_INTERP != 0 /* Emit heap_type firstly */ emit_uint32(loader_ctx, (uint32)heap_type); #endif - read_leb_int32(p, p_end, heap_type_dst); + pb_read_leb_int32(p, p_end, heap_type_dst); #if WASM_ENABLE_FAST_INTERP != 0 /* Emit heap_type firstly */ emit_uint32(loader_ctx, (uint32)heap_type_dst); @@ -14391,7 +14642,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, func->has_memory_operations = true; #endif - read_leb_uint32(p, p_end, memidx); + pb_read_leb_uint32(p, p_end, memidx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, (uint32)memidx); #endif @@ -14405,7 +14656,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { uint32 contents; - read_leb_uint32(p, p_end, contents); + pb_read_leb_uint32(p, p_end, contents); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, (uint32)contents); #endif @@ -14432,7 +14683,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, func->has_memory_operations = true; #endif - read_leb_uint32(p, p_end, memidx); + pb_read_leb_uint32(p, p_end, memidx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, (uint32)memidx); #endif @@ -14486,7 +14737,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, func->has_memory_operations = true; #endif - read_leb_uint32(p, p_end, memidx); + pb_read_leb_uint32(p, p_end, memidx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, (uint32)memidx); #endif @@ -14534,7 +14785,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, func->has_memory_operations = true; #endif - read_leb_uint32(p, p_end, memidx); + pb_read_leb_uint32(p, p_end, memidx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, (uint32)memidx); #endif @@ -14618,7 +14869,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { uint32 opcode1; - read_leb_uint32(p, p_end, opcode1); + pb_read_leb_uint32(p, p_end, opcode1); #if WASM_ENABLE_FAST_INTERP != 0 emit_byte(loader_ctx, ((uint8)opcode1)); #endif @@ -14642,7 +14893,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #if WASM_ENABLE_BULK_MEMORY != 0 case WASM_OP_MEMORY_INIT: { - read_leb_uint32(p, p_end, data_seg_idx); + pb_read_leb_uint32(p, p_end, data_seg_idx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, data_seg_idx); #endif @@ -14650,7 +14901,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, && module->memory_count == 0) goto fail_unknown_memory; - read_leb_uint32(p, p_end, memidx); + pb_read_leb_uint32(p, p_end, memidx); check_memidx(module, memidx); if (data_seg_idx >= module->data_seg_count) { @@ -14676,7 +14927,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } case WASM_OP_DATA_DROP: { - read_leb_uint32(p, p_end, data_seg_idx); + pb_read_leb_uint32(p, p_end, data_seg_idx); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, data_seg_idx); #endif @@ -14701,9 +14952,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { CHECK_BUF(p, p_end, sizeof(int16)); /* check both src and dst memory index */ - read_leb_uint32(p, p_end, memidx); + pb_read_leb_uint32(p, p_end, memidx); check_memidx(module, memidx); - read_leb_uint32(p, p_end, memidx); + pb_read_leb_uint32(p, p_end, memidx); check_memidx(module, memidx); if (module->import_memory_count == 0 @@ -14723,7 +14974,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } case WASM_OP_MEMORY_FILL: { - read_leb_uint32(p, p_end, memidx); + pb_read_leb_uint32(p, p_end, memidx); check_memidx(module, memidx); if (module->import_memory_count == 0 && module->memory_count == 0) { @@ -14758,8 +15009,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, WASMRefType *seg_ref_type = NULL, *tbl_ref_type = NULL; #endif - read_leb_uint32(p, p_end, table_seg_idx); - read_leb_uint32(p, p_end, table_idx); + pb_read_leb_uint32(p, p_end, table_seg_idx); + pb_read_leb_uint32(p, p_end, table_idx); if (!get_table_elem_type(module, table_idx, &tbl_type, #if WASM_ENABLE_GC != 0 @@ -14816,7 +15067,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } case WASM_OP_ELEM_DROP: { - read_leb_uint32(p, p_end, table_seg_idx); + pb_read_leb_uint32(p, p_end, table_seg_idx); if (!get_table_seg_elem_type(module, table_seg_idx, NULL, NULL, error_buf, error_buf_size)) @@ -14839,7 +15090,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, #endif uint32 src_tbl_idx, dst_tbl_idx; - read_leb_uint32(p, p_end, dst_tbl_idx); + pb_read_leb_uint32(p, p_end, dst_tbl_idx); if (!get_table_elem_type(module, dst_tbl_idx, &dst_type, #if WASM_ENABLE_GC != 0 (void **)&dst_ref_type, @@ -14849,7 +15100,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, error_buf, error_buf_size)) goto fail; - read_leb_uint32(p, p_end, src_tbl_idx); + pb_read_leb_uint32(p, p_end, src_tbl_idx); if (!get_table_elem_type(module, src_tbl_idx, &src_type, #if WASM_ENABLE_GC != 0 (void **)&src_ref_type, @@ -14912,7 +15163,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } case WASM_OP_TABLE_SIZE: { - read_leb_uint32(p, p_end, table_idx); + pb_read_leb_uint32(p, p_end, table_idx); /* TODO: shall we create a new function to check table idx instead of using below function? */ if (!get_table_elem_type(module, table_idx, NULL, NULL, @@ -14943,7 +15194,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, WASMRefType *ref_type = NULL; #endif - read_leb_uint32(p, p_end, table_idx); + pb_read_leb_uint32(p, p_end, table_idx); if (!get_table_elem_type(module, table_idx, &decl_type, #if WASM_ENABLE_GC != 0 (void **)&ref_type, @@ -15018,7 +15269,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, module->is_simd_used = true; #endif - read_leb_uint32(p, p_end, opcode1); + pb_read_leb_uint32(p, p_end, opcode1); /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h */ @@ -15038,13 +15289,14 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ + pb_read_leb_uint32(p, p_end, align); /* align */ if (!check_simd_memory_access_align( opcode1, align, error_buf, error_buf_size)) { goto fail; } - read_leb_mem_offset(p, p_end, mem_offset); /* offset */ + pb_read_leb_mem_offset(p, p_end, + mem_offset); /* offset */ POP_AND_PUSH(mem_offset_type, VALUE_TYPE_V128); #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 @@ -15057,13 +15309,14 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ + pb_read_leb_uint32(p, p_end, align); /* align */ if (!check_simd_memory_access_align( opcode1, align, error_buf, error_buf_size)) { goto fail; } - read_leb_mem_offset(p, p_end, mem_offset); /* offset */ + pb_read_leb_mem_offset(p, p_end, + mem_offset); /* offset */ POP_V128(); POP_MEM_OFFSET(); @@ -15275,13 +15528,14 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ + pb_read_leb_uint32(p, p_end, align); /* align */ if (!check_simd_memory_access_align( opcode1, align, error_buf, error_buf_size)) { goto fail; } - read_leb_mem_offset(p, p_end, mem_offset); /* offset */ + pb_read_leb_mem_offset(p, p_end, + mem_offset); /* offset */ CHECK_BUF(p, p_end, 1); lane = read_uint8(p); @@ -15306,13 +15560,14 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ + pb_read_leb_uint32(p, p_end, align); /* align */ if (!check_simd_memory_access_align( opcode1, align, error_buf, error_buf_size)) { goto fail; } - read_leb_mem_offset(p, p_end, mem_offset); /* offset */ + pb_read_leb_mem_offset(p, p_end, + mem_offset); /* offset */ POP_AND_PUSH(mem_offset_type, VALUE_TYPE_V128); #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 @@ -15670,15 +15925,15 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { uint32 opcode1; - read_leb_uint32(p, p_end, opcode1); + pb_read_leb_uint32(p, p_end, opcode1); #if WASM_ENABLE_FAST_INTERP != 0 emit_byte(loader_ctx, opcode1); #endif if (opcode1 != WASM_OP_ATOMIC_FENCE) { CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ - read_leb_mem_offset(p, p_end, mem_offset); /* offset */ + pb_read_leb_uint32(p, p_end, align); /* align */ + pb_read_leb_mem_offset(p, p_end, mem_offset); /* offset */ if (!check_memory_align_equal(opcode1, align, error_buf, error_buf_size)) { goto fail; @@ -15842,29 +16097,25 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, if (loader_ctx->p_code_compiled == NULL) goto re_scan; - func->const_cell_num = loader_ctx->const_cell_num; + func->const_cell_num = + loader_ctx->i64_const_num * 2 + loader_ctx->i32_const_num; if (func->const_cell_num > 0) { - int32 j; - - if (!(func->consts = func_const = loader_malloc( - func->const_cell_num * 4, error_buf, error_buf_size))) + if (!(func->consts = + loader_malloc((uint64)sizeof(uint32) * func->const_cell_num, + error_buf, error_buf_size))) goto fail; - - func_const_end = func->consts + func->const_cell_num * 4; - /* reverse the const buf */ - for (j = loader_ctx->num_const - 1; j >= 0; j--) { - Const *c = (Const *)(loader_ctx->const_buf + j * sizeof(Const)); - if (c->value_type == VALUE_TYPE_F64 - || c->value_type == VALUE_TYPE_I64) { - bh_memcpy_s(func_const, (uint32)(func_const_end - func_const), - &(c->value.f64), (uint32)sizeof(int64)); - func_const += sizeof(int64); - } - else { - bh_memcpy_s(func_const, (uint32)(func_const_end - func_const), - &(c->value.f32), (uint32)sizeof(int32)); - func_const += sizeof(int32); - } + if (loader_ctx->i64_const_num > 0) { + bh_memcpy_s(func->consts, + (uint32)sizeof(int64) * loader_ctx->i64_const_num, + loader_ctx->i64_consts, + (uint32)sizeof(int64) * loader_ctx->i64_const_num); + } + if (loader_ctx->i32_const_num > 0) { + bh_memcpy_s(func->consts + + sizeof(int64) * loader_ctx->i64_const_num, + (uint32)sizeof(int32) * loader_ctx->i32_const_num, + loader_ctx->i32_consts, + (uint32)sizeof(int32) * loader_ctx->i32_const_num); } } diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index a1fb3102fa..d20c28d7d0 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -48,7 +48,9 @@ is_table_64bit(WASMModule *module, uint32 table_idx) return !!(module->import_tables[table_idx].u.table.table_type.flags & TABLE64_FLAG); else - return !!(module->tables[table_idx].table_type.flags & TABLE64_FLAG); + return !!(module->tables[table_idx - module->import_table_count] + .table_type.flags + & TABLE64_FLAG); return false; } @@ -206,9 +208,14 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf, { uint8 *mem_new; bh_assert(size_new > size_old); + + if ((mem_new = wasm_runtime_realloc(mem_old, size_new))) { + memset(mem_new + size_old, 0, size_new - size_old); + return mem_new; + } + if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) { bh_memcpy_s(mem_new, size_new, mem_old, size_old); - memset(mem_new + size_old, 0, size_new - size_old); wasm_runtime_free(mem_old); } return mem_new; @@ -2566,7 +2573,7 @@ get_table_elem_type(const WASMModule *module, uint32 table_idx, module->import_tables[table_idx].u.table.table_type.elem_type; else *p_elem_type = - module->tables[module->import_table_count + table_idx] + module->tables[table_idx - module->import_table_count] .table_type.elem_type; } return true; @@ -2727,6 +2734,11 @@ load_from_sections(WASMModule *module, WASMSection *sections, section = section->next; } +#if WASM_ENABLE_BULK_MEMORY != 0 + bh_assert(!has_datacount_section + || module->data_seg_count == module->data_seg_count1); +#endif + module->aux_data_end_global_index = (uint32)-1; module->aux_heap_base_global_index = (uint32)-1; module->aux_stack_top_global_index = (uint32)-1; @@ -2736,6 +2748,12 @@ load_from_sections(WASMModule *module, WASMSection *sections, for (i = 0; i < module->export_count; i++, export ++) { if (export->kind == EXPORT_KIND_GLOBAL) { if (!strcmp(export->name, "__heap_base")) { + if (export->index < module->import_global_count) { + LOG_DEBUG("Skip the process if __heap_base is imported " + "instead of being a local global"); + continue; + } + global_index = export->index - module->import_global_count; global = module->globals + global_index; if (global->type.val_type == VALUE_TYPE_I32 @@ -2750,6 +2768,12 @@ load_from_sections(WASMModule *module, WASMSection *sections, } } else if (!strcmp(export->name, "__data_end")) { + if (export->index < module->import_global_count) { + LOG_DEBUG("Skip the process if __data_end is imported " + "instead of being a local global"); + continue; + } + global_index = export->index - module->import_global_count; global = module->globals + global_index; if (global->type.val_type == VALUE_TYPE_I32 @@ -2944,9 +2968,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, } if (!module->possible_memory_grow) { - WASMMemoryImport *memory_import; - WASMMemory *memory; - +#if WASM_ENABLE_SHRUNK_MEMORY != 0 if (aux_data_end_global && aux_heap_base_global && aux_stack_top_global) { uint64 init_memory_size; @@ -2956,7 +2978,8 @@ load_from_sections(WASMModule *module, WASMSection *sections, * valid range of uint32 */ if (shrunk_memory_size <= UINT32_MAX) { if (module->import_memory_count) { - memory_import = &module->import_memories[0].u.memory; + WASMMemoryImport *memory_import = + &module->import_memories[0].u.memory; init_memory_size = (uint64)memory_import->mem_type.num_bytes_per_page * memory_import->mem_type.init_page_count; @@ -2971,7 +2994,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, } if (module->memory_count) { - memory = &module->memories[0]; + WASMMemory *memory = &module->memories[0]; init_memory_size = (uint64)memory->num_bytes_per_page * memory->init_page_count; if (shrunk_memory_size <= init_memory_size) { @@ -2984,9 +3007,11 @@ load_from_sections(WASMModule *module, WASMSection *sections, } } } +#endif /* WASM_ENABLE_SHRUNK_MEMORY != 0 */ if (module->import_memory_count) { - memory_import = &module->import_memories[0].u.memory; + WASMMemoryImport *memory_import = + &module->import_memories[0].u.memory; 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; @@ -3000,7 +3025,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, } if (module->memory_count) { - memory = &module->memories[0]; + WASMMemory *memory = &module->memories[0]; if (memory->init_page_count < DEFAULT_MAX_PAGES) { memory->num_bytes_per_page *= memory->init_page_count; if (memory->init_page_count > 0) @@ -4032,11 +4057,16 @@ typedef struct WASMLoaderContext { /* preserved local offset */ int16 preserved_local_offset; - /* const buffer */ - uint8 *const_buf; - uint16 num_const; - uint16 const_cell_num; - uint32 const_buf_size; + /* const buffer for i64 and f64 consts, note that the raw bytes + * of i64 and f64 are the same, so we read an i64 value from an + * f64 const with its raw bytes, something like `*(int64 *)&f64 */ + int64 *i64_consts; + uint32 i64_const_max_num; + uint32 i64_const_num; + /* const buffer for i32 and f32 consts */ + int32 *i32_consts; + uint32 i32_const_max_num; + uint32 i32_const_num; /* processed code */ uint8 *p_code_compiled; @@ -4049,12 +4079,6 @@ typedef struct WASMLoaderContext { #endif } WASMLoaderContext; -typedef struct Const { - WASMValue value; - uint16 slot_index; - uint8 value_type; -} Const; - #define CHECK_CSP_PUSH() \ do { \ if (ctx->frame_csp >= ctx->frame_csp_boundary) { \ @@ -4209,8 +4233,10 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx) #if WASM_ENABLE_FAST_INTERP != 0 if (ctx->frame_offset_bottom) wasm_runtime_free(ctx->frame_offset_bottom); - if (ctx->const_buf) - wasm_runtime_free(ctx->const_buf); + if (ctx->i64_consts) + wasm_runtime_free(ctx->i64_consts); + if (ctx->i32_consts) + wasm_runtime_free(ctx->i32_consts); #endif wasm_runtime_free(ctx); } @@ -4244,10 +4270,15 @@ wasm_loader_ctx_init(WASMFunction *func, char *error_buf, uint32 error_buf_size) goto fail; loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32; - loader_ctx->num_const = 0; - loader_ctx->const_buf_size = sizeof(Const) * 8; - if (!(loader_ctx->const_buf = loader_malloc(loader_ctx->const_buf_size, - error_buf, error_buf_size))) + loader_ctx->i64_const_max_num = 8; + if (!(loader_ctx->i64_consts = + loader_malloc(sizeof(int64) * loader_ctx->i64_const_max_num, + error_buf, error_buf_size))) + goto fail; + loader_ctx->i32_const_max_num = 8; + if (!(loader_ctx->i32_consts = + loader_malloc(sizeof(int32) * loader_ctx->i32_const_max_num, + error_buf, error_buf_size))) goto fail; if (func->param_cell_num >= (int32)INT16_MAX - func->local_cell_num) { @@ -5070,107 +5101,116 @@ wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt, return true; } +static int +cmp_i64_const(const void *p_i64_const1, const void *p_i64_const2) +{ + int64 i64_const1 = *(int64 *)p_i64_const1; + int64 i64_const2 = *(int64 *)p_i64_const2; + + return (i64_const1 < i64_const2) ? -1 : (i64_const1 > i64_const2) ? 1 : 0; +} + +static int +cmp_i32_const(const void *p_i32_const1, const void *p_i32_const2) +{ + int32 i32_const1 = *(int32 *)p_i32_const1; + int32 i32_const2 = *(int32 *)p_i32_const2; + + return (i32_const1 < i32_const2) ? -1 : (i32_const1 > i32_const2) ? 1 : 0; +} + static bool wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value, int16 *offset, char *error_buf, uint32 error_buf_size) { - int8 bytes_to_increase; - int16 operand_offset = 0; - Const *c; - - /* Search existing constant */ - for (c = (Const *)ctx->const_buf; - (uint8 *)c < ctx->const_buf + ctx->num_const * sizeof(Const); c++) { - if ((type == c->value_type) - && ((type == VALUE_TYPE_I64 && *(int64 *)value == c->value.i64) - || (type == VALUE_TYPE_I32 && *(int32 *)value == c->value.i32) -#if WASM_ENABLE_REF_TYPES != 0 - || (type == VALUE_TYPE_FUNCREF - && *(int32 *)value == c->value.i32) - || (type == VALUE_TYPE_EXTERNREF - && *(int32 *)value == c->value.i32) -#endif - || (type == VALUE_TYPE_F64 - && (0 == memcmp(value, &(c->value.f64), sizeof(float64)))) - || (type == VALUE_TYPE_F32 - && (0 - == memcmp(value, &(c->value.f32), sizeof(float32)))))) { - operand_offset = c->slot_index; - break; - } - if (c->value_type == VALUE_TYPE_I64 || c->value_type == VALUE_TYPE_F64) - operand_offset += 2; - else - operand_offset += 1; - } + if (!ctx->p_code_compiled) { + /* Treat i64 and f64 as the same by reading i64 value from + the raw bytes */ + if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) { + /* No slot left, emit const instead */ + if (ctx->i64_const_num * 2 + ctx->i32_const_num > INT16_MAX - 2) { + *offset = 0; + return true; + } + + /* Traverse the list if the const num is small */ + if (ctx->i64_const_num < 10) { + for (uint32 i = 0; i < ctx->i64_const_num; i++) { + if (ctx->i64_consts[i] == *(int64 *)value) { + *offset = -1; + return true; + } + } + } - if ((uint8 *)c == ctx->const_buf + ctx->num_const * sizeof(Const)) { - /* New constant, append to the const buffer */ - if ((type == VALUE_TYPE_F64) || (type == VALUE_TYPE_I64)) { - bytes_to_increase = 2; + if (ctx->i64_const_num >= ctx->i64_const_max_num) { + MEM_REALLOC(ctx->i64_consts, + sizeof(int64) * ctx->i64_const_max_num, + sizeof(int64) * (ctx->i64_const_max_num * 2)); + ctx->i64_const_max_num *= 2; + } + ctx->i64_consts[ctx->i64_const_num++] = *(int64 *)value; } else { - bytes_to_increase = 1; - } + /* Treat i32 and f32 as the same by reading i32 value from + the raw bytes */ + bh_assert(type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32); + + /* No slot left, emit const instead */ + if (ctx->i64_const_num * 2 + ctx->i32_const_num > INT16_MAX - 1) { + *offset = 0; + return true; + } - /* The max cell num of const buffer is 32768 since the valid index range - * is -32768 ~ -1. Return an invalid index 0 to indicate the buffer is - * full */ - if (ctx->const_cell_num > INT16_MAX - bytes_to_increase + 1) { - *offset = 0; - return true; + /* Traverse the list if the const num is small */ + if (ctx->i32_const_num < 10) { + for (uint32 i = 0; i < ctx->i32_const_num; i++) { + if (ctx->i32_consts[i] == *(int32 *)value) { + *offset = -1; + return true; + } + } + } + + if (ctx->i32_const_num >= ctx->i32_const_max_num) { + MEM_REALLOC(ctx->i32_consts, + sizeof(int32) * ctx->i32_const_max_num, + sizeof(int32) * (ctx->i32_const_max_num * 2)); + ctx->i32_const_max_num *= 2; + } + ctx->i32_consts[ctx->i32_const_num++] = *(int32 *)value; } - if ((uint8 *)c == ctx->const_buf + ctx->const_buf_size) { - MEM_REALLOC(ctx->const_buf, ctx->const_buf_size, - ctx->const_buf_size + 4 * sizeof(Const)); - ctx->const_buf_size += 4 * sizeof(Const); - c = (Const *)(ctx->const_buf + ctx->num_const * sizeof(Const)); + *offset = -1; + return true; + } + else { + if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) { + int64 key = *(int64 *)value, *i64_const; + i64_const = bsearch(&key, ctx->i64_consts, ctx->i64_const_num, + sizeof(int64), cmp_i64_const); + if (!i64_const) { /* not found, emit const instead */ + *offset = 0; + return true; + } + *offset = -(uint32)(ctx->i64_const_num * 2 + ctx->i32_const_num) + + (uint32)(i64_const - ctx->i64_consts) * 2; } - c->value_type = type; - switch (type) { - case VALUE_TYPE_F64: - bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value, - sizeof(float64)); - ctx->const_cell_num += 2; - /* The const buf will be reversed, we use the second cell */ - /* of the i64/f64 const so the finnal offset is corrent */ - operand_offset++; - break; - case VALUE_TYPE_I64: - c->value.i64 = *(int64 *)value; - ctx->const_cell_num += 2; - operand_offset++; - break; - case VALUE_TYPE_F32: - bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value, - sizeof(float32)); - ctx->const_cell_num++; - break; - case VALUE_TYPE_I32: - c->value.i32 = *(int32 *)value; - ctx->const_cell_num++; - break; -#if WASM_ENABLE_REF_TYPES != 0 - case VALUE_TYPE_EXTERNREF: - case VALUE_TYPE_FUNCREF: - c->value.i32 = *(int32 *)value; - ctx->const_cell_num++; - break; -#endif - default: - break; + else { + int32 key = *(int32 *)value, *i32_const; + i32_const = bsearch(&key, ctx->i32_consts, ctx->i32_const_num, + sizeof(int32), cmp_i32_const); + if (!i32_const) { /* not found, emit const instead */ + *offset = 0; + return true; + } + *offset = -(uint32)(ctx->i32_const_num) + + (uint32)(i32_const - ctx->i32_consts); } - c->slot_index = operand_offset; - ctx->num_const++; - LOG_OP("#### new const [%d]: %ld\n", ctx->num_const, - (int64)c->value.i64); - } - /* use negetive index for const */ - operand_offset = -(operand_offset + 1); - *offset = operand_offset; - return true; + + return true; + } fail: return false; } @@ -5561,7 +5601,12 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 opcode, else { loader_ctx->frame_offset = frame_offset; loader_ctx->dynamic_offset = dynamic_offset; - PUSH_OFFSET_TYPE(return_types[i]); + if (!(wasm_loader_push_frame_offset( + loader_ctx, return_types[i], disable_emit, + operand_offset, error_buf, error_buf_size))) { + wasm_runtime_free(emit_data); + goto fail; + } wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); loader_ctx->frame_offset = frame_offset_org; loader_ctx->dynamic_offset = dynamic_offset_org; @@ -6028,6 +6073,86 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, char *error_buf, } \ } while (0) +#if WASM_ENABLE_FAST_INTERP == 0 + +#define pb_read_leb_uint32 read_leb_uint32 +#define pb_read_leb_int32 read_leb_int32 +#define pb_read_leb_int64 read_leb_int64 +#define pb_read_leb_memarg read_leb_memarg +#define pb_read_leb_mem_offset read_leb_mem_offset +#define pb_read_leb_memidx read_leb_memidx + +#else + +/* Read leb without malformed format check */ +static uint64 +read_leb_quick(uint8 **p_buf, uint32 maxbits, bool sign) +{ + uint8 *buf = *p_buf; + uint64 result = 0, byte = 0; + uint32 shift = 0; + + do { + byte = *buf++; + result |= ((byte & 0x7f) << shift); + shift += 7; + } while (byte & 0x80); + + if (sign && (shift < maxbits) && (byte & 0x40)) { + /* Sign extend */ + result |= (~((uint64)0)) << shift; + } + + *p_buf = buf; + return result; +} + +#define pb_read_leb_uint32(p, p_end, res) \ + do { \ + if (!loader_ctx->p_code_compiled) \ + /* Enable format check in the first scan */ \ + read_leb_uint32(p, p_end, res); \ + else \ + /* Disable format check in the second scan */ \ + res = (uint32)read_leb_quick(&p, 32, false); \ + } while (0) + +#define pb_read_leb_int32(p, p_end, res) \ + do { \ + if (!loader_ctx->p_code_compiled) \ + /* Enable format check in the first scan */ \ + read_leb_int32(p, p_end, res); \ + else \ + /* Disable format check in the second scan */ \ + res = (int32)read_leb_quick(&p, 32, true); \ + } while (0) + +#define pb_read_leb_int64(p, p_end, res) \ + do { \ + if (!loader_ctx->p_code_compiled) \ + /* Enable format check in the first scan */ \ + read_leb_int64(p, p_end, res); \ + else \ + /* Disable format check in the second scan */ \ + res = (int64)read_leb_quick(&p, 64, true); \ + } while (0) + +#if WASM_ENABLE_MULTI_MEMORY != 0 +#define pb_read_leb_memarg read_leb_memarg +#else +#define pb_read_leb_memarg pb_read_leb_uint32 +#endif + +#if WASM_ENABLE_MEMORY64 != 0 +#define pb_read_leb_mem_offset read_leb_mem_offset +#else +#define pb_read_leb_mem_offset pb_read_leb_uint32 +#endif + +#define pb_read_leb_memidx pb_read_leb_uint32 + +#endif /* end of WASM_ENABLE_FAST_INTERP != 0 */ + static bool wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 cur_func_idx, char *error_buf, @@ -6051,11 +6176,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 segment_index; #endif #if WASM_ENABLE_FAST_INTERP != 0 - uint8 *func_const_end, *func_const = NULL; int16 operand_offset = 0; uint8 last_op = 0; bool disable_emit, preserve_local = false, if_condition_available = true; - ; float32 f32_const; float64 f64_const; @@ -6106,6 +6229,68 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, p = func->code; func->code_compiled = loader_ctx->p_code_compiled; func->code_compiled_size = loader_ctx->code_compiled_size; + + if (loader_ctx->i64_const_num > 0) { + int64 *i64_consts_old = loader_ctx->i64_consts; + + /* Sort the i64 consts */ + qsort(i64_consts_old, loader_ctx->i64_const_num, sizeof(int64), + cmp_i64_const); + + /* Remove the duplicated i64 consts */ + uint32 k = 1; + for (i = 1; i < loader_ctx->i64_const_num; i++) { + if (i64_consts_old[i] != i64_consts_old[i - 1]) { + i64_consts_old[k++] = i64_consts_old[i]; + } + } + + if (k < loader_ctx->i64_const_num) { + int64 *i64_consts_new; + /* Try to reallocate memory with a smaller size */ + if ((i64_consts_new = + wasm_runtime_malloc((uint32)sizeof(int64) * k))) { + bh_memcpy_s(i64_consts_new, (uint32)sizeof(int64) * k, + i64_consts_old, (uint32)sizeof(int64) * k); + /* Free the old memory */ + wasm_runtime_free(i64_consts_old); + loader_ctx->i64_consts = i64_consts_new; + loader_ctx->i64_const_max_num = k; + } + loader_ctx->i64_const_num = k; + } + } + + if (loader_ctx->i32_const_num > 0) { + int32 *i32_consts_old = loader_ctx->i32_consts; + + /* Sort the i32 consts */ + qsort(i32_consts_old, loader_ctx->i32_const_num, sizeof(int32), + cmp_i32_const); + + /* Remove the duplicated i32 consts */ + uint32 k = 1; + for (i = 1; i < loader_ctx->i32_const_num; i++) { + if (i32_consts_old[i] != i32_consts_old[i - 1]) { + i32_consts_old[k++] = i32_consts_old[i]; + } + } + + if (k < loader_ctx->i32_const_num) { + int32 *i32_consts_new; + /* Try to reallocate memory with a smaller size */ + if ((i32_consts_new = + wasm_runtime_malloc((uint32)sizeof(int32) * k))) { + bh_memcpy_s(i32_consts_new, (uint32)sizeof(int32) * k, + i32_consts_old, (uint32)sizeof(int32) * k); + /* Free the old memory */ + wasm_runtime_free(i32_consts_old); + loader_ctx->i32_consts = i32_consts_new; + loader_ctx->i32_const_max_num = k; + } + loader_ctx->i32_const_num = k; + } + } } #endif @@ -6175,7 +6360,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, int32 type_index; /* Resolve the leb128 encoded type index as block type */ p--; - read_leb_int32(p, p_end, type_index); + pb_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]; @@ -6488,7 +6673,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 j; #endif - read_leb_uint32(p, p_end, count); + pb_read_leb_uint32(p, p_end, count); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, count); #endif @@ -6497,7 +6682,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, /* Get each depth and check it */ p_org = p; for (i = 0; i <= count; i++) { - read_leb_uint32(p, p_end, depth); + pb_read_leb_uint32(p, p_end, depth); bh_assert(loader_ctx->csp_num > 0); bh_assert(loader_ctx->csp_num - 1 >= depth); (void)depth; @@ -6595,7 +6780,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 func_idx; int32 idx; - read_leb_uint32(p, p_end, func_idx); + pb_read_leb_uint32(p, p_end, func_idx); #if WASM_ENABLE_FAST_INTERP != 0 /* we need to emit func_idx before arguments */ emit_uint32(loader_ctx, func_idx); @@ -6668,10 +6853,10 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, bh_assert(module->import_table_count + module->table_count > 0); - read_leb_uint32(p, p_end, type_idx); + pb_read_leb_uint32(p, p_end, type_idx); #if WASM_ENABLE_REF_TYPES != 0 - read_leb_uint32(p, p_end, table_idx); + pb_read_leb_uint32(p, p_end, table_idx); #else CHECK_BUF(p, p_end, 1); table_idx = read_uint8(p); @@ -6681,6 +6866,15 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, goto fail; } + bh_assert( + (table_idx < module->import_table_count + ? module->import_tables[table_idx] + .u.table.table_type.elem_type + : module + ->tables[table_idx - module->import_table_count] + .table_type.elem_type) + == VALUE_TYPE_FUNCREF); + #if WASM_ENABLE_FAST_INTERP != 0 /* we need to emit before arguments */ emit_uint32(loader_ctx, type_idx); @@ -6902,7 +7096,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled; #endif - read_leb_uint32(p, p_end, vec_len); + pb_read_leb_uint32(p, p_end, vec_len); if (vec_len != 1) { /* typed select must have exactly one result */ set_error_buf(error_buf, error_buf_size, @@ -6977,7 +7171,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint8 decl_ref_type; uint32 table_idx; - read_leb_uint32(p, p_end, table_idx); + pb_read_leb_uint32(p, p_end, table_idx); if (!get_table_elem_type(module, table_idx, &decl_ref_type, error_buf, error_buf_size)) goto fail; @@ -7071,7 +7265,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_REF_FUNC: { uint32 func_idx = 0; - read_leb_uint32(p, p_end, func_idx); + pb_read_leb_uint32(p, p_end, func_idx); if (!check_function_index(module, func_idx, error_buf, error_buf_size)) { @@ -7288,7 +7482,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_GET_GLOBAL: { p_org = p - 1; - read_leb_uint32(p, p_end, global_idx); + pb_read_leb_uint32(p, p_end, global_idx); bh_assert(global_idx < global_count); global_type = global_idx < module->import_global_count @@ -7322,7 +7516,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, bool is_mutable = false; p_org = p - 1; - read_leb_uint32(p, p_end, global_idx); + pb_read_leb_uint32(p, p_end, global_idx); bh_assert(global_idx < global_count); is_mutable = global_idx < module->import_global_count @@ -7419,8 +7613,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } #endif CHECK_MEMORY(); - read_leb_memarg(p, p_end, align); /* align */ - read_leb_mem_offset(p, p_end, mem_offset); /* offset */ + pb_read_leb_memarg(p, p_end, align); /* align */ + pb_read_leb_mem_offset(p, p_end, mem_offset); /* offset */ #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, mem_offset); #endif @@ -7481,7 +7675,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_MEMORY_SIZE: CHECK_MEMORY(); - read_leb_memidx(p, p_end, memidx); + pb_read_leb_memidx(p, p_end, memidx); check_memidx(module, memidx); PUSH_PAGE_COUNT(); @@ -7493,7 +7687,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_MEMORY_GROW: CHECK_MEMORY(); - read_leb_memidx(p, p_end, memidx); + pb_read_leb_memidx(p, p_end, memidx); check_memidx(module, memidx); POP_AND_PUSH(mem_offset_type, mem_offset_type); @@ -7508,7 +7702,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, break; case WASM_OP_I32_CONST: - read_leb_int32(p, p_end, i32_const); + pb_read_leb_int32(p, p_end, i32_const); #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); disable_emit = true; @@ -7526,7 +7720,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, break; case WASM_OP_I64_CONST: - read_leb_int64(p, p_end, i64_const); + pb_read_leb_int64(p, p_end, i64_const); #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); disable_emit = true; @@ -7808,7 +8002,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { uint32 opcode1; - read_leb_uint32(p, p_end, opcode1); + pb_read_leb_uint32(p, p_end, opcode1); #if WASM_ENABLE_FAST_INTERP != 0 emit_byte(loader_ctx, ((uint8)opcode1)); #endif @@ -7833,11 +8027,11 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_MEMORY_INIT: { CHECK_MEMORY(); - read_leb_uint32(p, p_end, segment_index); + pb_read_leb_uint32(p, p_end, segment_index); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, segment_index); #endif - read_leb_memidx(p, p_end, memidx); + pb_read_leb_memidx(p, p_end, memidx); check_memidx(module, memidx); bh_assert(segment_index < module->data_seg_count); @@ -7853,7 +8047,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } case WASM_OP_DATA_DROP: { - read_leb_uint32(p, p_end, segment_index); + pb_read_leb_uint32(p, p_end, segment_index); #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, segment_index); #endif @@ -7869,9 +8063,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, CHECK_MEMORY(); CHECK_BUF(p, p_end, sizeof(int16)); /* check both src and dst memory index */ - read_leb_memidx(p, p_end, memidx); + pb_read_leb_memidx(p, p_end, memidx); check_memidx(module, memidx); - read_leb_memidx(p, p_end, memidx); + pb_read_leb_memidx(p, p_end, memidx); check_memidx(module, memidx); POP_MEM_OFFSET(); @@ -7885,7 +8079,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_MEMORY_FILL: { CHECK_MEMORY(); - read_leb_memidx(p, p_end, memidx); + pb_read_leb_memidx(p, p_end, memidx); check_memidx(module, memidx); POP_MEM_OFFSET(); @@ -7903,8 +8097,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint8 seg_ref_type, tbl_ref_type; uint32 table_seg_idx, table_idx; - read_leb_uint32(p, p_end, table_seg_idx); - read_leb_uint32(p, p_end, table_idx); + pb_read_leb_uint32(p, p_end, table_seg_idx); + pb_read_leb_uint32(p, p_end, table_idx); if (!get_table_elem_type(module, table_idx, &tbl_ref_type, error_buf, @@ -7939,7 +8133,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, case WASM_OP_ELEM_DROP: { uint32 table_seg_idx; - read_leb_uint32(p, p_end, table_seg_idx); + pb_read_leb_uint32(p, p_end, table_seg_idx); if (!get_table_seg_elem_type(module, table_seg_idx, NULL, error_buf, error_buf_size)) @@ -7955,13 +8149,13 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 src_tbl_idx, dst_tbl_idx, src_tbl_idx_type, dst_tbl_idx_type, min_tbl_idx_type; - read_leb_uint32(p, p_end, src_tbl_idx); + pb_read_leb_uint32(p, p_end, src_tbl_idx); if (!get_table_elem_type(module, src_tbl_idx, &src_ref_type, error_buf, error_buf_size)) goto fail; - read_leb_uint32(p, p_end, dst_tbl_idx); + pb_read_leb_uint32(p, p_end, dst_tbl_idx); if (!get_table_elem_type(module, dst_tbl_idx, &dst_ref_type, error_buf, error_buf_size)) @@ -8008,7 +8202,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { uint32 table_idx; - read_leb_uint32(p, p_end, table_idx); + pb_read_leb_uint32(p, p_end, table_idx); /* TODO: shall we create a new function to check table idx instead of using below function? */ if (!get_table_elem_type(module, table_idx, NULL, @@ -8033,7 +8227,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint8 decl_ref_type; uint32 table_idx; - read_leb_uint32(p, p_end, table_idx); + pb_read_leb_uint32(p, p_end, table_idx); if (!get_table_elem_type(module, table_idx, &decl_ref_type, error_buf, error_buf_size)) @@ -8085,15 +8279,15 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, { uint32 opcode1; - read_leb_uint32(p, p_end, opcode1); + pb_read_leb_uint32(p, p_end, opcode1); #if WASM_ENABLE_FAST_INTERP != 0 emit_byte(loader_ctx, opcode1); #endif if (opcode1 != WASM_OP_ATOMIC_FENCE) { CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ - read_leb_mem_offset(p, p_end, mem_offset); /* offset */ + pb_read_leb_uint32(p, p_end, align); /* align */ + pb_read_leb_mem_offset(p, p_end, mem_offset); /* offset */ #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, mem_offset); #endif @@ -8243,29 +8437,25 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, if (loader_ctx->p_code_compiled == NULL) goto re_scan; - func->const_cell_num = loader_ctx->const_cell_num; + func->const_cell_num = + loader_ctx->i64_const_num * 2 + loader_ctx->i32_const_num; if (func->const_cell_num > 0) { - int32 j; - - if (!(func->consts = func_const = loader_malloc( - func->const_cell_num * 4, error_buf, error_buf_size))) + if (!(func->consts = + loader_malloc((uint64)sizeof(uint32) * func->const_cell_num, + error_buf, error_buf_size))) goto fail; - - func_const_end = func->consts + func->const_cell_num * 4; - /* reverse the const buf */ - for (j = loader_ctx->num_const - 1; j >= 0; j--) { - Const *c = (Const *)(loader_ctx->const_buf + j * sizeof(Const)); - if (c->value_type == VALUE_TYPE_F64 - || c->value_type == VALUE_TYPE_I64) { - bh_memcpy_s(func_const, (uint32)(func_const_end - func_const), - &(c->value.f64), (uint32)sizeof(int64)); - func_const += sizeof(int64); - } - else { - bh_memcpy_s(func_const, (uint32)(func_const_end - func_const), - &(c->value.f32), (uint32)sizeof(int32)); - func_const += sizeof(int32); - } + if (loader_ctx->i64_const_num > 0) { + bh_memcpy_s(func->consts, + (uint32)sizeof(int64) * loader_ctx->i64_const_num, + loader_ctx->i64_consts, + (uint32)sizeof(int64) * loader_ctx->i64_const_num); + } + if (loader_ctx->i32_const_num > 0) { + bh_memcpy_s(func->consts + + sizeof(int64) * loader_ctx->i64_const_num, + (uint32)sizeof(int32) * loader_ctx->i32_const_num, + loader_ctx->i32_consts, + (uint32)sizeof(int32) * loader_ctx->i32_const_num); } } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 9856c4a6cd..dd3d2f2229 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1501,10 +1501,8 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst, /* The linked global instance has been initialized, we just need to copy the value. */ - bh_memcpy_s( - &(global->initial_value), sizeof(WASMValue), - &(import_global_type->import_global_linked->init_expr.u), - sizeof(WASMValue)); + global->initial_value = + global_import->import_global_linked->init_expr.u; } #if WASM_ENABLE_LIBC_BUILTIN != 0 else { @@ -2808,7 +2806,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, goto fail; } for (i = 0; i < module->table_seg_count; i++) { - if (wasm_elem_is_active(module->table_segments[i].mode)) + if (wasm_elem_is_active(module->table_segments[i].mode) + || wasm_elem_is_declarative(module->table_segments[i].mode)) bh_bitmap_set_bit(module_inst->e->common.elem_dropped, i); } } @@ -5058,7 +5057,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx, if (!(func_obj = wasm_create_func_obj(module_inst, init_values[i].u.ref_index, true, NULL, 0))) { - wasm_set_exception(module_inst, "null function object"); + wasm_set_exception(module_inst, "null function reference"); return; } table_elems[i] = func_obj; diff --git a/core/iwasm/libraries/wasi-nn/cmake/wasi_nn.cmake b/core/iwasm/libraries/wasi-nn/cmake/wasi_nn.cmake index a903f0af1f..c6deab6fca 100644 --- a/core/iwasm/libraries/wasi-nn/cmake/wasi_nn.cmake +++ b/core/iwasm/libraries/wasi-nn/cmake/wasi_nn.cmake @@ -22,6 +22,7 @@ add_compile_definitions( # - tflite if(WAMR_BUILD_WASI_NN_TFLITE EQUAL 1) find_package(tensorflow_lite REQUIRED) + enable_language(CXX) add_library( wasi_nn_tflite diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-smoke b/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-smoke index fe3a8c5122..fdbe971d26 100644 --- a/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-smoke +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-smoke @@ -13,7 +13,7 @@ RUN apt-get update \ && apt-get upgrade -y \ && apt-get install -y --no-install-recommends cmake -RUN rustup target add wasm32-wasi +RUN rustup target add wasm32-wasip1 # # Openvino @@ -37,10 +37,10 @@ WORKDIR /workspaces/wasi-nn RUN git clone --depth 1 https://github.com/bytecodealliance/wasi-nn.git . WORKDIR /workspaces/wasi-nn/rust/examples/classification-example/ -RUN cargo build --target=wasm32-wasi +RUN cargo build --target=wasm32-wasip1 WORKDIR /workspaces/wasi-nn/rust/examples/classification-example/build -RUN cp ../target/wasm32-wasi/debug/wasi-nn-example.wasm . \ +RUN cp ../target/wasm32-wasip1/debug/wasi-nn-example.wasm . \ && wget -q --no-clobber https://github.com/intel/openvino-rs/raw/main/crates/openvino/tests/fixtures/mobilenet/mobilenet.xml \ && wget -q --no-clobber https://github.com/intel/openvino-rs/raw/main/crates/openvino/tests/fixtures/mobilenet/mobilenet.bin # There are model files(mobilenet*) and wasm files(wasi-nn-example.wasm) in the directory, @@ -67,30 +67,30 @@ RUN git apply ./bump_wasi_nn_to_0_6_0.patch # recompile with wasi-nn 0.6.0 WORKDIR /workspaces/wasmedge-wasinn-examples/openvino-mobilenet-image/ RUN pushd rust \ - && cargo build --target=wasm32-wasi \ + && cargo build --target=wasm32-wasip1 \ && popd \ && ./download_mobilenet.sh . \ && ls -l mobilenet.xml mobilenet.bin WORKDIR /workspaces/wasmedge-wasinn-examples/openvino-mobilenet-raw/ RUN pushd rust \ - && cargo build --target=wasm32-wasi \ + && cargo build --target=wasm32-wasip1 \ && popd \ && ./download_mobilenet.sh . \ && ls -l mobilenet.xml mobilenet.bin tensor-1x224x224x3-f32.bgr WORKDIR /workspaces/wasmedge-wasinn-examples/openvino-road-segmentation-adas/ RUN pushd openvino-road-seg-adas \ - && cargo build --target=wasm32-wasi + && cargo build --target=wasm32-wasip1 WORKDIR /workspaces/wasmedge-wasinn-examples/tflite-birds_v1-image/ RUN pushd rust \ - && cargo build --target=wasm32-wasi + && cargo build --target=wasm32-wasip1 # mount models when running WORKDIR /workspaces/wasmedge-wasinn-examples/wasmedge-ggml/qwen RUN wget --progress=dot:giga https://www.modelscope.cn/models/qwen/Qwen1.5-0.5B-Chat-GGUF/resolve/master/qwen1_5-0_5b-chat-q2_k.gguf -RUN cargo build --target=wasm32-wasi +RUN cargo build --target=wasm32-wasip1 # # iwasm. build from source @@ -107,7 +107,7 @@ RUN OpenVINO_DIR=/usr/lib/openvino-2023.2.0 \ -DWAMR_BUILD_WASI_NN_LLAMACPP=1 \ && cmake --build build \ && cmake --install build - + ENV LD_LIBRARY_PATH=/usr/local/lib # add smoke test script diff --git a/core/iwasm/libraries/wasi-nn/test/run_smoke_test.py b/core/iwasm/libraries/wasi-nn/test/run_smoke_test.py index 304b0c9774..00e126d880 100644 --- a/core/iwasm/libraries/wasi-nn/test/run_smoke_test.py +++ b/core/iwasm/libraries/wasi-nn/test/run_smoke_test.py @@ -53,7 +53,7 @@ def execute_openvino_road_segmentation_adas_once( """ wasm_file = ( - "./openvino-road-seg-adas/target/wasm32-wasi/debug/openvino-road-seg-adas.wasm" + "./openvino-road-seg-adas/target/wasm32-wasip1/debug/openvino-road-seg-adas.wasm" ) wasm_args = [ "./model/road-segmentation-adas-0001.xml", @@ -70,7 +70,7 @@ def execute_openvino_mobilenet_raw_once( execute openvino-mobilenet-image with iwasm and wasmedge """ - wasm_file = "./rust/target/wasm32-wasi/debug/wasmedge-wasinn-example-mobilenet.wasm" + wasm_file = "./rust/target/wasm32-wasip1/debug/wasmedge-wasinn-example-mobilenet.wasm" wasm_args = [ "mobilenet.xml", "mobilenet.bin", @@ -87,7 +87,7 @@ def execute_openvino_mobilenet_image_once( """ wasm_file = ( - "./rust/target/wasm32-wasi/debug/wasmedge-wasinn-example-mobilenet-image.wasm" + "./rust/target/wasm32-wasip1/debug/wasmedge-wasinn-example-mobilenet-image.wasm" ) wasm_args = [ "mobilenet.xml", @@ -105,7 +105,7 @@ def execute_tflite_birds_v1_image_once( """ wasm_file = ( - "rust/target/wasm32-wasi/debug/wasmedge-wasinn-example-tflite-bird-image.wasm" + "rust/target/wasm32-wasip1/debug/wasmedge-wasinn-example-tflite-bird-image.wasm" ) wasm_args = ["lite-model_aiy_vision_classifier_birds_V1_3.tflite", "bird.jpg"] return execute_once(runtime_bin, runtime_args, wasm_file, wasm_args, cwd) @@ -262,7 +262,7 @@ def filter_output(output: str) -> str: def execute_wasmedge_ggml_qwen(iwasm_bin: str, wasmedge_bin: str, cwd: Path): iwasm_args = ["--dir=."] - wasm_file = ["./target/wasm32-wasi/debug/wasmedge-ggml-qwen.wasm"] + wasm_file = ["./target/wasm32-wasip1/debug/wasmedge-ggml-qwen.wasm"] wasm_args = ["./qwen1_5-0_5b-chat-q2_k.gguf"] cmd = [iwasm_bin] diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index 5ec957e523..1d10246068 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -712,6 +712,13 @@ os_thread_signal_init(os_signal_handler handler) #if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 sigalt_stack_base_addr = map_addr; #endif + +#if defined(os_thread_local_attribute) + // calculate and cache the new stack boundary. + // see https://github.com/bytecodealliance/wasm-micro-runtime/issues/3966 + (void)os_thread_get_stack_boundary(); +#endif + signal_handler = handler; thread_signal_inited = true; return 0; diff --git a/core/shared/platform/windows/shared_platform.cmake b/core/shared/platform/windows/shared_platform.cmake index c2d74463fb..7a3331eff1 100644 --- a/core/shared/platform/windows/shared_platform.cmake +++ b/core/shared/platform/windows/shared_platform.cmake @@ -6,6 +6,7 @@ set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) add_definitions(-DBH_PLATFORM_WINDOWS) add_definitions(-DHAVE_STRUCT_TIMESPEC) add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS) +enable_language(CXX) include_directories(${PLATFORM_SHARED_DIR}) include_directories(${PLATFORM_SHARED_DIR}/../include) diff --git a/core/shared/platform/windows/win_clock.c b/core/shared/platform/windows/win_clock.c index c402330aad..1d618c8b67 100644 --- a/core/shared/platform/windows/win_clock.c +++ b/core/shared/platform/windows/win_clock.c @@ -11,9 +11,19 @@ #define NANOSECONDS_PER_TICK 100 #if WINAPI_PARTITION_DESKTOP -extern NTSTATUS -NtQueryTimerResolution(PULONG MinimumResolution, PULONG MaximumResolution, - PULONG CurrentResolution); +#ifndef __kernel_entry +#define __kernel_entry +#endif +#ifndef NTAPI +#define NTAPI +#endif +#ifndef _Out_ +#define _Out_ +#endif +extern __kernel_entry NTSTATUS NTAPI +NtQueryTimerResolution(_Out_ PULONG MinimumResolution, + _Out_ PULONG MaximumResolution, + _Out_ PULONG CurrentResolution); #endif static __wasi_errno_t diff --git a/core/shared/platform/windows/win_file.c b/core/shared/platform/windows/win_file.c index 408d0d00c2..770c5c741b 100644 --- a/core/shared/platform/windows/win_file.c +++ b/core/shared/platform/windows/win_file.c @@ -1758,7 +1758,7 @@ os_closedir(os_dir_stream dir_stream) if (!success) { DWORD win_error = GetLastError(); - if (win_error = ERROR_INVALID_HANDLE) + if (win_error == ERROR_INVALID_HANDLE) BH_FREE(dir_stream); return convert_windows_error_code(win_error); } diff --git a/core/shared/platform/windows/win_thread.c b/core/shared/platform/windows/win_thread.c index f37250fa4e..1f6a57ebbf 100644 --- a/core/shared/platform/windows/win_thread.c +++ b/core/shared/platform/windows/win_thread.c @@ -71,6 +71,63 @@ os_sem_reltimed_wait(korp_sem *sem, uint64 useconds); int os_sem_signal(korp_sem *sem); +static void +thread_data_list_add(os_thread_data *thread_data) +{ + os_mutex_lock(&thread_data_list_lock); + /* If already in list, just return */ + os_thread_data *p = &supervisor_thread_data; + while (p) { + if (p == thread_data) { + os_mutex_unlock(&thread_data_list_lock); + return; + } + p = p->next; + } + thread_data->next = supervisor_thread_data.next; + supervisor_thread_data.next = thread_data; + os_mutex_unlock(&thread_data_list_lock); +} + +static void +thread_data_list_remove(os_thread_data *thread_data) +{ + os_mutex_lock(&thread_data_list_lock); + /* Search and remove it from list */ + os_thread_data *p = &supervisor_thread_data; + while (p && p->next != thread_data) + p = p->next; + + if (p && p->next) { + bh_assert(p->next == thread_data); + p->next = p->next->next; + /* Release the resources in thread_data */ + os_cond_destroy(&thread_data->wait_cond); + os_mutex_destroy(&thread_data->wait_lock); + os_sem_destroy(&thread_data->wait_node.sem); + BH_FREE(thread_data); + } + os_mutex_unlock(&thread_data_list_lock); +} + +static os_thread_data * +thread_data_list_lookup(korp_tid tid) +{ + os_thread_data *thread_data = (os_thread_data *)tid; + os_mutex_lock(&thread_data_list_lock); + os_thread_data *p = supervisor_thread_data.next; + while (p) { + if (p == thread_data) { + /* Found */ + os_mutex_unlock(&thread_data_list_lock); + return p; + } + p = p->next; + } + os_mutex_unlock(&thread_data_list_lock); + return NULL; +} + int os_thread_sys_init() { @@ -254,10 +311,7 @@ os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, } /* Add thread data into thread data list */ - os_mutex_lock(&thread_data_list_lock); - thread_data->next = supervisor_thread_data.next; - supervisor_thread_data.next = thread_data; - os_mutex_unlock(&thread_data_list_lock); + thread_data_list_add(thread_data); /* Wait for the thread routine to set thread_data's tid and add thread_data to thread data list */ @@ -302,8 +356,12 @@ os_thread_join(korp_tid thread, void **p_retval) curr_thread_data->wait_node.next = NULL; /* Get thread data of thread to join */ - thread_data = (os_thread_data *)thread; - bh_assert(thread_data); + thread_data = thread_data_list_lookup(thread); + + if (thread_data == NULL) { + os_printf("Can't join thread %p, it does not exist", thread); + return BHT_ERROR; + } os_mutex_lock(&thread_data->wait_lock); @@ -312,6 +370,7 @@ os_thread_join(korp_tid thread, void **p_retval) if (p_retval) *p_retval = thread_data->thread_retval; os_mutex_unlock(&thread_data->wait_lock); + thread_data_list_remove(thread_data); return BHT_OK; } @@ -332,6 +391,7 @@ os_thread_join(korp_tid thread, void **p_retval) os_sem_wait(&curr_thread_data->wait_node.sem); if (p_retval) *p_retval = curr_thread_data->wait_node.retval; + thread_data_list_remove(thread_data); return BHT_OK; } diff --git a/core/shared/platform/zephyr/zephyr_thread.c b/core/shared/platform/zephyr/zephyr_thread.c index 628a842d62..31aaad7a93 100644 --- a/core/shared/platform/zephyr/zephyr_thread.c +++ b/core/shared/platform/zephyr/zephyr_thread.c @@ -393,6 +393,16 @@ os_thread_join(korp_tid thread, void **value_ptr) os_thread_data *thread_data; os_thread_wait_node *node; + /* Get thread data */ + thread_data = thread_data_list_lookup(thread); + + if (thread_data == NULL) { + os_printf( + "Can't join thread %p, probably already exited or does not exist", + thread); + return BHT_OK; + } + /* Create wait node and append it to wait list */ if (!(node = BH_MALLOC(sizeof(os_thread_wait_node)))) return BHT_ERROR; @@ -400,10 +410,6 @@ os_thread_join(korp_tid thread, void **value_ptr) sem_init(&node->sem, 0, 1); node->next = NULL; - /* Get thread data */ - thread_data = thread_data_list_lookup(thread); - bh_assert(thread_data != NULL); - mutex_lock(&thread_data->wait_list_lock, K_FOREVER); if (!thread_data->thread_wait_list) thread_data->thread_wait_list = node; diff --git a/core/shared/platform/zephyr/zephyr_time.c b/core/shared/platform/zephyr/zephyr_time.c index 78bc3e0761..5b84057379 100644 --- a/core/shared/platform/zephyr/zephyr_time.c +++ b/core/shared/platform/zephyr/zephyr_time.c @@ -14,6 +14,23 @@ os_time_get_boot_us() uint64 os_time_thread_cputime_us(void) { - /* FIXME if u know the right api */ + /* On certain boards, enabling userspace could impact the collection of + * thread runtime statistics */ +#ifdef CONFIG_THREAD_RUNTIME_STATS + k_tid_t tid; + struct k_thread_runtime_stats stats; + uint32 clock_freq; + uint64 cpu_cycles, time_in_us = 0; + + tid = k_current_get(); + if (k_thread_runtime_stats_get(tid, &stats) == 0) { + cpu_cycles = stats.execution_cycles; + clock_freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + time_in_us = (cpu_cycles * 1000000) / clock_freq; + } + + return time_in_us; +#else return os_time_get_boot_us(); +#endif } diff --git a/core/shared/utils/bh_assert.h b/core/shared/utils/bh_assert.h index b7c995af88..ec9e632af0 100644 --- a/core/shared/utils/bh_assert.h +++ b/core/shared/utils/bh_assert.h @@ -26,7 +26,7 @@ bh_assert_internal(int64 v, const char *file_name, int line_number, #define __has_extension(a) 0 #endif -#if __STDC_VERSION__ >= 201112L \ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \ || (defined(__GNUC__) && __GNUC__ * 0x100 + __GNUC_MINOR__ >= 0x406) \ || __has_extension(c_static_assert) diff --git a/core/shared/utils/bh_atomic.h b/core/shared/utils/bh_atomic.h index 5148497f8c..57cb4d1c91 100644 --- a/core/shared/utils/bh_atomic.h +++ b/core/shared/utils/bh_atomic.h @@ -114,7 +114,8 @@ typedef uint16 bh_atomic_16_t; #endif /* On some 32-bit platform, disable 64-bit atomic operations, otherwise - * undefined reference to `__atomic_load_8' */ + * undefined reference to `__atomic_load_8', if on Zephyr, can add board related + * macro in autoconf.h to control */ #ifndef WASM_UINT64_IS_ATOMIC #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) \ && !defined(__OpenBSD__) && (defined(__riscv) || defined(__arm__)) \ diff --git a/core/version.h b/core/version.h index 4fe37e2d76..d1becac61f 100644 --- a/core/version.h +++ b/core/version.h @@ -3,9 +3,22 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +/* + * version.h.in is a template file. version.h is a generated file. + * Please do not edit both files directly. + * + * Any changes to the version should be done in build-scripts/version.cmake. + * + * Continue to maintain the version.h for certain embedded platforms. + */ + #ifndef _WAMR_VERSION_H_ #define _WAMR_VERSION_H_ + +/* clang-format off */ #define WAMR_VERSION_MAJOR 2 #define WAMR_VERSION_MINOR 2 #define WAMR_VERSION_PATCH 0 +/* clang-format on */ + #endif diff --git a/core/version.h.in b/core/version.h.in new file mode 100644 index 0000000000..e28df65ce4 --- /dev/null +++ b/core/version.h.in @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +/* + * version.h.in is a template file. version.h is a generated file. + * Please do not edit both files directly. + * + * Any changes to the version should be done in build-scripts/version.cmake. + * + * Continue to maintain the version.h for certain embedded platforms. + */ + +#ifndef _WAMR_VERSION_H_ +#define _WAMR_VERSION_H_ + +/* clang-format off */ +#define WAMR_VERSION_MAJOR @WAMR_VERSION_MAJOR@ +#define WAMR_VERSION_MINOR @WAMR_VERSION_MINOR@ +#define WAMR_VERSION_PATCH @WAMR_VERSION_PATCH@ +/* clang-format on */ + +#endif diff --git a/doc/build_wamr.md b/doc/build_wamr.md index 4537ee0841..cde884457b 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -20,7 +20,7 @@ add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) The script `runtime_lib.cmake` defines a number of variables for configuring the WAMR runtime features. You can set these variables in your CMakeList.txt or pass the configurations from cmake command line. -#### **Configure platform and architecture** +### **Configure platform and architecture** - **WAMR_BUILD_PLATFORM**: set the target platform. It can be set to any platform name (folder name) under folder [core/shared/platform](../core/shared/platform). @@ -34,7 +34,7 @@ The script `runtime_lib.cmake` defines a number of variables for configuring the cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM ``` -#### **Configure interpreters** +### **Configure interpreters** - **WAMR_BUILD_INTERP**=1/0: enable or disable WASM interpreter @@ -42,14 +42,14 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM NOTE: the fast interpreter runs ~2X faster than classic interpreter, but consumes about 2X memory to hold the pre-compiled code. -#### **Configure AOT and JITs** +### **Configure AOT and JITs** - **WAMR_BUILD_AOT**=1/0, enable AOT or not, default to enable if not set - **WAMR_BUILD_JIT**=1/0, enable LLVM JIT or not, default to disable if not set - **WAMR_BUILD_FAST_JIT**=1/0, enable Fast JIT or not, default to disable if not set - **WAMR_BUILD_FAST_JIT**=1 and **WAMR_BUILD_JIT**=1, enable Multi-tier JIT, default to disable if not set -#### **Configure LIBC** +### **Configure LIBC** - **WAMR_BUILD_LIBC_BUILTIN**=1/0, build the built-in libc subset for WASM app, default to enable if not set @@ -59,98 +59,98 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM > Note: for platform which doesn't support **WAMR_BUILD_LIBC_WASI**, e.g. Windows, developer can try using **WAMR_BUILD_LIBC_UVWASI**. -#### **Enable Multi-Module feature** +### **Enable Multi-Module feature** - **WAMR_BUILD_MULTI_MODULE**=1/0, default to disable if not set > Note: See [Multiple Modules as Dependencies](./multi_module.md) for more details. -#### **Enable WASM mini loader** +### **Enable WASM mini loader** - **WAMR_BUILD_MINI_LOADER**=1/0, default to disable if not set > Note: the mini loader doesn't check the integrity of the WASM binary file, developer must ensure that the WASM file is well-formed. -#### **Enable shared memory feature** +### **Enable shared memory feature** - **WAMR_BUILD_SHARED_MEMORY**=1/0, default to disable if not set -#### **Enable bulk memory feature** +### **Enable bulk memory feature** - **WAMR_BUILD_BULK_MEMORY**=1/0, default to disable if not set -#### **Enable memory64 feature** +### **Enable memory64 feature** - **WAMR_BUILD_MEMORY64**=1/0, default to disable if not set > Note: Currently, the memory64 feature is only supported in classic interpreter running mode and AOT mode. -#### **Enable thread manager** +### **Enable thread manager** - **WAMR_BUILD_THREAD_MGR**=1/0, default to disable if not set -#### **Enable lib-pthread** +### **Enable lib-pthread** - **WAMR_BUILD_LIB_PTHREAD**=1/0, default to disable if not set > Note: The dependent feature of lib pthread such as the `shared memory` and `thread manager` will be enabled automatically. > See [WAMR pthread library](./pthread_library.md) for more details. -#### **Enable lib-pthread-semaphore** +### **Enable lib-pthread-semaphore** - **WAMR_BUILD_LIB_PTHREAD_SEMAPHORE**=1/0, default to disable if not set > Note: This feature depends on `lib-pthread`, it will be enabled automatically if this feature is enabled. -#### **Enable lib wasi-threads** +### **Enable lib wasi-threads** - **WAMR_BUILD_LIB_WASI_THREADS**=1/0, default to disable if not set > Note: The dependent feature of lib wasi-threads such as the `shared memory` and `thread manager` will be enabled automatically. > See [wasi-threads](./pthread_impls.md#wasi-threads-new) and [Introduction to WAMR WASI threads](https://bytecodealliance.github.io/wamr.dev/blog/introduction-to-wamr-wasi-threads) for more details. -#### **Enable lib wasi-nn** +### **Enable lib wasi-nn** - **WAMR_BUILD_WASI_NN**=1/0, default to disable if not set > Note: See [WASI-NN](../core/iwasm/libraries/wasi-nn) for more details. -#### **Enable lib wasi-nn GPU mode** +### **Enable lib wasi-nn GPU mode** - **WAMR_BUILD_WASI_NN_ENABLE_GPU**=1/0, default to disable if not set -#### **Enable lib wasi-nn external delegate mode** +### **Enable lib wasi-nn external delegate mode** - **WAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE**=1/0, default to disable if not set - **WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH**=Path to the external delegate shared library (e.g. `libedgetpu.so.1.0` for Coral USB) -#### **Enable lib wasi-nn with `wasi_ephemeral_nn` module support** +### **Enable lib wasi-nn with `wasi_ephemeral_nn` module support** - **WAMR_BUILD_WASI_EPHEMERAL_NN**=1/0, default to disable if not set -#### **Disable boundary check with hardware trap** +### **Disable boundary check with hardware trap** - **WAMR_DISABLE_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform > Note: by default only platform [linux/darwin/android/windows/vxworks 64-bit](https://github.com/bytecodealliance/wasm-micro-runtime/blob/5fb5119239220b0803e7045ca49b0a29fe65e70e/core/shared/platform/linux/platform_internal.h#L81) will enable the boundary check with hardware trap feature, for 32-bit platforms it's automatically disabled even when the flag is set to 0, and the wamrc tool will generate AOT code without boundary check instructions in all 64-bit targets except SGX to improve performance. The boundary check includes linear memory access boundary and native stack access boundary, if `WAMR_DISABLE_STACK_HW_BOUND_CHECK` below isn't set. -#### **Disable native stack boundary check with hardware trap** +### **Disable native stack boundary check with hardware trap** - **WAMR_DISABLE_STACK_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform, same as `WAMR_DISABLE_HW_BOUND_CHECK`. > Note: When boundary check with hardware trap is disabled, or `WAMR_DISABLE_HW_BOUND_CHECK` is set to 1, the native stack boundary check with hardware trap will be disabled too, no matter what value is set to `WAMR_DISABLE_STACK_HW_BOUND_CHECK`. And when boundary check with hardware trap is enabled, the status of this feature is set according to the value of `WAMR_DISABLE_STACK_HW_BOUND_CHECK`. -#### **Disable async wakeup of blocking operation** +### **Disable async wakeup of blocking operation** - **WAMR_DISABLE_WAKEUP_BLOCKING_OP**=1/0, default to enable if supported by the platform > Note: The feature helps async termination of blocking threads. If you disable it, the runtime can wait for termination of blocking threads possibly forever. -#### **Enable tail call feature** +### **Enable tail call feature** - **WAMR_BUILD_TAIL_CALL**=1/0, default to disable if not set -#### **Enable 128-bit SIMD feature** +### **Enable 128-bit SIMD feature** - **WAMR_BUILD_SIMD**=1/0, default to enable if not set > Note: only supported in AOT mode x86-64 target. -#### **Enable Exception Handling** +### **Enable Exception Handling** - **WAMR_BUILD_EXCE_HANDLING**=1/0, default to disable if not set > Note: Currently, the exception handling feature is only supported in classic interpreter running mode. -#### **Enable Garbage Collection** +### **Enable Garbage Collection** - **WAMR_BUILD_GC**=1/0, default to disable if not set -#### **Configure Debug** +### **Configure Debug** - **WAMR_BUILD_CUSTOM_NAME_SECTION**=1/0, load the function name from custom name section, default to disable if not set -#### **Enable AOT stack frame feature** +### **Enable AOT stack frame feature** - **WAMR_BUILD_AOT_STACK_FRAME**=1/0, default to disable if not set > Note: if it is enabled, the AOT or JIT stack frames (like stack frame of classic interpreter but only necessary data is committed) will be created for AOT or JIT mode in function calls. And please add `--enable-dump-call-stack` option to wamrc during compiling AOT module. -#### **Enable dump call stack feature** +### **Enable dump call stack feature** - **WAMR_BUILD_DUMP_CALL_STACK**=1/0, default to disable if not set > Note: if it is enabled, the call stack will be dumped when exception occurs. @@ -158,14 +158,14 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM > - For interpreter mode, the function names are firstly extracted from *custom name section*, if this section doesn't exist or the feature is not enabled, then the name will be extracted from the import/export sections > - For AOT/JIT mode, the function names are extracted from import/export section, please export as many functions as possible (for `wasi-sdk` you can use `-Wl,--export-all`) when compiling wasm module, and add `--enable-dump-call-stack --emit-custom-sections=name` option to wamrc during compiling AOT module. -#### **Enable memory profiling (Experiment)** +### **Enable memory profiling (Experiment)** - **WAMR_BUILD_MEMORY_PROFILING**=1/0, default to disable if not set > Note: if it is enabled, developer can use API `void wasm_runtime_dump_mem_consumption(wasm_exec_env_t exec_env)` to dump the memory consumption info. Currently we only profile the memory consumption of module, module_instance and exec_env, the memory consumed by other components such as `wasi-ctx`, `multi-module` and `thread-manager` are not included. > Also refer to [Memory usage estimation for a module](./memory_usage.md). -#### **Enable performance profiling (Experiment)** +### **Enable performance profiling (Experiment)** - **WAMR_BUILD_PERF_PROFILING**=1/0, default to disable if not set > Note: if it is enabled, developer can use API `void wasm_runtime_dump_perf_profiling(wasm_module_inst_t module_inst)` to dump the performance consumption info. Currently we only profile the performance consumption of each WASM function. @@ -173,24 +173,24 @@ Currently we only profile the memory consumption of module, module_instance and > Also refer to [Tune the performance of running wasm/aot file](./perf_tune.md). -#### **Enable the global heap** +### **Enable the global heap** - **WAMR_BUILD_GLOBAL_HEAP_POOL**=1/0, default to disable if not set for all *iwasm* applications, except for the platforms Alios and Zephyr. > **WAMR_BUILD_GLOBAL_HEAP_POOL** is used in the *iwasm* applications provided in the directory `product-mini`. When writing your own host application using WAMR, if you want to use a global heap and allocate memory from it, you must set the initialization argument `mem_alloc_type` to `Alloc_With_Pool`. > The global heap is defined in the documentation [Memory model and memory usage tunning](memory_tune.md). -#### **Set the global heap size** +### **Set the global heap size** - **WAMR_BUILD_GLOBAL_HEAP_SIZE**=n, default to 10 MB (10485760) if not set for all *iwasm* applications, except for the platforms Alios (256 kB), Riot (256 kB) and Zephyr (128 kB). > **WAMR_BUILD_GLOBAL_HEAP_SIZE** is used in the *iwasm* applications provided in the directory `product-mini`. When writing your own host application using WAMR, if you want to set the amount of memory dedicated to the global heap pool, you must set the initialization argument `mem_alloc_option.pool` with the appropriate values. > The global heap is defined in the documentation [Memory model and memory usage tunning](memory_tune.md). > Note: if `WAMR_BUILD_GLOBAL_HEAP_SIZE` is not set and the flag `WAMR_BUILD_SPEC_TEST` is set, the global heap size is equal to 300 MB (314572800), or 100 MB (104857600) when compiled for Intel SGX (Linux). -#### **Set maximum app thread stack size** +### **Set maximum app thread stack size** - **WAMR_APP_THREAD_STACK_SIZE_MAX**=n, default to 8 MB (8388608) if not set > Note: the AOT boundary check with hardware trap mechanism might consume large stack since the OS may lazily grow the stack mapping as a guard page is hit, we may use this configuration to reduce the total stack usage, e.g. -DWAMR_APP_THREAD_STACK_SIZE_MAX=131072 (128 KB). -#### **Set vprintf callback** +### **Set vprintf callback** - **WAMR_BH_VPRINTF**=, default to disable if not set > Note: if the vprintf_callback function is provided by developer, the os_printf() and os_vprintf() in Linux, Darwin, Windows, VxWorks, Android and esp-idf platforms, besides WASI Libc output will call the callback function instead of libc vprintf() function to redirect the stdout output. For example, developer can define the callback function like below outside runtime lib: > @@ -212,7 +212,7 @@ Currently we only profile the memory consumption of module, module_instance and > > and then use `cmake -DWAMR_BH_VPRINTF=my_vprintf ..` to pass the callback function, or add `BH_VPRINTF=my_vprintf` macro for the compiler, e.g. add line `add_definitions(-DBH_VPRINTF=my_vprintf)` in CMakeLists.txt. See [basic sample](../samples/basic/src/main.c) for a usage example. -#### **WAMR_BH_LOG**=, default to disable if not set +### **WAMR_BH_LOG**=, default to disable if not set > Note: if the log_callback function is provided by the developer, WAMR logs are redirected to such callback. For example: > ```C > void my_log(uint32 log_level, const char *file, int line, const char *fmt, ...) @@ -222,20 +222,20 @@ Currently we only profile the memory consumption of module, module_instance and > ``` > See [basic sample](../samples/basic/src/main.c) for a usage example. -#### **Enable reference types feature** -- **WAMR_BUILD_REF_TYPES**=1/0, default to disable if not set +### **Enable reference types feature** +- **WAMR_BUILD_REF_TYPES**=1/0, default to enable if not set -#### **Exclude WAMR application entry functions** +### **Exclude WAMR application entry functions** - **WAMR_DISABLE_APP_ENTRY**=1/0, default to disable if not set > Note: The WAMR application entry (`core/iwasm/common/wasm_application.c`) encapsulate some common process to instantiate, execute the wasm functions and print the results. Some platform related APIs are used in these functions, so you can enable this flag to exclude this file if your platform doesn't support those APIs. > *Don't enable this flag if you are building `product-mini`* -#### **Enable source debugging features** +### **Enable source debugging features** - **WAMR_BUILD_DEBUG_INTERP**=1/0, default to 0 if not set > Note: There are some other setup required by source debugging, please refer to [source_debugging.md](./source_debugging.md) and [WAMR source debugging basic](https://bytecodealliance.github.io/wamr.dev/blog/wamr-source-debugging-basic) for more details. -#### **Enable load wasm custom sections** +### **Enable load wasm custom sections** - **WAMR_BUILD_LOAD_CUSTOM_SECTION**=1/0, default to disable if not set > Note: By default, the custom sections are ignored. If the embedder wants to get custom sections from `wasm_module_t`, then `WAMR_BUILD_LOAD_CUSTOM_SECTION` should be enabled, and then `wasm_runtime_get_custom_section` can be used to get a custom section by name. @@ -244,29 +244,29 @@ Currently we only profile the memory consumption of module, module_instance and > For AoT file, must use `--emit-custom-sections` to specify which sections need to be emitted into AoT file, otherwise all custom sections will be ignored. -#### **Stack guard size** +### **Stack guard size** - **WAMR_BUILD_STACK_GUARD_SIZE**=n, default to N/A if not set. > Note: By default, the stack guard size is 1K (1024) or 24K (if uvwasi enabled). -#### **Disable writing the linear memory base address to x86 GS segment register** +### **Disable writing the linear memory base address to x86 GS segment register** - **WAMR_DISABLE_WRITE_GS_BASE**=1/0, default to enable if not set and supported by platform > Note: by default only platform [linux x86-64](https://github.com/bytecodealliance/wasm-micro-runtime/blob/5fb5119239220b0803e7045ca49b0a29fe65e70e/core/shared/platform/linux/platform_internal.h#L67) will enable this feature, for 32-bit platforms it's automatically disabled even when the flag is set to 0. In linux x86-64, writing the linear memory base address to x86 GS segment register may be used to speedup the linear memory access for LLVM AOT/JIT, when `--enable-segue=[]` option is added for `wamrc` or `iwasm`. > See [Enable segue optimization for wamrc when generating the aot file](./perf_tune.md#3-enable-segue-optimization-for-wamrc-when-generating-the-aot-file) for more details. -#### **User defined linear memory allocator** +### **User defined linear memory allocator** - **WAMR_BUILD_ALLOC_WITH_USAGE**=1/0, default to disable if not set > Notes: by default, the linear memory is allocated by system. when it's set to 1 and Alloc_With_Allocator is selected, it will be allocated by customer. -#### **Enable running PGO(Profile-Guided Optimization) instrumented AOT file** +### **Enable running PGO(Profile-Guided Optimization) instrumented AOT file** - **WAMR_BUILD_STATIC_PGO**=1/0, default to disable if not set > Note: See [Use the AOT static PGO method](./perf_tune.md#5-use-the-aot-static-pgo-method) for more details. -#### **Enable linux perf support** +### **Enable linux perf support** - **WAMR_BUILD_LINUX_PERF**=1/0, enable linux perf support to generate the flamegraph to analyze the performance of a wasm application, default to disable if not set > Note: See [Use linux-perf](./perf_tune.md#7-use-linux-perf) for more details. -#### **Enable module instance context APIs** +### **Enable module instance context APIs** - **WAMR_BUILD_MODULE_INST_CONTEXT**=1/0, enable module instance context APIs which can set one or more contexts created by the embedder for a wasm module instance, default to enable if not set: ```C wasm_runtime_create_context_key @@ -277,19 +277,19 @@ Currently we only profile the memory consumption of module, module_instance and ``` > Note: See [wasm_export.h](../core/iwasm/include/wasm_export.h) for more details. -#### **Enable quick AOT/JTI entries** +### **Enable quick AOT/JTI entries** - **WAMR_BUILD_QUICK_AOT_ENTRY**=1/0, enable registering quick call entries to speedup the aot/jit func call process, default to enable if not set > Note: See [Refine callings to AOT/JIT functions from host native](./perf_tune.md#83-refine-callings-to-aotjit-functions-from-host-native) for more details. -#### **Enable AOT intrinsics** +### **Enable AOT intrinsics** - **WAMR_BUILD_AOT_INTRINSICS**=1/0, enable the AOT intrinsic functions, default to enable if not set. These functions can be called from the AOT code when `--disable-llvm-intrinsics` flag or `--enable-builtin-intrinsics=` flag is used by wamrc to generate the AOT file. > Note: See [Tuning the XIP intrinsic functions](./xip.md#tuning-the-xip-intrinsic-functions) for more details. -#### **Configurable memory access boundary check** +### **Configurable memory access boundary check** - **WAMR_CONFIGURABLE_BOUNDS_CHECKS**=1/0, default to disable if not set > Note: If it is enabled, allow to run `iwasm --disable-bounds-checks` to disable the memory access boundary checks for interpreter mode. -#### **Module instance context APIs** +### **Module instance context APIs** - **WAMR_BUILD_MODULE_INST_CONTEXT**=1/0, default to disable if not set > Note: If it is enabled, allow to set one or more contexts created by embedder for a module instance, the below APIs are provided: ```C @@ -300,7 +300,7 @@ Currently we only profile the memory consumption of module, module_instance and wasm_runtime_get_context ``` -#### **Shared heap among wasm apps and host native** +### **Shared heap among wasm apps and host native** - **WAMR_BUILD_SHARED_HEAP**=1/0, default to disable if not set > Note: If it is enabled, allow to create one or more shared heaps, and attach one to a module instance, the belows APIs ared provided: ```C @@ -316,7 +316,11 @@ And the wasm app can calls below APIs to allocate/free memory from/to the shared void shared_heap_free(void *ptr); ``` -**Combination of configurations:** +### **Shrunk the memory usage** +- **WAMR_BUILD_SHRUNK_MEMORY**=1/0, default to enable if not set +> Note: When enabled, this feature will reduce memory usage by decreasing the size of the linear memory, particularly when the `memory.grow` opcode is not used and memory usage is somewhat predictable. + +## **Combination of configurations:** We can combine the configurations. For example, if we want to disable interpreter, enable AOT and WASI, we can run command: @@ -328,4 +332,4 @@ Or if we want to enable interpreter, disable AOT and WASI, and build as X86_32, ``` Bash cmake .. -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_AOT=0 -DWAMR_BUILD_LIBC_WASI=0 -DWAMR_BUILD_TARGET=X86_32 -``` +``` \ No newline at end of file diff --git a/doc/build_wasm_app.md b/doc/build_wasm_app.md index 9536d1a8d1..95d237346c 100644 --- a/doc/build_wasm_app.md +++ b/doc/build_wasm_app.md @@ -16,24 +16,24 @@ For [AssemblyScript](https://github.com/AssemblyScript/assemblyscript), please r For Rust, please refer to [Install Rust and Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) to install *cargo*, *rustc* and *rustup*. By default they are under ~/.cargo/bin. -And then run such a command to install `wasm32-wasi` target. +And then run such a command to install `wasm32-wasip1` target. ``` bash -$ rustup target add wasm32-wasi +$ rustup target add wasm32-wasip1 ``` To build WASM applications, run ``` bash -$ cargo build --target wasm32-wasi +$ cargo build --target wasm32-wasip1 ``` -The output files are under `target/wasm32-wasi`. +The output files are under `target/wasm32-wasip1`. To build a release version ``` bash -$ cargo build --release --target wasm32-wasi +$ cargo build --release --target wasm32-wasip1 ``` diff --git a/doc/memory_tune.md b/doc/memory_tune.md index 48c6417101..30e0b7a79d 100644 --- a/doc/memory_tune.md +++ b/doc/memory_tune.md @@ -32,6 +32,7 @@ Normally there are some methods to tune the memory usage: - use XIP mode, refer to [WAMR XIP (Execution In Place) feature introduction](./xip.md) for more details - when using the Wasm C API in fast interpreter or AOT mode, set `clone_wasm_binary=false` in `LoadArgs` and free the wasm binary buffer (with `wasm_byte_vec_delete`) after module loading; `wasm_module_is_underlying_binary_freeable` can be queried to check if the wasm binary buffer can be safely freed (see [the example](../samples/basic/src/free_buffer_early.c)); after the buffer is freed, `wasm_runtime_get_custom_section` cannot be called anymore - when using the wasm/AOT loader in fast interpreter or AOT mode, set `wasm_binary_freeable=true` in `LoadArgs` and free the wasm binary buffer (with `wasm_byte_vec_delete`) after module loading; `wasm_runtime_is_underlying_binary_freeable` can be queried to check if the wasm binary buffer can be safely freed; after the buffer is freed, `wasm_runtime_get_custom_section` cannot be called anymore +- `WAMR_BUILD_SHRUNK_MEMORY` can be used to reduce the memory usage of WAMR, but it might affect the standard expected behavior of WAMR. ## With valgrind diff --git a/doc/security_need_to_know.md b/doc/security_need_to_know.md new file mode 100644 index 0000000000..b2b358983d --- /dev/null +++ b/doc/security_need_to_know.md @@ -0,0 +1,33 @@ +# About security issues + +This document aims to explain the process of identifying a security issue and the steps for managing a security issue. + +## identifying a security issue + +It is commonly stated that a security issue is an issue that: + +- Exposes sensitive information to unauthorized parties. +- Allows unauthorized modification of data or system state. +- Affects the availability of the system or its services. +- Permits unauthorized access to the system. +- Enables users to perform actions they should not be able to. +- Allows users to deny actions they have performed. + +Given that WASI is a set of Capability-based APIs, all unauthorized actions are not supposed to happen. Most of the above security concerns can be alleviated. What remains for us is to ensure that the execution of Wasm modules is secure. In other words, do not compromise the sandbox. Unless it is explicitly disabled beforehand. + +Thus, we share most of the criteria for judging security issues with [the Bytecode Alliance](https://github.com/bytecodealliance/rfcs/blob/main/accepted/what-is-considered-a-security-bug.md#definition). + +> [!NOTE] +> keep updating this document as the project evolves. + +## reporting a security issue + +Follow the [same guidelines](https://bytecodealliance.org/security) as other projects within the Bytecode Alliance. + +## managing a security issue + +Before reporting an issue, particularly one related to crashing, consult [the cheat sheet](https://github.com/bytecodealliance/rfcs/blob/main/accepted/what-is-considered-a-security-bug.md#cheat-sheet-is-this-bug-considered-a-security-vulnerability), _Report a security vulnerability_ if it qualifies. + +Upon receiving an issue, thoroughly review [the cheat sheet](https://github.com/bytecodealliance/rfcs/blob/main/accepted/what-is-considered-a-security-bug.md#cheat-sheet-is-this-bug-considered-a-security-vulnerability) to assess and _Report a security vulnerability_ if the issue is indeed a security vulnerability. + +Once a security issue is confirmed, please refer to [the runbook](https://github.com/bytecodealliance/rfcs/blob/main/accepted/vulnerability-response-runbook.md) for the subsequent steps to take. diff --git a/doc/semantic_version.md b/doc/semantic_version.md deleted file mode 100644 index 9fdd65d605..0000000000 --- a/doc/semantic_version.md +++ /dev/null @@ -1,21 +0,0 @@ -# WAMR uses semantic versioning - -WAMR uses the _semantic versioning_ to replace the current _date versioning_ system. - -There are three parts in the new version string: - -- _major_. Any incompatible modification, on both ABI and APIs, will lead an increment - in the value of _major_. APIs includes: `wasm_export.h`, `wasm_c_api.h`, - _sections in AOT files_, and so on. -- _minor_. It represents new features. It includes not just MVP or POST-MVP features - but also WASI features and WAMR private ones. -- _patch_. It represents patches. - -## Legacy versions - -All legacy versions(tags) will keep their current status. No existing release names -and links will be changed. - -## Reference - -- [Semantic Versioning 2.0.0](https://semver.org/) diff --git a/doc/stability_release.md b/doc/stability_release.md new file mode 100644 index 0000000000..78e034a3df --- /dev/null +++ b/doc/stability_release.md @@ -0,0 +1,33 @@ +# Semantic Versioning + +WAMR has adopted [semantic versioning](https://semver.org/) to replace the former *date versioning system*. The new version string consists of three parts: + +- *major*: Any change that is not compatible with previous versions, affecting either the ABI or APIs, will result in an increase in the major version number. APIs include: wasm_export.h, wasm_c_api.h, sections in AOT files, among others. +- *minor*: This number increases with the addition of new features. This encompasses not only MVP (Minimum Viable Product) or POST-MVP features but also WebAssembly System Interface (WASI) features and WAMR-specific features. +- *patch*: This number is incremented for patches. + +## Legacy releases + +All previous versions (tags) will retain their current status. There will be no changes to existing release names and links. + +# Release Process + +WAMR has been deployed across various devices. A frequent release cycle would strain customers' testing resources and add extra deployment work. Two factors can trigger a new WAMR release: + +- Community requests, particularly following the integration of significant and new features. +- Security vulnerabilities and critical bug fixes that ensure correctness. + +Patch releases will be made only to address security vulnerabilities and critical issues related to default behavior in prior releases. + +Once a release decision has been made: + +- Create a PR that: + 1. Modifies *build-scripts/version.cmake*. + 2. Executes cmake configuration to update the version. + 3. Updates *RELEASE_NOTES.md*. +- A checklist of the PR includes + - [ ] *build-scripts/version.cmake* + - [ ] *core/version.h* + - [ ] *RELEASE_NOTES.md* +- Once the PR is merged, create a new tag. +- Initiate the release process by triggering *the binary release processes* in *Actions*. diff --git a/doc/stability_wasm_proposals.md b/doc/stability_wasm_proposals.md new file mode 100644 index 0000000000..715f2f3bdf --- /dev/null +++ b/doc/stability_wasm_proposals.md @@ -0,0 +1,82 @@ +# Wasm Proposals + +This document is intended to describe the current status of WebAssembly proposals and WASI proposals in WAMR. + +Only track proposals that are followed in the [WebAssembly proposals](https://github.com/WebAssembly/proposals) and [WASI proposals](https://github.com/WebAssembly/WASI/blob/main/Proposals.md). + +Normally, the document tracks proposals that are in phase 4. However, if a proposal in an earlier phase receives support, it will be added to the list below. + +The _status_ represents the configuration _product-mini/platforms/linux/CMakeLists.txt_. There may be minor differences between the top-level CMakeLists and platform-specific CMakeLists. + +Users can turn those features on or off by using compilation options. If a relevant compilation option is not available(`N/A`), it indicates that the feature is permanently enabled. + +## On-by-default Wasm Proposals + +| Proposal | >= Phase 4 | Compilation Option | +| ------------------------------------- | ---------- | ------------------------ | +| Bulk memory operations | Yes | `WAMR_BUILD_BULK_MEMORY` | +| Extended Constant Expressions | Yes | N/A | +| Fixed-width SIMD[^1] | Yes | `WAMR_BUILD_SIMD` | +| Multi-value | Yes | N/A | +| Non-trapping float-to-int conversions | Yes | N/A | +| Reference Types | Yes | `WAMR_BUILD_REF_TYPES` | +| Sign-extension operators | Yes | N/A | +| WebAssembly C and C++ API | No | N/A | + +[^1]: llvm-jit and aot only. + +## Off-by-default Wasm Proposals + +| Proposal | >= Phase 4 | Compilation Option | +| ----------------------------- | ---------- | -------------------------- | +| Garbage collection | Yes | `WAMR_BUILD_GC` | +| Legacy Exception handling[^2] | No | `WAMR_BUILD_EXCE_HANDLING` | +| Memory64 | Yes | `WAMR_BUILD_MEMORY64` | +| Multiple memories[^3] | Yes | `WAMR_BUILD_MULTI_MEMORY` | +| Reference-Typed Strings | No | `WAMR_BUILD_STRINGREF` | +| Tail call | Yes | `WAMR_BUILD_TAIL_CALL` | +| Threads[^4] | Yes | `WAMR_BUILD_SHARED_MEMORY` | +| Typed Function References | Yes | `WAMR_BUILD_GC` | + +[^2]: + interpreter only. [a legacy version](https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md). + This proposal is currently also known as the "legacy proposal" and still + supported in the web, but can be deprecated in future and the use of + this proposal is discouraged. + +[^3]: interpreter only +[^4]: `WAMR_BUILD_LIB_PTHREAD` can also be used to enable + +## Unimplemented Wasm Proposals + +| Proposal | >= Phase 4 | +| ------------------------------------------- | ---------- | +| Branch Hinting | Yes | +| Custom Annotation Syntax in the Text Format | Yes | +| Exception handling[^5] | Yes | +| Import/Export of Mutable Globals | Yes | +| JS String Builtins | Yes | +| Relaxed SIMD | Yes | + +[^5]: [up-to-date version](https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md) + +## On-by-default WASI Proposals + +| Proposal | >= Phase 4 | Compilation Option | +| -------- | ---------- | ------------------ | + +## Off-by-default WASI Proposals + +| Proposal | >= Phase 4 | Compilation Option | +| -------------------------- | ---------- | ----------------------------- | +| Machine Learning (wasi-nn) | No | `WAMR_BUILD_WASI_NN` | +| Threads | No | `WAMR_BUILD_LIB_WASI_THREADS` | + +## Unimplemented WASI Proposals + +| Proposal | >= Phase 4 | +| -------- | ---------- | + +## WAMR features + +WAMR offers a variety of customizable features to create a highly efficient runtime. For more details, please refer to [build_wamr](./build_wamr.md). diff --git a/product-mini/platforms/android/CMakeLists.txt b/product-mini/platforms/android/CMakeLists.txt index 5c05259176..19bc1b11e7 100644 --- a/product-mini/platforms/android/CMakeLists.txt +++ b/product-mini/platforms/android/CMakeLists.txt @@ -107,6 +107,8 @@ include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +set_version_info (vmlib) + 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") @@ -135,6 +137,7 @@ endif() set (distribution_DIR ${CMAKE_BINARY_DIR}/distribution) set_target_properties (iwasm PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${distribution_DIR}/wasm/lib") +set_version_info (iwasm) add_custom_command (TARGET iwasm POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory "${WAMR_ROOT_DIR}/core/iwasm/include" "${distribution_DIR}/wasm/include/" diff --git a/product-mini/platforms/common/wasm_proposal.c b/product-mini/platforms/common/wasm_proposal.c new file mode 100644 index 0000000000..4bf6ab3e95 --- /dev/null +++ b/product-mini/platforms/common/wasm_proposal.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +void +wasm_proposal_print_status(void) +{ + printf("About Wasm Proposals:\n"); + printf(" Always-on:\n"); + printf(" - Extended Constant Expressions\n"); + printf(" - Multi-value\n"); + printf(" - Non-trapping float-to-int conversions\n"); + printf(" - Sign-extension operators\n"); + printf(" - WebAssembly C and C++ API\n"); + printf(" Compilation Configurable. 0 is OFF. 1 is ON:\n"); + printf(" - Bulk Memory Operation via WASM_ENABLE_BULK_MEMORY: %u\n", + WASM_ENABLE_BULK_MEMORY); + printf(" - Fixed-Width SIMD via WASM_ENABLE_SIMD: %u\n", + WASM_ENABLE_SIMD); + printf(" - Garbage Collection via WASM_ENABLE_GC: %u\n", WASM_ENABLE_GC); + printf( + " - Legacy Exception Handling via WASM_ENABLE_EXCE_HANDLING: %u\n", + WASM_ENABLE_EXCE_HANDLING); + printf(" - Memory64 via WASM_ENABLE_MEMORY64: %u\n", + WASM_ENABLE_MEMORY64); + printf(" - Multiple Memory via WASM_ENABLE_MULTI_MEMORY: %u\n", + WASM_ENABLE_MULTI_MEMORY); + printf(" - Reference Types via WASM_ENABLE_REF_TYPES: %u\n", + WASM_ENABLE_REF_TYPES); + printf(" - Reference-Typed Strings via WASM_ENABLE_REF_TYPES: %u\n", + WASM_ENABLE_REF_TYPES); + printf(" - Tail Call via WASM_ENABLE_TAIL_CALL: %u\n", + WASM_ENABLE_TAIL_CALL); + printf(" - Threads via WASM_ENABLE_SHARED_MEMORY: %u\n", + WASM_ENABLE_SHARED_MEMORY); + printf(" - Typed Function References via WASM_ENABLE_GC: %u\n", + WASM_ENABLE_GC); + printf(" Unsupported (>= Phase4):\n"); + printf(" - Branch Hinting\n"); + printf(" - Custom Annotation Syntax in the Text Format\n"); + printf(" - Exception handling\n"); + printf(" - Import/Export of Mutable Globals\n"); + printf(" - JS String Builtins\n"); + printf(" - Relaxed SIMD\n"); +} diff --git a/product-mini/platforms/cosmopolitan/CMakeLists.txt b/product-mini/platforms/cosmopolitan/CMakeLists.txt index 8533ea68ce..7676ea6fb8 100644 --- a/product-mini/platforms/cosmopolitan/CMakeLists.txt +++ b/product-mini/platforms/cosmopolitan/CMakeLists.txt @@ -132,6 +132,7 @@ include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) check_pie_supported() add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) set_target_properties (vmlib PROPERTIES POSITION_INDEPENDENT_CODE ON) +set_version_info (vmlib) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") @@ -160,6 +161,8 @@ include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) +set_version_info (iwasm) + set_target_properties (iwasm PROPERTIES POSITION_INDEPENDENT_CODE ON) install (TARGETS iwasm DESTINATION bin) @@ -168,6 +171,8 @@ target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} ${WASI_NN add_library (libiwasm STATIC ${WAMR_RUNTIME_LIB_SOURCE}) +set_version_info (libiwasm) + install (TARGETS libiwasm DESTINATION lib) set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) diff --git a/product-mini/platforms/darwin/CMakeLists.txt b/product-mini/platforms/darwin/CMakeLists.txt index 865e516fca..594110a442 100644 --- a/product-mini/platforms/darwin/CMakeLists.txt +++ b/product-mini/platforms/darwin/CMakeLists.txt @@ -1,10 +1,12 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 2.9) +cmake_minimum_required (VERSION 3.14) project (iwasm) +option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) + set (WAMR_BUILD_PLATFORM "darwin") # Reset default linker flags @@ -91,6 +93,11 @@ if (NOT DEFINED WAMR_BUILD_SIMD) set (WAMR_BUILD_SIMD 1) endif () +if (NOT DEFINED WAMR_BUILD_REF_TYPES) + # Enable reference types by default + set (WAMR_BUILD_REF_TYPES 1) +endif () + if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP) # Disable Debug feature by default set (WAMR_BUILD_DEBUG_INTERP 0) @@ -110,21 +117,41 @@ set (CMAKE_MACOSX_RPATH True) set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) -add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) - include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) +set_version_info (iwasm) + install (TARGETS iwasm DESTINATION bin) -target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) +target_link_libraries (iwasm vmlib) + +add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +set_version_info (vmlib) + +target_include_directories(vmlib INTERFACE + $ +) -add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) +set (WAMR_PUBLIC_HEADERS + ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_c_api.h + ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h + ${WAMR_ROOT_DIR}/core/iwasm/include/lib_export.h +) -install (TARGETS libiwasm DESTINATION lib) +set_target_properties (vmlib PROPERTIES + OUTPUT_NAME iwasm + PUBLIC_HEADER "${WAMR_PUBLIC_HEADERS}" +) -set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) +target_link_libraries (vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) -target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) +install (TARGETS vmlib + EXPORT iwasmTargets + DESTINATION lib + PUBLIC_HEADER DESTINATION include/iwasm +) +install_iwasm_package () diff --git a/product-mini/platforms/freebsd/CMakeLists.txt b/product-mini/platforms/freebsd/CMakeLists.txt index dd1bbc41a5..5640a384a0 100644 --- a/product-mini/platforms/freebsd/CMakeLists.txt +++ b/product-mini/platforms/freebsd/CMakeLists.txt @@ -113,17 +113,22 @@ 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_version_info (vmlib) include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) +set_version_info (iwasm) + install (TARGETS iwasm DESTINATION bin) target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) +set_version_info (libiwasm) + install (TARGETS libiwasm DESTINATION lib) set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) diff --git a/product-mini/platforms/ios/CMakeLists.txt b/product-mini/platforms/ios/CMakeLists.txt index ea5a4f4b9d..ca54aa1556 100644 --- a/product-mini/platforms/ios/CMakeLists.txt +++ b/product-mini/platforms/ios/CMakeLists.txt @@ -139,6 +139,7 @@ endif() set (distribution_DIR ${CMAKE_BINARY_DIR}/distribution) set_target_properties (iwasm PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${distribution_DIR}/wasm/lib") +set_version_info (iwasm) add_custom_command (TARGET iwasm POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory "${WAMR_ROOT_DIR}/core/iwasm/include" "${distribution_DIR}/wasm/include/" diff --git a/product-mini/platforms/linux-sgx/CMakeLists.txt b/product-mini/platforms/linux-sgx/CMakeLists.txt index 20b3fdfac1..927e6f4592 100644 --- a/product-mini/platforms/linux-sgx/CMakeLists.txt +++ b/product-mini/platforms/linux-sgx/CMakeLists.txt @@ -107,6 +107,7 @@ 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_version_info (vmlib) add_custom_command ( OUTPUT libvmlib_untrusted.a diff --git a/product-mini/platforms/linux-sgx/CMakeLists_minimal.txt b/product-mini/platforms/linux-sgx/CMakeLists_minimal.txt index aa3de6dacb..a29dbd69c1 100644 --- a/product-mini/platforms/linux-sgx/CMakeLists_minimal.txt +++ b/product-mini/platforms/linux-sgx/CMakeLists_minimal.txt @@ -78,6 +78,7 @@ 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_version_info (vmlib) add_custom_command ( OUTPUT libvmlib_untrusted.a diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt index 2e37b75f92..be0c57edef 100644 --- a/product-mini/platforms/linux/CMakeLists.txt +++ b/product-mini/platforms/linux/CMakeLists.txt @@ -7,6 +7,8 @@ include(CheckPIESupported) project (iwasm) +option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) + set (CMAKE_VERBOSE_MAKEFILE OFF) set (WAMR_BUILD_PLATFORM "linux") @@ -108,8 +110,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 types by default + set (WAMR_BUILD_REF_TYPES 1) endif () if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP) @@ -126,13 +128,7 @@ endif () # if enable wasi-nn, both wasi-nn-backends and iwasm # need to use same WAMR (dynamic) libraries if (WAMR_BUILD_WASI_NN EQUAL 1) - set (WAMR_BUILD_SHARED 1) -endif () - -if (NOT DEFINED WAMR_BUILD_SHARED) - set (WAMR_BUILD_SHARED 0) -elseif (WAMR_BUILD_SHARED EQUAL 1) - message ("build WAMR as shared libraries") + set (BUILD_SHARED_LIBS ON) endif () set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) @@ -140,8 +136,6 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) check_pie_supported() -add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) -set_target_properties (vmlib PROPERTIES POSITION_INDEPENDENT_CODE ON) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") @@ -170,23 +164,40 @@ include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) +set_version_info (iwasm) + set_target_properties (iwasm PROPERTIES POSITION_INDEPENDENT_CODE ON) -target_link_libraries(iwasm - $<$:libiwasm> $<$>:vmlib> - ${LLVM_AVAILABLE_LIBS} - ${UV_A_LIBS} - -lm - -ldl - -lpthread -) +target_link_libraries(iwasm vmlib) install (TARGETS iwasm DESTINATION bin) -add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) +add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +set_version_info (vmlib) -install (TARGETS libiwasm DESTINATION lib) +target_include_directories(vmlib INTERFACE + $ +) -set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) +set (WAMR_PUBLIC_HEADERS + ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_c_api.h + ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h + ${WAMR_ROOT_DIR}/core/iwasm/include/lib_export.h +) + +set_target_properties (vmlib PROPERTIES + OUTPUT_NAME iwasm + PUBLIC_HEADER "${WAMR_PUBLIC_HEADERS}" + POSITION_INDEPENDENT_CODE ON +) + +target_link_libraries (vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) + +install (TARGETS vmlib + EXPORT iwasmTargets + DESTINATION lib + PUBLIC_HEADER DESTINATION include/iwasm +) -target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) +install_iwasm_package () diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 9fa1ba33a0..77de737740 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -18,6 +18,8 @@ #include "../common/libc_wasi.c" #endif +#include "../common/wasm_proposal.c" + #if BH_HAS_DLFCN #include #endif @@ -798,6 +800,8 @@ main(int argc, char *argv[]) wasm_runtime_get_version(&major, &minor, &patch); printf("iwasm %" PRIu32 ".%" PRIu32 ".%" PRIu32 "\n", major, minor, patch); + printf("\n"); + wasm_proposal_print_status(); return 0; } else { diff --git a/product-mini/platforms/riot/CMakeLists.txt b/product-mini/platforms/riot/CMakeLists.txt index 0032832627..c32a0b9777 100644 --- a/product-mini/platforms/riot/CMakeLists.txt +++ b/product-mini/platforms/riot/CMakeLists.txt @@ -62,3 +62,5 @@ include_directories(SYSTEM ${RIOT_INCLUDES_LIST}) # executable linking is done by RIOT build system add_library( wamr ${WAMR_RUNTIME_LIB_SOURCE}) + +set_version_info (wamr) diff --git a/product-mini/platforms/rt-thread/iwasm.c b/product-mini/platforms/rt-thread/iwasm.c index 7d15a041d0..f8932bdec3 100644 --- a/product-mini/platforms/rt-thread/iwasm.c +++ b/product-mini/platforms/rt-thread/iwasm.c @@ -192,6 +192,21 @@ my_read_file_to_buffer(char *filename, rt_uint32_t *size) { struct stat f_stat; + if (!filename || !size) { + rt_set_errno(-EINVAL); + return RT_NULL; + } + + if (stat(filename, &f_stat) != 0) { + rt_set_errno(errno); + return RT_NULL; + } + + if (f_stat.st_size <= 0) { + rt_set_errno(-EINVAL); + return RT_NULL; + } + rt_uint8_t *buff = rt_malloc(f_stat.st_size); *size = 0; if (!buff) { diff --git a/product-mini/platforms/vxworks/CMakeLists.txt b/product-mini/platforms/vxworks/CMakeLists.txt index 0dc5d96999..dd03cb356f 100644 --- a/product-mini/platforms/vxworks/CMakeLists.txt +++ b/product-mini/platforms/vxworks/CMakeLists.txt @@ -78,17 +78,22 @@ 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_version_info (vmlib) include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) +set_version_info (iwasm) + install (TARGETS iwasm DESTINATION bin) target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl -lunix) add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) +set_version_info (libiwasm) + install (TARGETS libiwasm DESTINATION lib) set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) diff --git a/product-mini/platforms/windows/CMakeLists.txt b/product-mini/platforms/windows/CMakeLists.txt index 40e925b16a..5fcc276a19 100644 --- a/product-mini/platforms/windows/CMakeLists.txt +++ b/product-mini/platforms/windows/CMakeLists.txt @@ -6,6 +6,8 @@ cmake_minimum_required (VERSION 2.9) project (iwasm C ASM CXX) # set (CMAKE_VERBOSE_MAKEFILE 1) +option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) + set (WAMR_BUILD_PLATFORM "windows") # Reset default linker flags @@ -105,7 +107,6 @@ endif() 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_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN") if (NOT MINGW) @@ -132,30 +133,46 @@ endif () include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) -add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) +add_executable (iwasm main.c ${PLATFORM_SHARED_SOURCE} ${UNCOMMON_SHARED_SOURCE} ${UTILS_SHARED_SOURCE}) -install (TARGETS iwasm DESTINATION bin) +set_version_info (iwasm) -target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS}) +install (TARGETS iwasm DESTINATION bin) -if (MINGW) - target_link_libraries (iwasm ws2_32) -endif () +target_link_libraries (iwasm vmlib) -add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) +add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +set_version_info (vmlib) -install (TARGETS libiwasm DESTINATION lib) +target_include_directories(vmlib INTERFACE + $ +) -set_target_properties (libiwasm PROPERTIES OUTPUT_NAME libiwasm) +set (WAMR_PUBLIC_HEADERS + ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_c_api.h + ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h + ${WAMR_ROOT_DIR}/core/iwasm/include/lib_export.h +) -target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS}) +set_target_properties (vmlib PROPERTIES + OUTPUT_NAME libiwasm + PUBLIC_HEADER "${WAMR_PUBLIC_HEADERS}" + POSITION_INDEPENDENT_CODE ON +) +target_link_libraries (vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS}) if (MINGW) - target_link_libraries (libiwasm ws2_32) + target_link_libraries (vmlib ws2_32) endif () if (WIN32) - target_link_libraries(libiwasm ntdll) - - target_link_libraries(iwasm ntdll) + target_link_libraries(vmlib ntdll) endif() + +install (TARGETS vmlib + EXPORT iwasmTargets + DESTINATION lib + PUBLIC_HEADER DESTINATION include/iwasm +) + +install_iwasm_package () diff --git a/product-mini/platforms/zephyr/simple/CMakeLists.txt b/product-mini/platforms/zephyr/simple/CMakeLists.txt index 8b2af15eb7..78dd322858 100644 --- a/product-mini/platforms/zephyr/simple/CMakeLists.txt +++ b/product-mini/platforms/zephyr/simple/CMakeLists.txt @@ -32,7 +32,8 @@ if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) endif () if (NOT DEFINED WAMR_BUILD_LIBC_WASI) - # Disable libc wasi support by default + # Disable libc wasi support by default, in the future, + # it can be enabled if libc wasi file/socket/lock support is ready on Zephyr platform set (WAMR_BUILD_LIBC_WASI 0) endif () diff --git a/product-mini/platforms/zephyr/simple/build_and_run.sh b/product-mini/platforms/zephyr/simple/build_and_run.sh index 6b8fb4f872..bd89906d4a 100755 --- a/product-mini/platforms/zephyr/simple/build_and_run.sh +++ b/product-mini/platforms/zephyr/simple/build_and_run.sh @@ -38,7 +38,7 @@ TARGET=$1 case $TARGET in $X86_TARGET) - west build -b qemu_x86_nommu \ + west build -b qemu_x86_tiny \ . -p always -- \ -DWAMR_BUILD_TARGET=X86_32 west build -t run diff --git a/product-mini/platforms/zephyr/simple/prj.conf b/product-mini/platforms/zephyr/simple/prj.conf index c269b8ab42..8ab3c52f8c 100644 --- a/product-mini/platforms/zephyr/simple/prj.conf +++ b/product-mini/platforms/zephyr/simple/prj.conf @@ -5,3 +5,4 @@ CONFIG_STACK_SENTINEL=y CONFIG_PRINTK=y CONFIG_LOG=y CONFIG_LOG_BUFFER_SIZE=4096 +CONFIG_THREAD_RUNTIME_STATS=y diff --git a/product-mini/platforms/zephyr/user-mode/CMakeLists.txt b/product-mini/platforms/zephyr/user-mode/CMakeLists.txt new file mode 100644 index 0000000000..16c9b26dc0 --- /dev/null +++ b/product-mini/platforms/zephyr/user-mode/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.13.1) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(wamr_user_mode LANGUAGES C) + +# Add the wamr-lib directory +add_subdirectory(lib-wamr-zephyr) + +# Link the wamr library to the app target +target_link_libraries(app PRIVATE wamr_lib) + +target_sources(app PRIVATE src/main.c) diff --git a/product-mini/platforms/zephyr/user-mode/README.md b/product-mini/platforms/zephyr/user-mode/README.md new file mode 100644 index 0000000000..b157467329 --- /dev/null +++ b/product-mini/platforms/zephyr/user-mode/README.md @@ -0,0 +1,60 @@ +# How to use WAMR with Zephyr in user mode + +This example demonstrates how to build and run a WebAssembly application in user mode on Zephyr. + +> Note: The user mode is not supported on all Zephyr boards. Please refer to the Zephyr documentation for more information. + +## Setup + +Please refer to the [previous WAMR Zephyr README.md](../simple/README.md) for general Zephyr setup instructions. + +And refer to [official documentation of Zephyr user mode](https://docs.zephyrproject.org/latest/kernel/usermode/index.html) for more information about Zephyr user mode. + +### Enable user mode + +To enable Zephyr user mode, set the `CONFIG_USERSPACE` option to yes in the Zephyr configuration. + +```conf +CONFIG_USERSPACE=y +``` + +And link the WAMR runtime as a separate library in CMakelists.txt. + +```cmake +...WAMR CMake set up... + +zephyr_library_named (wamr_lib) + +zephyr_library_sources ( + ${WAMR_RUNTIME_LIB_SOURCE} + wamr_lib.c +) + +zephyr_library_app_memory (wamr_partition) +``` + +The `wamr_partition` is a memory partition that will be granted to the WAMR runtime. It is defined in the Zephyr application code. + +```C +K_APPMEM_PARTITION_DEFINE(wamr_partition); +``` + +When creating a Zephyr thread, set the thread option to `K_USER` and the timeout to `K_FOREVER`. This can ensure that the `wamr_partition` is granted access to the thread before starting it with `k_thread_start`. + +### Advantage of using WAMR runtime in Zephyr user mode thread + +In a user-mode Zephyr thread, the application can only access a restricted partition of memory it granted to. It creates a sandbox for the WAMR runtime to run in, and the WAMR runtime can only access that memory space, meaning that all global variables in the WAMR runtime and both runtime and wasm app heap memory will be allocated from it. In this way, an extra layer of security is added to the wasm application on top of the wasm sandbox provided by WAMR. + +### Example Targets + +x86_64 QEMU (x86_64) is a 64-bit x86 target for emulating the x86_64 platform. + +```shell +west build -b qemu_x86_tiny . -p always -- -DWAMR_BUILD_TARGET=X86_32 +``` + +Use qemu to run the image. + +```shell +qemu-system-i386 -m 32 -cpu qemu32,+nx,+pae -machine pc -device isa-debug-exit,iobase=0xf4,iosize=0x04 -no-reboot -nographic -net none -pidfile qemu.pid -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -icount shift=5,align=off,sleep=off -rtc clock=vm -kernel ./build/zephyr/zephyr.elf +``` diff --git a/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/CMakeLists.txt b/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/CMakeLists.txt new file mode 100644 index 0000000000..7c68a71ac7 --- /dev/null +++ b/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/CMakeLists.txt @@ -0,0 +1,63 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.8.2) + +set (WAMR_BUILD_PLATFORM "zephyr") + +# Build as X86_32 by default, change to "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA" +# if we want to support arm, thumb, mips or xtensa +if (NOT DEFINED WAMR_BUILD_TARGET) + set (WAMR_BUILD_TARGET "X86_32") +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_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Disable libc wasi support by default, in the future, + # it can be enabled if libc wasi file/socket/lock support is ready on Zephyr platform + set (WAMR_BUILD_LIBC_WASI 0) +endif () + +if (WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64" OR WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32") + set (WAMR_BUILD_FAST_INTERP 1) +endif () + +# Limited to global heap usage in Zephyr user mode +set (WAMR_BUILD_GLOBAL_HEAP_POOL 1) + +# Override the global heap size for small devices +if (NOT DEFINED WAMR_BUILD_GLOBAL_HEAP_SIZE) + set (WAMR_BUILD_GLOBAL_HEAP_SIZE 40960) # 40 KB +endif () + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../..) + +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +# Embed WAMR as a Zephyr library +zephyr_library_named (wamr_lib) + +# Add source files to the library +zephyr_library_sources ( + ${WAMR_RUNTIME_LIB_SOURCE} + wamr_lib.c +) + +# Specify the memory partition where all globals(including the WAMR global heap buffer) +# in the library should be placed. This partition will be defined in the app source code +# and added to the use-mode thread that uses the WAMR library. +zephyr_library_app_memory (wamr_partition) diff --git a/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/test_wasm.h b/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/test_wasm.h new file mode 100644 index 0000000000..a729cadef3 --- /dev/null +++ b/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/test_wasm.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +/** + * The byte array buffer is the file content of a test wasm binary file, + * which is compiled by wasi-sdk toolchain from C source file of: + * product-mini/app-samples/hello-world/main.c. + */ +unsigned char __aligned(4) wasm_test_file[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x01, + 0x7F, 0x00, 0x02, 0x31, 0x04, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x70, 0x75, + 0x74, 0x73, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x61, 0x6C, + 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x70, 0x72, + 0x69, 0x6E, 0x74, 0x66, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x66, + 0x72, 0x65, 0x65, 0x00, 0x02, 0x03, 0x02, 0x01, 0x01, 0x04, 0x05, 0x01, + 0x70, 0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x13, 0x03, + 0x7F, 0x01, 0x41, 0xC0, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0xBA, 0x08, 0x0B, + 0x7F, 0x00, 0x41, 0xC0, 0x28, 0x0B, 0x07, 0x2C, 0x04, 0x06, 0x6D, 0x65, + 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, + 0x61, 0x5F, 0x65, 0x6E, 0x64, 0x03, 0x01, 0x0B, 0x5F, 0x5F, 0x68, 0x65, + 0x61, 0x70, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x02, 0x04, 0x6D, 0x61, + 0x69, 0x6E, 0x00, 0x04, 0x0A, 0xB2, 0x01, 0x01, 0xAF, 0x01, 0x01, 0x03, + 0x7F, 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x20, 0x6B, 0x22, 0x02, + 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x9B, 0x88, 0x80, 0x80, 0x00, + 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1A, 0x02, 0x40, 0x02, 0x40, 0x41, + 0x80, 0x08, 0x10, 0x81, 0x80, 0x80, 0x80, 0x00, 0x22, 0x03, 0x0D, 0x00, + 0x41, 0xA8, 0x88, 0x80, 0x80, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x1A, 0x41, 0x7F, 0x21, 0x04, 0x0C, 0x01, 0x0B, 0x20, 0x02, 0x20, 0x03, + 0x36, 0x02, 0x10, 0x41, 0x80, 0x88, 0x80, 0x80, 0x00, 0x20, 0x02, 0x41, + 0x10, 0x6A, 0x10, 0x82, 0x80, 0x80, 0x80, 0x00, 0x1A, 0x41, 0x00, 0x21, + 0x04, 0x20, 0x03, 0x41, 0x04, 0x6A, 0x41, 0x00, 0x2F, 0x00, 0x91, 0x88, + 0x80, 0x80, 0x00, 0x3B, 0x00, 0x00, 0x20, 0x03, 0x41, 0x00, 0x28, 0x00, + 0x8D, 0x88, 0x80, 0x80, 0x00, 0x36, 0x00, 0x00, 0x20, 0x02, 0x20, 0x03, + 0x36, 0x02, 0x00, 0x41, 0x93, 0x88, 0x80, 0x80, 0x00, 0x20, 0x02, 0x10, + 0x82, 0x80, 0x80, 0x80, 0x00, 0x1A, 0x20, 0x03, 0x10, 0x83, 0x80, 0x80, + 0x80, 0x00, 0x0B, 0x20, 0x02, 0x41, 0x20, 0x6A, 0x24, 0x80, 0x80, 0x80, + 0x80, 0x00, 0x20, 0x04, 0x0B, 0x0B, 0x41, 0x01, 0x00, 0x41, 0x80, 0x08, + 0x0B, 0x3A, 0x62, 0x75, 0x66, 0x20, 0x70, 0x74, 0x72, 0x3A, 0x20, 0x25, + 0x70, 0x0A, 0x00, 0x31, 0x32, 0x33, 0x34, 0x0A, 0x00, 0x62, 0x75, 0x66, + 0x3A, 0x20, 0x25, 0x73, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, + 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, + 0x20, 0x62, 0x75, 0x66, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x00 +}; diff --git a/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/test_wasm_riscv64.h b/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/test_wasm_riscv64.h new file mode 100644 index 0000000000..1b45211d7a --- /dev/null +++ b/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/test_wasm_riscv64.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +unsigned char __aligned(4) wasm_test_file[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x03, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x01, + 0x7F, 0x00, 0x02, 0x31, 0x04, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x70, 0x75, + 0x74, 0x73, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x61, 0x6C, + 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x70, 0x72, + 0x69, 0x6E, 0x74, 0x66, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x66, + 0x72, 0x65, 0x65, 0x00, 0x02, 0x03, 0x02, 0x01, 0x01, 0x04, 0x05, 0x01, + 0x70, 0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x12, 0x03, + 0x7F, 0x01, 0x41, 0xC0, 0x01, 0x0B, 0x7F, 0x00, 0x41, 0x3A, 0x0B, 0x7F, + 0x00, 0x41, 0xC0, 0x01, 0x0B, 0x07, 0x2C, 0x04, 0x06, 0x6D, 0x65, 0x6D, + 0x6F, 0x72, 0x79, 0x02, 0x00, 0x04, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x04, + 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x65, 0x6E, 0x64, 0x03, + 0x01, 0x0B, 0x5F, 0x5F, 0x68, 0x65, 0x61, 0x70, 0x5F, 0x62, 0x61, 0x73, + 0x65, 0x03, 0x02, 0x0A, 0xB1, 0x01, 0x01, 0xAE, 0x01, 0x01, 0x03, 0x7F, + 0x23, 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x20, 0x6B, 0x22, 0x02, 0x24, + 0x80, 0x80, 0x80, 0x80, 0x00, 0x41, 0x9B, 0x80, 0x80, 0x80, 0x00, 0x10, + 0x80, 0x80, 0x80, 0x80, 0x00, 0x1A, 0x02, 0x40, 0x02, 0x40, 0x41, 0x10, + 0x10, 0x81, 0x80, 0x80, 0x80, 0x00, 0x22, 0x03, 0x0D, 0x00, 0x41, 0xA8, + 0x80, 0x80, 0x80, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, 0x1A, 0x41, + 0x7F, 0x21, 0x04, 0x0C, 0x01, 0x0B, 0x20, 0x02, 0x20, 0x03, 0x36, 0x02, + 0x10, 0x41, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x02, 0x41, 0x10, 0x6A, + 0x10, 0x82, 0x80, 0x80, 0x80, 0x00, 0x1A, 0x41, 0x00, 0x21, 0x04, 0x20, + 0x03, 0x41, 0x04, 0x6A, 0x41, 0x00, 0x2F, 0x00, 0x91, 0x80, 0x80, 0x80, + 0x00, 0x3B, 0x00, 0x00, 0x20, 0x03, 0x41, 0x00, 0x28, 0x00, 0x8D, 0x80, + 0x80, 0x80, 0x00, 0x36, 0x00, 0x00, 0x20, 0x02, 0x20, 0x03, 0x36, 0x02, + 0x00, 0x41, 0x93, 0x80, 0x80, 0x80, 0x00, 0x20, 0x02, 0x10, 0x82, 0x80, + 0x80, 0x80, 0x00, 0x1A, 0x20, 0x03, 0x10, 0x83, 0x80, 0x80, 0x80, 0x00, + 0x0B, 0x20, 0x02, 0x41, 0x20, 0x6A, 0x24, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x20, 0x04, 0x0B, 0x0B, 0x40, 0x01, 0x00, 0x41, 0x00, 0x0B, 0x3A, 0x62, + 0x75, 0x66, 0x20, 0x70, 0x74, 0x72, 0x3A, 0x20, 0x25, 0x70, 0x0A, 0x00, + 0x31, 0x32, 0x33, 0x34, 0x0A, 0x00, 0x62, 0x75, 0x66, 0x3A, 0x20, 0x25, + 0x73, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, + 0x64, 0x21, 0x00, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x62, 0x75, + 0x66, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x00 +}; diff --git a/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/wamr_lib.c b/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/wamr_lib.c new file mode 100644 index 0000000000..a2c639e802 --- /dev/null +++ b/product-mini/platforms/zephyr/user-mode/lib-wamr-zephyr/wamr_lib.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include "bh_platform.h" +#include "bh_assert.h" +#include "bh_log.h" +#include "bh_queue.h" +#include "wasm_export.h" +#if defined(BUILD_TARGET_RISCV64_LP64) || defined(BUILD_TARGET_RISCV32_ILP32) +#include "test_wasm_riscv64.h" +#else +#include "test_wasm.h" +#endif /* end of BUILD_TARGET_RISCV64_LP64 || BUILD_TARGET_RISCV32_ILP32 */ + +#if defined(BUILD_TARGET_RISCV64_LP64) || defined(BUILD_TARGET_RISCV32_ILP32) +#define CONFIG_GLOBAL_HEAP_BUF_SIZE 5120 +#define CONFIG_APP_STACK_SIZE 512 +#define CONFIG_APP_HEAP_SIZE 512 +#else /* else of BUILD_TARGET_RISCV64_LP64 || BUILD_TARGET_RISCV32_ILP32 */ +#define CONFIG_GLOBAL_HEAP_BUF_SIZE WASM_GLOBAL_HEAP_SIZE +#define CONFIG_APP_STACK_SIZE 8192 +#define CONFIG_APP_HEAP_SIZE 8192 +#endif /* end of BUILD_TARGET_RISCV64_LP64 || BUILD_TARGET_RISCV32_ILP32 */ + +static int app_argc; +static char **app_argv; + +/** + * Find the unique main function from a WASM module instance + * and execute that function. + * + * @param module_inst the WASM module instance + * @param argc the number of arguments + * @param argv the arguments array + * + * @return true if the main function is called, false otherwise. + */ +bool +wasm_application_execute_main(wasm_module_inst_t module_inst, int argc, + char *argv[]); + +static void * +app_instance_main(wasm_module_inst_t module_inst) +{ + const char *exception; + wasm_function_inst_t func; + wasm_exec_env_t exec_env; + unsigned argv[2] = { 0 }; + + if (wasm_runtime_lookup_function(module_inst, "main") + || wasm_runtime_lookup_function(module_inst, "__main_argc_argv")) { + LOG_VERBOSE("Calling main function\n"); + wasm_application_execute_main(module_inst, app_argc, app_argv); + } + else if ((func = wasm_runtime_lookup_function(module_inst, "app_main"))) { + exec_env = + wasm_runtime_create_exec_env(module_inst, CONFIG_APP_HEAP_SIZE); + if (!exec_env) { + os_printf("Create exec env failed\n"); + return NULL; + } + + LOG_VERBOSE("Calling app_main function\n"); + wasm_runtime_call_wasm(exec_env, func, 0, argv); + + if (!wasm_runtime_get_exception(module_inst)) { + os_printf("result: 0x%x\n", argv[0]); + } + + wasm_runtime_destroy_exec_env(exec_env); + } + else { + os_printf("Failed to lookup function main or app_main to call\n"); + return NULL; + } + + if ((exception = wasm_runtime_get_exception(module_inst))) + os_printf("%s\n", exception); + + return NULL; +} + +#if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 +static char global_heap_buf[CONFIG_GLOBAL_HEAP_BUF_SIZE] = { 0 }; +#endif + +void +iwasm_main(void *arg1, void *arg2, void *arg3) +{ + int start, end; + start = k_uptime_get_32(); + uint8 *wasm_file_buf = NULL; + uint32 wasm_file_size; + wasm_module_t wasm_module = NULL; + wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; + char error_buf[128]; +#if WASM_ENABLE_LOG != 0 + int log_verbose_level = 2; +#endif + + (void)arg1; + (void)arg2; + (void)arg3; + + os_printf("User mode thread: start\n"); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + +#if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 + 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); +#elif (defined(CONFIG_COMMON_LIBC_MALLOC) \ + && CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE != 0) \ + || defined(CONFIG_NEWLIB_LIBC) + init_args.mem_alloc_type = Alloc_With_System_Allocator; +#else +#error "memory allocation scheme is not defined." +#endif + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + printf("Init runtime environment failed.\n"); + return; + } + +#if WASM_ENABLE_LOG != 0 + bh_log_set_verbose_level(log_verbose_level); +#endif + + /* load WASM byte buffer from byte buffer of include file */ + wasm_file_buf = (uint8 *)wasm_test_file; + wasm_file_size = sizeof(wasm_test_file); + + /* load WASM module */ + if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("%s\n", error_buf); + goto fail1; + } + + /* instantiate the module */ + if (!(wasm_module_inst = wasm_runtime_instantiate( + wasm_module, CONFIG_APP_STACK_SIZE, CONFIG_APP_HEAP_SIZE, + error_buf, sizeof(error_buf)))) { + printf("%s\n", error_buf); + goto fail2; + } + + /* invoke the main function */ + app_instance_main(wasm_module_inst); + + /* destroy the module instance */ + wasm_runtime_deinstantiate(wasm_module_inst); + +fail2: + /* unload the module */ + wasm_runtime_unload(wasm_module); + +fail1: + /* destroy runtime environment */ + wasm_runtime_destroy(); + + end = k_uptime_get_32(); + + os_printf("User mode thread: elapsed %d\n", (end - start)); +} diff --git a/product-mini/platforms/zephyr/user-mode/prj.conf b/product-mini/platforms/zephyr/user-mode/prj.conf new file mode 100644 index 0000000000..023a3caa20 --- /dev/null +++ b/product-mini/platforms/zephyr/user-mode/prj.conf @@ -0,0 +1,9 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +CONFIG_USERSPACE=y +CONFIG_STACK_SENTINEL=y +CONFIG_PRINTK=y +CONFIG_LOG=y +CONFIG_LOG_BUFFER_SIZE=8096 +CONFIG_THREAD_RUNTIME_STATS=y diff --git a/product-mini/platforms/zephyr/user-mode/src/main.c b/product-mini/platforms/zephyr/user-mode/src/main.c new file mode 100644 index 0000000000..4f51e10d3f --- /dev/null +++ b/product-mini/platforms/zephyr/user-mode/src/main.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include +#include + +#define MAIN_THREAD_STACK_SIZE 2048 +#define MAIN_THREAD_PRIORITY 5 + +static struct k_thread iwasm_user_mode_thread; +K_THREAD_STACK_DEFINE(iwasm_user_mode_thread_stack, MAIN_THREAD_STACK_SIZE); + +extern struct k_mem_partition z_libc_partition; +K_APPMEM_PARTITION_DEFINE(wamr_partition); + +/* WAMR memory domain */ +struct k_mem_domain wamr_domain; + +extern void +iwasm_main(void *arg1, void *arg2, void *arg3); + +bool +iwasm_user_mode(void) +{ + struct k_mem_partition *wamr_domain_parts[] = { &wamr_partition, + &z_libc_partition }; + + printk("wamr_partition start addr: %ld, size: %zu\n", wamr_partition.start, + wamr_partition.size); + + /* Initialize the memory domain with single WAMR partition */ + if (k_mem_domain_init(&wamr_domain, 2, wamr_domain_parts) != 0) { + printk("Failed to initialize memory domain.\n"); + return false; + } + + k_tid_t tid = + k_thread_create(&iwasm_user_mode_thread, iwasm_user_mode_thread_stack, + MAIN_THREAD_STACK_SIZE, iwasm_main, NULL, NULL, NULL, + MAIN_THREAD_PRIORITY, K_USER, K_FOREVER); + + /* Grant WAMR memory domain access to user mode thread */ + if (k_mem_domain_add_thread(&wamr_domain, tid) != 0) { + printk("Failed to add memory domain to thread.\n"); + return false; + } + +#if KERNEL_VERSION_NUMBER < 0x040000 /* version 4.0.0 */ + /* k_thread_start is a legacy API for compatibility. Modern Zephyr threads + * are initialized in the "sleeping" state and do not need special handling + * for "start".*/ + k_thread_start(tid); +#else + /* wakes up thread from sleeping */ + k_wakeup(tid); +#endif + + return tid ? true : false; +} + +#if KERNEL_VERSION_NUMBER < 0x030400 /* version 3.4.0 */ +void +main(void) +{ + iwasm_user_mode(); +} +#else +int +main(void) +{ + iwasm_user_mode(); + return 0; +} +#endif diff --git a/samples/debug-tools/CMakeLists.txt b/samples/debug-tools/CMakeLists.txt index ce06029a56..411106bb30 100644 --- a/samples/debug-tools/CMakeLists.txt +++ b/samples/debug-tools/CMakeLists.txt @@ -72,7 +72,7 @@ add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) include(ExternalProject) # wasm32-wasi -ExternalProject_Add(wasm33-wasi +ExternalProject_Add(wasm32-wasi SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps" CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps -B build -DWASI_SDK_PREFIX=${WASISDK_HOME} diff --git a/test-tools/wamr-ide/VSCode-Extension/resource/test/build.sh b/test-tools/wamr-ide/VSCode-Extension/resource/test/build.sh index e175c91066..33ae79d442 100755 --- a/test-tools/wamr-ide/VSCode-Extension/resource/test/build.sh +++ b/test-tools/wamr-ide/VSCode-Extension/resource/test/build.sh @@ -1,2 +1,2 @@ # compile with debug symbols and no optimization -rustc --target wasm32-wasi ./test.rs -g -C opt-level=0 \ No newline at end of file +rustc --target wasm32-wasip1 ./test.rs -g -C opt-level=0 \ No newline at end of file diff --git a/test-tools/wamr-ide/VSCode-Extension/src/test/suite/utils.ts b/test-tools/wamr-ide/VSCode-Extension/src/test/suite/utils.ts index 3f40596c3d..69c474b258 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/test/suite/utils.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/test/suite/utils.ts @@ -39,7 +39,7 @@ export function setBpAtMarker(file: string, bpMarker: string): void { export function compileRustToWasm(): void { const testResourceFolder = `${EXTENSION_PATH}/resource/test`; // compile with debug symbols and no optimization - const cmd = `rustc --target wasm32-wasi ${testResourceFolder}/test.rs -g -C opt-level=0 -o ${testResourceFolder}/test.wasm`; + const cmd = `rustc --target wasm32-wasip1 ${testResourceFolder}/test.rs -g -C opt-level=0 -o ${testResourceFolder}/test.wasm`; try { cp.execSync(cmd, { stdio: [null, null, process.stderr] }); diff --git a/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt b/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt index 356869d178..c0c7622c9d 100644 --- a/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt +++ b/tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt @@ -66,7 +66,7 @@ if (NOT DEFINED WAMR_BUILD_JIT) endif () if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) - # Enable libc builtin support by default + # Disable libc builtin support by default set (WAMR_BUILD_LIBC_BUILTIN 0) endif () @@ -81,7 +81,7 @@ if (NOT DEFINED WAMR_BUILD_FAST_INTERP) endif () if (NOT DEFINED WAMR_BUILD_MULTI_MODULE) - # Enable multiple modules + # Disable multiple modules set (WAMR_BUILD_MULTI_MODULE 0) endif () @@ -116,6 +116,12 @@ if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) set (WAMR_BUILD_SIMD 0) endif () +# sanitizer may use kHandleSignalExclusive to handle SIGSEGV +# like `UBSAN_OPTIONS=handle_segv=2:...` +set (WAMR_DISABLE_HW_BOUND_CHECK 1) +# Enable aot validator +set (WAMR_BUILD_AOT_VALIDATOR 1) + set (REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..) message([ceith]:REPO_ROOT_DIR, ${REPO_ROOT_DIR}) diff --git a/tests/fuzz/wasm-mutator-fuzz/README.md b/tests/fuzz/wasm-mutator-fuzz/README.md index 0d21519a1c..acf210ae42 100644 --- a/tests/fuzz/wasm-mutator-fuzz/README.md +++ b/tests/fuzz/wasm-mutator-fuzz/README.md @@ -19,6 +19,7 @@ $ wasm-tools help mkdir build && cd build # Without custom mutator (libfuzzer modify the buffer randomly) cmake .. +# TODO: TBC. `wasm-tools mutate` is not supported yet # With custom mutator (wasm-tools mutate) cmake .. -DCUSTOM_MUTATOR=1 make -j$(nproc) diff --git a/tests/fuzz/wasm-mutator-fuzz/portal/osv-scanner.toml b/tests/fuzz/wasm-mutator-fuzz/portal/osv-scanner.toml index 1eb55cd8df..b1b7145dec 100644 --- a/tests/fuzz/wasm-mutator-fuzz/portal/osv-scanner.toml +++ b/tests/fuzz/wasm-mutator-fuzz/portal/osv-scanner.toml @@ -50,3 +50,10 @@ name = "vite" ecosystem = "npm" ignore = true reason = "Development server not exposed to untrusted networks" + +# GHSA-mwcw-c2x4-8c55 +[[PackageOverrides]] +name = "nanoid" +ecosystem = "npm" +ignore = true +reason = "Accepted known vulnerabilities for testing purposes" diff --git a/tests/fuzz/wasm-mutator-fuzz/server/app/main.py b/tests/fuzz/wasm-mutator-fuzz/server/app/main.py index d8a0955e27..620625dd33 100644 --- a/tests/fuzz/wasm-mutator-fuzz/server/app/main.py +++ b/tests/fuzz/wasm-mutator-fuzz/server/app/main.py @@ -56,7 +56,7 @@ app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False -app.secret_key = "hwhefsewljfejrlesjfl" +app.secret_key = os.urandom(12).hex() db = SQLAlchemy(app) diff --git a/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh b/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh index 29d24dbd08..097e5348b4 100755 --- a/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh +++ b/tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh @@ -33,36 +33,38 @@ function try_generate_wasm() 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 + # Larger input seeds tend to generate larger WebAssembly modules. (256KB) + head -c 262144 /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" +WASM_SHAPE=" --ensure-termination \ +--export-everything true \ +--fuel 7 \ +--generate-custom-sections true \ +--min-funcs 5 \ +--max-instructions 1024 \ +--min-globals 10" + +WASM_MVP_FEATURES=" --bulk-memory-enabled true \ +--multi-value-enabled true \ +--reference-types-enabled true \ +--simd-enabled true \ +--tail-call-enabled true" for i in $(seq 1 $EXPECTED_NUM) do - # 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 + try_generate_wasm "${WASM_SHAPE} ${WASM_MVP_FEATURES}" test_mvp_$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 + # other proposals + try_generate_wasm "${WASM_SHAPE} --exceptions-enabled true" test_exception_$i.wasm + try_generate_wasm "${WASM_SHAPE} --gc-enabled true" test_gc_$i.wasm + try_generate_wasm "${WASM_SHAPE} --memory64-enabled true" test_memory64_$i.wasm + try_generate_wasm "${WASM_SHAPE} --threads-enabled true" test_threads_$i.wasm done printf "Done\n" diff --git a/tests/fuzz/wasm-mutator-fuzz/wasm_mutator_fuzz.cc b/tests/fuzz/wasm-mutator-fuzz/wasm_mutator_fuzz.cc index 0817e5bdd0..391d899cf4 100644 --- a/tests/fuzz/wasm-mutator-fuzz/wasm_mutator_fuzz.cc +++ b/tests/fuzz/wasm-mutator-fuzz/wasm_mutator_fuzz.cc @@ -13,14 +13,149 @@ using namespace std; -extern "C" WASMModuleCommon * -wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf, - uint32 error_buf_size); +static bool +is_supported_val_kind(wasm_valkind_t kind) +{ + return kind == WASM_I32 || kind == WASM_I64 || kind == WASM_F32 + || kind == WASM_F64 || kind == WASM_EXTERNREF + || kind == WASM_FUNCREF; +} + +static wasm_val_t +pre_defined_val(wasm_valkind_t kind) +{ + if (kind == WASM_I32) { + return wasm_val_t{ .kind = WASM_I32, .of = { .i32 = 2025 } }; + } + else if (kind == WASM_I64) { + return wasm_val_t{ .kind = WASM_I64, .of = { .i64 = 168 } }; + } + else if (kind == WASM_F32) { + return wasm_val_t{ .kind = WASM_F32, .of = { .f32 = 3.14159f } }; + } + else if (kind == WASM_F64) { + return wasm_val_t{ .kind = WASM_F64, .of = { .f64 = 2.71828 } }; + } + else if (kind == WASM_EXTERNREF) { + return wasm_val_t{ .kind = WASM_EXTERNREF, + .of = { .foreign = 0xabcddead } }; + } + // because aft is_supported_val_kind() check, so we can safely return as + // WASM_FUNCREF + else { + return wasm_val_t{ .kind = WASM_FUNCREF, .of = { .ref = nullptr } }; + } +} +void +print_execution_args(const wasm_export_t &export_type, + const std::vector &args, unsigned param_count) +{ + std::cout << "[EXECUTION] " << export_type.name << "("; + for (unsigned p_i = 0; p_i < param_count; p_i++) { + if (p_i != 0) { + std::cout << ", "; + } + + switch (args[p_i].kind) { + case WASM_I32: + std::cout << "i32:" << args[p_i].of.i32; + break; + case WASM_I64: + std::cout << "i64:" << args[p_i].of.i64; + break; + case WASM_F32: + std::cout << "f32:" << args[p_i].of.f32; + break; + case WASM_F64: + std::cout << "f64:" << args[p_i].of.f64; + break; + case WASM_EXTERNREF: + std::cout << "externref:" << args[p_i].of.foreign; + break; + default: + // because aft is_supported_val_kind() check, so we can safely + // return as WASM_FUNCREF + std::cout << "funcref:" << args[p_i].of.ref; + break; + } + } + std::cout << ")" << std::endl; +} + +static bool +execute_export_functions(wasm_module_t module, wasm_module_inst_t inst) +{ + int32_t export_count = wasm_runtime_get_export_count(module); + + for (int e_i = 0; e_i < export_count; e_i++) { + wasm_export_t export_type = { 0 }; + wasm_runtime_get_export_type(module, e_i, &export_type); + + if (export_type.kind != WASM_IMPORT_EXPORT_KIND_FUNC) { + continue; + } + + wasm_function_inst_t func = + wasm_runtime_lookup_function(inst, export_type.name); + if (!func) { + std::cout << "Failed to lookup function: " << export_type.name + << std::endl; + continue; + } + + wasm_func_type_t func_type = export_type.u.func_type; + uint32_t param_count = wasm_func_type_get_param_count(func_type); -extern "C" WASMModuleInstanceCommon * -wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size, - uint32 heap_size, char *error_buf, - uint32 error_buf_size); + /* build arguments */ + std::vector args; + for (unsigned p_i = 0; p_i < param_count; p_i++) { + wasm_valkind_t param_type = + wasm_func_type_get_param_valkind(func_type, p_i); + + if (!is_supported_val_kind(param_type)) { + std::cout + << "Bypass execution because of unsupported value kind: " + << param_type << std::endl; + return true; + } + + wasm_val_t arg = pre_defined_val(param_type); + args.push_back(arg); + } + + /* build results storage */ + uint32_t result_count = wasm_func_type_get_result_count(func_type); + std::vector results = std::vector(result_count); + + print_execution_args(export_type, args, param_count); + + /* execute the function */ + wasm_exec_env_t exec_env = wasm_runtime_get_exec_env_singleton(inst); + if (!exec_env) { + std::cout << "Failed to get exec env" << std::endl; + return false; + } + + bool ret = + wasm_runtime_call_wasm_a(exec_env, func, result_count, + results.data(), param_count, args.data()); + if (!ret) { + const char *exception = wasm_runtime_get_exception(inst); + if (!exception) { + std::cout << "[EXECUTION] " << export_type.name + << "() failed. No exception info." << std::endl; + } + else { + std::cout << "[EXECUTION] " << export_type.name << "() failed. " + << exception << std::endl; + } + } + + wasm_runtime_clear_exception(inst); + } + + return true; +} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) @@ -28,16 +163,35 @@ LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) /* libfuzzer don't allow us to modify the given Data, so we copy the data * here */ std::vector myData(Data, Data + Size); + /* init runtime environment */ wasm_runtime_init(); + + char error_buf[128] = { 0 }; wasm_module_t module = - wasm_runtime_load((uint8_t *)myData.data(), Size, nullptr, 0); - if (module) { + wasm_runtime_load((uint8_t *)myData.data(), Size, error_buf, 120); + if (!module) { + std::cout << "[LOADING] " << error_buf << std::endl; + wasm_runtime_destroy(); + /* return SUCCESS because the failure has been handled */ + return 0; + } + + wasm_module_inst_t inst = wasm_runtime_instantiate( + module, 8 * 1024 * 1024, 16 * 1024 * 1024, error_buf, 120); + if (!inst) { + std::cout << "[INSTANTIATE] " << error_buf << std::endl; wasm_runtime_unload(module); + wasm_runtime_destroy(); + /* return SUCCESS because the failure has been handled */ + return 0; } - /* destroy runtime environment */ - wasm_runtime_destroy(); + execute_export_functions(module, inst); + + wasm_runtime_deinstantiate(inst); + wasm_runtime_unload(module); + wasm_runtime_destroy(); return 0; /* Values other than 0 and -1 are reserved for future use. */ } diff --git a/tests/unit/interpreter/interpreter_test.cc b/tests/unit/interpreter/interpreter_test.cc index e9fa8f9e16..af00020c97 100644 --- a/tests/unit/interpreter/interpreter_test.cc +++ b/tests/unit/interpreter/interpreter_test.cc @@ -45,6 +45,6 @@ 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"); + ret = wasm_runtime_is_built_in_module("env1"); ASSERT_FALSE(ret); } \ No newline at end of file diff --git a/tests/unit/libc-builtin/libc_builtin_test.cc b/tests/unit/libc-builtin/libc_builtin_test.cc index 6598f7a8b6..f4f02bff63 100644 --- a/tests/unit/libc-builtin/libc_builtin_test.cc +++ b/tests/unit/libc-builtin/libc_builtin_test.cc @@ -185,7 +185,7 @@ TEST_F(LibcBuiltinTest, printf) va_list.add(20); //%zd va_list.add(20); //%ld - va_list.add(20L); //%jd + va_list.add(intmax_t(20)); //%jd testing::internal::CaptureStdout(); @@ -323,7 +323,7 @@ TEST_F(LibcBuiltinTest, printf) TEST_F(LibcBuiltinTest, sprintf) { - const char *buf; + char buf[200] = {0}; const char *str = "Hello Wrold"; const char *str_sig = "c"; const char *str_f = "20, 3.140000, Hello World"; @@ -508,7 +508,7 @@ TEST_F(LibcBuiltinTest, memcmp) TEST_F(LibcBuiltinTest, memcpy) { const char *src = "Hell World"; - char *dest; + char dest[sizeof(src)] = {0}; AppData src_app{ dummy_exec_env.get(), src }; AppData dest_app{ dummy_exec_env.get(), dest }; @@ -535,7 +535,7 @@ TEST_F(LibcBuiltinTest, memcpy) TEST_F(LibcBuiltinTest, memmove) { const char *src = "Hell World"; - char *dest; + char dest[sizeof(src)] = {0}; AppData src_app{ dummy_exec_env.get(), src }; AppData dest_app{ dummy_exec_env.get(), dest }; @@ -673,7 +673,7 @@ TEST_F(LibcBuiltinTest, strncmp) TEST_F(LibcBuiltinTest, strcpy) { char *src = (char *)"Hello World!"; - char *dest; + char dest[sizeof(src)] = {0}; AppData src_app{ dummy_exec_env.get(), src }; AppData dest_app{ dummy_exec_env.get(), dest }; @@ -696,7 +696,7 @@ TEST_F(LibcBuiltinTest, strcpy) TEST_F(LibcBuiltinTest, strncpy) { char *src = (char *)"Hello World!"; - char *dest; + char dest[sizeof(src)] = {0}; AppData src_app{ dummy_exec_env.get(), src }; AppData dest_app{ dummy_exec_env.get(), dest }; @@ -1295,7 +1295,7 @@ TEST_F(LibcBuiltinTest, isalnum) TEST_F(LibcBuiltinTest, emscripten_memcpy_big) { const char *src = "Hell World"; - char *dest; + char dest[sizeof(src)] = {0}; AppData src_app{ dummy_exec_env.get(), src }; AppData dest_app{ dummy_exec_env.get(), dest }; diff --git a/tests/unit/shared-heap/CMakeLists.txt b/tests/unit/shared-heap/CMakeLists.txt index 6baf420f89..2b06c537f8 100644 --- a/tests/unit/shared-heap/CMakeLists.txt +++ b/tests/unit/shared-heap/CMakeLists.txt @@ -8,7 +8,7 @@ project(test-shared-heap) add_definitions(-DRUN_ON_LINUX) set(WAMR_BUILD_APP_FRAMEWORK 0) -set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_AOT 1) set(WAMR_BUILD_INTERP 1) set(WAMR_BUILD_FAST_INTERP 1) set(WAMR_BUILD_JIT 0) diff --git a/tests/unit/shared-heap/shared_heap_test.cc b/tests/unit/shared-heap/shared_heap_test.cc index 5e45d31119..deb4bbb388 100644 --- a/tests/unit/shared-heap/shared_heap_test.cc +++ b/tests/unit/shared-heap/shared_heap_test.cc @@ -92,37 +92,28 @@ destroy_module_env(struct ret_env module_env) } } -TEST_F(shared_heap_test, test_shared_heap) +static void test_shared_heap(WASMSharedHeap *shared_heap, const char *file, const char *func_name, uint32 argc, uint32 argv[]) { struct ret_env tmp_module_env; WASMFunctionInstanceCommon *func_test = nullptr; bool ret = false; - uint32 argv[1] = { 65535 }; const char *exception = nullptr; - SharedHeapInitArgs args; - WASMSharedHeap *shared_heap = nullptr; - args.size = 1024; - shared_heap = wasm_runtime_create_shared_heap(&args); - tmp_module_env = load_wasm((char *)"test.wasm", 0); + tmp_module_env = load_wasm((char *)file, 0); - if (!shared_heap) { - printf("Failed to create shared heap\n"); - goto test_failed; - } if (!wasm_runtime_attach_shared_heap(tmp_module_env.wasm_module_inst, shared_heap)) { printf("Failed to attach shared heap\n"); goto test_failed; } - func_test = wasm_runtime_lookup_function( - tmp_module_env.wasm_module_inst, "test"); + func_test = wasm_runtime_lookup_function(tmp_module_env.wasm_module_inst, + func_name); if (!func_test) { printf("\nFailed to wasm_runtime_lookup_function!\n"); goto test_failed; } ret = - wasm_runtime_call_wasm(tmp_module_env.exec_env, func_test, 1, argv); + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_test, argc, argv); if (!ret) { printf("\nFailed to wasm_runtime_call_wasm!\n"); const char *s = wasm_runtime_get_exception(tmp_module_env.wasm_module_inst); @@ -131,12 +122,119 @@ TEST_F(shared_heap_test, test_shared_heap) } wasm_runtime_detach_shared_heap(tmp_module_env.wasm_module_inst); - - EXPECT_EQ(10, argv[0]); - destroy_module_env(tmp_module_env); return; test_failed: destroy_module_env(tmp_module_env); EXPECT_EQ(1, 0); } + +TEST_F(shared_heap_test, test_shared_heap_basic) +{ + SharedHeapInitArgs args; + WASMSharedHeap *shared_heap = nullptr; + uint32 argv[1] = { 0 }; + + args.size = 1024; + shared_heap = wasm_runtime_create_shared_heap(&args); + + if (!shared_heap) { + printf("Failed to create shared heap\n"); + EXPECT_EQ(1, 0); + } + + // test wasm + test_shared_heap(shared_heap, "test.wasm", "test", 1, argv); + EXPECT_EQ(10, argv[0]); + + // test aot + test_shared_heap(shared_heap, "test.aot", "test", 1, argv); + EXPECT_EQ(10, argv[0]); + +} + +TEST_F(shared_heap_test, test_shared_heap_malloc_fail) +{ + SharedHeapInitArgs args; + WASMSharedHeap *shared_heap = nullptr; + uint32 argv[1] = { 0 }; + + args.size = 1024; + shared_heap = wasm_runtime_create_shared_heap(&args); + + if (!shared_heap) { + printf("Failed to create shared heap\n"); + EXPECT_EQ(1, 0); + } + + // test wasm + test_shared_heap(shared_heap, "test.wasm", "test_malloc_fail", 1, argv); + EXPECT_EQ(1, argv[0]); + + // test aot + test_shared_heap(shared_heap, "test.aot", "test_malloc_fail", 1, argv); + EXPECT_EQ(1, argv[0]); +} + +#ifndef native_function +#define native_function(func_name, signature) \ + { #func_name, (void *)glue_##func_name, signature, NULL } + +#endif +#ifndef nitems +#define nitems(_a) (sizeof(_a) / sizeof(0 [(_a)])) +#endif /* nitems */ +uintptr_t glue_test_addr_conv(wasm_exec_env_t env, uintptr_t addr) +{ + wasm_module_inst_t module_inst = get_module_inst(env); + uintptr_t ret; + void *native_addr = (void *)addr; + uintptr_t app_addr = addr_native_to_app(native_addr); + + native_addr = addr_app_to_native(app_addr); + if (native_addr != (void *)addr) + { + EXPECT_EQ(1, 0); + } + return app_addr; +} + +static NativeSymbol g_test_native_symbols[] = +{ + native_function(test_addr_conv,"(*)i"), +}; + +TEST_F(shared_heap_test, test_addr_conv) +{ + SharedHeapInitArgs args; + WASMSharedHeap *shared_heap = nullptr; + uint32 argv[1] = { 0 }; + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func_test = nullptr; + bool ret = false; + const char *exception = nullptr; + wasm_module_inst_t module_inst = tmp_module_env.wasm_module_inst; + + ret = wasm_native_register_natives("env", g_test_native_symbols, + nitems(g_test_native_symbols)); + if (!ret) + { + EXPECT_EQ(1, 0); + return; + } + + args.size = 1024; + shared_heap = wasm_runtime_create_shared_heap(&args); + if (!shared_heap) { + printf("Failed to create shared heap\n"); + EXPECT_EQ(1, 0); + } + + // test wasm + test_shared_heap(shared_heap, "test_addr_conv.wasm", "test", 1, argv); + EXPECT_EQ(1, argv[0]); + + // test aot + test_shared_heap(shared_heap, "test_addr_conv.aot", "test", 1, argv); + EXPECT_EQ(1, argv[0]); +} diff --git a/tests/unit/shared-heap/wasm-apps/CMakeLists.txt b/tests/unit/shared-heap/wasm-apps/CMakeLists.txt index 3627a2c144..097f66ae5d 100644 --- a/tests/unit/shared-heap/wasm-apps/CMakeLists.txt +++ b/tests/unit/shared-heap/wasm-apps/CMakeLists.txt @@ -5,6 +5,7 @@ cmake_minimum_required(VERSION 3.14) project(wasm-apps) set(WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../..) +set(WAMRC_ROOT_DIR ${WAMR_ROOT_DIR}/wamr-compiler/build) set(CMAKE_SYSTEM_PROCESSOR wasm32) set(CMAKE_SYSROOT ${WAMR_ROOT_DIR}/wamr-sdk/app/libc-builtin-sysroot) @@ -36,4 +37,36 @@ add_custom_command(TARGET test.wasm POST_BUILD ${CMAKE_CURRENT_BINARY_DIR}/test.wasm ${CMAKE_CURRENT_BINARY_DIR}/../ COMMENT "Copy test.wasm to the same directory of google test" - ) \ No newline at end of file + ) + +add_custom_command(TARGET test.wasm POST_BUILD + COMMAND ${WAMRC_ROOT_DIR}/wamrc --opt-level=0 --enable-shared-heap --bounds-checks=1 + -o + test.aot + test.wasm + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/test.aot + ${CMAKE_CURRENT_BINARY_DIR}/../ + COMMENT "Copy test.aot to the same directory of google test" + ) + +add_executable(test_addr_conv.wasm test_addr_conv.c) +target_link_libraries(test.wasm) + +add_custom_command(TARGET test_addr_conv.wasm POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/test_addr_conv.wasm + ${CMAKE_CURRENT_BINARY_DIR}/../ + COMMENT "Copy test_addr_conv.wasm to the same directory of google test" + ) + +add_custom_command(TARGET test_addr_conv.wasm POST_BUILD + COMMAND ${WAMRC_ROOT_DIR}/wamrc --opt-level=0 --enable-shared-heap --bounds-checks=1 + -o + test_addr_conv.aot + test_addr_conv.wasm + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/test_addr_conv.aot + ${CMAKE_CURRENT_BINARY_DIR}/../ + COMMENT "Copy test_addr_conv.aot to the same directory of google test" + ) diff --git a/tests/unit/shared-heap/wasm-apps/test.c b/tests/unit/shared-heap/wasm-apps/test.c index b83ee64ffa..bd0df19c20 100644 --- a/tests/unit/shared-heap/wasm-apps/test.c +++ b/tests/unit/shared-heap/wasm-apps/test.c @@ -13,10 +13,22 @@ shared_heap_free(void *offset); int test() { - int *ptr = (int *)shared_heap_malloc(10); + int *ptr = (int *)shared_heap_malloc(4); *ptr = 10; int a = *ptr; shared_heap_free(ptr); return a; } + +int +test_malloc_fail() +{ + int *ptr = (int *)shared_heap_malloc(8192); + + if (ptr == NULL) { + return 1; + } + shared_heap_free(ptr); + return 0; +} diff --git a/tests/unit/shared-heap/wasm-apps/test_addr_conv.c b/tests/unit/shared-heap/wasm-apps/test_addr_conv.c new file mode 100644 index 0000000000..f91764c84c --- /dev/null +++ b/tests/unit/shared-heap/wasm-apps/test_addr_conv.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 Xiaomi Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +extern void * +shared_heap_malloc(int size); +extern void +shared_heap_free(void *offset); +extern void * +test_addr_conv(void *ptr); + +int +test() +{ + int *ptr = NULL; + int *ptr2 = NULL; + + ptr = (int *)shared_heap_malloc(4); + + if (ptr == NULL) { + return 0; + } + ptr2 = test_addr_conv(ptr); + if (ptr2 != ptr) { + return 0; + } + shared_heap_free(ptr); + return 1; +} diff --git a/tests/unit/wasm-vm/wasm_vm.cc b/tests/unit/wasm-vm/wasm_vm.cc index f4f5a834d1..73c2c761f6 100644 --- a/tests/unit/wasm-vm/wasm_vm.cc +++ b/tests/unit/wasm-vm/wasm_vm.cc @@ -65,7 +65,7 @@ class WasmVMTest : public testing::Test TEST_F(WasmVMTest, Test_app1) { - unsigned argv[10]; + uint32 argv[10]; ASSERT_TRUE(app1_wasm != NULL); @@ -151,7 +151,7 @@ TEST_F(WasmVMTest, Test_app1) TEST_F(WasmVMTest, Test_app2) { - unsigned argv[10]; + uint32 argv[10]; /* Load module */ module = wasm_runtime_load(app2_wasm, sizeof(app2_wasm), error_buf, @@ -416,7 +416,7 @@ TEST_F(WasmVMTest, Test_app2) TEST_F(WasmVMTest, Test_app3) { - unsigned argv[10]; + uint32 argv[10]; /* Load module */ module = wasm_runtime_load(app3_wasm, sizeof(app3_wasm), error_buf, @@ -465,7 +465,6 @@ TEST_F(WasmVMTest, Test_app3) 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"); @@ -482,7 +481,6 @@ TEST_F(WasmVMTest, Test_app3) 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); @@ -526,7 +524,7 @@ TEST_F(WasmVMTest, Test_app4_single) uint8 *buffer = NULL; uint32 buffer_size = 0; bool ret = false; - unsigned argv[10]; + uint32 argv[10]; wasm_runtime_set_module_reader(&module_reader_callback, &module_destroyer_callback); @@ -584,7 +582,7 @@ TEST_F(WasmVMTest, Test_app4_plus_one) uint8 *buffer = NULL; uint32 buffer_size = 0; bool ret = false; - uint32_t argv[10] = { 0 }; + uint32 argv[10] = { 0 }; wasm_runtime_set_module_reader(&module_reader_callback, &module_destroyer_callback); diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index 6744d5b635..9133498495 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -116,7 +116,12 @@ def ignore_the_case( return True if gc_flag: - if case_name in ["array_init_elem", "array_init_data"]: + if case_name in [ + "array_init_elem", + "array_init_data", + "array_new_data", + "array_new_elem" + ]: return True if sgx_flag: diff --git a/tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch index bc91d6b065..e333dd933e 100644 --- a/tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch +++ b/tests/wamr-test-suites/spec-test-script/gc_ignore_cases.patch @@ -1,417 +1,332 @@ -diff --git a/test/core/binary-leb128.wast b/test/core/binary-leb128.wast -index 335496f0..5b975028 100644 ---- a/test/core/binary-leb128.wast -+++ b/test/core/binary-leb128.wast -@@ -1078,5 +1078,5 @@ - "\e0\7f" ;; Malformed functype, -0x20 in signed LEB128 encoding - "\00\00" - ) -- "integer representation too long" -+ "invalid type flag" ;; In GC extension, the first byte in rectype define is just one byte, not LEB128 encoded. - ) -diff --git a/test/core/elem.wast b/test/core/elem.wast -index df1610f6..32c1d8b3 100644 ---- a/test/core/elem.wast -+++ b/test/core/elem.wast -@@ -400,7 +400,7 @@ +diff --git a/test/core/br_if.wast b/test/core/br_if.wast +index 9d0cdd81..19902310 100644 +--- a/test/core/br_if.wast ++++ b/test/core/br_if.wast +@@ -663,6 +663,7 @@ + "unknown label" ) ++(;; Activate the test case once the capability to manage such edge cases is enabled. + ;; https://github.com/WebAssembly/gc/issues/516 (assert_invalid -- (module -+ (module - (table 1 funcref) - (elem (offset (;empty instruction sequence;))) + (module +@@ -677,3 +678,4 @@ ) -@@ -476,7 +476,7 @@ + "type mismatch" ) - ++;;) +diff --git a/test/core/br_on_non_null.wast b/test/core/br_on_non_null.wast +index 43800194..b9bb5c41 100644 +--- a/test/core/br_on_non_null.wast ++++ b/test/core/br_on_non_null.wast +@@ -72,7 +72,8 @@ + (assert_return (invoke "args-null" (i32.const 3)) (i32.const 3)) + (assert_return (invoke "args-f" (i32.const 3)) (i32.const 9)) + +- ++(;;Activate the test case once the capability to manage such edge cases is enabled. ++;; ASSERTION FAILED: 0, at file /workspaces/wasm-micro-runtime/core/iwasm/common/gc/gc_type.c, line 1059 + ;; https://github.com/WebAssembly/gc/issues/516 (assert_invalid -- (module -+ (module - (table 1 funcref) - (elem (global.get 0)) - ) -@@ -493,7 +493,7 @@ + (module +@@ -88,3 +89,4 @@ + ) + "type mismatch" ) - - (assert_invalid -- (module -+ (module - (global (import "test" "global-mut-i32") (mut i32)) - (table 1 funcref) - (elem (global.get 0)) -@@ -603,12 +603,13 @@ ++;;) +diff --git a/test/core/br_on_null.wast b/test/core/br_on_null.wast +index e47dae50..58abf6a9 100644 +--- a/test/core/br_on_null.wast ++++ b/test/core/br_on_null.wast +@@ -66,6 +66,7 @@ + (assert_return (invoke "args-f" (i32.const 3)) (i32.const 9)) + + ++(;; Activate the test case once the capability to manage such edge cases is enabled. + ;; https://github.com/WebAssembly/gc/issues/516 + ;; Tests that validators are correctly doing + ;; +@@ -92,3 +93,4 @@ ) + "type mismatch" + ) ++;;) +diff --git a/test/core/elem.wast b/test/core/elem.wast +index bc1cc324..14af14ae 100644 +--- a/test/core/elem.wast ++++ b/test/core/elem.wast +@@ -462,6 +462,7 @@ + "\02\00\0b" ;; Function 0: empty ) --(register "module1" $module1) -+(; (register "module1" $module1) ;) ++(;; Enable the case once compatibility has been established. + (module + (func) + (table 1 (ref func) (ref.func 0)) +@@ -478,6 +479,7 @@ + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty + ) ++;;) --(assert_trap (invoke $module1 "call-7") "uninitialized element") --(assert_return (invoke $module1 "call-8") (i32.const 65)) --(assert_return (invoke $module1 "call-9") (i32.const 66)) -+(assert_trap (invoke "call-7") "uninitialized element") -+(assert_return (invoke "call-8") (i32.const 65)) -+(assert_return (invoke "call-9") (i32.const 66)) + (module + (func) +@@ -536,6 +538,7 @@ + "type mismatch" + ) -+(; - (module $module2 - (type $out-i32 (func (result i32))) - (import "module1" "shared-table" (table 10 funcref)) -@@ -617,11 +618,15 @@ - (func $const-i32-c (type $out-i32) (i32.const 67)) - (func $const-i32-d (type $out-i32) (i32.const 68)) ++(;; Enable the case once compatibility has been established. + (module + (func) + (table 1 (ref func) (ref.func 0)) +@@ -552,6 +555,7 @@ + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty ) -+;) ++;;) + + (module + (func) +@@ -929,8 +933,9 @@ + (assert_return (invoke "call-overwritten-element") (i32.const 66)) -+(; - (assert_return (invoke $module1 "call-7") (i32.const 67)) - (assert_return (invoke $module1 "call-8") (i32.const 68)) - (assert_return (invoke $module1 "call-9") (i32.const 66)) -+;) -+(; - (module $module3 ++(;;Activate test cases once the capability to import table is enabled ++;; + ;; Element sections across multiple modules change the same table +- + (module $module1 (type $out-i32 (func (result i32))) - (import "module1" "shared-table" (table 10 funcref)) -@@ -634,6 +639,7 @@ + (table (export "shared-table") 10 funcref) +@@ -980,6 +985,7 @@ (assert_return (invoke $module1 "call-7") (i32.const 67)) (assert_return (invoke $module1 "call-8") (i32.const 69)) (assert_return (invoke $module1 "call-9") (i32.const 70)) -+;) ++;;) ;; Element segments must match element type of table -@@ -666,6 +672,7 @@ +@@ -1019,17 +1025,18 @@ + (func (export "set") (param $i i32) (param $x externref) + (table.set $t (local.get $i) (local.get $x)))) + +-(register "exporter" $m) ++;; (register "exporter" $m) - ;; Initializing a table with an externref-type element segment +-(assert_return (invoke $m "get" (i32.const 0)) (ref.null extern)) +-(assert_return (invoke $m "get" (i32.const 1)) (ref.null extern)) ++(assert_return (invoke "get" (i32.const 0)) (ref.null extern)) ++(assert_return (invoke "get" (i32.const 1)) (ref.null extern)) -+(; - (module $m - (table $t (export "table") 2 externref) - (func (export "get") (param $i i32) (result externref) -@@ -713,3 +720,5 @@ +-(assert_return (invoke $m "set" (i32.const 0) (ref.extern 42))) +-(assert_return (invoke $m "set" (i32.const 1) (ref.extern 137))) ++(assert_return (invoke "set" (i32.const 0) (ref.extern 42))) ++(assert_return (invoke "set" (i32.const 1) (ref.extern 137))) + +-(assert_return (invoke $m "get" (i32.const 0)) (ref.extern 42)) +-(assert_return (invoke $m "get" (i32.const 1)) (ref.extern 137)) ++(assert_return (invoke "get" (i32.const 0)) (ref.extern 42)) ++(assert_return (invoke "get" (i32.const 1)) (ref.extern 137)) + ++(;;Activate test cases once the capability to import table is enabled + (module + (import "exporter" "table" (table $t 2 externref)) + (elem (i32.const 0) externref (ref.null extern))) +@@ -1059,3 +1066,4 @@ ) (assert_return (invoke "call_imported_elem") (i32.const 42)) -+ -+;) ++;;) diff --git a/test/core/gc/array.wast b/test/core/gc/array.wast -index f5888cb2..b4a2dc0a 100644 +index 6ad95c08..a184435d 100644 --- a/test/core/gc/array.wast +++ b/test/core/gc/array.wast -@@ -95,7 +95,7 @@ +@@ -95,7 +95,10 @@ ) (assert_return (invoke "new") (ref.array)) -(assert_return (invoke "new") (ref.eq)) ++(; Activate once the scripts perform ++ ; typing comparison rather than comparing strings ++ ;) +;; (assert_return (invoke "new") (ref.eq)) (assert_return (invoke "get" (i32.const 0)) (f32.const 0)) (assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7)) (assert_return (invoke "len") (i32.const 3)) -@@ -140,7 +140,7 @@ +@@ -140,7 +143,10 @@ ) (assert_return (invoke "new") (ref.array)) -(assert_return (invoke "new") (ref.eq)) ++(; Activate once the scripts perform ++ ; typing comparison rather than comparing strings ++ ;) +;; (assert_return (invoke "new") (ref.eq)) (assert_return (invoke "get" (i32.const 0)) (f32.const 1)) (assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7)) (assert_return (invoke "len") (i32.const 2)) -@@ -185,7 +185,7 @@ +@@ -192,7 +198,10 @@ ) (assert_return (invoke "new") (ref.array)) -(assert_return (invoke "new") (ref.eq)) ++(; Activate once the scripts perform ++ ; typing comparison rather than comparing strings ++ ;) +;; (assert_return (invoke "new") (ref.eq)) - (assert_return (invoke "get" (i32.const 0)) (i32.const 1)) + (assert_return (invoke "get_u" (i32.const 2)) (i32.const 0xff)) + (assert_return (invoke "get_s" (i32.const 2)) (i32.const -1)) (assert_return (invoke "set_get" (i32.const 1) (i32.const 7)) (i32.const 7)) - (assert_return (invoke "len") (i32.const 3)) -@@ -193,6 +193,7 @@ - (assert_trap (invoke "get" (i32.const 10)) "out of bounds array access") +@@ -202,6 +211,7 @@ + (assert_trap (invoke "get_s" (i32.const 10)) "out of bounds array access") (assert_trap (invoke "set_get" (i32.const 10) (i32.const 7)) "out of bounds array access") -+(; array.new_elem not supported ++(;; Activate once aligned `array.new_elem` (module (type $bvec (array i8)) (type $vec (array (ref $bvec))) -@@ -251,6 +252,7 @@ +@@ -260,6 +270,7 @@ (assert_trap (invoke "get" (i32.const 10) (i32.const 0)) "out of bounds array access") (assert_trap (invoke "set_get" (i32.const 10) (i32.const 0) (i32.const 0)) "out of bounds array access") -+;) ++;;) + + (assert_invalid + (module +diff --git a/test/core/gc/br_on_cast.wast b/test/core/gc/br_on_cast.wast +index 3c895c07..147f9a1a 100644 +--- a/test/core/gc/br_on_cast.wast ++++ b/test/core/gc/br_on_cast.wast +@@ -267,6 +267,7 @@ + ) + + ++(;;Activate the test case once the capability to manage such edge cases is enabled. + ;; https://github.com/WebAssembly/gc/issues/516 + (assert_invalid + (module +@@ -283,3 +284,4 @@ + ) + "type mismatch" + ) ++;;) +diff --git a/test/core/gc/br_on_cast_fail.wast b/test/core/gc/br_on_cast_fail.wast +index db6db11b..b0224c84 100644 +--- a/test/core/gc/br_on_cast_fail.wast ++++ b/test/core/gc/br_on_cast_fail.wast +@@ -282,6 +282,7 @@ + ) + ++(;;Activate the test case once the capability to manage such edge cases is enabled. + ;; https://github.com/WebAssembly/gc/issues/516 (assert_invalid (module +@@ -298,3 +299,4 @@ + ) + "type mismatch" + ) ++;;) diff --git a/test/core/gc/extern.wast b/test/core/gc/extern.wast -index abf31669..9ef86506 100644 +index abf31669..4243808d 100644 --- a/test/core/gc/extern.wast +++ b/test/core/gc/extern.wast -@@ -43,7 +43,7 @@ +@@ -43,7 +43,10 @@ (assert_return (invoke "externalize-i" (i32.const 1)) (ref.extern)) (assert_return (invoke "externalize-i" (i32.const 2)) (ref.extern)) (assert_return (invoke "externalize-i" (i32.const 3)) (ref.extern)) -(assert_return (invoke "externalize-i" (i32.const 4)) (ref.extern)) ++(; Switch back to the original configuration once the scripts perform ++ ; typing comparison rather than comparing strings ++ ;) +(assert_return (invoke "externalize-i" (i32.const 4)) (ref.extern 0)) (assert_return (invoke "externalize-i" (i32.const 5)) (ref.null extern)) (assert_return (invoke "externalize-ii" (i32.const 0)) (ref.null any)) -diff --git a/test/core/gc/initializer.wast b/test/core/gc/initializer.wast -new file mode 100644 -index 00000000..32650644 ---- /dev/null -+++ b/test/core/gc/initializer.wast -@@ -0,0 +1,34 @@ -+;; added cases to test constant expressions -+ -+(module -+ (type $struct (struct (field f32) (field $y (mut f32)) (field $z f32))) -+ (type $vec (array f32)) -+ -+ ;; table initializer -+ (table 10 anyref) -+ -+ ;; global initializer -+ (global (ref $vec) (array.new_fixed $vec 2 (f32.const 1) (f32.const 2))) -+ (global (ref $struct) (struct.new_default $struct)) -+ -+ ;; elem initializer -+ (elem (i32.const 0) (ref $vec) (array.new_default $vec (i32.const 2))) -+ (elem (i32.const 1) (ref $vec) (array.new $vec (f32.const 1) (i32.const 3))) -+ (elem (i32.const 2) (ref $struct) (struct.new_default $struct)) -+ -+ (func (export "get_table") (param $i i32) (result anyref) -+ (table.get (local.get $i)) -+ ) -+) -+ -+(assert_return (invoke "get_table" (i32.const 0)) (ref.array)) -+(assert_return (invoke "get_table" (i32.const 1)) (ref.array)) -+(assert_return (invoke "get_table" (i32.const 2)) (ref.struct)) -+ -+(assert_invalid -+ (module -+ (type $struct (struct (field f32) (field $y (mut f32)) (field $z f32))) -+ (table 10 anyref (struct.new_default $struct)) -+ ) -+ "unsupported initializer expression for table" -+) -diff --git a/test/core/gc/type-subtyping.wast b/test/core/gc/type-subtyping.wast -index a9022fc3..4aa36e2a 100644 ---- a/test/core/gc/type-subtyping.wast -+++ b/test/core/gc/type-subtyping.wast -@@ -740,7 +740,7 @@ - "sub type" - ) - --(assert_invalid -+(assert_invalid - (module - (type $f0 (sub (func (param i32) (result i32)))) - (type $s0 (sub $f0 (struct))) -@@ -764,7 +764,7 @@ - "sub type" +diff --git a/test/core/gc/i31.wast b/test/core/gc/i31.wast +index 6309e72b..39f35692 100644 +--- a/test/core/gc/i31.wast ++++ b/test/core/gc/i31.wast +@@ -52,12 +52,19 @@ + + (assert_trap (invoke "get_u-null") "null i31 reference") + (assert_trap (invoke "get_s-null") "null i31 reference") +- + (assert_return (invoke "get_globals") (i32.const 2) (i32.const 3)) +- + (invoke "set_global" (i32.const 1234)) + (assert_return (invoke "get_globals") (i32.const 2) (i32.const 1234)) + ++(;; Activate the following test once the new init expr is supported. ++ ;; ++ ;; ASSERTION FAILED: ++ ;; (init_expr->init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) ++ ;; || (init_expr->init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST) ++ ;; || (init_expr->init_expr_type >= INIT_EXPR_TYPE_FUNCREF_CONST ++ ;; && init_expr->init_expr_type <= INIT_EXPR_TYPE_ARRAY_NEW_FIXED), ++ ;; at file /workspaces/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c, line 4454 ++ ;; + (module $tables_of_i31ref + (table $table 3 10 i31ref) + (elem (table $table) (i32.const 0) i31ref (item (ref.i31 (i32.const 999))) +@@ -119,7 +126,9 @@ + (assert_return (invoke "get" (i32.const 1)) (i32.const 123)) + (assert_return (invoke "get" (i32.const 2)) (i32.const 456)) + (assert_return (invoke "get" (i32.const 3)) (i32.const 789)) ++;;) + ++(;; + (module $env + (global (export "g") i32 (i32.const 42)) ) - --(assert_invalid -+(assert_invalid - (module - (type $s0 (sub (struct))) - (type $f0 (sub $s0 (func (param i32) (result i32)))) -@@ -772,7 +772,7 @@ - "sub type" +@@ -146,6 +155,7 @@ ) --(assert_invalid -+(assert_invalid - (module - (type $a0 (sub (array i32))) - (type $f0 (sub $a0 (func (param i32) (result i32)))) + (assert_return (invoke "get") (i32.const 42)) ++ ;;) + + (module $anyref_global_of_i31ref + (global $c anyref (ref.i31 (i32.const 1234))) +@@ -165,6 +175,15 @@ + (invoke "set_global" (i32.const 0)) + (assert_return (invoke "get_globals") (i32.const 1234) (i32.const 0)) + ++(;; Activate the following test once the new init expr is supported. ++ ;; ++ ;; ASSERTION FAILED: ++ ;; (init_expr->init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) ++ ;; || (init_expr->init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST) ++ ;; || (init_expr->init_expr_type >= INIT_EXPR_TYPE_FUNCREF_CONST ++ ;; && init_expr->init_expr_type <= INIT_EXPR_TYPE_ARRAY_NEW_FIXED), ++ ;; at file /workspaces/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c, line 4454 ++ ;; + (module $anyref_table_of_i31ref + (table $table 3 10 anyref) + (elem (table $table) (i32.const 0) i31ref (item (ref.i31 (i32.const 999))) +@@ -226,3 +245,5 @@ + (assert_return (invoke "get" (i32.const 1)) (i32.const 123)) + (assert_return (invoke "get" (i32.const 2)) (i32.const 456)) + (assert_return (invoke "get" (i32.const 3)) (i32.const 789)) ++ ;; ++ ;;) diff --git a/test/core/global.wast b/test/core/global.wast -index 8c47fde2..1a8cc7e3 100644 +index 8c47fde2..8d3d8228 100644 --- a/test/core/global.wast +++ b/test/core/global.wast -@@ -644,7 +644,7 @@ +@@ -644,7 +644,10 @@ ) ) -(assert_return (invoke "get-elem" (i32.const 0)) (ref.null)) ++(; Switch back to the original configuration once the scripts perform ++ ; typing comparison rather than comparing strings ++ ;) +(assert_return (invoke "get-elem" (i32.const 0)) (ref.null func)) (assert_return (invoke "get-elem" (i32.const 4)) (ref.func)) (assert_return (invoke "get-elem" (i32.const 8)) (ref.func)) -@@ -652,7 +652,7 @@ - (assert_return (invoke "get-data" (i32.const 8)) (i32.const 0x88888888)) - - (assert_invalid -- (module -+ (module - (global $g1 i32 (global.get $g2)) - (global $g2 i32 (i32.const 0)) - ) -diff --git a/test/core/imports.wast b/test/core/imports.wast -index 69f76a0b..a3844c65 100644 ---- a/test/core/imports.wast -+++ b/test/core/imports.wast -@@ -572,6 +572,7 @@ - (assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) - (assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) - -+(; unsupported by multi-module currently - (module $Mgm - (memory (export "memory") 1) ;; initial size is 1 - (func (export "grow") (result i32) (memory.grow (i32.const 1))) -@@ -591,6 +592,7 @@ - (func (export "size") (result i32) (memory.size)) - ) - (assert_return (invoke $Mgim2 "size") (i32.const 3)) -+;) - - - ;; Syntax errors -diff --git a/test/core/linking.wast b/test/core/linking.wast -index 6a8ba1d0..a45534fd 100644 ---- a/test/core/linking.wast -+++ b/test/core/linking.wast -@@ -64,6 +64,7 @@ - (export "Mg.set_mut" (func $set_mut)) - ) - -+(; - (assert_return (get $Mg "glob") (i32.const 42)) - (assert_return (get $Ng "Mg.glob") (i32.const 42)) - (assert_return (get $Ng "glob") (i32.const 43)) -@@ -81,6 +82,7 @@ - (assert_return (get $Ng "Mg.mut_glob") (i32.const 241)) - (assert_return (invoke $Mg "get_mut") (i32.const 241)) - (assert_return (invoke $Ng "Mg.get_mut") (i32.const 241)) -+;) - - - (assert_unlinkable -@@ -300,6 +302,7 @@ - ) - ) - -+(; - (assert_return (invoke $Mt "call" (i32.const 2)) (i32.const 4)) - (assert_return (invoke $Nt "Mt.call" (i32.const 2)) (i32.const 4)) - (assert_return (invoke $Nt "call" (i32.const 2)) (i32.const 5)) -@@ -322,6 +325,7 @@ - - (assert_return (invoke $Nt "call" (i32.const 3)) (i32.const -4)) - (assert_trap (invoke $Nt "call" (i32.const 4)) "indirect call type mismatch") -+;) - - (module $Ot - (type (func (result i32))) -@@ -336,6 +340,7 @@ - ) - ) - -+(; - (assert_return (invoke $Mt "call" (i32.const 3)) (i32.const 4)) - (assert_return (invoke $Nt "Mt.call" (i32.const 3)) (i32.const 4)) - (assert_return (invoke $Nt "call Mt.call" (i32.const 3)) (i32.const 4)) -@@ -360,6 +365,7 @@ - (assert_trap (invoke $Ot "call" (i32.const 0)) "uninitialized element") - - (assert_trap (invoke $Ot "call" (i32.const 20)) "undefined element") -+;) - - (module - (table (import "Mt" "tab") 0 funcref) -@@ -398,6 +404,7 @@ - - ;; Unlike in the v1 spec, active element segments stored before an - ;; out-of-bounds access persist after the instantiation failure. -+(; - (assert_trap - (module - (table (import "Mt" "tab") 10 funcref) -@@ -409,7 +416,9 @@ - ) - (assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) - (assert_trap (invoke $Mt "call" (i32.const 8)) "uninitialized element") -+;) - -+(; - (assert_trap - (module - (table (import "Mt" "tab") 10 funcref) -@@ -421,6 +430,7 @@ - "out of bounds memory access" - ) - (assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) -+;) - - - (module $Mtable_ex -@@ -503,10 +513,12 @@ - ) - ) - -+(; - (assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 0xa7)) - (assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 0xa7)) - (assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) - (assert_return (invoke $Om "load" (i32.const 12)) (i32.const 0xa7)) -+;) - - (module - (memory (import "Mm" "mem") 0) -@@ -529,6 +541,7 @@ - ) - ) - -+(; - (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 1)) - (assert_return (invoke $Pm "grow" (i32.const 2)) (i32.const 1)) - (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 3)) -@@ -537,6 +550,7 @@ - (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) - (assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1)) - (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) -+;) - - (assert_unlinkable - (module -@@ -560,8 +574,10 @@ - ) - "out of bounds memory access" - ) -+(; - (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) - (assert_return (invoke $Mm "load" (i32.const 327670)) (i32.const 0)) -+;) - - (assert_trap - (module -@@ -573,7 +589,9 @@ - ) - "out of bounds table access" - ) -+(; - (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) -+;) - - ;; Store is modified if the start function traps. - (module $Ms -@@ -589,6 +607,7 @@ - ) - (register "Ms" $Ms) - -+(; - (assert_trap - (module - (import "Ms" "memory" (memory 1)) -@@ -608,3 +627,4 @@ - - (assert_return (invoke $Ms "get memory[0]") (i32.const 104)) ;; 'h' - (assert_return (invoke $Ms "get table[0]") (i32.const 0xdead)) -+;) diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast -index adb5cb78..590f6262 100644 +index adb5cb78..a4f8de5a 100644 --- a/test/core/ref_func.wast +++ b/test/core/ref_func.wast @@ -4,7 +4,8 @@ @@ -419,71 +334,85 @@ index adb5cb78..590f6262 100644 (module - (func $f (import "M" "f") (param i32) (result i32)) -+ (; aot mode does not support module linking ;) ++ (;Revert to the previous once the GC feature is operational with the multi-module feature.;) + (func $f (param $x i32) (result i32) (local.get $x)) (func $g (param $x i32) (result i32) (i32.add (local.get $x) (i32.const 1)) ) diff --git a/test/core/ref_null.wast b/test/core/ref_null.wast -index 1ffd03f8..bdf7471f 100644 +index 1ffd03f8..2961ffcd 100644 --- a/test/core/ref_null.wast +++ b/test/core/ref_null.wast -@@ -11,7 +11,7 @@ +@@ -11,7 +11,10 @@ (assert_return (invoke "anyref") (ref.null any)) (assert_return (invoke "funcref") (ref.null func)) -(assert_return (invoke "ref") (ref.null)) -+(assert_return (invoke "ref") (ref.null func)) ;; we alwasy require type information ++(; Switch back to the original configuration once the scripts perform ++ ; typing comparison rather than comparing strings ++ ;) ++(assert_return (invoke "ref") (ref.null func)) (module -@@ -41,23 +41,23 @@ +@@ -40,24 +43,33 @@ + (global (ref null $t) (ref.null nofunc)) ) ++(; Switch back to the original configuration once the scripts perform ++ ; typing comparison rather than comparing strings ++ ;) ++(assert_return (invoke "anyref") (ref.null any)) ++(assert_return (invoke "anyref") (ref.null any)) (assert_return (invoke "anyref") (ref.null any)) -(assert_return (invoke "anyref") (ref.null none)) -(assert_return (invoke "anyref") (ref.null)) -+;; (assert_return (invoke "anyref") (ref.null none)) -+;; (assert_return (invoke "anyref") (ref.null func)) ++ ++(assert_return (invoke "nullref") (ref.null any)) ++(assert_return (invoke "nullref") (ref.null any)) (assert_return (invoke "nullref") (ref.null any)) -(assert_return (invoke "nullref") (ref.null none)) -(assert_return (invoke "nullref") (ref.null)) -+;; (assert_return (invoke "nullref") (ref.null none)) -+;; (assert_return (invoke "nullref") (ref.null func)) ++ ++(assert_return (invoke "funcref") (ref.null func)) ++(assert_return (invoke "funcref") (ref.null func)) (assert_return (invoke "funcref") (ref.null func)) -(assert_return (invoke "funcref") (ref.null nofunc)) -(assert_return (invoke "funcref") (ref.null)) -+;; (assert_return (invoke "funcref") (ref.null nofunc)) -+(assert_return (invoke "funcref") (ref.null func)) ++ +(assert_return (invoke "nullfuncref") (ref.null func)) -+;; (assert_return (invoke "nullfuncref") (ref.null nofunc)) (assert_return (invoke "nullfuncref") (ref.null func)) -(assert_return (invoke "nullfuncref") (ref.null nofunc)) -(assert_return (invoke "nullfuncref") (ref.null)) ++(assert_return (invoke "nullfuncref") (ref.null func)) ++ ++(assert_return (invoke "externref") (ref.null extern)) (assert_return (invoke "externref") (ref.null extern)) -(assert_return (invoke "externref") (ref.null noextern)) -(assert_return (invoke "externref") (ref.null)) -+;; (assert_return (invoke "externref") (ref.null noextern)) -+;; (assert_return (invoke "externref") (ref.null func)) ++(assert_return (invoke "externref") (ref.null extern)) ++ (assert_return (invoke "nullexternref") (ref.null extern)) -(assert_return (invoke "nullexternref") (ref.null noextern)) -(assert_return (invoke "nullexternref") (ref.null)) -+;; (assert_return (invoke "nullexternref") (ref.null noextern)) -+;; (assert_return (invoke "nullexternref") (ref.null func)) ++(assert_return (invoke "nullexternref") (ref.null extern)) ++(assert_return (invoke "nullexternref") (ref.null extern)) ++ ++(assert_return (invoke "ref") (ref.null func)) +(assert_return (invoke "ref") (ref.null func)) -+;; (assert_return (invoke "ref") (ref.null nofunc)) (assert_return (invoke "ref") (ref.null func)) -(assert_return (invoke "ref") (ref.null nofunc)) -(assert_return (invoke "ref") (ref.null)) diff --git a/test/core/return_call.wast b/test/core/return_call.wast -index 2f91f4de..ad66acca 100644 +index b9e8f8f0..8a3d7512 100644 --- a/test/core/return_call.wast +++ b/test/core/return_call.wast -@@ -102,20 +102,20 @@ +@@ -102,20 +102,23 @@ (assert_return (invoke "count" (i64.const 0)) (i64.const 0)) (assert_return (invoke "count" (i64.const 1000)) (i64.const 0)) -(assert_return (invoke "count" (i64.const 1_000_000)) (i64.const 0)) ++(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) +(assert_return (invoke "count" (i64.const 100_000)) (i64.const 0)) (assert_return (invoke "even" (i64.const 0)) (i32.const 44)) @@ -492,6 +421,7 @@ index 2f91f4de..ad66acca 100644 (assert_return (invoke "even" (i64.const 77)) (i32.const 99)) -(assert_return (invoke "even" (i64.const 1_000_000)) (i32.const 44)) -(assert_return (invoke "even" (i64.const 1_000_001)) (i32.const 99)) ++(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) +(assert_return (invoke "even" (i64.const 100_000)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 100_001)) (i32.const 99)) (assert_return (invoke "odd" (i64.const 0)) (i32.const 99)) @@ -500,36 +430,39 @@ index 2f91f4de..ad66acca 100644 (assert_return (invoke "odd" (i64.const 77)) (i32.const 44)) -(assert_return (invoke "odd" (i64.const 1_000_000)) (i32.const 99)) -(assert_return (invoke "odd" (i64.const 999_999)) (i32.const 44)) ++(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) +(assert_return (invoke "odd" (i64.const 100_000)) (i32.const 99)) -+(assert_return (invoke "odd" (i64.const 99_999)) (i32.const 44)) ++(assert_return (invoke "odd" (i64.const 99_999)) (i32.const 44)) ;; Invalid typing diff --git a/test/core/return_call_indirect.wast b/test/core/return_call_indirect.wast -index acf0a72e..6b95c24b 100644 +index aa158be2..7f68b4a5 100644 --- a/test/core/return_call_indirect.wast +++ b/test/core/return_call_indirect.wast -@@ -263,8 +263,8 @@ +@@ -263,8 +263,9 @@ (assert_return (invoke "odd" (i32.const 1)) (i32.const 44)) (assert_return (invoke "odd" (i32.const 200)) (i32.const 99)) (assert_return (invoke "odd" (i32.const 77)) (i32.const 44)) -(assert_return (invoke "odd" (i32.const 200_002)) (i32.const 99)) -(assert_return (invoke "odd" (i32.const 300_003)) (i32.const 44)) ++(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) +(assert_return (invoke "odd" (i32.const 100_002)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 100_003)) (i32.const 44)) ;; Invalid syntax diff --git a/test/core/return_call_ref.wast b/test/core/return_call_ref.wast -index 353811f0..f79975b4 100644 +index 5f5a7cba..574d34a3 100644 --- a/test/core/return_call_ref.wast +++ b/test/core/return_call_ref.wast -@@ -192,20 +192,20 @@ +@@ -192,20 +192,23 @@ (assert_return (invoke "count" (i64.const 0)) (i64.const 0)) (assert_return (invoke "count" (i64.const 1000)) (i64.const 0)) -(assert_return (invoke "count" (i64.const 1_000_000)) (i64.const 0)) -+(assert_return (invoke "count" (i64.const 1200)) (i64.const 0)) ++(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) ++(assert_return (invoke "count" (i64.const 1_200)) (i64.const 0)) (assert_return (invoke "even" (i64.const 0)) (i64.const 44)) (assert_return (invoke "even" (i64.const 1)) (i64.const 99)) @@ -537,53 +470,62 @@ index 353811f0..f79975b4 100644 (assert_return (invoke "even" (i64.const 77)) (i64.const 99)) -(assert_return (invoke "even" (i64.const 1_000_000)) (i64.const 44)) -(assert_return (invoke "even" (i64.const 1_000_001)) (i64.const 99)) -+(assert_return (invoke "even" (i64.const 1200)) (i64.const 44)) -+(assert_return (invoke "even" (i64.const 1201)) (i64.const 99)) ++(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) ++(assert_return (invoke "even" (i64.const 1_200)) (i64.const 44)) ++(assert_return (invoke "even" (i64.const 1_201)) (i64.const 99)) (assert_return (invoke "odd" (i64.const 0)) (i64.const 99)) (assert_return (invoke "odd" (i64.const 1)) (i64.const 44)) (assert_return (invoke "odd" (i64.const 200)) (i64.const 99)) (assert_return (invoke "odd" (i64.const 77)) (i64.const 44)) -(assert_return (invoke "odd" (i64.const 1_000_000)) (i64.const 99)) -(assert_return (invoke "odd" (i64.const 999_999)) (i64.const 44)) -+(assert_return (invoke "odd" (i64.const 1200)) (i64.const 99)) -+(assert_return (invoke "odd" (i64.const 1119)) (i64.const 44)) ++(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) ++(assert_return (invoke "odd" (i64.const 1_200)) (i64.const 99)) ++(assert_return (invoke "odd" (i64.const 1_199)) (i64.const 44)) ;; More typing diff --git a/test/core/select.wast b/test/core/select.wast -index 61e4dc22..b0b1344c 100644 +index 61e4dc22..f7f92f81 100644 --- a/test/core/select.wast +++ b/test/core/select.wast -@@ -277,7 +277,7 @@ +@@ -277,7 +277,10 @@ (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304)) (assert_return (invoke "join-funcnull" (i32.const 1)) (ref.func)) -(assert_return (invoke "join-funcnull" (i32.const 0)) (ref.null)) -+(assert_return (invoke "join-funcnull" (i32.const 0)) (ref.null func)) ;; we require type in expected results ++(; Switch back to the original configuration once the scripts perform ++ ; typing comparison rather than comparing strings ++ ;) ++(assert_return (invoke "join-funcnull" (i32.const 0)) (ref.null func)) (assert_trap (invoke "select-trap-left" (i32.const 1)) "unreachable") (assert_trap (invoke "select-trap-left" (i32.const 0)) "unreachable") diff --git a/test/core/table.wast b/test/core/table.wast -index a11dce56..ace19ac8 100644 +index a11dce56..d9820382 100644 --- a/test/core/table.wast +++ b/test/core/table.wast -@@ -103,11 +103,11 @@ +@@ -103,11 +103,15 @@ (func (export "get5") (result funcref) (table.get $t5 (i32.const 9))) ) -(assert_return (invoke "get1") (ref.null)) ++(; Switch back to the original configuration once the scripts perform ++ ; typing comparison rather than comparing strings ++ ;) +(assert_return (invoke "get1") (ref.null func)) (assert_return (invoke "get2") (ref.func)) (assert_return (invoke "get3") (ref.func)) -(assert_return (invoke "get4") (ref.func)) -(assert_return (invoke "get5") (ref.func)) -+(assert_return (invoke "get4") (ref.null func)) ;; We don't give a value to the imported global -+(assert_return (invoke "get5") (ref.null func)) ;; So these two tables are initialized as ref.null ++(;Revert to previous ones once the capability to import global is aligned;) ++(assert_return (invoke "get4") (ref.null func)) ++(assert_return (invoke "get5") (ref.null func)) (assert_invalid diff --git a/test/core/table_copy.wast b/test/core/table_copy.wast -index 380e84ee..f37e745c 100644 +index 380e84ee..288cc985 100644 --- a/test/core/table_copy.wast +++ b/test/core/table_copy.wast @@ -14,11 +14,12 @@ @@ -595,16 +537,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ ;; aot mode does not support module linking -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -106,11 +107,11 @@ +@@ -106,11 +107,12 @@ (module (type (func (result i32))) ;; type #0 @@ -613,15 +555,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 + (func (export "ef1") (result i32) (i32.const 1)) + (func (export "ef2") (result i32) (i32.const 2)) + (func (export "ef3") (result i32) (i32.const 3)) -+ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -198,11 +199,11 @@ +@@ -198,11 +200,12 @@ (module (type (func (result i32))) ;; type #0 @@ -630,15 +573,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -290,11 +291,11 @@ +@@ -290,11 +293,12 @@ (module (type (func (result i32))) ;; type #0 @@ -647,15 +591,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -382,11 +383,11 @@ +@@ -382,11 +386,12 @@ (module (type (func (result i32))) ;; type #0 @@ -664,15 +609,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -474,11 +475,11 @@ +@@ -474,11 +479,12 @@ (module (type (func (result i32))) ;; type #0 @@ -681,15 +627,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -566,11 +567,11 @@ +@@ -566,11 +572,12 @@ (module (type (func (result i32))) ;; type #0 @@ -698,15 +645,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -658,11 +659,11 @@ +@@ -658,11 +665,12 @@ (module (type (func (result i32))) ;; type #0 @@ -715,15 +663,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -750,11 +751,11 @@ +@@ -750,11 +758,12 @@ (module (type (func (result i32))) ;; type #0 @@ -732,15 +681,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -842,11 +843,11 @@ +@@ -842,11 +851,12 @@ (module (type (func (result i32))) ;; type #0 @@ -749,15 +699,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -934,11 +935,11 @@ +@@ -934,11 +944,12 @@ (module (type (func (result i32))) ;; type #0 @@ -766,15 +717,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1026,11 +1027,11 @@ +@@ -1026,11 +1037,12 @@ (module (type (func (result i32))) ;; type #0 @@ -783,15 +735,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1118,11 +1119,11 @@ +@@ -1118,11 +1130,12 @@ (module (type (func (result i32))) ;; type #0 @@ -800,15 +753,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1210,11 +1211,11 @@ +@@ -1210,11 +1223,12 @@ (module (type (func (result i32))) ;; type #0 @@ -817,15 +771,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1302,11 +1303,11 @@ +@@ -1302,11 +1316,12 @@ (module (type (func (result i32))) ;; type #0 @@ -834,15 +789,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1394,11 +1395,11 @@ +@@ -1394,11 +1409,12 @@ (module (type (func (result i32))) ;; type #0 @@ -851,15 +807,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1486,11 +1487,11 @@ +@@ -1486,11 +1502,12 @@ (module (type (func (result i32))) ;; type #0 @@ -868,15 +825,16 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1578,11 +1579,11 @@ +@@ -1578,11 +1595,12 @@ (module (type (func (result i32))) ;; type #0 @@ -885,16 +843,17 @@ index 380e84ee..f37e745c 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) diff --git a/test/core/table_init.wast b/test/core/table_init.wast -index 0b2d26f7..bdab6a01 100644 +index 0b2d26f7..65b92bf8 100644 --- a/test/core/table_init.wast +++ b/test/core/table_init.wast @@ -14,11 +14,12 @@ @@ -906,12 +865,12 @@ index 0b2d26f7..bdab6a01 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ ;; aot mode does not support module linking -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) @@ -924,12 +883,12 @@ index 0b2d26f7..bdab6a01 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ ;; aot mode does not support module linking -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) @@ -942,12 +901,12 @@ index 0b2d26f7..bdab6a01 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ ;; aot mode does not support module linking -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) @@ -960,12 +919,12 @@ index 0b2d26f7..bdab6a01 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ ;; aot mode does not support module linking -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) @@ -978,12 +937,12 @@ index 0b2d26f7..bdab6a01 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ ;; aot mode does not support module linking -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) @@ -996,12 +955,12 @@ index 0b2d26f7..bdab6a01 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 -+ ;; aot mode does not support module linking -+ (func (result i32) (i32.const 0)) ;; index 0 -+ (func (result i32) (i32.const 1)) -+ (func (result i32) (i32.const 2)) -+ (func (result i32) (i32.const 3)) -+ (func (result i32) (i32.const 4)) ;; index 4 ++ (;Revert to previous ones once the capability to import table is enabled;) ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) diff --git a/tests/wamr-test-suites/spec-test-script/gc_nuttx_tail_call.patch b/tests/wamr-test-suites/spec-test-script/gc_nuttx_tail_call.patch index efbd9e1780..5992950907 100644 --- a/tests/wamr-test-suites/spec-test-script/gc_nuttx_tail_call.patch +++ b/tests/wamr-test-suites/spec-test-script/gc_nuttx_tail_call.patch @@ -1,53 +1,56 @@ diff --git a/test/core/return_call.wast b/test/core/return_call.wast -index ad66acca..b27af19b 100644 +index 8a3d7512..5a4eba68 100644 --- a/test/core/return_call.wast +++ b/test/core/return_call.wast -@@ -102,20 +102,20 @@ - +@@ -103,22 +103,22 @@ (assert_return (invoke "count" (i64.const 0)) (i64.const 0)) (assert_return (invoke "count" (i64.const 1000)) (i64.const 0)) + (;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) -(assert_return (invoke "count" (i64.const 100_000)) (i64.const 0)) -+(assert_return (invoke "count" (i64.const 1001)) (i64.const 0)) ++(assert_return (invoke "count" (i64.const 1_001)) (i64.const 0)) (assert_return (invoke "even" (i64.const 0)) (i32.const 44)) (assert_return (invoke "even" (i64.const 1)) (i32.const 99)) (assert_return (invoke "even" (i64.const 100)) (i32.const 44)) (assert_return (invoke "even" (i64.const 77)) (i32.const 99)) + (;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) -(assert_return (invoke "even" (i64.const 100_000)) (i32.const 44)) -(assert_return (invoke "even" (i64.const 100_001)) (i32.const 99)) -+(assert_return (invoke "even" (i64.const 1000)) (i32.const 44)) -+(assert_return (invoke "even" (i64.const 1001)) (i32.const 99)) ++(assert_return (invoke "even" (i64.const 1_000)) (i32.const 44)) ++(assert_return (invoke "even" (i64.const 1_001)) (i32.const 99)) (assert_return (invoke "odd" (i64.const 0)) (i32.const 99)) (assert_return (invoke "odd" (i64.const 1)) (i32.const 44)) (assert_return (invoke "odd" (i64.const 200)) (i32.const 99)) (assert_return (invoke "odd" (i64.const 77)) (i32.const 44)) + (;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) -(assert_return (invoke "odd" (i64.const 100_000)) (i32.const 99)) --(assert_return (invoke "odd" (i64.const 99_999)) (i32.const 44)) -+(assert_return (invoke "odd" (i64.const 1000)) (i32.const 99)) -+(assert_return (invoke "odd" (i64.const 999)) (i32.const 44)) +-(assert_return (invoke "odd" (i64.const 99_999)) (i32.const 44)) ++(assert_return (invoke "odd" (i64.const 1_000)) (i32.const 99)) ++(assert_return (invoke "odd" (i64.const 999)) (i32.const 44)) ;; Invalid typing diff --git a/test/core/return_call_indirect.wast b/test/core/return_call_indirect.wast -index 6b95c24b..a9e86d42 100644 +index 7f68b4a5..08a31417 100644 --- a/test/core/return_call_indirect.wast +++ b/test/core/return_call_indirect.wast -@@ -257,14 +257,14 @@ +@@ -257,15 +257,15 @@ (assert_return (invoke "even" (i32.const 1)) (i32.const 99)) (assert_return (invoke "even" (i32.const 100)) (i32.const 44)) (assert_return (invoke "even" (i32.const 77)) (i32.const 99)) -(assert_return (invoke "even" (i32.const 100_000)) (i32.const 44)) -(assert_return (invoke "even" (i32.const 111_111)) (i32.const 99)) -+(assert_return (invoke "even" (i32.const 1000)) (i32.const 44)) -+(assert_return (invoke "even" (i32.const 1111)) (i32.const 99)) ++(assert_return (invoke "even" (i32.const 1_000)) (i32.const 44)) ++(assert_return (invoke "even" (i32.const 1_001)) (i32.const 99)) (assert_return (invoke "odd" (i32.const 0)) (i32.const 99)) (assert_return (invoke "odd" (i32.const 1)) (i32.const 44)) (assert_return (invoke "odd" (i32.const 200)) (i32.const 99)) (assert_return (invoke "odd" (i32.const 77)) (i32.const 44)) + (;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;) -(assert_return (invoke "odd" (i32.const 100_002)) (i32.const 99)) -(assert_return (invoke "odd" (i32.const 100_003)) (i32.const 44)) -+(assert_return (invoke "odd" (i32.const 1002)) (i32.const 99)) -+(assert_return (invoke "odd" (i32.const 1003)) (i32.const 44)) ++(assert_return (invoke "odd" (i32.const 1_002)) (i32.const 99)) ++(assert_return (invoke "odd" (i32.const 1_003)) (i32.const 44)) ;; Invalid syntax diff --git a/tests/wamr-test-suites/spec-test-script/ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/ignore_cases.patch index 73f749737c..e0bcf362e4 100644 --- a/tests/wamr-test-suites/spec-test-script/ignore_cases.patch +++ b/tests/wamr-test-suites/spec-test-script/ignore_cases.patch @@ -1,136 +1,66 @@ -diff --git a/test/core/data.wast b/test/core/data.wast -index b1e1239..a0f6967 100644 ---- a/test/core/data.wast -+++ b/test/core/data.wast -@@ -312,7 +312,8 @@ - "\02\01\41\00\0b" ;; active data segment 0 for memory 1 - "\00" ;; empty vec(byte) - ) -- "unknown memory 1" -+ ;; TODO: restore after supporting multi memory" -+ "unknown memory" - ) - - ;; Data segment with memory index 0 (no memory section) -@@ -334,7 +335,8 @@ - "\02\01\41\00\0b" ;; active data segment 0 for memory 1 - "\00" ;; empty vec(byte) - ) -- "unknown memory 1" -+ ;; TODO: restore after supporting multi memory" -+ "unknown memory" - ) - - ;; Data segment with memory index 1 and vec(byte) as above, -@@ -354,7 +356,8 @@ - "\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f" - "\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d" - ) -- "unknown memory 1" -+ ;; TODO: restore after supporting multi memory" -+ "unknown memory" - ) - - ;; Data segment with memory index 1 and specially crafted vec(byte) after. -@@ -374,7 +377,8 @@ - "\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f" - "\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d" - ) -- "unknown memory 1" -+ ;; TODO: restore after supporting multi memory" -+ "unknown memory" - ) - - diff --git a/test/core/elem.wast b/test/core/elem.wast -index 33b3f67..a4c1a2d 100644 +index 68a244b..a42cbd4 100644 --- a/test/core/elem.wast +++ b/test/core/elem.wast -@@ -586,6 +586,7 @@ - (assert_return (invoke $module1 "call-8") (i32.const 65)) - (assert_return (invoke $module1 "call-9") (i32.const 66)) - -+(; - (module $module2 - (type $out-i32 (func (result i32))) - (import "module1" "shared-table" (table 10 funcref)) -@@ -598,7 +599,9 @@ - (assert_return (invoke $module1 "call-7") (i32.const 67)) - (assert_return (invoke $module1 "call-8") (i32.const 68)) - (assert_return (invoke $module1 "call-9") (i32.const 66)) -+;) - -+(; - (module $module3 - (type $out-i32 (func (result i32))) - (import "module1" "shared-table" (table 10 funcref)) -@@ -611,6 +614,7 @@ - (assert_return (invoke $module1 "call-7") (i32.const 67)) - (assert_return (invoke $module1 "call-8") (i32.const 69)) - (assert_return (invoke $module1 "call-9") (i32.const 70)) -+;) - - ;; Element segments must match element type of table - -@@ -643,6 +647,7 @@ - - ;; Initializing a table with an externref-type element segment - -+(; - (module $m - (table $t (export "table") 2 externref) - (func (export "get") (param $i i32) (result externref) -@@ -667,9 +672,11 @@ - - (assert_return (invoke $m "get" (i32.const 0)) (ref.null extern)) - (assert_return (invoke $m "get" (i32.const 1)) (ref.extern 137)) -+;) - - ;; Initializing a table with imported funcref global - -+(; - (module $module4 - (func (result i32) - i32.const 42 -@@ -690,3 +697,4 @@ +@@ -560,6 +560,9 @@ + ) + (assert_return (invoke "call-overwritten-element") (i32.const 66)) + ++(;; FIXME: enable the following cases after supporting the import of tables ++ ;; ++ + ;; Element sections across multiple modules change the same table + + (module $module1 +@@ -690,3 +693,5 @@ ) (assert_return (invoke "call_imported_elem") (i32.const 42)) -+;) -diff --git a/test/core/if.wast b/test/core/if.wast -index 2ea45f6..6f07304 100644 ---- a/test/core/if.wast -+++ b/test/core/if.wast -@@ -530,7 +530,10 @@ - (func (export "atypical-condition") - i32.const 0 - (if (then) (else)) -- (if (i32.const 1) (i32.eqz) (then) (else)) -+ ;; restore after wabt(> 1.34.0) supports it -+ (i32.const 1) -+ (i32.eqz) -+ (if (then) (else)) - ) ++;; ++;;) +diff --git a/test/core/memory_grow.wast b/test/core/memory_grow.wast +index 882e4b5..d17a509 100644 +--- a/test/core/memory_grow.wast ++++ b/test/core/memory_grow.wast +@@ -308,7 +308,8 @@ + + (assert_return (invoke "as-memory.grow-size") (i32.const 1)) + +- ++(;; FIXME: enable the following cases after supporting the import of memories ++ ;; + (module $Mgm + (memory (export "memory") 1) ;; initial size is 1 + (func (export "grow") (result i32) (memory.grow (i32.const 1))) +@@ -328,7 +329,8 @@ + (func (export "size") (result i32) (memory.size)) ) + (assert_return (invoke $Mgim2 "size") (i32.const 3)) +- ++;; ++;;) + (assert_invalid + (module diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast -index adb5cb7..6396013 100644 +index adb5cb7..98e02cd 100644 --- a/test/core/ref_func.wast +++ b/test/core/ref_func.wast -@@ -4,7 +4,7 @@ +@@ -4,7 +4,8 @@ (register "M") (module - (func $f (import "M" "f") (param i32) (result i32)) ++ (;;FIXME: change it back after supporting the import by default ;;) + (func $f (param $x i32) (result i32) (local.get $x)) (func $g (param $x i32) (result i32) (i32.add (local.get $x) (i32.const 1)) ) diff --git a/test/core/table_copy.wast b/test/core/table_copy.wast -index 380e84e..59230cf 100644 +index 380e84e..2ac9fdc 100644 --- a/test/core/table_copy.wast +++ b/test/core/table_copy.wast -@@ -14,11 +14,11 @@ +@@ -14,11 +14,12 @@ (module (type (func (result i32))) ;; type #0 @@ -139,6 +69,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -147,7 +78,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -106,11 +106,11 @@ +@@ -106,11 +107,12 @@ (module (type (func (result i32))) ;; type #0 @@ -156,6 +87,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -164,7 +96,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -198,11 +198,11 @@ +@@ -198,11 +200,12 @@ (module (type (func (result i32))) ;; type #0 @@ -173,6 +105,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -181,7 +114,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -290,11 +290,11 @@ +@@ -290,11 +293,12 @@ (module (type (func (result i32))) ;; type #0 @@ -190,6 +123,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -198,7 +132,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -382,11 +382,11 @@ +@@ -382,11 +386,12 @@ (module (type (func (result i32))) ;; type #0 @@ -207,6 +141,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -215,7 +150,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -474,11 +474,11 @@ +@@ -474,11 +479,12 @@ (module (type (func (result i32))) ;; type #0 @@ -224,6 +159,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -232,7 +168,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -566,11 +566,11 @@ +@@ -566,11 +572,12 @@ (module (type (func (result i32))) ;; type #0 @@ -241,6 +177,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -249,7 +186,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -658,11 +658,11 @@ +@@ -658,11 +665,12 @@ (module (type (func (result i32))) ;; type #0 @@ -258,6 +195,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -266,7 +204,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -750,11 +750,11 @@ +@@ -750,11 +758,12 @@ (module (type (func (result i32))) ;; type #0 @@ -275,6 +213,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -283,7 +222,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t0) (i32.const 2) func 3 1 4 1) -@@ -842,11 +842,11 @@ +@@ -842,11 +851,12 @@ (module (type (func (result i32))) ;; type #0 @@ -292,6 +231,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -300,7 +240,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -934,11 +934,11 @@ +@@ -934,11 +944,12 @@ (module (type (func (result i32))) ;; type #0 @@ -309,6 +249,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -317,7 +258,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1026,11 +1026,11 @@ +@@ -1026,11 +1037,12 @@ (module (type (func (result i32))) ;; type #0 @@ -326,6 +267,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -334,7 +276,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1118,11 +1118,11 @@ +@@ -1118,11 +1130,12 @@ (module (type (func (result i32))) ;; type #0 @@ -343,6 +285,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -351,7 +294,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1210,11 +1210,11 @@ +@@ -1210,11 +1223,12 @@ (module (type (func (result i32))) ;; type #0 @@ -360,6 +303,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -368,7 +312,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1302,11 +1302,11 @@ +@@ -1302,11 +1316,12 @@ (module (type (func (result i32))) ;; type #0 @@ -377,6 +321,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -385,7 +330,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1394,11 +1394,11 @@ +@@ -1394,11 +1409,12 @@ (module (type (func (result i32))) ;; type #0 @@ -394,6 +339,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -402,7 +348,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1486,11 +1486,11 @@ +@@ -1486,11 +1502,12 @@ (module (type (func (result i32))) ;; type #0 @@ -411,6 +357,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -419,7 +366,7 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) -@@ -1578,11 +1578,11 @@ +@@ -1578,11 +1595,12 @@ (module (type (func (result i32))) ;; type #0 @@ -428,6 +375,7 @@ index 380e84e..59230cf 100644 - (import "a" "ef2" (func (result i32))) - (import "a" "ef3" (func (result i32))) - (import "a" "ef4" (func (result i32))) ;; index 4 ++ (;;FIXME: change it back after supporting the import of tables ;;) + (func (result i32) (i32.const 0)) ;; index 0 + (func (result i32) (i32.const 1)) + (func (result i32) (i32.const 2)) @@ -436,6 +384,29 @@ index 380e84e..59230cf 100644 (table $t0 30 30 funcref) (table $t1 30 30 funcref) (elem (table $t1) (i32.const 2) func 3 1 4 1) +diff --git a/test/core/table_grow.wast b/test/core/table_grow.wast +index 5345a80..0636f67 100644 +--- a/test/core/table_grow.wast ++++ b/test/core/table_grow.wast +@@ -108,6 +108,8 @@ + (assert_return (invoke "check-table-null" (i32.const 0) (i32.const 19)) (ref.null func)) + + ++(;; FIXME: enable the following cases after supporting the import of tables ++ ;; + (module $Tgt + (table (export "table") 1 funcref) ;; initial size is 1 + (func (export "grow") (result i32) (table.grow (ref.null func) (i32.const 1))) +@@ -127,7 +129,8 @@ + (func (export "size") (result i32) (table.size)) + ) + (assert_return (invoke $Tgit2 "size") (i32.const 3)) +- ++;; ++;;) + + ;; Type errors + diff --git a/test/core/table_init.wast b/test/core/table_init.wast index 0b2d26f..3c595e5 100644 --- a/test/core/table_init.wast diff --git a/tests/wamr-test-suites/spec-test-script/multi_module_ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/multi_module_ignore_cases.patch index 9f908488e4..3ff4966d11 100644 --- a/tests/wamr-test-suites/spec-test-script/multi_module_ignore_cases.patch +++ b/tests/wamr-test-suites/spec-test-script/multi_module_ignore_cases.patch @@ -1,56 +1,3 @@ -diff --git a/test/core/imports.wast b/test/core/imports.wast -index 0cc07cb..4e8367a 100644 ---- a/test/core/imports.wast -+++ b/test/core/imports.wast -@@ -86,7 +86,7 @@ - (assert_return (invoke "print64" (i64.const 24))) - - (assert_invalid -- (module -+ (module - (type (func (result i32))) - (import "test" "func" (func (type 1))) - ) -@@ -578,6 +578,7 @@ - (assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) - (assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) - -+(; - (module $Mgm - (memory (export "memory") 1) ;; initial size is 1 - (func (export "grow") (result i32) (memory.grow (i32.const 1))) -@@ -586,7 +587,7 @@ - (assert_return (invoke $Mgm "grow") (i32.const 1)) ;; now size is 2 - (module $Mgim1 - ;; imported memory limits should match, because external memory size is 2 now -- (memory (export "memory") (import "grown-memory" "memory") 2) -+ (memory (export "memory") (import "grown-memory" "memory") 2) - (func (export "grow") (result i32) (memory.grow (i32.const 1))) - ) - (register "grown-imported-memory" $Mgim1) -@@ -597,7 +598,7 @@ - (func (export "size") (result i32) (memory.size)) - ) - (assert_return (invoke $Mgim2 "size") (i32.const 3)) -- -+;) - - ;; Syntax errors - -@@ -669,6 +670,7 @@ - "import after memory" - ) - -+(; - ;; This module is required to validate, regardless of whether it can be - ;; linked. Overloading is not possible in wasm itself, but it is possible - ;; in modules from which wasm can import. -@@ -695,3 +697,4 @@ - ) - "unknown import" - ) -+;) -\ No newline at end of file diff --git a/test/core/linking.wast b/test/core/linking.wast index 994e0f4..8fbcc02 100644 --- a/test/core/linking.wast diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index 72c733d750..f855285062 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -1103,7 +1103,8 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts): elif opts.multi_memory: cmd = [opts.wast2wasm, "--enable-multi-memory", "--no-check", wast_tempfile, "-o", wasm_tempfile ] else: - cmd = [opts.wast2wasm, "--enable-threads", "--no-check", + # `--enable-multi-memory` for a case in memory.wast but doesn't require runtime support + cmd = [opts.wast2wasm, "--enable-multi-memory", "--enable-threads", "--no-check", wast_tempfile, "-o", wasm_tempfile ] # remove reference-type and bulk-memory enabling options since a WABT diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index b7a9248bc8..f87e9a2f0e 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -269,16 +269,12 @@ readonly WAMRC_CMD_DEFAULT="${WAMR_DIR}/wamr-compiler/build/wamrc" readonly CLASSIC_INTERP_COMPILE_FLAGS="\ -DWAMR_BUILD_TARGET=${TARGET} \ -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=0 \ - -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=0 \ - -DWAMR_BUILD_SPEC_TEST=1 \ - -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=0" readonly FAST_INTERP_COMPILE_FLAGS="\ -DWAMR_BUILD_TARGET=${TARGET} \ -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=1 \ - -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=0 \ - -DWAMR_BUILD_SPEC_TEST=1 \ - -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=0" # jit: report linking error if set COLLECT_CODE_COVERAGE, # now we don't collect code coverage of jit type @@ -286,39 +282,29 @@ readonly ORC_EAGER_JIT_COMPILE_FLAGS="\ -DWAMR_BUILD_TARGET=${TARGET} \ -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_INTERP=0 \ -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_AOT=1 \ - -DWAMR_BUILD_LAZY_JIT=0 \ - -DWAMR_BUILD_SPEC_TEST=1 \ - -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + -DWAMR_BUILD_LAZY_JIT=0" readonly ORC_LAZY_JIT_COMPILE_FLAGS="\ -DWAMR_BUILD_TARGET=${TARGET} \ -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_INTERP=0 \ -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_AOT=1 \ - -DWAMR_BUILD_LAZY_JIT=1 \ - -DWAMR_BUILD_SPEC_TEST=1 \ - -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + -DWAMR_BUILD_LAZY_JIT=1" readonly AOT_COMPILE_FLAGS="\ -DWAMR_BUILD_TARGET=${TARGET} \ -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_INTERP=0 \ - -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=1 \ - -DWAMR_BUILD_SPEC_TEST=1 \ - -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=1" readonly FAST_JIT_COMPILE_FLAGS="\ -DWAMR_BUILD_TARGET=${TARGET} \ -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=0 \ -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=0 \ - -DWAMR_BUILD_FAST_JIT=1 \ - -DWAMR_BUILD_SPEC_TEST=1 \ - -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + -DWAMR_BUILD_FAST_JIT=1" readonly MULTI_TIER_JIT_COMPILE_FLAGS="\ -DWAMR_BUILD_TARGET=${TARGET} \ -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=0 \ - -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 \ - -DWAMR_BUILD_SPEC_TEST=1 \ - -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1" readonly COMPILE_FLAGS=( "${CLASSIC_INTERP_COMPILE_FLAGS}" @@ -481,8 +467,8 @@ function spec_test() git clone -b main --single-branch https://github.com/WebAssembly/gc.git spec pushd spec - # Reset to commit: "[test] Unify the error message." - git reset --hard 0caaadc65b5e1910512d8ae228502edcf9d60390 + # Dec 9, 2024. Merge branch 'funcref' + git reset --hard 756060f5816c7e2159f4817fbdee76cf52f9c923 git apply ../../spec-test-script/gc_ignore_cases.patch || exit 1 if [[ ${ENABLE_QEMU} == 1 ]]; then @@ -491,6 +477,13 @@ function spec_test() git apply ../../spec-test-script/gc_nuttx_tail_call.patch || exit 1 fi + # As of version 1.0.36, wabt is still unable to correctly handle the GC proposal. + # + # $ $ /opt/wabt-1.0.36/bin/wast2json --enable-all ../spec/test/core/br_if.wast + # + # ../spec/test/core/br_if.wast:670:26: error: unexpected token "null", expected a numeric index or a name (e.g. 12 or $foo). + # (func $f (param (ref null $t)) (result funcref) (local.get 0)) + # compile_reference_interpreter elif [[ ${ENABLE_MEMORY64} == 1 ]]; then echo "checkout spec for memory64 proposal" @@ -525,8 +518,8 @@ function spec_test() git clone -b main --single-branch https://github.com/WebAssembly/spec pushd spec - # Apr 3, 2024 [js-api] Integrate with the ResizableArrayBuffer proposal (#1300) - git reset --hard bc76fd79cfe61033d7f4ad4a7e8fc4f996dc5ba8 + # Dec 20, 2024. Use WPT version of test harness for HTML core test conversion (#1859) + git reset --hard f3a0e06235d2d84bb0f3b5014da4370613886965 git apply ../../spec-test-script/ignore_cases.patch || exit 1 if [[ ${ENABLE_SIMD} == 1 ]]; then git apply ../../spec-test-script/simd_ignore_cases.patch || exit 1 @@ -832,6 +825,7 @@ function build_wamrc() local EXTRA_COMPILE_FLAGS="" EXTRA_COMPILE_FLAGS+=" -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_SHRUNK_MEMORY=0" if [[ ${ENABLE_DEBUG_VERSION} == 1 ]]; then EXTRA_COMPILE_FLAGS+=" -DCMAKE_BUILD_TYPE=Debug" @@ -970,6 +964,11 @@ function trigger() fi local EXTRA_COMPILE_FLAGS="" + # for spec test + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_SPEC_TEST=1" + EXTRA_COMPILE_FLAGS+=" -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_SHRUNK_MEMORY=0" + # default enabled features EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_BULK_MEMORY=1" EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_REF_TYPES=1" diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index ab98b03825..9975dab7b3 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -58,6 +58,7 @@ if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1) endif () if (LINUX) + set(WAMR_BUILD_LINUX_PERF 1) add_definitions(-DWASM_ENABLE_LINUX_PERF=1) endif () @@ -238,6 +239,12 @@ if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS) set (WAMR_BUILD_LIB_WASI_THREADS 1) endif () +# Enable by default +if (NOT DEFINED WAMR_BUILD_SHRUNK_MEMORY) + set (WAMR_BUILD_SHRUNK_MEMORY 1) +endif () +add_definitions (-DWASM_ENABLE_SHRUNK_MEMORY=${WAMR_BUILD_SHRUNK_MEMORY}) + if (WAMR_BUILD_LIBC_UVWASI EQUAL 1) message ("-- Libc WASI enabled with uvwasi implementation") endif () @@ -278,6 +285,7 @@ include (${IWASM_DIR}/common/gc/iwasm_gc.cmake) include (${IWASM_DIR}/interpreter/iwasm_interp.cmake) include (${IWASM_DIR}/aot/iwasm_aot.cmake) include (${IWASM_DIR}/compilation/iwasm_compl.cmake) +include (${PROJECT_SOURCE_DIR}/../build-scripts/version.cmake) if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake) @@ -369,6 +377,7 @@ add_library (aotclib ${IWASM_COMPL_SOURCE}) add_executable (wamrc main.c) check_pie_supported() set_target_properties (wamrc PROPERTIES POSITION_INDEPENDENT_CODE ON) +set_version_info (wamrc) if (LLVM_LINK_LLVM_DYLIB) set(WAMRC_LINK_LLVM_LIBS LLVM)