From b98f150f828e0fcfc5f8129d98fcff6051158f2b Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Sat, 27 Jan 2024 07:55:49 +0800 Subject: [PATCH 01/15] CI: Update version of checkout to suppress warnings (#3093) --- .github/workflows/build_docker_images.yml | 2 +- .github/workflows/build_iwasm_release.yml | 4 ++-- .github/workflows/build_llvm_libraries.yml | 10 ++++---- .github/workflows/build_wamr_lldb.yml | 4 ++-- .github/workflows/build_wamr_sdk.yml | 2 +- .github/workflows/build_wamr_vscode_ext.yml | 2 +- .github/workflows/build_wamrc.yml | 4 ++-- .github/workflows/coding_guidelines.yml | 2 +- .../compilation_on_android_ubuntu.yml | 24 +++++++++---------- .github/workflows/compilation_on_macos.yml | 12 +++++----- .github/workflows/compilation_on_nuttx.yml | 6 ++--- .github/workflows/compilation_on_sgx.yml | 10 ++++---- .github/workflows/compilation_on_windows.yml | 4 ++-- .github/workflows/create_tag.yml | 2 +- .github/workflows/hadolint_dockerfiles.yml | 2 +- .github/workflows/nightly_run.yml | 20 ++++++++-------- .github/workflows/release_process.yml | 2 +- .../reuse_latest_release_binaries.yml | 2 +- .github/workflows/spec_test_on_nuttx.yml | 8 +++---- 19 files changed, 61 insertions(+), 61 deletions(-) diff --git a/.github/workflows/build_docker_images.yml b/.github/workflows/build_docker_images.yml index 819bf94c3..d5bf682c4 100644 --- a/.github/workflows/build_docker_images.yml +++ b/.github/workflows/build_docker_images.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build and save Docker image(wasm-debug-server:${{ inputs.ver_num }}) to tar file run: | diff --git a/.github/workflows/build_iwasm_release.yml b/.github/workflows/build_iwasm_release.yml index 64aa9a92c..86e50ede9 100644 --- a/.github/workflows/build_iwasm_release.yml +++ b/.github/workflows/build_iwasm_release.yml @@ -35,11 +35,11 @@ jobs: build: runs-on: ${{ inputs.runner }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: get cached LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/build_llvm_libraries.yml b/.github/workflows/build_llvm_libraries.yml index a24e340fa..18b90e568 100644 --- a/.github/workflows/build_llvm_libraries.yml +++ b/.github/workflows/build_llvm_libraries.yml @@ -31,7 +31,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install dependencies run: /usr/bin/env python3 -m pip install -r requirements.txt @@ -52,7 +52,7 @@ jobs: - name: Cache LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -62,7 +62,7 @@ jobs: ./core/deps/llvm/build/share key: ${{ steps.create_lib_cache_key.outputs.key}} - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.ccache key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} @@ -70,7 +70,7 @@ jobs: 0-ccache-${{ inputs.os }} if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && inputs.os == 'ubuntu-20.04' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache/ccache key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} @@ -82,7 +82,7 @@ jobs: - run: sudo apt install -y ccache ninja-build if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'ubuntu') && inputs.container_image == '' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/Library/Caches/ccache key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} diff --git a/.github/workflows/build_wamr_lldb.yml b/.github/workflows/build_wamr_lldb.yml index 1a73750a6..3e1e10ffd 100644 --- a/.github/workflows/build_wamr_lldb.yml +++ b/.github/workflows/build_wamr_lldb.yml @@ -47,7 +47,7 @@ jobs: PYTHON_UBUNTU_STANDALONE_BUILD: https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-unknown-linux-gnu-install_only.tar.gz PYTHON_MACOS_STANDALONE_BUILD: https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-apple-darwin-install_only.tar.gz steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: download and install wasi-sdk run: | @@ -60,7 +60,7 @@ jobs: - name: Cache build id: lldb_build_cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm-project/build/bin diff --git a/.github/workflows/build_wamr_sdk.yml b/.github/workflows/build_wamr_sdk.yml index fff6d85df..f4ca9afd4 100644 --- a/.github/workflows/build_wamr_sdk.yml +++ b/.github/workflows/build_wamr_sdk.yml @@ -35,7 +35,7 @@ jobs: build: runs-on: ${{ inputs.runner }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: download and install wasi-sdk run: | diff --git a/.github/workflows/build_wamr_vscode_ext.yml b/.github/workflows/build_wamr_vscode_ext.yml index 3dfb290cf..b91f054cf 100644 --- a/.github/workflows/build_wamr_vscode_ext.yml +++ b/.github/workflows/build_wamr_vscode_ext.yml @@ -18,7 +18,7 @@ jobs: build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Use Node.js 16.x uses: actions/setup-node@v3 diff --git a/.github/workflows/build_wamrc.yml b/.github/workflows/build_wamrc.yml index 11c5de9ba..7c4dab039 100644 --- a/.github/workflows/build_wamrc.yml +++ b/.github/workflows/build_wamrc.yml @@ -35,11 +35,11 @@ jobs: build: runs-on: ${{ inputs.runner }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: get cached LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/coding_guidelines.yml b/.github/workflows/coding_guidelines.yml index 17d60ac43..b0aa0a2b8 100644 --- a/.github/workflows/coding_guidelines.yml +++ b/.github/workflows/coding_guidelines.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index d6fe4b51d..99260bfc8 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -85,13 +85,13 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # since jobs.id can't contain the dot character # it is hard to use `format` to assemble the cache key - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -214,13 +214,13 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # only download llvm cache when needed - name: Get LLVM libraries id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -285,12 +285,12 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get LLVM libraries id: retrieve_llvm_libs if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -351,7 +351,7 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk run: | @@ -368,7 +368,7 @@ jobs: sudo mv wabt-1.0.31 wabt - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -520,7 +520,7 @@ jobs: test_option: $SIMD_TEST_OPTIONS steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk if: matrix.test_option == '$WASI_TEST_OPTIONS' @@ -555,7 +555,7 @@ jobs: - name: Get LLVM libraries if: env.USE_LLVM == 'true' id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -617,7 +617,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install dependencies run: | @@ -636,7 +636,7 @@ jobs: - name: Cache LLDB id: cache-lldb - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-lldb-vscode with: diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml index fbf81ae1f..19ff1874a 100644 --- a/.github/workflows/compilation_on_macos.yml +++ b/.github/workflows/compilation_on_macos.yml @@ -71,11 +71,11 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -174,13 +174,13 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # only download llvm cache when needed - name: Get LLVM libraries id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -226,7 +226,7 @@ jobs: ] steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wabt run: | @@ -258,7 +258,7 @@ jobs: ] steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk run: | diff --git a/.github/workflows/compilation_on_nuttx.yml b/.github/workflows/compilation_on_nuttx.yml index 5368b06a1..2eff73c2c 100644 --- a/.github/workflows/compilation_on_nuttx.yml +++ b/.github/workflows/compilation_on_nuttx.yml @@ -87,21 +87,21 @@ jobs: steps: - name: Checkout NuttX - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: apache/incubator-nuttx ref: releases/12.4 path: nuttx - name: Checkout NuttX Apps - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: apache/incubator-nuttx-apps ref: releases/12.4 path: apps - name: Checkout WAMR - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ github.repository }} path: apps/interpreters/wamr/wamr diff --git a/.github/workflows/compilation_on_sgx.yml b/.github/workflows/compilation_on_sgx.yml index 2cb37bdc6..8dadb518d 100644 --- a/.github/workflows/compilation_on_sgx.yml +++ b/.github/workflows/compilation_on_sgx.yml @@ -119,7 +119,7 @@ jobs: source /opt/intel/sgxsdk/environment - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build iwasm run: | @@ -165,7 +165,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk run: | @@ -221,7 +221,7 @@ jobs: - name: Get LLVM libraries if: matrix.iwasm_make_options_run_mode == '$AOT_BUILD_OPTIONS' id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -290,12 +290,12 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get LLVM libraries if: matrix.running_mode == 'aot' id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/compilation_on_windows.yml b/.github/workflows/compilation_on_windows.yml index 97a4aaae2..a623ab1a7 100644 --- a/.github/workflows/compilation_on_windows.yml +++ b/.github/workflows/compilation_on_windows.yml @@ -74,7 +74,7 @@ jobs: "-DWAMR_BUILD_LIBC_UVWASI=0 -DWAMR_BUILD_LIBC_WASI=1" ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: clone uvwasi library if: ${{ !contains(matrix.build_options, '-DWAMR_BUILD_LIBC_UVWASI=0') }} @@ -108,7 +108,7 @@ jobs: ] steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk if: matrix.test_option == '$WASI_TEST_OPTIONS' diff --git a/.github/workflows/create_tag.yml b/.github/workflows/create_tag.yml index 3a145bf04..27eee2acf 100644 --- a/.github/workflows/create_tag.yml +++ b/.github/workflows/create_tag.yml @@ -24,7 +24,7 @@ jobs: new_tag: ${{ steps.preparation.outputs.new_tag }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Full git history is needed to get a proper list of commits and tags with: fetch-depth: 0 diff --git a/.github/workflows/hadolint_dockerfiles.yml b/.github/workflows/hadolint_dockerfiles.yml index bdabeb6e5..c540649c8 100644 --- a/.github/workflows/hadolint_dockerfiles.yml +++ b/.github/workflows/hadolint_dockerfiles.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # on default, hadolint will fail on warnings and errors - name: Run hadolint on dockerfiles diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index 17d6f35bd..8b9a0ed5e 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -68,13 +68,13 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # since jobs.id can't contain the dot character # it is hard to use `format` to assemble the cache key - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -199,13 +199,13 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # only download llvm cache when needed - name: Get LLVM libraries id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -347,12 +347,12 @@ jobs: sanitizer: asan steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get LLVM libraries id: retrieve_llvm_libs if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -414,7 +414,7 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk run: | @@ -431,7 +431,7 @@ jobs: - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -601,7 +601,7 @@ jobs: test_option: $SIMD_TEST_OPTIONS steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk if: matrix.test_option == '$WASI_TEST_OPTIONS' @@ -639,7 +639,7 @@ jobs: - name: Get LLVM libraries if: env.USE_LLVM == 'true' id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/release_process.yml b/.github/workflows/release_process.yml index ef722acdb..5808b821c 100644 --- a/.github/workflows/release_process.yml +++ b/.github/workflows/release_process.yml @@ -28,7 +28,7 @@ jobs: outputs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: prepare the release note run: | diff --git a/.github/workflows/reuse_latest_release_binaries.yml b/.github/workflows/reuse_latest_release_binaries.yml index 7f82672a6..c9832cec9 100644 --- a/.github/workflows/reuse_latest_release_binaries.yml +++ b/.github/workflows/reuse_latest_release_binaries.yml @@ -28,7 +28,7 @@ jobs: outputs: result: ${{ steps.try_reuse.outputs.result }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Full git history is needed to get a proper list of commits and tags with: fetch-depth: 0 diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 864bb0b7c..5bdad8f23 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -96,21 +96,21 @@ jobs: steps: - name: Checkout NuttX - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: apache/incubator-nuttx ref: releases/12.4 path: nuttx - name: Checkout NuttX Apps - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: apache/incubator-nuttx-apps ref: releases/12.4 path: apps - name: Checkout WAMR - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ github.repository }} path: apps/interpreters/wamr/wamr @@ -118,7 +118,7 @@ jobs: - name: Get LLVM libraries if: contains(matrix.wamr_test_option.mode, 'aot') id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin From 7f8e2133ec25f80fc855c5bf2d6ecb6592068b61 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 29 Jan 2024 18:57:57 +0800 Subject: [PATCH 02/15] Fix windows build error and compilation warnings (#3095) Fix wamrc build error reported on Windows: ```bash CMake Error at CMakeLists.txt:84 (message): Unsupported CMAKE_HOST_SYSTEM_PROCESSOR AMD64 ``` And clear several compilation warnings. --- core/iwasm/common/wasm_c_api.c | 22 ++++++++++++++-------- wamr-compiler/CMakeLists.txt | 23 ++++++++++++----------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 873dc3b3f..a9fac87ba 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -1934,8 +1934,8 @@ wasm_frame_vec_clone_internal(Vector *src, Vector *out) return; } - bh_memcpy_s(out->data, src->num_elems * sizeof(WASMCApiFrame), src->data, - src->num_elems * sizeof(WASMCApiFrame)); + bh_memcpy_s(out->data, (uint32)(src->num_elems * sizeof(WASMCApiFrame)), + src->data, (uint32)(src->num_elems * sizeof(WASMCApiFrame))); out->num_elems = src->num_elems; } @@ -2962,8 +2962,10 @@ wasm_func_new_basic(wasm_store_t *store, const wasm_functype_t *type, if (!(func->type = wasm_functype_copy(type))) { goto failed; } - func->param_count = func->type->params->num_elems; - func->result_count = func->type->results->num_elems; + /* func type's param_count and result_count were checked in + loader and are no larger than UINT16_MAX */ + func->param_count = (uint16)func->type->params->num_elems; + func->result_count = (uint16)func->type->results->num_elems; RETURN_OBJ(func, wasm_func_delete) } @@ -2994,8 +2996,10 @@ wasm_func_new_with_env_basic(wasm_store_t *store, const wasm_functype_t *type, if (!(func->type = wasm_functype_copy(type))) { goto failed; } - func->param_count = func->type->params->num_elems; - func->result_count = func->type->results->num_elems; + /* func type's param_count and result_count were checked in + loader and are no larger than UINT16_MAX */ + func->param_count = (uint16)func->type->params->num_elems; + func->result_count = (uint16)func->type->results->num_elems; RETURN_OBJ(func, wasm_func_delete) } @@ -3085,8 +3089,10 @@ wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt, if (!func->type) { goto failed; } - func->param_count = func->type->params->num_elems; - func->result_count = func->type->results->num_elems; + /* func type's param_count and result_count were checked in + loader and are no larger than UINT16_MAX */ + func->param_count = (uint16)func->type->params->num_elems; + func->result_count = (uint16)func->type->results->num_elems; /* will add name information when processing "exports" */ func->store = store; diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index f7617fed9..84e8b524c 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -59,30 +59,31 @@ if (DEFINED WAMR_BUILD_AOT_FUNC_PREFIX) endif () if (NOT WAMR_BUILD_TARGET) - if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") + string(TOLOWER "${CMAKE_HOST_SYSTEM_PROCESSOR}" HOST_SYSTEM_PROCESSOR) + if (${HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64") set (WAMR_BUILD_TARGET "X86_64") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "i686") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "i686") set (WAMR_BUILD_TARGET "X86_32") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "amd64") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "amd64") set (WAMR_BUILD_TARGET "AMD_64") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64" - OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "aarch64" + OR ${HOST_SYSTEM_PROCESSOR} STREQUAL "arm64") set (WAMR_BUILD_TARGET "AARCH64") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm.*") + elseif (${HOST_SYSTEM_PROCESSOR} MATCHES "arm.*") message(STATUS "Assuming ${CMAKE_HOST_SYSTEM_PROCESSOR} as ARM_32") set (WAMR_BUILD_TARGET "ARM_32") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "mips") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "mips") set (WAMR_BUILD_TARGET "MIPS_32") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "xtensa") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "xtensa") set (WAMR_BUILD_TARGET "XTENSA_32") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "riscv64") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "riscv64") set (WAMR_BUILD_TARGET "RISCV64") - elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "riscv") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "riscv") message(STATUS "Assuming ${CMAKE_HOST_SYSTEM_PROCESSOR} as RISCV32") set (WAMR_BUILD_TARGET "RISCV32") else () message (FATAL_ERROR "Unsupported CMAKE_HOST_SYSTEM_PROCESSOR " - "${CMAKE_HOST_SYSTEM_PROCESSOR}") + "${CMAKE_HOST_SYSTEM_PROCESSOR}") endif() if (WAMR_BUILD_PLATFORM STREQUAL "windows") From 170ae3513135d9f54c54a811c5f2b470382966c6 Mon Sep 17 00:00:00 2001 From: Enrico Loparco Date: Tue, 30 Jan 2024 04:02:40 +0100 Subject: [PATCH 03/15] test_wamr.sh: Allow using test script on different platforms (#3098) The `^^` for uppercase is not widely supported, e.g. not working on some MacOS M1. --- tests/wamr-test-suites/test_wamr.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 76b235d49..663403233 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -119,7 +119,7 @@ do ;; m) echo "set compile target of wamr" ${OPTARG} - TARGET=${OPTARG^^} # set target to uppercase if input x86_32 or x86_64 --> X86_32 and X86_64 + TARGET=$(echo "$OPTARG" | tr '[a-z]' '[A-Z]') # set target to uppercase if input x86_32 or x86_64 --> X86_32 and X86_64 ;; w) echo "enable WASI threads" From 7e65f9a2441a61b50c4e39e7a8e010f80fb5f9bc Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 30 Jan 2024 21:50:33 +0900 Subject: [PATCH 04/15] aot: Fix LLVMSetTailCallKind check (#3099) --- core/iwasm/compilation/aot_llvm.c | 6 ------ core/iwasm/compilation/aot_llvm_extra2.cpp | 2 +- core/iwasm/compilation/aot_llvm_extra2.h | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 6f5cddcd9..028faf6e4 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -533,18 +533,12 @@ aot_add_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module, } wasm_runtime_free(params); params = NULL; - -#if LLVM_VERSION_MAJOR < 17 if (aot_target_precheck_can_use_musttail(comp_ctx)) { LLVMSetTailCallKind(retval, LLVMTailCallKindMustTail); } else { LLVMSetTailCallKind(retval, LLVMTailCallKindTail); } -#else - LLVMSetTailCall(retval, true); -#endif - if (ret_type == VOID_TYPE) { if (!LLVMBuildRetVoid(b)) { goto fail; diff --git a/core/iwasm/compilation/aot_llvm_extra2.cpp b/core/iwasm/compilation/aot_llvm_extra2.cpp index 42d9c4bee..ccbccd1e0 100644 --- a/core/iwasm/compilation/aot_llvm_extra2.cpp +++ b/core/iwasm/compilation/aot_llvm_extra2.cpp @@ -163,7 +163,7 @@ LLVMCreateTargetMachineWithOpts(LLVMTargetRef ctarget, const char *triple, } /* https://reviews.llvm.org/D153107 */ -#if LLVM_VERSION_MAJOR < 17 +#if LLVM_VERSION_MAJOR < 18 using namespace llvm; LLVMTailCallKind diff --git a/core/iwasm/compilation/aot_llvm_extra2.h b/core/iwasm/compilation/aot_llvm_extra2.h index f3f897994..be89faae0 100644 --- a/core/iwasm/compilation/aot_llvm_extra2.h +++ b/core/iwasm/compilation/aot_llvm_extra2.h @@ -17,7 +17,7 @@ LLVMCreateTargetMachineWithOpts(LLVMTargetRef ctarget, const char *triple, const char *StackUsageOutput); /* https://reviews.llvm.org/D153107 */ -#if LLVM_VERSION_MAJOR < 17 +#if LLVM_VERSION_MAJOR < 18 typedef enum { LLVMTailCallKindNone = 0, LLVMTailCallKindTail = 1, From af318bac818ac36dc7e0641fd6b15b4b52c496d6 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 31 Jan 2024 08:27:17 +0800 Subject: [PATCH 05/15] Implement Exception Handling for classic interpreter (#3096) This PR adds the initial support for WASM exception handling: * Inside the classic interpreter only: * Initial handling of Tags * Initial handling of Exceptions based on W3C Exception Proposal * Import and Export of Exceptions and Tags * Add `cmake -DWAMR_BUILD_EXCE_HANDLING=1/0` option to enable/disable the feature, and by default it is disabled * Update the wamr-test-suites scripts to test the feature * Additional CI/CD changes to validate the exception spec proposal cases Refer to: https://github.com/bytecodealliance/wasm-micro-runtime/issues/1884 https://github.com/bytecodealliance/wasm-micro-runtime/commit/587513f3c60f1707681af606a578a8c9f2dfb586 https://github.com/bytecodealliance/wasm-micro-runtime/commit/8bebfe9ad75695a2390d2db6ccbef8ba5350da34 https://github.com/bytecodealliance/wasm-micro-runtime/commit/59bccdfed82178c39ea4e14295ceb24289b3b857 Signed-off-by: Ricardo Aguilar Co-authored-by: Chris Woods Co-authored-by: Rene Ermler Co-authored-by: Trenner Thomas --- build-scripts/config_common.cmake | 5 + core/config.h | 8 + core/iwasm/interpreter/wasm.h | 67 ++ core/iwasm/interpreter/wasm_interp.h | 8 + core/iwasm/interpreter/wasm_interp_classic.c | 508 ++++++++++++++- core/iwasm/interpreter/wasm_interp_fast.c | 30 +- core/iwasm/interpreter/wasm_loader.c | 595 +++++++++++++++++- core/iwasm/interpreter/wasm_mini_loader.c | 23 + core/iwasm/interpreter/wasm_opcode.h | 31 +- core/iwasm/interpreter/wasm_runtime.c | 183 +++++- core/iwasm/interpreter/wasm_runtime.h | 49 ++ product-mini/platforms/nuttx/wamr.mk | 8 + .../wamr-test-suites/spec-test-script/all.py | 38 +- .../spec-test-script/exception_handling.patch | 20 + .../spec-test-script/runtest.py | 50 ++ tests/wamr-test-suites/test_wamr.sh | 36 +- 16 files changed, 1620 insertions(+), 39 deletions(-) create mode 100644 tests/wamr-test-suites/spec-test-script/exception_handling.patch diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index cb0b7210b..22783a509 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -335,6 +335,11 @@ if (WAMR_BUILD_REF_TYPES EQUAL 1) else () message (" Reference types disabled") endif () +if (WAMR_BUILD_EXCE_HANDLING EQUAL 1) + add_definitions (-DWASM_ENABLE_EXCE_HANDLING=1) + add_definitions (-DWASM_ENABLE_TAGS=1) + message (" Exception Handling enabled") +endif () if (DEFINED WAMR_BH_VPRINTF) add_definitions (-DBH_VPRINTF=${WAMR_BH_VPRINTF}) endif () diff --git a/core/config.h b/core/config.h index ef322647f..25c45107e 100644 --- a/core/config.h +++ b/core/config.h @@ -457,6 +457,14 @@ #define WASM_ENABLE_REF_TYPES 0 #endif +#ifndef WASM_ENABLE_EXCE_HANDLING +#define WASM_ENABLE_EXCE_HANDLING 0 +#endif + +#ifndef WASM_ENABLE_TAGS +#define WASM_ENABLE_TAGS 0 +#endif + #ifndef WASM_ENABLE_SGX_IPFS #define WASM_ENABLE_SGX_IPFS 0 #endif diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 518e76642..60e1238ad 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -65,6 +65,9 @@ extern "C" { #if WASM_ENABLE_BULK_MEMORY != 0 #define SECTION_TYPE_DATACOUNT 12 #endif +#if WASM_ENABLE_TAGS != 0 +#define SECTION_TYPE_TAG 13 +#endif #define SUB_SECTION_TYPE_MODULE 0 #define SUB_SECTION_TYPE_FUNC 1 @@ -74,20 +77,34 @@ extern "C" { #define IMPORT_KIND_TABLE 1 #define IMPORT_KIND_MEMORY 2 #define IMPORT_KIND_GLOBAL 3 +#if WASM_ENABLE_TAGS != 0 +#define IMPORT_KIND_TAG 4 +#endif #define EXPORT_KIND_FUNC 0 #define EXPORT_KIND_TABLE 1 #define EXPORT_KIND_MEMORY 2 #define EXPORT_KIND_GLOBAL 3 +#if WASM_ENABLE_TAGS != 0 +#define EXPORT_KIND_TAG 4 +#endif #define LABEL_TYPE_BLOCK 0 #define LABEL_TYPE_LOOP 1 #define LABEL_TYPE_IF 2 #define LABEL_TYPE_FUNCTION 3 +#if WASM_ENABLE_EXCE_HANDLING != 0 +#define LABEL_TYPE_TRY 4 +#define LABEL_TYPE_CATCH 5 +#define LABEL_TYPE_CATCH_ALL 6 +#endif typedef struct WASMModule WASMModule; typedef struct WASMFunction WASMFunction; typedef struct WASMGlobal WASMGlobal; +#if WASM_ENABLE_TAGS != 0 +typedef struct WASMTag WASMTag; +#endif typedef union V128 { int8 i8x16[16]; @@ -201,6 +218,24 @@ typedef struct WASMFunctionImport { bool call_conv_wasm_c_api; } WASMFunctionImport; +#if WASM_ENABLE_TAGS != 0 +typedef struct WASMTagImport { + char *module_name; + char *field_name; + uint8 attribute; /* the type of the tag (numerical) */ + uint32 type; /* the type of the catch function (numerical)*/ + WASMType *tag_type; + void *tag_ptr_linked; + +#if WASM_ENABLE_MULTI_MODULE != 0 + /* imported tag pointer after linked */ + WASMModule *import_module; + WASMTag *import_tag_linked; + uint32 import_tag_index_linked; +#endif +} WASMTagImport; +#endif + typedef struct WASMGlobalImport { char *module_name; char *field_name; @@ -227,6 +262,9 @@ typedef struct WASMImport { WASMFunctionImport function; WASMTableImport table; WASMMemoryImport memory; +#if WASM_ENABLE_TAGS != 0 + WASMTagImport tag; +#endif WASMGlobalImport global; struct { char *module_name; @@ -265,6 +303,10 @@ struct WASMFunction { uint32 const_cell_num; #endif +#if WASM_ENABLE_EXCE_HANDLING != 0 + uint32 exception_handler_count; +#endif + #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ || WASM_ENABLE_WAMR_COMPILER != 0 /* Whether function has opcode memory.grow */ @@ -294,6 +336,14 @@ struct WASMFunction { #endif }; +#if WASM_ENABLE_TAGS != 0 +struct WASMTag { + uint8 attribute; /* the attribute property of the tag (expected to be 0) */ + uint32 type; /* the type of the tag (expected valid inden in type table) */ + WASMType *tag_type; +}; +#endif + struct WASMGlobal { uint8 type; bool is_mutable; @@ -420,6 +470,9 @@ struct WASMModule { uint32 function_count; uint32 table_count; uint32 memory_count; +#if WASM_ENABLE_TAGS != 0 + uint32 tag_count; +#endif uint32 global_count; uint32 export_count; uint32 table_seg_count; @@ -433,11 +486,17 @@ struct WASMModule { uint32 import_function_count; uint32 import_table_count; uint32 import_memory_count; +#if WASM_ENABLE_TAGS != 0 + uint32 import_tag_count; +#endif uint32 import_global_count; WASMImport *import_functions; WASMImport *import_tables; WASMImport *import_memories; +#if WASM_ENABLE_TAGS != 0 + WASMImport *import_tags; +#endif WASMImport *import_globals; WASMType **types; @@ -445,6 +504,9 @@ struct WASMModule { WASMFunction **functions; WASMTable *tables; WASMMemory *memories; +#if WASM_ENABLE_TAGS != 0 + WASMTag **tags; +#endif WASMGlobal *globals; WASMExport *exports; WASMTableSeg *table_segments; @@ -628,6 +690,11 @@ typedef struct WASMBranchBlock { uint8 *target_addr; uint32 *frame_sp; uint32 cell_num; +#if WASM_ENABLE_EXCE_HANDLING != 0 + /* in exception handling, label_type needs to be stored to lookup exception + * handlers */ + uint8 label_type; +#endif } WASMBranchBlock; /** diff --git a/core/iwasm/interpreter/wasm_interp.h b/core/iwasm/interpreter/wasm_interp.h index d3692ff21..2b5a51ea8 100644 --- a/core/iwasm/interpreter/wasm_interp.h +++ b/core/iwasm/interpreter/wasm_interp.h @@ -34,6 +34,14 @@ typedef struct WASMInterpFrame { uint64 time_started; #endif +#if WASM_ENABLE_EXCE_HANDLING != 0 + /* set to true if the callee returns an exception rather than + * result values on the stack + */ + bool exception_raised; + uint32 tag_index; +#endif + #if WASM_ENABLE_FAST_INTERP != 0 /* Return offset of the first return value of current frame, the callee will put return values here continuously */ diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 7364a25fa..10de23742 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -338,10 +338,19 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) frame_sp += 2; \ } while (0) +/* in exception handling, label_type needs to be stored to lookup exception + * handlers */ + +#if WASM_ENABLE_EXCE_HANDLING != 0 +#define SET_LABEL_TYPE(_label_type) frame_csp->label_type = _label_type +#else +#define SET_LABEL_TYPE(_label_type) (void)0 +#endif + #define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \ do { \ bh_assert(frame_csp < frame->csp_boundary); \ - /* frame_csp->label_type = _label_type; */ \ + SET_LABEL_TYPE(_label_type); \ frame_csp->cell_num = cell_num; \ frame_csp->begin_addr = frame_ip; \ frame_csp->target_addr = _target_addr; \ @@ -392,6 +401,18 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) frame_sp -= n; \ } while (0) +#if WASM_ENABLE_EXCE_HANDLING != 0 +/* unwind the CSP to a given label and optionally modify the labeltype */ +#define UNWIND_CSP(N, T) \ + do { \ + /* unwind to function frame */ \ + frame_csp -= N; \ + /* drop handlers and values pushd in try block */ \ + frame_sp = (frame_csp - 1)->frame_sp; \ + (frame_csp - 1)->label_type = T ? T : (frame_csp - 1)->label_type; \ + } while (0) +#endif + #define SYNC_ALL_TO_FRAME() \ do { \ frame->sp = frame_sp; \ @@ -1188,6 +1209,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 local_idx, local_offset, global_idx; uint8 local_type, *global_addr; uint32 cache_index, type_index, param_cell_num, cell_num; +#if WASM_ENABLE_EXCE_HANDLING != 0 + int32_t exception_tag_index; +#endif uint8 value_type; #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 @@ -1230,6 +1254,379 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_NOP) { HANDLE_OP_END(); } +#if WASM_ENABLE_EXCE_HANDLING != 0 + + HANDLE_OP(WASM_OP_RETHROW) + { + int32_t relative_depth; + read_leb_int32(frame_ip, frame_ip_end, relative_depth); + + /* No frame found with exception handler; validation should + * catch it */ + bh_assert(frame_csp >= frame->csp_bottom + relative_depth); + + /* go up the frame stack */ + WASMBranchBlock *tgtframe = (frame_csp - 1) - relative_depth; + + bh_assert(tgtframe->label_type == LABEL_TYPE_CATCH + || tgtframe->label_type == LABEL_TYPE_CATCH_ALL); + + /* tgtframe points to the frame containing a thrown + * exception */ + + uint32 *tgtframe_sp = tgtframe->frame_sp; + + /* frame sp of tgtframe points to catched exception */ + exception_tag_index = *((uint32 *)tgtframe_sp); + tgtframe_sp++; + + /* get tag type */ + uint8 tag_type_index = + module->module->tags[exception_tag_index]->type; + uint32 cell_num_to_copy = + wasm_types[tag_type_index]->param_cell_num; + + /* move exception parameters (if there are any) onto top + * of stack */ + if (cell_num_to_copy > 0) { + word_copy(frame_sp, tgtframe_sp - cell_num_to_copy, + cell_num_to_copy); + } + + frame_sp += cell_num_to_copy; + goto find_a_catch_handler; + } + + HANDLE_OP(WASM_OP_THROW) + { + read_leb_int32(frame_ip, frame_ip_end, exception_tag_index); + + /* landing pad for the rethrow ? */ + find_a_catch_handler: + { + WASMType *tag_type = NULL; + uint32 cell_num_to_copy = 0; + if (IS_INVALID_TAGINDEX(exception_tag_index)) { + /* + * invalid exception index, + * generated if a submodule throws an exception + * that has not been imported here + * + * This should result in a branch to the CATCH_ALL block, + * if there is one + */ + tag_type = NULL; + cell_num_to_copy = 0; + } + else { + if (module->e->tags[exception_tag_index].is_import_tag) { + tag_type = module->e->tags[exception_tag_index] + .u.tag_import->tag_type; + } + else { + tag_type = module->e->tags[exception_tag_index] + .u.tag->tag_type; + } + cell_num_to_copy = tag_type->param_cell_num; + } + + /* browse through frame stack */ + uint32 relative_depth = 0; + do { + POP_CSP_CHECK_OVERFLOW(relative_depth - 1); + WASMBranchBlock *tgtframe = frame_csp - relative_depth - 1; + + switch (tgtframe->label_type) { + case LABEL_TYPE_BLOCK: + case LABEL_TYPE_IF: + case LABEL_TYPE_LOOP: + case LABEL_TYPE_CATCH: + case LABEL_TYPE_CATCH_ALL: + /* + * skip that blocks in search + * BLOCK, IF and LOOP do not contain handlers and + * cannot catch exceptions. + * blocks marked as CATCH or + * CATCH_ALL did already caugth an exception and can + * only be a target for RETHROW, but cannot catch an + * exception again + */ + break; + case LABEL_TYPE_TRY: + { + uint32 handler_number = 0; + uint8 **handlers = (uint8 **)tgtframe->frame_sp; + uint8 *handler = NULL; + while ((handler = handlers[handler_number]) != 0) { + uint8 handler_opcode = *handler; + uint8 *target_addr = + handler + + 1; /* first instruction or leb-immediate + behind the handler opcode */ + switch (handler_opcode) { + case WASM_OP_CATCH: + { + int32 lookup_index = 0; + /* read the tag_index and advance + * target_addr to the first instruction + * in the block */ + read_leb_int32(target_addr, 0, + lookup_index); + + if (exception_tag_index + == lookup_index) { + /* set ip */ + frame_ip = target_addr; + /* save frame_sp (points to + * exception values) */ + uint32 *frame_sp_old = frame_sp; + + UNWIND_CSP(relative_depth, + LABEL_TYPE_CATCH); + + /* push exception_tag_index and + * exception values for rethrow */ + PUSH_I32(exception_tag_index); + word_copy(frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + /* push exception values for catch + */ + word_copy(frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + + /* advance to handler */ + HANDLE_OP_END(); + } + break; + } + case WASM_OP_DELEGATE: + { + int32 lookup_depth = 0; + /* read the depth */ + read_leb_int32(target_addr, 0, + lookup_depth); + + /* save frame_sp (points to exception + * values) */ + uint32 *frame_sp_old = frame_sp; + + UNWIND_CSP(relative_depth, + LABEL_TYPE_CATCH); + + /* leave the block (the delegate is + * technically not inside the frame) */ + frame_csp--; + + /* unwind to delegated frame */ + frame_csp -= lookup_depth; + + /* push exception values for catch */ + word_copy(frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + + /* tag_index is already stored in + * exception_tag_index */ + goto find_a_catch_handler; + } + case WASM_OP_CATCH_ALL: + { + /* no immediate */ + /* save frame_sp (points to exception + * values) */ + uint32 *frame_sp_old = frame_sp; + /* set ip */ + frame_ip = target_addr; + + UNWIND_CSP(relative_depth, + LABEL_TYPE_CATCH_ALL); + + /* push exception_tag_index and + * exception values for rethrow */ + PUSH_I32(exception_tag_index); + word_copy(frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + /* catch_all has no exception values */ + + /* advance to handler */ + HANDLE_OP_END(); + } + default: + wasm_set_exception( + module, "WASM_OP_THROW found " + "unexpected handler type"); + goto got_exception; + } + handler_number++; + } + /* exception not catched in this frame */ + break; + } + case LABEL_TYPE_FUNCTION: + { + /* save frame_sp (points to exception values) */ + uint32 *frame_sp_old = frame_sp; + + UNWIND_CSP(relative_depth, LABEL_TYPE_FUNCTION); + /* push exception values for catch + * The values are copied to the CALLER FRAME + * (prev_frame->sp) same behvior ad WASM_OP_RETURN + */ + word_copy(prev_frame->sp, + frame_sp_old - cell_num_to_copy, + cell_num_to_copy); + prev_frame->sp += cell_num_to_copy; + *((int32 *)(prev_frame->sp)) = exception_tag_index; + prev_frame->sp++; + + /* mark frame as raised exception */ + wasm_set_exception(module, + "uncaught wasm exception"); + + /* end of function, treat as WASM_OP_RETURN */ + goto return_func; + } + default: + wasm_set_exception( + module, + "unexpected or invalid label in THROW or " + "RETHROW when searching a catch handler"); + goto got_exception; + } + + relative_depth++; + + } while (1); + } + + /* something went wrong. normally, we should always find the + * func label. if not, stop the interpreter */ + wasm_set_exception( + module, "WASM_OP_THROW hit the bottom of the frame stack"); + goto got_exception; + } + + HANDLE_OP(EXT_OP_TRY) + { + /* read the blocktype */ + read_leb_uint32(frame_ip, frame_ip_end, type_index); + param_cell_num = wasm_types[type_index]->param_cell_num; + cell_num = wasm_types[type_index]->ret_cell_num; + goto handle_op_try; + } + + HANDLE_OP(WASM_OP_TRY) + { + value_type = *frame_ip++; + param_cell_num = 0; + cell_num = wasm_value_type_cell_num(value_type); + + handle_op_try: + + cache_index = ((uintptr_t)frame_ip) + & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1); + cache_items = exec_env->block_addr_cache[cache_index]; + if (cache_items[0].start_addr == frame_ip) { + cache_items[0].start_addr = 0; + } + if (cache_items[1].start_addr == frame_ip) { + cache_items[1].start_addr = 0; + } + + /* start at the first opcode following the try and its blocktype + */ + uint8 *lookup_cursor = frame_ip; + uint8 handler_opcode = WASM_OP_UNREACHABLE; + + /* target_addr filled in when END or DELEGATE is found */ + PUSH_CSP(LABEL_TYPE_TRY, param_cell_num, cell_num, 0); + + /* reset to begin of block */ + lookup_cursor = frame_ip; + do { + /* lookup the next CATCH, CATCH_ALL or END for this TRY */ + if (!wasm_loader_find_block_addr( + exec_env, (BlockAddr *)exec_env->block_addr_cache, + lookup_cursor, (uint8 *)-1, LABEL_TYPE_TRY, + &else_addr, &end_addr)) { + /* something went wrong */ + wasm_set_exception(module, "find block address failed"); + goto got_exception; + } + + /* place cursor for continuation past opcode */ + lookup_cursor = end_addr + 1; + + /* end_addr points to CATCH, CATCH_ALL, DELEGATE or END */ + handler_opcode = *end_addr; + switch (handler_opcode) { + case WASM_OP_CATCH: + skip_leb(lookup_cursor); /* skip tag_index */ + PUSH_I64(end_addr); + break; + case WASM_OP_CATCH_ALL: + PUSH_I64(end_addr); + break; + case WASM_OP_DELEGATE: + skip_leb(lookup_cursor); /* skip depth */ + PUSH_I64(end_addr); + /* patch target_addr */ + (frame_csp - 1)->target_addr = lookup_cursor; + break; + case WASM_OP_END: + PUSH_I64(0); + /* patch target_addr */ + (frame_csp - 1)->target_addr = end_addr; + break; + default: + /* something went wrong */ + wasm_set_exception(module, + "find block address returned an " + "unexpected opcode"); + goto got_exception; + } + /* ... search until the returned address is the END of the + * TRY block */ + } while (handler_opcode != WASM_OP_END + && handler_opcode != WASM_OP_DELEGATE); + /* handler setup on stack complete */ + + HANDLE_OP_END(); + } + HANDLE_OP(WASM_OP_CATCH) + { + /* skip the tag_index */ + skip_leb(frame_ip); + /* leave the frame */ + POP_CSP_N(0); + HANDLE_OP_END(); + } + HANDLE_OP(WASM_OP_CATCH_ALL) + { + /* leave the frame */ + POP_CSP_N(0); + HANDLE_OP_END(); + } + HANDLE_OP(WASM_OP_DELEGATE) + { + /* skip the delegate depth */ + skip_leb(frame_ip); + /* leave the frame like WASM_OP_END */ + POP_CSP(); + HANDLE_OP_END(); + } +#endif HANDLE_OP(EXT_OP_BLOCK) { read_leb_uint32(frame_ip, frame_ip_end, type_index); @@ -3814,10 +4211,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 - HANDLE_OP(WASM_OP_UNUSED_0x06) - HANDLE_OP(WASM_OP_UNUSED_0x07) - HANDLE_OP(WASM_OP_UNUSED_0x08) - HANDLE_OP(WASM_OP_UNUSED_0x09) HANDLE_OP(WASM_OP_UNUSED_0x0a) #if WASM_ENABLE_TAIL_CALL == 0 HANDLE_OP(WASM_OP_RETURN_CALL) @@ -3834,6 +4227,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_REF_IS_NULL) HANDLE_OP(WASM_OP_REF_FUNC) #endif +#if WASM_ENABLE_EXCE_HANDLING == 0 + HANDLE_OP(WASM_OP_TRY) + HANDLE_OP(WASM_OP_CATCH) + HANDLE_OP(WASM_OP_THROW) + HANDLE_OP(WASM_OP_RETHROW) + HANDLE_OP(WASM_OP_DELEGATE) + HANDLE_OP(WASM_OP_CATCH_ALL) + HANDLE_OP(EXT_OP_TRY) +#endif #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_SIMD != 0 /* SIMD isn't supported by interpreter, but when JIT is enabled, `iwasm --interp ` may be run to @@ -3844,8 +4246,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_UNUSED_0x15) HANDLE_OP(WASM_OP_UNUSED_0x16) HANDLE_OP(WASM_OP_UNUSED_0x17) - HANDLE_OP(WASM_OP_UNUSED_0x18) - HANDLE_OP(WASM_OP_UNUSED_0x19) HANDLE_OP(WASM_OP_UNUSED_0x27) /* Used by fast interpreter */ HANDLE_OP(EXT_OP_SET_LOCAL_FAST_I64) @@ -3896,6 +4296,50 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (cur_func->import_func_inst) { wasm_interp_call_func_import(module, exec_env, cur_func, prev_frame); +#if WASM_ENABLE_EXCE_HANDLING != 0 + char uncaught_exception[128] = { 0 }; + bool has_exception = + wasm_copy_exception(module, uncaught_exception); + if (has_exception + && strstr(uncaught_exception, "uncaught wasm exception")) { + /* fix framesp */ + UPDATE_ALL_FROM_FRAME(); + + uint32 import_exception; + /* initialize imported exception index to be invalid */ + SET_INVALID_TAGINDEX(import_exception); + + /* pull external exception */ + uint32 ext_exception = POP_I32(); + + /* external function came back with an exception or trap */ + /* lookup exception in import tags */ + WASMTagInstance *tag = module->e->tags; + for (uint32 t = 0; t < module->module->import_tag_count; + tag++, t++) { + + /* compare the module and the external index with the + * imort tag data */ + if ((cur_func->u.func_import->import_module + == tag->u.tag_import->import_module) + && (ext_exception + == tag->u.tag_import + ->import_tag_index_linked)) { + /* set the import_exception to the import tag */ + import_exception = t; + break; + } + } + /* + * excange the thrown exception (index valid in submodule) + * with the imported exception index (valid in this module) + * if the module did not import the exception, + * that results in a "INVALID_TAGINDEX", that triggers + * an CATCH_ALL block, if there is one. + */ + PUSH_I32(import_exception); + } +#endif } else #endif @@ -3916,19 +4360,57 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (memory) linear_mem_size = get_linear_mem_size(); #endif - if (wasm_copy_exception(module, NULL)) + if (wasm_copy_exception(module, NULL)) { +#if WASM_ENABLE_EXCE_HANDLING != 0 + /* the caller raised an exception */ + char uncaught_exception[128] = { 0 }; + bool has_exception = + wasm_copy_exception(module, uncaught_exception); + + /* libc_builtin signaled a "exception thrown by stdc++" trap */ + if (has_exception + && strstr(uncaught_exception, + "exception thrown by stdc++")) { + wasm_set_exception(module, NULL); + + /* setup internal c++ rethrow */ + exception_tag_index = 0; + goto find_a_catch_handler; + } + + /* when throw hits the end of a function it signalles with a + * "uncaught wasm exception" trap */ + if (has_exception + && strstr(uncaught_exception, "uncaught wasm exception")) { + wasm_set_exception(module, NULL); + exception_tag_index = POP_I32(); + + /* rethrow the exception into that frame */ + goto find_a_catch_handler; + } +#endif goto got_exception; + } } else { WASMFunction *cur_wasm_func = cur_func->u.func; WASMType *func_type; +#if WASM_ENABLE_EXCE_HANDLING != 0 + /* account for exception handlers */ + /* bundle them here */ + uint32 eh_size = + cur_wasm_func->exception_handler_count * sizeof(uint8 *); + cur_wasm_func->max_stack_cell_num += eh_size; +#endif + func_type = cur_wasm_func->func_type; all_cell_num = cur_func->param_cell_num + cur_func->local_cell_num + cur_wasm_func->max_stack_cell_num + cur_wasm_func->max_block_num * (uint32)sizeof(WASMBranchBlock) / 4; + /* param_cell_num, local_cell_num, max_stack_cell_num and max_block_num are all no larger than UINT16_MAX (checked in loader), all_cell_num must be smaller than 1MB */ @@ -3977,11 +4459,19 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, FREE_FRAME(exec_env, frame); wasm_exec_env_set_cur_frame(exec_env, prev_frame); - if (!prev_frame->ip) + if (!prev_frame->ip) { /* Called from native. */ return; + } RECOVER_CONTEXT(prev_frame); +#if WASM_ENABLE_EXCE_HANDLING != 0 + if (wasm_get_exception(module)) { + wasm_set_exception(module, NULL); + exception_tag_index = POP_I32(); + goto find_a_catch_handler; + } +#endif HANDLE_OP_END(); } diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 521f547f0..335fefca0 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1437,6 +1437,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto call_func_from_interp; } +#if WASM_ENABLE_EXCE_HANDLING != 0 + HANDLE_OP(WASM_OP_TRY) + HANDLE_OP(WASM_OP_CATCH) + HANDLE_OP(WASM_OP_THROW) + HANDLE_OP(WASM_OP_RETHROW) + HANDLE_OP(WASM_OP_DELEGATE) + HANDLE_OP(WASM_OP_CATCH_ALL) + HANDLE_OP(EXT_OP_TRY) + { + wasm_set_exception(module, "unsupported opcode"); + goto got_exception; + } +#endif + /* parametric instructions */ HANDLE_OP(WASM_OP_SELECT) { @@ -3670,10 +3684,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 - HANDLE_OP(WASM_OP_UNUSED_0x06) - HANDLE_OP(WASM_OP_UNUSED_0x07) - HANDLE_OP(WASM_OP_UNUSED_0x08) - HANDLE_OP(WASM_OP_UNUSED_0x09) HANDLE_OP(WASM_OP_UNUSED_0x0a) #if WASM_ENABLE_TAIL_CALL == 0 HANDLE_OP(WASM_OP_RETURN_CALL) @@ -3688,6 +3698,16 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_REF_NULL) HANDLE_OP(WASM_OP_REF_IS_NULL) HANDLE_OP(WASM_OP_REF_FUNC) +#endif +#if WASM_ENABLE_EXCE_HANDLING == 0 + /* if exception handling is disabled, these opcodes issue a trap */ + HANDLE_OP(WASM_OP_TRY) + HANDLE_OP(WASM_OP_CATCH) + HANDLE_OP(WASM_OP_THROW) + HANDLE_OP(WASM_OP_RETHROW) + HANDLE_OP(WASM_OP_DELEGATE) + HANDLE_OP(WASM_OP_CATCH_ALL) + HANDLE_OP(EXT_OP_TRY) #endif /* SELECT_T is converted to SELECT or SELECT_64 */ HANDLE_OP(WASM_OP_SELECT_T) @@ -3695,8 +3715,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_UNUSED_0x15) HANDLE_OP(WASM_OP_UNUSED_0x16) HANDLE_OP(WASM_OP_UNUSED_0x17) - HANDLE_OP(WASM_OP_UNUSED_0x18) - HANDLE_OP(WASM_OP_UNUSED_0x19) HANDLE_OP(WASM_OP_UNUSED_0x27) /* optimized op code */ HANDLE_OP(WASM_OP_F32_STORE) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index db82ab494..11417fa19 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -707,7 +707,6 @@ wasm_loader_find_export(const WASMModule *module, const char *module_name, WASMExport *export = loader_find_export((WASMModuleCommon *)module, module_name, field_name, export_kind, error_buf, error_buf_size); - ; return export; } #endif @@ -898,6 +897,58 @@ wasm_loader_resolve_global(const char *module_name, const char *global_name, return global; } +#if WASM_ENABLE_TAGS != 0 +static WASMTag * +wasm_loader_resolve_tag(const char *module_name, const char *tag_name, + const WASMType *expected_tag_type, + uint32 *linked_tag_index, char *error_buf, + uint32 error_buf_size) +{ + WASMModuleCommon *module_reg; + WASMTag *tag = NULL; + WASMExport *export = NULL; + WASMModule *module = NULL; + + module_reg = wasm_runtime_find_module_registered(module_name); + if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) { + LOG_DEBUG("can not find a module named %s for tag %s", module_name, + tag_name); + set_error_buf(error_buf, error_buf_size, "unknown import"); + return NULL; + } + + module = (WASMModule *)module_reg; + export = + wasm_loader_find_export(module, module_name, tag_name, EXPORT_KIND_TAG, + error_buf, error_buf_size); + if (!export) { + return NULL; + } + + /* resolve tag type and tag */ + if (export->index < module->import_tag_count) { + /* importing an imported tag from the submodule */ + tag = module->import_tags[export->index].u.tag.import_tag_linked; + } + else { + /* importing an section tag from the submodule */ + tag = module->tags[export->index - module->import_tag_count]; + } + + /* check function type */ + if (!wasm_type_equal(expected_tag_type, tag->tag_type)) { + LOG_DEBUG("%s.%s failed the type check", module_name, tag_name); + set_error_buf(error_buf, error_buf_size, "incompatible import type"); + return NULL; + } + + if (linked_tag_index != NULL) { + *linked_tag_index = export->index; + } + + return tag; +} +#endif #endif /* end of WASM_ENABLE_MULTI_MODULE */ static bool @@ -1237,6 +1288,89 @@ fail: return false; } +#if WASM_ENABLE_TAGS != 0 +static bool +load_tag_import(const uint8 **p_buf, const uint8 *buf_end, + const WASMModule *parent_module, /* this module ! */ + const char *sub_module_name, const char *tag_name, + WASMTagImport *tag, /* structure to fill */ + char *error_buf, uint32 error_buf_size) +{ + /* attribute and type of the import statement */ + uint8 declare_tag_attribute; + uint32 declare_type_index; + const uint8 *p = *p_buf, *p_end = buf_end; +#if WASM_ENABLE_MULTI_MODULE != 0 + WASMModule *sub_module = NULL; +#endif + + /* get the one byte attribute */ + CHECK_BUF(p, p_end, 1); + declare_tag_attribute = read_uint8(p); + if (declare_tag_attribute != 0) { + set_error_buf(error_buf, error_buf_size, "unknown tag attribute"); + goto fail; + } + + /* get type */ + read_leb_uint32(p, p_end, declare_type_index); + /* compare against module->types */ + if (declare_type_index >= parent_module->type_count) { + set_error_buf(error_buf, error_buf_size, "unknown tag type"); + goto fail; + } + + WASMType *declare_tag_type = parent_module->types[declare_type_index]; + + /* check, that the type of the declared tag returns void */ + if (declare_tag_type->result_count != 0) { + set_error_buf(error_buf, error_buf_size, + "tag type signature does not return void"); + + goto fail; + } + +#if WASM_ENABLE_MULTI_MODULE != 0 + if (!wasm_runtime_is_built_in_module(sub_module_name)) { + sub_module = (WASMModule *)wasm_runtime_load_depended_module( + (WASMModuleCommon *)parent_module, sub_module_name, error_buf, + error_buf_size); + if (!sub_module) { + return false; + } + /* wasm_loader_resolve_tag checks, that the imported tag + * and the declared tag have the same type + */ + uint32 linked_tag_index = 0; + WASMTag *linked_tag = wasm_loader_resolve_tag( + sub_module_name, tag_name, declare_tag_type, + &linked_tag_index /* out */, error_buf, error_buf_size); + if (linked_tag) { + tag->import_module = sub_module; + tag->import_tag_linked = linked_tag; + tag->import_tag_index_linked = linked_tag_index; + } + } +#endif + /* store to module tag declarations */ + tag->attribute = declare_tag_attribute; + tag->type = declare_type_index; + + tag->module_name = (char *)sub_module_name; + tag->field_name = (char *)tag_name; + tag->tag_type = declare_tag_type; + + *p_buf = p; + (void)parent_module; + + LOG_VERBOSE("Load tag import success\n"); + + return true; +fail: + return false; +} +#endif + static bool load_global_import(const uint8 **p_buf, const uint8 *buf_end, const WASMModule *parent_module, char *sub_module_name, @@ -1458,6 +1592,9 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, WASMImport *import; WASMImport *import_functions = NULL, *import_tables = NULL; WASMImport *import_memories = NULL, *import_globals = NULL; +#if WASM_ENABLE_TAGS != 0 + WASMImport *import_tags = NULL; +#endif char *sub_module_name, *field_name; uint8 u8, kind; @@ -1486,7 +1623,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, p += name_len; CHECK_BUF(p, p_end, 1); - /* 0x00/0x01/0x02/0x03 */ + /* 0x00/0x01/0x02/0x03/0x04 */ kind = read_uint8(p); switch (kind) { @@ -1527,6 +1664,16 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } break; +#if WASM_ENABLE_TAGS != 0 + case IMPORT_KIND_TAG: /* import tags */ + /* it only counts the number of tags to import */ + module->import_tag_count++; + CHECK_BUF(p, p_end, 1); + u8 = read_uint8(p); + read_leb_uint32(p, p_end, type_index); + break; +#endif + case IMPORT_KIND_GLOBAL: /* import global */ CHECK_BUF(p, p_end, 2); p += 2; @@ -1549,10 +1696,23 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, import_memories = module->import_memories = module->imports + module->import_function_count + module->import_table_count; + +#if WASM_ENABLE_TAGS != 0 + if (module->import_tag_count) + import_tags = module->import_tags = + module->imports + module->import_function_count + + module->import_table_count + module->import_memory_count; + if (module->import_global_count) + import_globals = module->import_globals = + module->imports + module->import_function_count + + module->import_table_count + module->import_memory_count + + module->import_tag_count; +#else if (module->import_global_count) import_globals = module->import_globals = module->imports + module->import_function_count + module->import_table_count + module->import_memory_count; +#endif p = p_old; @@ -1579,7 +1739,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, p += name_len; CHECK_BUF(p, p_end, 1); - /* 0x00/0x01/0x02/0x03 */ + /* 0x00/0x01/0x02/0x03/0x4 */ kind = read_uint8(p); switch (kind) { @@ -1615,6 +1775,18 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } break; +#if WASM_ENABLE_TAGS != 0 + case IMPORT_KIND_TAG: + bh_assert(import_tags); + import = import_tags++; + if (!load_tag_import(&p, p_end, module, sub_module_name, + field_name, &import->u.tag, error_buf, + error_buf_size)) { + return false; + } + break; +#endif + case IMPORT_KIND_GLOBAL: /* import global */ bh_assert(import_globals); import = import_globals++; @@ -2126,6 +2298,16 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } break; +#if WASM_ENABLE_TAGS != 0 + /* export tag */ + case EXPORT_KIND_TAG: + if (index >= module->tag_count + module->import_tag_count) { + set_error_buf(error_buf, error_buf_size, "unknown tag"); + return false; + } + break; +#endif + /* global index */ case EXPORT_KIND_GLOBAL: if (index @@ -2135,6 +2317,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } break; + default: set_error_buf(error_buf, error_buf_size, "invalid export kind"); @@ -2541,6 +2724,83 @@ fail: } #endif +#if WASM_ENABLE_TAGS != 0 +static bool +load_tag_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_code, + const uint8 *buf_code_end, WASMModule *module, char *error_buf, + uint32 error_buf_size) +{ + (void)buf_code; + (void)buf_code_end; + + const uint8 *p = buf, *p_end = buf_end; + size_t total_size = 0; + /* number of tags defined in the section */ + uint32 section_tag_count = 0; + uint8 tag_attribute; + uint32 tag_type; + WASMTag *tag = NULL; + + /* get tag count */ + read_leb_uint32(p, p_end, section_tag_count); + module->tag_count = section_tag_count; + + if (section_tag_count) { + total_size = sizeof(WASMTag *) * module->tag_count; + if (!(module->tags = + loader_malloc(total_size, error_buf, error_buf_size))) { + return false; + } + /* load each tag, imported tags precede the tags */ + uint32 tag_index; + for (tag_index = 0; tag_index < section_tag_count; tag_index++) { + + /* get the one byte attribute */ + CHECK_BUF(p, p_end, 1); + tag_attribute = read_uint8(p); + + /* get type */ + read_leb_uint32(p, p_end, tag_type); + /* compare against module->types */ + if (tag_type >= module->type_count) { + set_error_buf(error_buf, error_buf_size, "unknown type"); + return false; + } + + /* get return type (must be 0) */ + /* check, that the type of the referred tag returns void */ + WASMType *func_type = (WASMType *)module->types[tag_type]; + if (func_type->result_count != 0) { + set_error_buf(error_buf, error_buf_size, + "non-empty tag result type"); + + goto fail; + } + + if (!(tag = module->tags[tag_index] = loader_malloc( + sizeof(WASMTag), error_buf, error_buf_size))) { + return false; + } + + /* store to module tag declarations */ + tag->attribute = tag_attribute; + tag->type = tag_type; + tag->tag_type = func_type; + } + } + + if (p != p_end) { + set_error_buf(error_buf, error_buf_size, "section size mismatch"); + return false; + } + + LOG_VERBOSE("Load tag section success.\n"); + return true; +fail: + return false; +} +#endif + static bool load_code_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_func, const uint8 *buf_func_end, WASMModule *module, @@ -3336,6 +3596,14 @@ load_from_sections(WASMModule *module, WASMSection *sections, error_buf_size)) return false; break; +#if WASM_ENABLE_TAGS != 0 + case SECTION_TYPE_TAG: + /* load tag declaration section */ + if (!load_tag_section(buf, buf_end, buf_code, buf_code_end, + module, error_buf, error_buf_size)) + return false; + break; +#endif case SECTION_TYPE_GLOBAL: if (!load_global_section(buf, buf_end, module, error_buf, error_buf_size)) @@ -3805,6 +4073,9 @@ static uint8 section_ids[] = { SECTION_TYPE_FUNC, SECTION_TYPE_TABLE, SECTION_TYPE_MEMORY, +#if WASM_ENABLE_TAGS != 0 + SECTION_TYPE_TAG, +#endif SECTION_TYPE_GLOBAL, SECTION_TYPE_EXPORT, SECTION_TYPE_START, @@ -4210,6 +4481,16 @@ wasm_loader_unload(WASMModule *module) if (module->memories) wasm_runtime_free(module->memories); +#if WASM_ENABLE_TAGS != 0 + if (module->tags) { + for (i = 0; i < module->tag_count; i++) { + if (module->tags[i]) + wasm_runtime_free(module->tags[i]); + } + wasm_runtime_free(module->tags); + } +#endif + if (module->globals) wasm_runtime_free(module->globals); @@ -4350,6 +4631,64 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case WASM_OP_NOP: break; +#if WASM_ENABLE_EXCE_HANDLING != 0 + case WASM_OP_TRY: + u8 = read_uint8(p); + if (block_nested_depth + < sizeof(block_stack) / sizeof(BlockAddr)) { + block_stack[block_nested_depth].start_addr = p; + block_stack[block_nested_depth].else_addr = NULL; + } + block_nested_depth++; + break; + case EXT_OP_TRY: + skip_leb_uint32(p, p_end); + if (block_nested_depth + < sizeof(block_stack) / sizeof(BlockAddr)) { + block_stack[block_nested_depth].start_addr = p; + block_stack[block_nested_depth].else_addr = NULL; + } + block_nested_depth++; + break; + case WASM_OP_CATCH: + if (block_nested_depth == 1) { + *p_end_addr = (uint8 *)(p - 1); + /* stop search and return the address of the catch block */ + return true; + } + break; + case WASM_OP_CATCH_ALL: + if (block_nested_depth == 1) { + *p_end_addr = (uint8 *)(p - 1); + /* stop search and return the address of the catch_all block + */ + return true; + } + break; + case WASM_OP_THROW: + /* skip tag_index */ + skip_leb(p); + break; + case WASM_OP_RETHROW: + /* skip depth */ + skip_leb(p); + break; + case WASM_OP_DELEGATE: + if (block_nested_depth == 1) { + *p_end_addr = (uint8 *)(p - 1); + return true; + } + else { + /* the DELEGATE opcode ends the tryblock, */ + block_nested_depth--; + if (block_nested_depth + < sizeof(block_stack) / sizeof(BlockAddr)) + block_stack[block_nested_depth].end_addr = + (uint8 *)(p - 1); + } + break; +#endif + case WASM_OP_BLOCK: case WASM_OP_LOOP: case WASM_OP_IF: @@ -5221,6 +5560,10 @@ wasm_loader_ctx_init(WASMFunction *func, char *error_buf, uint32 error_buf_size) goto fail; loader_ctx->frame_csp_boundary = loader_ctx->frame_csp_bottom + 8; +#if WASM_ENABLE_EXCE_HANDLING != 0 + func->exception_handler_count = 0; +#endif + #if WASM_ENABLE_FAST_INTERP != 0 loader_ctx->frame_offset_size = sizeof(int16) * 32; if (!(loader_ctx->frame_offset_bottom = loader_ctx->frame_offset = @@ -6832,11 +7175,26 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, return true; } - /* Check stack cell num equals return cell num */ if (available_stack_cell != return_cell_num) { +#if WASM_ENABLE_EXCE_HANDLING != 0 + /* testspec: this error message format is expected by try_catch.wast */ + snprintf( + error_buf, error_buf_size, "type mismatch: %s requires [%s]%s[%s]", + block->label_type == LABEL_TYPE_TRY + || (block->label_type == LABEL_TYPE_CATCH + && return_cell_num > 0) + ? "instruction" + : "block", + return_cell_num > 0 ? type2str(return_types[0]) : "", + " but stack has ", + available_stack_cell > 0 ? type2str(*(loader_ctx->frame_ref - 1)) + : ""); + goto fail; +#else set_error_buf(error_buf, error_buf_size, "type mismatch: stack size does not match block type"); goto fail; +#endif } /* Check stack values match return types */ @@ -7185,6 +7543,24 @@ re_scan: } case WASM_OP_BLOCK: case WASM_OP_LOOP: +#if WASM_ENABLE_EXCE_HANDLING != 0 + case WASM_OP_TRY: + if (opcode == WASM_OP_TRY) { + /* + * keep track of exception handlers to account for + * memory allocation + */ + func->exception_handler_count++; + + /* + * try is a block + * do nothing special, but execution continues to + * to handle_op_block_and_loop, + * and that be pushes the csp + */ + } + +#endif #if WASM_ENABLE_FAST_INTERP != 0 PRESERVE_LOCAL_FOR_BLOCK(); #endif @@ -7258,7 +7634,6 @@ re_scan: wasm_type->types[wasm_type->param_count - i - 1]); } } - PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK), block_type, p); @@ -7291,6 +7666,11 @@ re_scan: loader_ctx->p_code_compiled; } } +#if WASM_ENABLE_EXCE_HANDLING != 0 + else if (opcode == WASM_OP_TRY) { + skip_label(); + } +#endif else if (opcode == WASM_OP_IF) { BranchBlock *block = loader_ctx->frame_csp - 1; /* If block has parameters, we should make sure they are in @@ -7351,7 +7731,212 @@ re_scan: #endif break; } +#if WASM_ENABLE_EXCE_HANDLING != 0 + case WASM_OP_THROW: + { + SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true); + BranchBlock *cur_block = loader_ctx->frame_csp - 1; + + uint8 label_type = cur_block->label_type; + uint32 tag_index = 0; + 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 */ + if (tag_index >= module->import_tag_count + module->tag_count) { + snprintf(error_buf, error_buf_size, "unknown tag %d", + tag_index); + goto fail; + } + + /* the tag_type is stored in either the WASMTag (section tags) + * or WASMTagImport (import tag) */ + WASMType *tag_type = NULL; + if (tag_index < module->import_tag_count) { + tag_type = module->import_tags[tag_index].u.tag.tag_type; + } + else { + tag_type = + module->tags[tag_index - module->import_tag_count] + ->tag_type; + } + + if (tag_type->result_count != 0) { + set_error_buf(error_buf, error_buf_size, + "tag type signature does not return void"); + goto fail; + } + + int32 available_stack_cell = + (int32)(loader_ctx->stack_cell_num + - cur_block->stack_cell_num); + + /* Check stack values match return types by comparing tag param + * types with stack cells */ + uint8 *frame_ref = loader_ctx->frame_ref; + for (int tti = (int32)tag_type->param_count - 1; tti >= 0; + tti--) { + if (!check_stack_top_values(frame_ref, available_stack_cell, + tag_type->types[tti], error_buf, + error_buf_size)) { + snprintf(error_buf, error_buf_size, + "type mismatch: instruction requires [%s] but " + "stack has [%s]", + tag_type->param_count > 0 + ? type2str(tag_type->types[tti]) + : "", + available_stack_cell > 0 + ? type2str(*(loader_ctx->frame_ref - 1)) + : ""); + goto fail; + } + frame_ref -= wasm_value_type_cell_num(tag_type->types[tti]); + available_stack_cell -= + wasm_value_type_cell_num(tag_type->types[tti]); + } + + /* throw is stack polymorphic */ + (void)label_type; + RESET_STACK(); + + break; + } + case WASM_OP_RETHROW: + { + /* must be done before checking branch block */ + SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true); + + /* check the target catching block: LABEL_TYPE_CATCH */ + if (!(frame_csp_tmp = check_branch_block( + loader_ctx, &p, p_end, error_buf, error_buf_size))) + goto fail; + + if (frame_csp_tmp->label_type != LABEL_TYPE_CATCH + && frame_csp_tmp->label_type != LABEL_TYPE_CATCH_ALL) { + /* trap according to spectest (rethrow.wast) */ + set_error_buf(error_buf, error_buf_size, + "invalid rethrow label"); + goto fail; + } + + BranchBlock *cur_block = loader_ctx->frame_csp - 1; + uint8 label_type = cur_block->label_type; + (void)label_type; + /* rethrow is stack polymorphic */ + RESET_STACK(); + break; + } + case WASM_OP_DELEGATE: + { + /* check target block is valid */ + if (!(frame_csp_tmp = check_branch_block( + loader_ctx, &p, p_end, error_buf, error_buf_size))) + goto fail; + + /* valid types */ + if (LABEL_TYPE_TRY != frame_csp_tmp->label_type) { + snprintf(error_buf, error_buf_size, "unknown label"); + goto fail; + } + + BranchBlock *cur_block = loader_ctx->frame_csp - 1; + uint8 label_type = cur_block->label_type; + + (void)label_type; + /* DELEGATE ends the block */ + POP_CSP(); + break; + } + case WASM_OP_CATCH: + { + BranchBlock *cur_block = loader_ctx->frame_csp - 1; + + uint8 label_type = cur_block->label_type; + uint32 tag_index = 0; + 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 */ + if (tag_index >= module->import_tag_count + module->tag_count) { + LOG_VERBOSE("In %s, unknown tag at WASM_OP_CATCH\n", + __FUNCTION__); + set_error_buf(error_buf, error_buf_size, "unknown tag"); + goto fail; + } + + /* the tag_type is stored in either the WASMTag (section tags) + * or WASMTagImport (import tag) */ + WASMType *func_type = NULL; + if (tag_index < module->import_tag_count) { + func_type = module->import_tags[tag_index].u.tag.tag_type; + } + else { + func_type = + module->tags[tag_index - module->import_tag_count] + ->tag_type; + } + + if (func_type->result_count != 0) { + set_error_buf(error_buf, error_buf_size, + "tag type signature does not return void"); + goto fail; + } + + /* check validity of current label (expect LABEL_TYPE_TRY or + * LABEL_TYPE_CATCH) */ + if ((LABEL_TYPE_CATCH != label_type) + && (LABEL_TYPE_TRY != label_type)) { + set_error_buf(error_buf, error_buf_size, + "Unexpected block sequence encountered."); + goto fail; + } + + BlockType new_block_type; + new_block_type.is_value_type = false; + new_block_type.u.type = func_type; + + /* + * replace frame_csp by LABEL_TYPE_CATCH + */ + cur_block->label_type = LABEL_TYPE_CATCH; + + /* RESET_STACK removes the values pushed in TRY or pervious + * CATCH Blocks */ + RESET_STACK(); + + /* push types on the stack according to catched type */ + if (BLOCK_HAS_PARAM(new_block_type)) { + for (i = 0; i < new_block_type.u.type->param_count; i++) + PUSH_TYPE(new_block_type.u.type->types[i]); + } + break; + } + case WASM_OP_CATCH_ALL: + { + BranchBlock *cur_block = loader_ctx->frame_csp - 1; + + /* expecting a TRY or CATCH, anything else will be considered an + * error */ + if ((LABEL_TYPE_CATCH != cur_block->label_type) + && (LABEL_TYPE_TRY != cur_block->label_type)) { + set_error_buf(error_buf, error_buf_size, + "Unexpected block sequence encountered."); + goto fail; + } + + /* no immediates */ + /* replace frame_csp by LABEL_TYPE_CATCH_ALL */ + cur_block->label_type = LABEL_TYPE_CATCH_ALL; + + /* RESET_STACK removes the values pushed in TRY or pervious + * CATCH Blocks */ + RESET_STACK(); + + /* catch_all has no tagtype and therefore no parameters */ + break; + } +#endif case WASM_OP_ELSE: { BranchBlock *block = NULL; diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 857212e17..3abf4a96e 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -3259,6 +3259,17 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, u8 = read_uint8(p); /* 0x00 */ break; +#if WASM_ENABLE_EXCE_HANDLING != 0 + case WASM_OP_TRY: + case WASM_OP_CATCH: + case WASM_OP_THROW: + case WASM_OP_RETHROW: + case WASM_OP_DELEGATE: + case WASM_OP_CATCH_ALL: + /* TODO */ + return false; +#endif + case WASM_OP_DROP: case WASM_OP_SELECT: case WASM_OP_DROP_64: @@ -6173,6 +6184,18 @@ re_scan: break; } +#if WASM_ENABLE_EXCE_HANDLING != 0 + case WASM_OP_TRY: + case WASM_OP_CATCH: + case WASM_OP_THROW: + case WASM_OP_RETHROW: + case WASM_OP_DELEGATE: + case WASM_OP_CATCH_ALL: + /* TODO */ + set_error_buf(error_buf, error_buf_size, "unsupported opcode"); + goto fail; +#endif + case WASM_OP_DROP: { BranchBlock *cur_block = loader_ctx->frame_csp - 1; diff --git a/core/iwasm/interpreter/wasm_opcode.h b/core/iwasm/interpreter/wasm_opcode.h index 276d15c3d..4f8a6a695 100644 --- a/core/iwasm/interpreter/wasm_opcode.h +++ b/core/iwasm/interpreter/wasm_opcode.h @@ -20,11 +20,10 @@ typedef enum WASMOpcode { WASM_OP_LOOP = 0x03, /* loop */ WASM_OP_IF = 0x04, /* if */ WASM_OP_ELSE = 0x05, /* else */ - - WASM_OP_UNUSED_0x06 = 0x06, - WASM_OP_UNUSED_0x07 = 0x07, - WASM_OP_UNUSED_0x08 = 0x08, - WASM_OP_UNUSED_0x09 = 0x09, + WASM_OP_TRY = 0x06, /* try */ + WASM_OP_CATCH = 0x07, /* catch* */ + WASM_OP_THROW = 0x08, /* throw of a try catch */ + WASM_OP_RETHROW = 0x09, /* rethrow of a try catch */ WASM_OP_UNUSED_0x0a = 0x0a, WASM_OP_END = 0x0b, /* end */ @@ -41,8 +40,9 @@ typedef enum WASMOpcode { WASM_OP_UNUSED_0x15 = 0x15, WASM_OP_UNUSED_0x16 = 0x16, WASM_OP_UNUSED_0x17 = 0x17, - WASM_OP_UNUSED_0x18 = 0x18, - WASM_OP_UNUSED_0x19 = 0x19, + + WASM_OP_DELEGATE = 0x18, /* delegate block of the try catch*/ + WASM_OP_CATCH_ALL = 0x19, /* a catch_all handler in a try block */ /* parametric instructions */ WASM_OP_DROP = 0x1a, /* drop */ @@ -268,8 +268,10 @@ typedef enum WASMOpcode { EXT_OP_IF = 0xd5, /* if with blocktype */ EXT_OP_BR_TABLE_CACHE = 0xd6, /* br_table from cache */ + EXT_OP_TRY = 0xd7, /* try block with blocktype */ + #if WASM_ENABLE_DEBUG_INTERP != 0 - DEBUG_OP_BREAK = 0xd7, /* debug break point */ + DEBUG_OP_BREAK = 0xd8, /* debug break point */ #endif /* Post-MVP extend op prefix */ @@ -703,10 +705,10 @@ typedef enum WASMAtomicEXTOpcode { HANDLE_OPCODE(WASM_OP_LOOP), /* 0x03 */ \ HANDLE_OPCODE(WASM_OP_IF), /* 0x04 */ \ HANDLE_OPCODE(WASM_OP_ELSE), /* 0x05 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x06), /* 0x06 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x07), /* 0x07 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x08), /* 0x08 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x09), /* 0x09 */ \ + HANDLE_OPCODE(WASM_OP_TRY), /* 0x06 */ \ + HANDLE_OPCODE(WASM_OP_CATCH), /* 0x07 */ \ + HANDLE_OPCODE(WASM_OP_THROW), /* 0x08 */ \ + HANDLE_OPCODE(WASM_OP_RETHROW), /* 0x09 */ \ HANDLE_OPCODE(WASM_OP_UNUSED_0x0a), /* 0x0a */ \ HANDLE_OPCODE(WASM_OP_END), /* 0x0b */ \ HANDLE_OPCODE(WASM_OP_BR), /* 0x0c */ \ @@ -721,8 +723,8 @@ typedef enum WASMAtomicEXTOpcode { HANDLE_OPCODE(WASM_OP_UNUSED_0x15), /* 0x15 */ \ HANDLE_OPCODE(WASM_OP_UNUSED_0x16), /* 0x16 */ \ HANDLE_OPCODE(WASM_OP_UNUSED_0x17), /* 0x17 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x18), /* 0x18 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x19), /* 0x19 */ \ + HANDLE_OPCODE(WASM_OP_DELEGATE), /* 0x18 */ \ + HANDLE_OPCODE(WASM_OP_CATCH_ALL), /* 0x19 */ \ HANDLE_OPCODE(WASM_OP_DROP), /* 0x1a */ \ HANDLE_OPCODE(WASM_OP_SELECT), /* 0x1b */ \ HANDLE_OPCODE(WASM_OP_SELECT_T), /* 0x1c */ \ @@ -912,6 +914,7 @@ typedef enum WASMAtomicEXTOpcode { HANDLE_OPCODE(EXT_OP_LOOP), /* 0xd4 */ \ HANDLE_OPCODE(EXT_OP_IF), /* 0xd5 */ \ HANDLE_OPCODE(EXT_OP_BR_TABLE_CACHE), /* 0xd6 */ \ + HANDLE_OPCODE(EXT_OP_TRY), /* 0xd7 */ \ SET_GOTO_TABLE_ELEM(WASM_OP_MISC_PREFIX), /* 0xfc */ \ SET_GOTO_TABLE_SIMD_PREFIX_ELEM() /* 0xfd */ \ SET_GOTO_TABLE_ELEM(WASM_OP_ATOMIC_PREFIX), /* 0xfe */ \ diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 43844f2c6..44ef3db03 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -732,6 +732,101 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, return functions; } +#if WASM_ENABLE_TAGS != 0 +/** + * Destroy tags instances. + */ +static void +tags_deinstantiate(WASMTagInstance *tags, void **import_tag_ptrs) +{ + if (tags) { + wasm_runtime_free(tags); + } + if (import_tag_ptrs) { + wasm_runtime_free(import_tag_ptrs); + } +} + +/** + * Instantiate tags in a module. + */ +static WASMTagInstance * +tags_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, + char *error_buf, uint32 error_buf_size) +{ + WASMImport *import; + uint32 i, tag_count = module->import_tag_count + module->tag_count; + uint64 total_size = sizeof(WASMTagInstance) * (uint64)tag_count; + WASMTagInstance *tags, *tag; + + if (!(tags = runtime_malloc(total_size, error_buf, error_buf_size))) { + return NULL; + } + + total_size = sizeof(void *) * (uint64)module->import_tag_count; + if (total_size > 0 + && !(module_inst->e->import_tag_ptrs = + runtime_malloc(total_size, error_buf, error_buf_size))) { + wasm_runtime_free(tags); + return NULL; + } + + /* instantiate tags from import section */ + tag = tags; + import = module->import_tags; + for (i = 0; i < module->import_tag_count; i++, import++) { + tag->is_import_tag = true; + tag->u.tag_import = &import->u.tag; + tag->type = import->u.tag.type; + tag->attribute = import->u.tag.attribute; +#if WASM_ENABLE_MULTI_MODULE != 0 + if (import->u.tag.import_module) { + if (!(tag->import_module_inst = get_sub_module_inst( + module_inst, import->u.tag.import_module))) { + set_error_buf(error_buf, error_buf_size, "unknown tag"); + goto fail; + } + + if (!(tag->import_tag_inst = + wasm_lookup_tag(tag->import_module_inst, + import->u.tag.field_name, NULL))) { + set_error_buf(error_buf, error_buf_size, "unknown tag"); + goto fail; + } + + /* Copy the imported tag to current instance */ + module_inst->e->import_tag_ptrs[i] = + tag->u.tag_import->import_tag_linked; + } +#endif + tag++; + } + + /* instantiate tags from tag section */ + for (i = 0; i < module->tag_count; i++) { + tag->is_import_tag = false; + tag->type = module->tags[i]->type; + tag->u.tag = module->tags[i]; + +#if WASM_ENABLE_FAST_INTERP != 0 + /* tag->const_cell_num = function->u.func->const_cell_num; */ +#endif + tag++; + } + bh_assert((uint32)(tag - tags) == tag_count); + + return tags; + +#if WASM_ENABLE_MULTI_MODULE != 0 +fail: + tags_deinstantiate(tags, module_inst->e->import_tag_ptrs); + /* clean up */ + module_inst->e->import_tag_ptrs = NULL; + return NULL; +#endif +} +#endif + /** * Destroy global instances. */ @@ -931,6 +1026,52 @@ export_functions_instantiate(const WASMModule *module, return export_funcs; } +#if WASM_ENABLE_TAGS != 0 +/** + * Destroy export function instances. + */ +static void +export_tags_deinstantiate(WASMExportTagInstance *tags) +{ + if (tags) + wasm_runtime_free(tags); +} + +/** + * Instantiate export functions in a module. + */ +static WASMExportTagInstance * +export_tags_instantiate(const WASMModule *module, + WASMModuleInstance *module_inst, + uint32 export_tag_count, char *error_buf, + uint32 error_buf_size) +{ + WASMExportTagInstance *export_tags, *export_tag; + WASMExport *export = module->exports; + uint32 i; + uint64 total_size = + sizeof(WASMExportTagInstance) * (uint64)export_tag_count; + + if (!(export_tag = export_tags = + runtime_malloc(total_size, error_buf, error_buf_size))) { + return NULL; + } + + for (i = 0; i < module->export_count; i++, export ++) + if (export->kind == EXPORT_KIND_TAG) { + export_tag->name = export->name; + + bh_assert((uint32)(module_inst->export_tags)); + + export_tag->tag = &module_inst->e->tags[export->index]; + export_tag++; + } + + bh_assert((uint32)(export_tag - export_tags) == export_tag_count); + return export_tags; +} +#endif + #if WASM_ENABLE_MULTI_MODULE != 0 static void export_globals_deinstantiate(WASMExportGlobInstance *globals) @@ -1720,6 +1861,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, module_inst->table_count = module->import_table_count + module->table_count; module_inst->e->function_count = module->import_function_count + module->function_count; +#if WASM_ENABLE_TAGS != 0 + module_inst->e->tag_count = module->import_tag_count + module->tag_count; +#endif /* export */ module_inst->export_func_count = get_export_count(module, EXPORT_KIND_FUNC); @@ -1728,11 +1872,15 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, get_export_count(module, EXPORT_KIND_TABLE); module_inst->export_memory_count = get_export_count(module, EXPORT_KIND_MEMORY); +#if WASM_ENABLE_TAGS != 0 + module_inst->e->export_tag_count = + get_export_count(module, EXPORT_KIND_TAG); +#endif module_inst->export_global_count = get_export_count(module, EXPORT_KIND_GLOBAL); #endif - /* Instantiate memories/tables/functions */ + /* Instantiate memories/tables/functions/tags */ if ((module_inst->memory_count > 0 && !(module_inst->memories = memories_instantiate(module, module_inst, parent, heap_size, @@ -1748,6 +1896,15 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, && !(module_inst->export_functions = export_functions_instantiate( module, module_inst, module_inst->export_func_count, error_buf, error_buf_size))) +#if WASM_ENABLE_TAGS != 0 + || (module_inst->e->tag_count > 0 + && !(module_inst->e->tags = tags_instantiate( + module, module_inst, error_buf, error_buf_size))) + || (module_inst->e->export_tag_count > 0 + && !(module_inst->e->export_tags = export_tags_instantiate( + module, module_inst, module_inst->e->export_tag_count, + error_buf, error_buf_size))) +#endif #if WASM_ENABLE_MULTI_MODULE != 0 || (module_inst->export_global_count > 0 && !(module_inst->export_globals = export_globals_instantiate( @@ -1765,7 +1922,6 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, ) { goto fail; } - if (global_count > 0) { /* Initialize the global data */ global_data = module_inst->global_data; @@ -2188,8 +2344,16 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) tables_deinstantiate(module_inst); functions_deinstantiate(module_inst->e->functions, module_inst->e->function_count); +#if WASM_ENABLE_TAGS != 0 + tags_deinstantiate(module_inst->e->tags, module_inst->e->import_tag_ptrs); +#endif + globals_deinstantiate(module_inst->e->globals); export_functions_deinstantiate(module_inst->export_functions); +#if WASM_ENABLE_TAGS != 0 + export_tags_deinstantiate(module_inst->e->export_tags); +#endif + #if WASM_ENABLE_MULTI_MODULE != 0 export_globals_deinstantiate(module_inst->export_globals); #endif @@ -2270,6 +2434,21 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name) (void)module_inst->export_tables; return module_inst->tables[0]; } + +#if WASM_ENABLE_TAGS != 0 +WASMTagInstance * +wasm_lookup_tag(const WASMModuleInstance *module_inst, const char *name, + const char *signature) +{ + uint32 i; + for (i = 0; i < module_inst->e->export_tag_count; i++) + if (!strcmp(module_inst->e->export_tags[i].name, name)) + return module_inst->e->export_tags[i].tag; + (void)signature; + return NULL; +} +#endif + #endif #ifdef OS_ENABLE_HW_BOUND_CHECK diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 80ffde349..b1224863e 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -28,6 +28,9 @@ typedef struct WASMFunctionInstance WASMFunctionInstance; typedef struct WASMMemoryInstance WASMMemoryInstance; typedef struct WASMTableInstance WASMTableInstance; typedef struct WASMGlobalInstance WASMGlobalInstance; +#if WASM_ENABLE_TAGS != 0 +typedef struct WASMTagInstance WASMTagInstance; +#endif /** * When LLVM JIT, WAMR compiler or AOT is enabled, we should ensure that @@ -191,6 +194,30 @@ struct WASMFunctionInstance { #endif }; +#if WASM_ENABLE_TAGS != 0 +struct WASMTagInstance { + bool is_import_tag; + /* tag attribute */ + uint8 attribute; + /* tag type index */ + uint32 type; + union { + WASMTagImport *tag_import; + WASMTag *tag; + } u; + +#if WASM_ENABLE_MULTI_MODULE != 0 + WASMModuleInstance *import_module_inst; + WASMTagInstance *import_tag_inst; +#endif +}; +#endif + +#if WASM_ENABLE_EXCE_HANDLING != 0 +#define INVALID_TAGINDEX ((uint32)0xFFFFFFFF) +#define SET_INVALID_TAGINDEX(tag) (tag = INVALID_TAGINDEX) +#define IS_INVALID_TAGINDEX(tag) ((tag & INVALID_TAGINDEX) == INVALID_TAGINDEX) +#endif typedef struct WASMExportFuncInstance { char *name; WASMFunctionInstance *function; @@ -211,6 +238,13 @@ typedef struct WASMExportMemInstance { WASMMemoryInstance *memory; } WASMExportMemInstance; +#if WASM_ENABLE_TAGS != 0 +typedef struct WASMExportTagInstance { + char *name; + WASMTagInstance *tag; +} WASMExportTagInstance; +#endif + /* wasm-c-api import function info */ typedef struct CApiFuncImport { /* host func pointer after linked */ @@ -263,6 +297,14 @@ typedef struct WASMModuleInstanceExtra { WASMTableInstance **table_insts_linked; #endif +#if WASM_ENABLE_TAGS != 0 + uint32 tag_count; + uint32 export_tag_count; + WASMTagInstance *tags; + WASMExportTagInstance *export_tags; + void **import_tag_ptrs; +#endif + #if WASM_ENABLE_MEMORY_PROFILING != 0 uint32 max_aux_stack_used; #endif @@ -461,6 +503,13 @@ wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name); WASMTableInstance * wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name); + +#if WASM_ENABLE_TAGS != 0 +WASMTagInstance * +wasm_lookup_tag(const WASMModuleInstance *module_inst, const char *name, + const char *signature); +#endif + #endif bool diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 341034e51..748fb6a87 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -359,6 +359,14 @@ else CFLAGS += -DWASM_ENABLE_REF_TYPES=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_ENABLE_EXCE_HANDLING),y) +CFLAGS += -DWASM_ENABLE_EXCE_HANDLING=1 +CFLAGS += -DWASM_ENABLE_TAGS=1 +else +CFLAGS += -DWASM_ENABLE_EXCE_HANDLING=0 +CFLAGS += -DWASM_ENABLE_TAGS=0 +endif + CFLAGS += -Wno-strict-prototypes -Wno-shadow -Wno-unused-variable CFLAGS += -Wno-int-conversion -Wno-implicit-function-declaration diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index 551a3176c..7aa47cf41 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -47,6 +47,7 @@ IWASM_CMD = get_iwasm_cmd(PLATFORM_NAME) IWASM_SGX_CMD = "../../../product-mini/platforms/linux-sgx/enclave-sample/iwasm" IWASM_QEMU_CMD = "iwasm" SPEC_TEST_DIR = "spec/test/core" +EXCE_HANDLING_DIR = "exception-handling/test/core" WAST2WASM_CMD = exe_file_path("./wabt/out/gcc/Release/wat2wasm") SPEC_INTERPRETER_CMD = "spec/interpreter/wasm" WAMRC_CMD = "../../../wamr-compiler/build/wamrc" @@ -78,8 +79,10 @@ def ignore_the_case( simd_flag=False, gc_flag=False, xip_flag=False, + eh_flag=False, qemu_flag=False, ): + if case_name in ["comments", "inline-module", "names"]: return True @@ -126,7 +129,7 @@ def ignore_the_case( return False -def preflight_check(aot_flag): +def preflight_check(aot_flag, eh_flag): if not pathlib.Path(SPEC_TEST_DIR).resolve().exists(): print(f"Can not find {SPEC_TEST_DIR}") return False @@ -139,6 +142,10 @@ def preflight_check(aot_flag): print(f"Can not find {WAMRC_CMD}") return False + if eh_flag and not pathlib.Path(EXCE_HANDLING_DIR).resolve().exists(): + print(f"Can not find {EXCE_HANDLING_DIR}") + return False + return True @@ -151,6 +158,7 @@ def test_case( multi_thread_flag=False, simd_flag=False, xip_flag=False, + eh_flag=False, clean_up_flag=True, verbose_flag=True, gc_flag=False, @@ -195,6 +203,9 @@ def test_case( if xip_flag: CMD.append("--xip") + if eh_flag: + CMD.append("--eh") + if qemu_flag: CMD.append("--qemu") CMD.append("--qemu-firmware") @@ -268,6 +279,7 @@ def test_suite( multi_thread_flag=False, simd_flag=False, xip_flag=False, + eh_flag=False, clean_up_flag=True, verbose_flag=True, gc_flag=False, @@ -291,6 +303,15 @@ def test_suite( gc_case_list = sorted(suite_path.glob("gc/*.wast")) case_list.extend(gc_case_list) + if eh_flag: + eh_path = pathlib.Path(EXCE_HANDLING_DIR).resolve() + if not eh_path.exists(): + print(f"can not find spec test cases at {eh_path}") + return False + eh_case_list = sorted(eh_path.glob("*.wast")) + eh_case_list_include = [test for test in eh_case_list if test.stem in ["throw", "tag", "try_catch", "rethrow", "try_delegate"]] + case_list.extend(eh_case_list_include) + # ignore based on command line options filtered_case_list = [] for case_path in case_list: @@ -305,6 +326,7 @@ def test_suite( simd_flag, gc_flag, xip_flag, + eh_flag, qemu_flag, ): filtered_case_list.append(case_path) @@ -331,6 +353,7 @@ def test_suite( multi_thread_flag, simd_flag, xip_flag, + eh_flag, clean_up_flag, verbose_flag, gc_flag, @@ -369,6 +392,7 @@ def test_suite( multi_thread_flag, simd_flag, xip_flag, + eh_flag, clean_up_flag, verbose_flag, gc_flag, @@ -428,6 +452,14 @@ def main(): dest="xip_flag", help="Running with the XIP feature", ) + # added to support WASM_ENABLE_EXCE_HANDLING + parser.add_argument( + "-e", + action="store_true", + default=False, + dest="eh_flag", + help="Running with the exception-handling feature", + ) parser.add_argument( "-t", action="store_true", @@ -508,7 +540,7 @@ def main(): if options.target == "x86_32": options.target = "i386" - if not preflight_check(options.aot_flag): + if not preflight_check(options.aot_flag, options.eh_flag): return False if not options.cases: @@ -527,6 +559,7 @@ def main(): options.multi_thread_flag, options.simd_flag, options.xip_flag, + options.eh_flag, options.clean_up_flag, options.verbose_flag, options.gc_flag, @@ -552,6 +585,7 @@ def main(): options.multi_thread_flag, options.simd_flag, options.xip_flag, + options.eh_flag, options.clean_up_flag, options.verbose_flag, options.gc_flag, diff --git a/tests/wamr-test-suites/spec-test-script/exception_handling.patch b/tests/wamr-test-suites/spec-test-script/exception_handling.patch new file mode 100644 index 000000000..0c9e8d40f --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/exception_handling.patch @@ -0,0 +1,20 @@ +diff --git a/test/core/try_catch.wast b/test/core/try_catch.wast +index 2a0e9ff6..f243489d 100644 +--- a/test/core/try_catch.wast ++++ b/test/core/try_catch.wast +@@ -203,7 +203,6 @@ + + (assert_return (invoke "catch-param-i32" (i32.const 5)) (i32.const 5)) + +-(assert_return (invoke "catch-imported") (i32.const 2)) + + (assert_return (invoke "catchless-try" (i32.const 0)) (i32.const 0)) + (assert_return (invoke "catchless-try" (i32.const 1)) (i32.const 1)) +@@ -231,7 +230,6 @@ + ) + ) + +-(assert_return (invoke "imported-mismatch") (i32.const 3)) + + (assert_malformed + (module quote "(module (func (catch_all)))") diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index dcc0c3361..60d4607e9 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -301,6 +301,9 @@ parser.add_argument('--simd', default=False, action='store_true', parser.add_argument('--xip', default=False, action='store_true', help="Enable XIP") +parser.add_argument('--eh', default=False, action='store_true', + help="Enable Exception Handling") + parser.add_argument('--multi-module', default=False, action='store_true', help="Enable Multi-thread") @@ -762,6 +765,13 @@ def test_assert(r, opts, mode, cmd, expected): if o.find(e) >= 0 or e.find(o) >= 0: return True + # wasm-exception thrown out of function call, not a trap + if mode=='wasmexception': + o = re.sub('^Exception: ', '', out) + e = re.sub('^Exception: ', '', expected) + if o.find(e) >= 0 or e.find(o) >= 0: + return True + ## 0x9:i32,-0x1:i32 -> ['0x9:i32', '-0x1:i32'] expected_list = re.split(',', expected) out_list = re.split(',', out) @@ -987,6 +997,42 @@ def test_assert_exhaustion(r,opts,form): expected = "Exception: %s\n" % m.group(3) test_assert(r, opts, "exhaustion", "%s %s" % (func, " ".join(args)), expected) + +# added to support WASM_ENABLE_EXCE_HANDLING +def test_assert_wasmexception(r,opts,form): + # params + + # ^ + # \(assert_exception\s+ + # \(invoke\s+"([^"]+)"\s+ + # (\(.*\))\s* + # () + # \)\s* + # \)\s* + # $ + m = re.search('^\(assert_exception\s+\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*\)\s*$', form) + if not m: + # no params + + # ^ + # \(assert_exception\s+ + # \(invoke\s+"([^"]+)"\s* + # () + # \)\s* + # \)\s* + # $ + m = re.search('^\(assert_exception\s+\(invoke\s+"([^"]+)"\s*()\)\s*\)\s*$', form) + if not m: + raise Exception("unparsed assert_exception: '%s'" % form) + func = m.group(1) # function name + if m.group(2) == '': # arguments + args = [] + else: + args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])] + + expected = "Exception: uncaught wasm exception\n" + test_assert(r, opts, "wasmexception", "%s %s" % (func, " ".join(args)), expected) + def do_invoke(r, opts, form): # params m = re.search('^\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*$', form) @@ -1025,6 +1071,8 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts): # default arguments if opts.gc: cmd = [opts.wast2wasm, "-u", "-d", wast_tempfile, "-o", wasm_tempfile] + elif opts.eh: + cmd = [opts.wast2wasm, "--enable-thread", "--no-check", "--enable-exceptions", "--enable-tail-call", wast_tempfile, "-o", wasm_tempfile ] else: cmd = [opts.wast2wasm, "--enable-thread", "--no-check", wast_tempfile, "-o", wasm_tempfile ] @@ -1236,6 +1284,8 @@ if __name__ == "__main__": test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r) elif re.match("^\(assert_exhaustion\\b.*", form): test_assert_exhaustion(r, opts, form) + elif re.match("^\(assert_exception\\b.*", form): + test_assert_wasmexception(r, opts, form) elif re.match("^\(assert_unlinkable\\b.*", form): test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r, False) elif re.match("^\(assert_malformed\\b.*", form): diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 663403233..7f41fc43d 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -24,6 +24,7 @@ function help() echo "-S enable SIMD feature" echo "-G enable GC feature" echo "-X enable XIP feature" + echo "-e enable exception handling" echo "-x test SGX" echo "-w enable WASI threads" echo "-b use the wabt binary release package instead of compiling from the source code" @@ -50,6 +51,7 @@ COLLECT_CODE_COVERAGE=0 ENABLE_SIMD=0 ENABLE_GC=0 ENABLE_XIP=0 +ENABLE_EH=0 ENABLE_DEBUG_VERSION=0 ENABLE_GC_HEAP_VERIFY=0 #unit test case arrary @@ -70,7 +72,7 @@ WASI_TESTSUITE_COMMIT="ee807fc551978490bf1c277059aabfa1e589a6c2" TARGET_LIST=("AARCH64" "AARCH64_VFP" "ARMV7" "ARMV7_VFP" "THUMBV7" "THUMBV7_VFP" \ "RISCV32" "RISCV32_ILP32F" "RISCV32_ILP32D" "RISCV64" "RISCV64_LP64F" "RISCV64_LP64D") -while getopts ":s:cabgvt:m:MCpSXxwPGQF:j:T:" opt +while getopts ":s:cabgvt:m:MCpSXexwPGQF:j:T:" opt do OPT_PARSED="TRUE" case $opt in @@ -145,6 +147,10 @@ do echo "enable XIP feature" ENABLE_XIP=1 ;; + e) + echo "enable exception handling feature" + ENABLE_EH=1 + ;; x) echo "test SGX" SGX_OPT="--sgx" @@ -425,6 +431,26 @@ function spec_test() git apply ../../spec-test-script/thread_proposal_fix_atomic_case.patch fi + if [ ${ENABLE_EH} == 1 ]; then + echo "checkout exception-handling test cases" + popd + if [ ! -d "exception-handling" ];then + echo "exception-handling not exist, clone it from github" + git clone -b master --single-branch https://github.com/WebAssembly/exception-handling + fi + pushd exception-handling + + # restore and clean everything + git reset --hard 51c721661b671bb7dc4b3a3acb9e079b49778d36 + + if [[ ${ENABLE_MULTI_MODULE} == 0 ]]; then + git apply ../../spec-test-script/exception_handling.patch + fi + + popd + echo $(pwd) + fi + # update GC cases if [[ ${ENABLE_GC} == 1 ]]; then echo "checkout spec for GC proposal" @@ -463,6 +489,10 @@ function spec_test() fi fi + if [[ 1 == ${ENABLE_EH} ]]; then + ARGS_FOR_SPEC_TEST+="-e " + fi + # sgx only enable in interp mode and aot mode if [[ ${SGX_OPT} == "--sgx" ]];then if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' || $1 == 'fast-jit' ]]; then @@ -827,6 +857,10 @@ function trigger() EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_WASI_THREADS=1" fi + if [[ ${ENABLE_EH} == 1 ]]; then + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_EXCE_HANDLING=1" + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_TAIL_CALL=1" + fi echo "SANITIZER IS" $WAMR_BUILD_SANITIZER if [[ "$WAMR_BUILD_SANITIZER" == "ubsan" ]]; then From 5a99866c01ac0f1a8998c730b376a1d59298a285 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Wed, 31 Jan 2024 11:23:23 +0800 Subject: [PATCH 06/15] fast-interp: Fix stack recovery for else branch (#3100) The issue was reported in #3090. --- core/iwasm/interpreter/wasm_loader.c | 25 +++++++++++++++-------- core/iwasm/interpreter/wasm_mini_loader.c | 25 +++++++++++++++-------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 11417fa19..6b26b5307 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -7980,20 +7980,29 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 /* Recover top param_count values of frame_offset stack */ if (block->available_param_num) { - uint32 size; - size = sizeof(int16) * block->available_param_num; - bh_memcpy_s(loader_ctx->frame_offset, size, - block->param_frame_offsets, size); - loader_ctx->frame_offset += (size / sizeof(int16)); + uint32 available_param_cell_num = 0; - /* recover dynamic offset */ + /* total cell num of available parameters */ for (i = 0; i < block->available_param_num; i++) { - if (block->param_frame_offsets[i] + uint32 cell_num = wasm_value_type_cell_num( + block->block_type.u.type->types[i]); + + /* recover dynamic offset */ + if (block->param_frame_offsets[available_param_cell_num] >= loader_ctx->dynamic_offset) { loader_ctx->dynamic_offset = - block->param_frame_offsets[i] + 1; + block->param_frame_offsets + [available_param_cell_num] + + cell_num; } + + available_param_cell_num += cell_num; } + + bh_memcpy_s( + loader_ctx->frame_offset, available_param_cell_num, + block->param_frame_offsets, available_param_cell_num); + loader_ctx->frame_offset += available_param_cell_num; } #endif diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 3abf4a96e..1e175dc4e 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -5819,20 +5819,29 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 /* Recover top param_count values of frame_offset stack */ if (block->available_param_num) { - uint32 size; - size = sizeof(int16) * block->available_param_num; - bh_memcpy_s(loader_ctx->frame_offset, size, - block->param_frame_offsets, size); - loader_ctx->frame_offset += (size / sizeof(int16)); + uint32 available_param_cell_num = 0; - /* recover dynamic offset */ + /* total cell num of available parameters */ for (i = 0; i < block->available_param_num; i++) { - if (block->param_frame_offsets[i] + uint32 cell_num = wasm_value_type_cell_num( + block->block_type.u.type->types[i]); + + /* recover dynamic offset */ + if (block->param_frame_offsets[available_param_cell_num] >= loader_ctx->dynamic_offset) { loader_ctx->dynamic_offset = - block->param_frame_offsets[i] + 1; + block->param_frame_offsets + [available_param_cell_num] + + cell_num; } + + available_param_cell_num += cell_num; } + + bh_memcpy_s( + loader_ctx->frame_offset, available_param_cell_num, + block->param_frame_offsets, available_param_cell_num); + loader_ctx->frame_offset += available_param_cell_num; } #endif From 51e25ef01ff42bcbd242a62ea35a1e32204c1e86 Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Wed, 31 Jan 2024 19:26:27 +0800 Subject: [PATCH 07/15] fast-interp: Fix frame_offset pop order (#3101) The issue was reported in #3062. --- core/iwasm/interpreter/wasm_loader.c | 6 +++--- core/iwasm/interpreter/wasm_mini_loader.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 6b26b5307..8f73e554e 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -8231,11 +8231,11 @@ re_scan: idx--) { ret_type = *(func->func_type->types + func->func_type->param_count + idx); - POP_TYPE(ret_type); #if WASM_ENABLE_FAST_INTERP != 0 /* emit the offset after return opcode */ POP_OFFSET_TYPE(ret_type); #endif + POP_TYPE(ret_type); } RESET_STACK(); @@ -8275,10 +8275,10 @@ re_scan: if (func_type->param_count > 0) { for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { - POP_TYPE(func_type->types[idx]); #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(func_type->types[idx]); #endif + POP_TYPE(func_type->types[idx]); } } @@ -8376,10 +8376,10 @@ re_scan: if (func_type->param_count > 0) { for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { - POP_TYPE(func_type->types[idx]); #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(func_type->types[idx]); #endif + POP_TYPE(func_type->types[idx]); } } diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 1e175dc4e..c617e0843 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -6028,11 +6028,11 @@ re_scan: idx--) { ret_type = *(func->func_type->types + func->func_type->param_count + idx); - POP_TYPE(ret_type); #if WASM_ENABLE_FAST_INTERP != 0 /* emit the offset after return opcode */ POP_OFFSET_TYPE(ret_type); #endif + POP_TYPE(ret_type); } RESET_STACK(); @@ -6071,10 +6071,10 @@ re_scan: if (func_type->param_count > 0) { for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { - POP_TYPE(func_type->types[idx]); #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(func_type->types[idx]); #endif + POP_TYPE(func_type->types[idx]); } } @@ -6152,10 +6152,10 @@ re_scan: if (func_type->param_count > 0) { for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { - POP_TYPE(func_type->types[idx]); #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(func_type->types[idx]); #endif + POP_TYPE(func_type->types[idx]); } } From dfd2a5b0b47fc32ca63be1b23a3aaa5e9ed71fe2 Mon Sep 17 00:00:00 2001 From: Enrico Loparco Date: Wed, 31 Jan 2024 13:06:22 +0100 Subject: [PATCH 08/15] Fix AOT compilation on MacOS (#3102) After #2995, AOT may stop working properly on arm MacOS: ```bash wasm-micro-runtime/core/iwasm/common/wasm_runtime_common.c, line 1270, WASM module load failed AOT module load failed: mmap memory failed ``` That's because, without `#include `, `TARGET_OS_OSX` is undefined, since it's definition is in that header file. --- core/shared/platform/common/posix/posix_memmap.c | 1 + core/shared/platform/common/posix/posix_thread.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/core/shared/platform/common/posix/posix_memmap.c b/core/shared/platform/common/posix/posix_memmap.c index aeb4530ab..2baf5aeb7 100644 --- a/core/shared/platform/common/posix/posix_memmap.c +++ b/core/shared/platform/common/posix/posix_memmap.c @@ -7,6 +7,7 @@ #if defined(__APPLE__) || defined(__MACH__) #include +#include #endif #ifndef BH_ENABLE_TRACE_MMAP diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index b5d8035df..1195d80eb 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -9,6 +9,10 @@ #include "platform_api_vmcore.h" #include "platform_api_extension.h" +#if defined(__APPLE__) || defined(__MACH__) +#include +#endif + typedef struct { thread_start_routine_t start; void *arg; From 43c4a5c434bc92619b3fd50b9b455bcd44edda38 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 31 Jan 2024 21:24:34 +0900 Subject: [PATCH 09/15] exception handling: Fix build error (#3104) --- core/iwasm/interpreter/wasm_runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 44ef3db03..003ceb1f5 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1061,7 +1061,7 @@ export_tags_instantiate(const WASMModule *module, if (export->kind == EXPORT_KIND_TAG) { export_tag->name = export->name; - bh_assert((uint32)(module_inst->export_tags)); + bh_assert(module_inst->e->tags); export_tag->tag = &module_inst->e->tags[export->index]; export_tag++; From 10e87d29666a5e797628ffa5275a0ca614ab3006 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 31 Jan 2024 22:54:19 +0900 Subject: [PATCH 10/15] EH: Don't call word_copy with zero size (#3105) --- core/iwasm/interpreter/wasm_interp_classic.c | 63 ++++++++++++-------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 10de23742..ff167b6e9 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1387,18 +1387,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, /* push exception_tag_index and * exception values for rethrow */ PUSH_I32(exception_tag_index); - word_copy(frame_sp, - frame_sp_old - - cell_num_to_copy, - cell_num_to_copy); - frame_sp += cell_num_to_copy; - /* push exception values for catch - */ - word_copy(frame_sp, - frame_sp_old - - cell_num_to_copy, - cell_num_to_copy); - frame_sp += cell_num_to_copy; + if (cell_num_to_copy > 0) { + word_copy( + frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + /* push exception values for + * catch + */ + word_copy( + frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + } /* advance to handler */ HANDLE_OP_END(); @@ -1427,11 +1432,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, frame_csp -= lookup_depth; /* push exception values for catch */ - word_copy(frame_sp, - frame_sp_old - - cell_num_to_copy, - cell_num_to_copy); - frame_sp += cell_num_to_copy; + if (cell_num_to_copy > 0) { + word_copy(frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + } /* tag_index is already stored in * exception_tag_index */ @@ -1452,11 +1459,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, /* push exception_tag_index and * exception values for rethrow */ PUSH_I32(exception_tag_index); - word_copy(frame_sp, - frame_sp_old - - cell_num_to_copy, - cell_num_to_copy); - frame_sp += cell_num_to_copy; + if (cell_num_to_copy > 0) { + word_copy(frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + } /* catch_all has no exception values */ /* advance to handler */ @@ -1483,10 +1492,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, * The values are copied to the CALLER FRAME * (prev_frame->sp) same behvior ad WASM_OP_RETURN */ - word_copy(prev_frame->sp, - frame_sp_old - cell_num_to_copy, - cell_num_to_copy); - prev_frame->sp += cell_num_to_copy; + if (cell_num_to_copy > 0) { + word_copy(prev_frame->sp, + frame_sp_old - cell_num_to_copy, + cell_num_to_copy); + prev_frame->sp += cell_num_to_copy; + } *((int32 *)(prev_frame->sp)) = exception_tag_index; prev_frame->sp++; From 3111a86cb341cee9eb0b3e7d8d1d43327846a627 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 1 Feb 2024 08:46:49 +0900 Subject: [PATCH 11/15] EH: Fix delegate parsing in wasm_loader_find_block_addr (#3106) --- core/iwasm/interpreter/wasm_loader.c | 1 + 1 file changed, 1 insertion(+) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 8f73e554e..520ca8091 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -4679,6 +4679,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, return true; } else { + skip_leb(p); /* the DELEGATE opcode ends the tryblock, */ block_nested_depth--; if (block_nested_depth From 40e51faca897e3952a0002ae4e1459f08d808cdc Mon Sep 17 00:00:00 2001 From: Xu Jun Date: Thu, 1 Feb 2024 11:55:29 +0800 Subject: [PATCH 12/15] fast-interp: Fix block with parameter in polymorphic stack issue (#3112) The issue was reported in https://github.com/bytecodealliance/wasm-micro-runtime/issues/3061. --- core/iwasm/interpreter/wasm_loader.c | 146 ++++++++++------------ core/iwasm/interpreter/wasm_mini_loader.c | 143 ++++++++++----------- 2 files changed, 130 insertions(+), 159 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 520ca8091..7b3eb365c 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -5280,9 +5280,8 @@ typedef struct BranchBlock { BranchBlockPatch *patch_list; /* This is used to save params frame_offset of of if block */ int16 *param_frame_offsets; - /* This is used to store available param num for if/else branch, so the else - * opcode can know how many parameters should be copied to the stack */ - uint32 available_param_num; + /* This is used to recover dynamic offset for else branch */ + uint16 start_dynamic_offset; #endif /* Indicate the operand stack is in polymorphic state. @@ -7219,18 +7218,15 @@ fail: * 1) POP original parameter out; * 2) Push and copy original values to dynamic space. * The copy instruction format: - * Part a: available param count + * Part a: param count * Part b: all param total cell num * Part c: each param's cell_num, src offset and dst offset * Part d: each param's src offset * Part e: each param's dst offset - * Note: if the stack is in polymorphic state, the actual copied parameters may - * be fewer than the defined number in block type */ static bool copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, - uint32 *p_available_param_count, char *error_buf, - uint32 error_buf_size) + char *error_buf, uint32 error_buf_size) { bool ret = false; int16 *frame_offset = NULL; @@ -7242,91 +7238,72 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, BlockType *block_type = &block->block_type; WASMType *wasm_type = block_type->u.type; uint32 param_count = block_type->u.type->param_count; - uint32 available_param_count = 0; int16 condition_offset = 0; bool disable_emit = false; int16 operand_offset = 0; - uint64 size; - if (is_if_block) - condition_offset = *loader_ctx->frame_offset; - - /* POP original parameter out */ - for (i = 0; i < param_count; i++) { - int32 available_stack_cell = - (int32)(loader_ctx->stack_cell_num - block->stack_cell_num); - - if (available_stack_cell <= 0 && block->is_stack_polymorphic) - break; - - POP_OFFSET_TYPE(wasm_type->types[param_count - i - 1]); - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); - } - available_param_count = i; - - size = - (uint64)available_param_count * (sizeof(*cells) + sizeof(*src_offsets)); + uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets)); + bh_assert(size > 0); /* For if block, we also need copy the condition operand offset. */ if (is_if_block) size += sizeof(*cells) + sizeof(*src_offsets); /* Allocate memory for the emit data */ - if ((size > 0) - && !(emit_data = loader_malloc(size, error_buf, error_buf_size))) + if (!(emit_data = loader_malloc(size, error_buf, error_buf_size))) return false; cells = emit_data; src_offsets = (int16 *)(cells + param_count); + if (is_if_block) + condition_offset = *loader_ctx->frame_offset; + + /* POP original parameter out */ + for (i = 0; i < param_count; i++) { + POP_OFFSET_TYPE(wasm_type->types[param_count - i - 1]); + wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); + } frame_offset = loader_ctx->frame_offset; /* Get each param's cell num and src offset */ - for (i = 0; i < available_param_count; i++) { + for (i = 0; i < param_count; i++) { cell = (uint8)wasm_value_type_cell_num(wasm_type->types[i]); cells[i] = cell; src_offsets[i] = *frame_offset; frame_offset += cell; } - /* emit copy instruction */ emit_label(EXT_OP_COPY_STACK_VALUES); /* Part a) */ - emit_uint32(loader_ctx, is_if_block ? available_param_count + 1 - : available_param_count); + emit_uint32(loader_ctx, is_if_block ? param_count + 1 : param_count); /* Part b) */ emit_uint32(loader_ctx, is_if_block ? wasm_type->param_cell_num + 1 : wasm_type->param_cell_num); /* Part c) */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) emit_byte(loader_ctx, cells[i]); if (is_if_block) emit_byte(loader_ctx, 1); /* Part d) */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) emit_operand(loader_ctx, src_offsets[i]); if (is_if_block) emit_operand(loader_ctx, condition_offset); /* Part e) */ /* Push to dynamic space. The push will emit the dst offset. */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) PUSH_OFFSET_TYPE(wasm_type->types[i]); if (is_if_block) PUSH_OFFSET_TYPE(VALUE_TYPE_I32); - if (p_available_param_count) { - *p_available_param_count = available_param_count; - } - ret = true; fail: /* Free the emit data */ - if (emit_data) { - wasm_runtime_free(emit_data); - } + wasm_runtime_free(emit_data); return ret; } @@ -7616,6 +7593,7 @@ re_scan: BranchBlock *cur_block = loader_ctx->frame_csp - 1; #if WASM_ENABLE_FAST_INTERP != 0 + uint32 cell_num; available_params = block_type.u.type->param_count; #endif for (i = 0; i < block_type.u.type->param_count; i++) { @@ -7633,6 +7611,13 @@ re_scan: POP_TYPE( wasm_type->types[wasm_type->param_count - i - 1]); +#if WASM_ENABLE_FAST_INTERP != 0 + /* decrease the frame_offset pointer accordingly to keep + * consistent with frame_ref stack */ + cell_num = wasm_value_type_cell_num( + wasm_type->types[wasm_type->param_count - i - 1]); + loader_ctx->frame_offset -= cell_num; +#endif } } PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK), @@ -7641,12 +7626,26 @@ re_scan: /* Pass parameters to block */ if (BLOCK_HAS_PARAM(block_type)) { for (i = 0; i < block_type.u.type->param_count; i++) { - PUSH_TYPE(block_type.u.type->types[i]); #if WASM_ENABLE_FAST_INTERP != 0 + uint32 cell_num = wasm_value_type_cell_num( + block_type.u.type->types[i]); if (i >= available_params) { - PUSH_OFFSET_TYPE(block_type.u.type->types[i]); + /* 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 */ + *loader_ctx->frame_offset++ = 0; + if (cell_num > 1) { + *loader_ctx->frame_offset++ = 0; + } + } + else { + loader_ctx->frame_offset += cell_num; } #endif + PUSH_TYPE(block_type.u.type->types[i]); } } @@ -7656,9 +7655,8 @@ re_scan: if (BLOCK_HAS_PARAM(block_type)) { /* Make sure params are in dynamic space */ - if (!copy_params_to_dynamic_space(loader_ctx, false, - NULL, error_buf, - error_buf_size)) + if (!copy_params_to_dynamic_space( + loader_ctx, false, error_buf, error_buf_size)) goto fail; } @@ -7691,17 +7689,21 @@ re_scan: * recover them before entering else branch. * */ - if (if_condition_available && BLOCK_HAS_PARAM(block_type)) { + if (BLOCK_HAS_PARAM(block_type)) { uint64 size; - /* skip the if condition operand offset */ - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); + /* In polymorphic state, there may be no if condition on + * the stack, so the offset may not emitted */ + if (if_condition_available) { + /* skip the if condition operand offset */ + wasm_loader_emit_backspace(loader_ctx, + sizeof(int16)); + } /* skip the if label */ skip_label(); /* Emit a copy instruction */ if (!copy_params_to_dynamic_space( - loader_ctx, true, &block->available_param_num, - error_buf, error_buf_size)) + loader_ctx, true, error_buf, error_buf_size)) goto fail; /* Emit the if instruction */ @@ -7722,9 +7724,8 @@ re_scan: - size / sizeof(int16), (uint32)size); } - else { - block->available_param_num = 0; - } + + block->start_dynamic_offset = loader_ctx->dynamic_offset; emit_empty_label_addr_and_frame_ip(PATCH_ELSE); emit_empty_label_addr_and_frame_ip(PATCH_END); @@ -7980,30 +7981,13 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 /* Recover top param_count values of frame_offset stack */ - if (block->available_param_num) { - uint32 available_param_cell_num = 0; - - /* total cell num of available parameters */ - for (i = 0; i < block->available_param_num; i++) { - uint32 cell_num = wasm_value_type_cell_num( - block->block_type.u.type->types[i]); - - /* recover dynamic offset */ - if (block->param_frame_offsets[available_param_cell_num] - >= loader_ctx->dynamic_offset) { - loader_ctx->dynamic_offset = - block->param_frame_offsets - [available_param_cell_num] - + cell_num; - } - - available_param_cell_num += cell_num; - } - - bh_memcpy_s( - loader_ctx->frame_offset, available_param_cell_num, - block->param_frame_offsets, available_param_cell_num); - loader_ctx->frame_offset += available_param_cell_num; + if (BLOCK_HAS_PARAM((block_type))) { + uint32 size; + size = sizeof(int16) * block_type.u.type->param_cell_num; + bh_memcpy_s(loader_ctx->frame_offset, size, + block->param_frame_offsets, size); + loader_ctx->frame_offset += (size / sizeof(int16)); + loader_ctx->dynamic_offset = block->start_dynamic_offset; } #endif diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index c617e0843..e283b10c9 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -3614,6 +3614,8 @@ typedef struct BranchBlock { /* This is used to store available param num for if/else branch, so the else * opcode can know how many parameters should be copied to the stack */ uint32 available_param_num; + /* This is used to recover dynamic offset for else branch */ + uint16 start_dynamic_offset; #endif /* Indicate the operand stack is in polymorphic state. @@ -5363,18 +5365,15 @@ fail: * 1) POP original parameter out; * 2) Push and copy original values to dynamic space. * The copy instruction format: - * Part a: available param count + * Part a: param count * Part b: all param total cell num * Part c: each param's cell_num, src offset and dst offset * Part d: each param's src offset * Part e: each param's dst offset - * Note: if the stack is in polymorphic state, the actual copied parameters may - * be fewer than the defined number in block type */ static bool copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, - uint32 *p_available_param_count, char *error_buf, - uint32 error_buf_size) + char *error_buf, uint32 error_buf_size) { bool ret = false; int16 *frame_offset = NULL; @@ -5386,91 +5385,72 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, BlockType *block_type = &block->block_type; WASMType *wasm_type = block_type->u.type; uint32 param_count = block_type->u.type->param_count; - uint32 available_param_count = 0; int16 condition_offset = 0; bool disable_emit = false; int16 operand_offset = 0; - uint64 size; - if (is_if_block) - condition_offset = *loader_ctx->frame_offset; - - /* POP original parameter out */ - for (i = 0; i < param_count; i++) { - int32 available_stack_cell = - (int32)(loader_ctx->stack_cell_num - block->stack_cell_num); - - if (available_stack_cell <= 0 && block->is_stack_polymorphic) - break; - - POP_OFFSET_TYPE(wasm_type->types[param_count - i - 1]); - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); - } - available_param_count = i; - - size = - (uint64)available_param_count * (sizeof(*cells) + sizeof(*src_offsets)); + uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets)); + bh_assert(size > 0); /* For if block, we also need copy the condition operand offset. */ if (is_if_block) size += sizeof(*cells) + sizeof(*src_offsets); /* Allocate memory for the emit data */ - if ((size > 0) - && !(emit_data = loader_malloc(size, error_buf, error_buf_size))) + if (!(emit_data = loader_malloc(size, error_buf, error_buf_size))) return false; cells = emit_data; src_offsets = (int16 *)(cells + param_count); + if (is_if_block) + condition_offset = *loader_ctx->frame_offset; + + /* POP original parameter out */ + for (i = 0; i < param_count; i++) { + POP_OFFSET_TYPE(wasm_type->types[param_count - i - 1]); + wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); + } frame_offset = loader_ctx->frame_offset; /* Get each param's cell num and src offset */ - for (i = 0; i < available_param_count; i++) { + for (i = 0; i < param_count; i++) { cell = (uint8)wasm_value_type_cell_num(wasm_type->types[i]); cells[i] = cell; src_offsets[i] = *frame_offset; frame_offset += cell; } - /* emit copy instruction */ emit_label(EXT_OP_COPY_STACK_VALUES); /* Part a) */ - emit_uint32(loader_ctx, is_if_block ? available_param_count + 1 - : available_param_count); + emit_uint32(loader_ctx, is_if_block ? param_count + 1 : param_count); /* Part b) */ emit_uint32(loader_ctx, is_if_block ? wasm_type->param_cell_num + 1 : wasm_type->param_cell_num); /* Part c) */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) emit_byte(loader_ctx, cells[i]); if (is_if_block) emit_byte(loader_ctx, 1); /* Part d) */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) emit_operand(loader_ctx, src_offsets[i]); if (is_if_block) emit_operand(loader_ctx, condition_offset); /* Part e) */ /* Push to dynamic space. The push will emit the dst offset. */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) PUSH_OFFSET_TYPE(wasm_type->types[i]); if (is_if_block) PUSH_OFFSET_TYPE(VALUE_TYPE_I32); - if (p_available_param_count) { - *p_available_param_count = available_param_count; - } - ret = true; fail: /* Free the emit data */ - if (emit_data) { - wasm_runtime_free(emit_data); - } + wasm_runtime_free(emit_data); return ret; } @@ -5672,6 +5652,7 @@ re_scan: BranchBlock *cur_block = loader_ctx->frame_csp - 1; #if WASM_ENABLE_FAST_INTERP != 0 + uint32 cell_num; available_params = block_type.u.type->param_count; #endif for (i = 0; i < block_type.u.type->param_count; i++) { @@ -5689,6 +5670,13 @@ re_scan: POP_TYPE( wasm_type->types[wasm_type->param_count - i - 1]); +#if WASM_ENABLE_FAST_INTERP != 0 + /* decrease the frame_offset pointer accordingly to keep + * consistent with frame_ref stack */ + cell_num = wasm_value_type_cell_num( + wasm_type->types[wasm_type->param_count - i - 1]); + loader_ctx->frame_offset -= cell_num; +#endif } } @@ -5698,12 +5686,26 @@ re_scan: /* Pass parameters to block */ if (BLOCK_HAS_PARAM(block_type)) { for (i = 0; i < block_type.u.type->param_count; i++) { - PUSH_TYPE(block_type.u.type->types[i]); #if WASM_ENABLE_FAST_INTERP != 0 + uint32 cell_num = wasm_value_type_cell_num( + block_type.u.type->types[i]); if (i >= available_params) { - PUSH_OFFSET_TYPE(block_type.u.type->types[i]); + /* 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 */ + *loader_ctx->frame_offset++ = 0; + if (cell_num > 1) { + *loader_ctx->frame_offset++ = 0; + } + } + else { + loader_ctx->frame_offset += cell_num; } #endif + PUSH_TYPE(block_type.u.type->types[i]); } } @@ -5712,9 +5714,8 @@ re_scan: skip_label(); if (BLOCK_HAS_PARAM(block_type)) { /* Make sure params are in dynamic space */ - if (!copy_params_to_dynamic_space(loader_ctx, false, - NULL, error_buf, - error_buf_size)) + if (!copy_params_to_dynamic_space( + loader_ctx, false, error_buf, error_buf_size)) goto fail; } if (opcode == WASM_OP_LOOP) { @@ -5741,17 +5742,21 @@ re_scan: * recover them before entering else branch. * */ - if (if_condition_available && BLOCK_HAS_PARAM(block_type)) { + if (BLOCK_HAS_PARAM(block_type)) { uint64 size; - /* skip the if condition operand offset */ - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); + /* In polymorphic state, there may be no if condition on + * the stack, so the offset may not emitted */ + if (if_condition_available) { + /* skip the if condition operand offset */ + wasm_loader_emit_backspace(loader_ctx, + sizeof(int16)); + } /* skip the if label */ skip_label(); /* Emit a copy instruction */ if (!copy_params_to_dynamic_space( - loader_ctx, true, &block->available_param_num, - error_buf, error_buf_size)) + loader_ctx, true, error_buf, error_buf_size)) goto fail; /* Emit the if instruction */ @@ -5772,9 +5777,8 @@ re_scan: - size / sizeof(int16), (uint32)size); } - else { - block->available_param_num = 0; - } + + block->start_dynamic_offset = loader_ctx->dynamic_offset; emit_empty_label_addr_and_frame_ip(PATCH_ELSE); emit_empty_label_addr_and_frame_ip(PATCH_END); @@ -5818,30 +5822,13 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 /* Recover top param_count values of frame_offset stack */ - if (block->available_param_num) { - uint32 available_param_cell_num = 0; - - /* total cell num of available parameters */ - for (i = 0; i < block->available_param_num; i++) { - uint32 cell_num = wasm_value_type_cell_num( - block->block_type.u.type->types[i]); - - /* recover dynamic offset */ - if (block->param_frame_offsets[available_param_cell_num] - >= loader_ctx->dynamic_offset) { - loader_ctx->dynamic_offset = - block->param_frame_offsets - [available_param_cell_num] - + cell_num; - } - - available_param_cell_num += cell_num; - } - - bh_memcpy_s( - loader_ctx->frame_offset, available_param_cell_num, - block->param_frame_offsets, available_param_cell_num); - loader_ctx->frame_offset += available_param_cell_num; + if (BLOCK_HAS_PARAM((block_type))) { + uint32 size; + size = sizeof(int16) * block_type.u.type->param_cell_num; + bh_memcpy_s(loader_ctx->frame_offset, size, + block->param_frame_offsets, size); + loader_ctx->frame_offset += (size / sizeof(int16)); + loader_ctx->dynamic_offset = block->start_dynamic_offset; } #endif From edc3643909ecb16990ac69c6bd6afafc1fb10242 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 1 Feb 2024 13:32:06 +0900 Subject: [PATCH 13/15] EH: Fix validation of delegate opcode (#3107) cf. https://github.com/bytecodealliance/wasm-micro-runtime/issues/1884#issuecomment-1914000294 --- core/iwasm/interpreter/wasm_loader.c | 42 +++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 7b3eb365c..3811f5a13 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -7128,6 +7128,40 @@ fail: return NULL; } +#if WASM_ENABLE_EXCE_HANDLING != 0 +static BranchBlock * +check_branch_block_for_delegate(WASMLoaderContext *loader_ctx, uint8 **p_buf, + uint8 *buf_end, char *error_buf, + uint32 error_buf_size) +{ + uint8 *p = *p_buf, *p_end = buf_end; + BranchBlock *frame_csp_tmp; + uint32 depth; + + read_leb_uint32(p, p_end, depth); + /* + * Note: "delegate 0" means the surrounding block, not the + * try-delegate block itself. + * + * Note: the caller hasn't popped the try-delegate frame yet. + */ + bh_assert(loader_ctx->csp_num > 0); + if (loader_ctx->csp_num - 1 <= depth) { + set_error_buf(error_buf, error_buf_size, "unknown delegate label"); + goto fail; + } + frame_csp_tmp = loader_ctx->frame_csp - depth - 2; +#if WASM_ENABLE_FAST_INTERP != 0 + emit_br_info(frame_csp_tmp); +#endif + + *p_buf = p; + return frame_csp_tmp; +fail: + return NULL; +} +#endif + static bool check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, char *error_buf, uint32 error_buf_size) @@ -7832,16 +7866,10 @@ re_scan: case WASM_OP_DELEGATE: { /* check target block is valid */ - if (!(frame_csp_tmp = check_branch_block( + if (!(frame_csp_tmp = check_branch_block_for_delegate( loader_ctx, &p, p_end, error_buf, error_buf_size))) goto fail; - /* valid types */ - if (LABEL_TYPE_TRY != frame_csp_tmp->label_type) { - snprintf(error_buf, error_buf_size, "unknown label"); - goto fail; - } - BranchBlock *cur_block = loader_ctx->frame_csp - 1; uint8 label_type = cur_block->label_type; From b3f728ceb36f9c72047a934436ef41699643ab99 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 1 Feb 2024 12:42:12 +0800 Subject: [PATCH 14/15] Update version number to 1.3.2 and update release notes (#3083) --- RELEASE_NOTES.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ core/version.h | 2 +- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e2cda8858..7570b8a7a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,78 @@ +## WAMR-1.3.2 + +### Breaking Changes + +### New Features +- Implement Exception Handling for classic interpreter (#3096) + - Use `cmake -DWAMR_BUILD_EXCE_HANDLING=1/0` option to enable/disable + the feature, and by default it is disabled + - It is still in highly experimental stage + +### Bug Fixes +- Fix build errors when initializing wasm_val_t values with macros (#3007) +- fix(wasm-c-api): Do not clone stack frames if there's no trap (#3008) +- classic-interp: Handle SIMD opcode when JIT is enabled (#3046) +- fast-interp: Fix dynamic offset error issue in else branch (#3058) +- wasm_cluster_destroy_spawned_exec_env: Avoid "invalid exec env" trap (#3068) +- thread-mgr: Fix locking problems around aux stack allocation (#3073) +- cosmopolitan: Update compiler and update platform_internal.h (#3079) +- wasi: Apply wasm_runtime_begin_blocking_op to poll as well (#3080) +- Fix memory/table segment checks in memory.init/table.init (#3081) +- perf profiling: Adjust the calculation of execution time (#3089) +- aot: Fix LLVMSetTailCallKind check (#3099) +- fast-interp: Fix stack recovery for else branch (#3100) +- fast-interp: Fix frame_offset pop order (#3101) +- Fix AOT compilation on MacOS (#3102) +- fast-interp: Fix block with parameter in polymorphic stack issue (#3112) + +### Enhancements +- Clear compilation warning and dead code (#3002) +- aot debug: Try to use a bit more appropriate file names (#3000) +- Increase default app thread stack size (#3010) +- Rename rwlock_init to avoid conflict (#3016) +- nuttx: Use larger alignment for os_mmap and comment why (#3017) +- Allow using mmap for shared memory if hw bound check is disabled (#3029) +- Don't redefine D_INO if already defined (#3036) +- Enhancements on wasm function execution time statistic (#2985) +- wamr-compiler: Fix non-x86{_64} host builds (#3037) +- Disable quick aot entry for interp and fast-jit (#3039) +- nuttx: Add option to enable quick aot entry (#3040) +- Set CONFIG_HAS_CAP_ENTER to support posix file api for freertos (#3041) +- Revert "Enable MAP_32BIT for macOS (#2992)" (#3032) +- Enable quick aot entry when hw bound check is disabled (#3044) +- Do not inherit WASM_SUSPEND_FLAG_BLOCKING from the parent thread (#3051) +- wasm_runtime_begin_blocking_op: A comment about usage expectation (#3056) +- Check arguments before calling bh_hash_map_find (#3055) +- Fix aot large model (--size-level=0) with LLVM 18 (#3057) +- Add flag to control Winsocket initialization (#3060) +- nuttx: If STACK_GUARD_SIZE is not set, leave it to config.h (#2927) +- Enhance setting write gs base with cmake variable (#3066) +- aot_reloc_x86_64.c: Suggest to try --size-level=0 as well (#3067) +- Fix some issues reported by CodeQL (#3064) +- Remove a lot of "unused parameter" warnings (#3075) +- Forward log and log level to custom bh_log callback (#3070) +- Fix inconsistent code style in aot_loader.c (#3082) +- freertos: Thread exit more common (#3094) +- Fix windows build error and compilation warnings (#3095) + +### Others +- Fix nightly-run CI failure (#3014) +- Build samples in debug mode (#3019) +- Remove deprecated tests in language-bindings python (#3018) +- Avoid unused thread_id warning and recompile multi-module sample (#3033) +- samples/terminate: Add a sample to demonstrate wasm_runtime_terminate (#3043) +- Bump NuttX version to 12.4.x in CI (#3047) +- perf_tune.md: Add refine the calling processes between host and wasm (#3065) +- build_wamr.md: Update the document (#3074) +- Fix download link for wasi-sdk (#3077) +- README.md: Fix typo tunning to tuning (#3078) +- Update outdated reference link in multi_module.md (#3092) +- Add comments to suppress warning from clang-tidy (#3088) +- CI: Update version of checkout to suppress warnings (#3093) +- test_wamr.sh: Allow using test script on different platforms (#3098) + +--- + ## WAMR-1.3.1 ### Breaking Changes diff --git a/core/version.h b/core/version.h index ec41ecd65..8f9f757a6 100644 --- a/core/version.h +++ b/core/version.h @@ -7,5 +7,5 @@ #define _WAMR_VERSION_H_ #define WAMR_VERSION_MAJOR 1 #define WAMR_VERSION_MINOR 3 -#define WAMR_VERSION_PATCH 1 +#define WAMR_VERSION_PATCH 2 #endif From 2eb60060d8eb6556ebbe411b22ee7b15ba4f7ec1 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 2 Feb 2024 12:03:58 +0800 Subject: [PATCH 15/15] Fix read and validation of misc/simd/atomic sub opcodes (#3115) The format of sub opcodes after misc, simd and atomic prefix is leb u32. The issue was found in #2921. --- RELEASE_NOTES.md | 1 + core/iwasm/compilation/aot_compiler.c | 21 +++++++++++---- core/iwasm/fast-jit/jit_frontend.c | 13 ++++++--- core/iwasm/interpreter/wasm_interp_classic.c | 8 +++++- core/iwasm/interpreter/wasm_loader.c | 28 +++++++++++++------- core/iwasm/interpreter/wasm_mini_loader.c | 26 +++++++++++++----- wamr-compiler/main.c | 6 +++-- 7 files changed, 75 insertions(+), 28 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7570b8a7a..3fcfaf4bc 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -24,6 +24,7 @@ - fast-interp: Fix frame_offset pop order (#3101) - Fix AOT compilation on MacOS (#3102) - fast-interp: Fix block with parameter in polymorphic stack issue (#3112) +- Fix read and validation of misc/simd/atomic sub opcodes (#3115) ### Enhancements - Clear compilation warning and dead code (#3002) diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 464ca61f3..fada0abc8 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -1050,7 +1050,9 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) uint32 opcode1; read_leb_uint32(frame_ip, frame_ip_end, opcode1); - opcode = (uint32)opcode1; + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; #if WASM_ENABLE_BULK_MEMORY != 0 if (WASM_OP_MEMORY_INIT <= opcode @@ -1211,10 +1213,13 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) case WASM_OP_ATOMIC_PREFIX: { uint8 bin_op, op_type; + uint32 opcode1; + + read_leb_uint32(frame_ip, frame_ip_end, opcode1); + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; - if (frame_ip < frame_ip_end) { - opcode = *frame_ip++; - } if (opcode != WASM_OP_ATOMIC_FENCE) { read_leb_uint32(frame_ip, frame_ip_end, align); read_leb_uint32(frame_ip, frame_ip_end, offset); @@ -1364,11 +1369,17 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) #if WASM_ENABLE_SIMD != 0 case WASM_OP_SIMD_PREFIX: { + uint32 opcode1; + if (!comp_ctx->enable_simd) { goto unsupport_simd; } - opcode = *frame_ip++; + read_leb_uint32(frame_ip, frame_ip_end, opcode1); + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; + /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h */ switch (opcode) { diff --git a/core/iwasm/fast-jit/jit_frontend.c b/core/iwasm/fast-jit/jit_frontend.c index e0b204ce9..e9d7a3ff3 100644 --- a/core/iwasm/fast-jit/jit_frontend.c +++ b/core/iwasm/fast-jit/jit_frontend.c @@ -2257,7 +2257,9 @@ jit_compile_func(JitCompContext *cc) uint32 opcode1; read_leb_uint32(frame_ip, frame_ip_end, opcode1); - opcode = (uint32)opcode1; + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; switch (opcode) { case WASM_OP_I32_TRUNC_SAT_S_F32: @@ -2396,10 +2398,13 @@ jit_compile_func(JitCompContext *cc) case WASM_OP_ATOMIC_PREFIX: { uint8 bin_op, op_type; + uint32 opcode1; + + read_leb_uint32(frame_ip, frame_ip_end, opcode1); + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; - if (frame_ip < frame_ip_end) { - opcode = *frame_ip++; - } if (opcode != WASM_OP_ATOMIC_FENCE) { read_leb_uint32(frame_ip, frame_ip_end, align); read_leb_uint32(frame_ip, frame_ip_end, offset); diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index ff167b6e9..e4da90b9c 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -3511,6 +3511,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 opcode1; read_leb_uint32(frame_ip, frame_ip_end, opcode1); + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ opcode = (uint8)opcode1; switch (opcode) { @@ -3843,8 +3845,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_ATOMIC_PREFIX) { uint32 offset = 0, align, addr; + uint32 opcode1; - opcode = *frame_ip++; + read_leb_uint32(frame_ip, frame_ip_end, opcode1); + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; if (opcode != WASM_OP_ATOMIC_FENCE) { read_leb_uint32(frame_ip, frame_ip_end, align); diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 3811f5a13..8ca3796bc 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -5092,9 +5092,13 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) case WASM_OP_SIMD_PREFIX: { - /* TODO: shall we ceate a table to be friendly to branch - * prediction */ - opcode = read_uint8(p); + uint32 opcode1; + + read_leb_uint32(p, p_end, opcode1); + /* opcode1 was checked in wasm_loader_prepare_bytecode and + is no larger than UINT8_MAX */ + opcode = (uint8)opcode1; + /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h */ switch (opcode) { @@ -5184,8 +5188,14 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if WASM_ENABLE_SHARED_MEMORY != 0 case WASM_OP_ATOMIC_PREFIX: { - /* atomic_op (1 u8) + memarg (2 u32_leb) */ - opcode = read_uint8(p); + uint32 opcode1; + + /* atomic_op (u32_leb) + memarg (2 u32_leb) */ + read_leb_uint32(p, p_end, opcode1); + /* opcode1 was checked in wasm_loader_prepare_bytecode and + is no larger than UINT8_MAX */ + opcode = (uint8)opcode1; + if (opcode != WASM_OP_ATOMIC_FENCE) { skip_leb_uint32(p, p_end); /* align */ skip_leb_uint32(p, p_end); /* offset */ @@ -9836,8 +9846,8 @@ re_scan: { uint32 opcode1; - CHECK_BUF(p, p_end, 1); - opcode1 = read_uint8(p); + read_leb_uint32(p, p_end, opcode1); + /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h */ switch (opcode1) { @@ -10498,8 +10508,8 @@ re_scan: { uint32 opcode1; - CHECK_BUF(p, p_end, 1); - opcode1 = read_uint8(p); + read_leb_uint32(p, p_end, opcode1); + #if WASM_ENABLE_FAST_INTERP != 0 emit_byte(loader_ctx, opcode1); #endif diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index e283b10c9..ba2c37fc7 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -3492,8 +3492,11 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, uint32 opcode1; read_leb_uint32(p, p_end, opcode1); + /* opcode1 was checked in wasm_loader_prepare_bytecode and + is no larger than UINT8_MAX */ + opcode = (uint8)opcode1; - switch (opcode1) { + switch (opcode) { case WASM_OP_I32_TRUNC_SAT_S_F32: case WASM_OP_I32_TRUNC_SAT_U_F32: case WASM_OP_I32_TRUNC_SAT_S_F64: @@ -3549,8 +3552,14 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if WASM_ENABLE_SHARED_MEMORY != 0 case WASM_OP_ATOMIC_PREFIX: { - /* atomic_op (1 u8) + memarg (2 u32_leb) */ - opcode = read_uint8(p); + uint32 opcode1; + + /* atomic_op (u32_leb) + memarg (2 u32_leb) */ + read_leb_uint32(p, p_end, opcode1); + /* opcode1 was checked in wasm_loader_prepare_bytecode and + is no larger than UINT8_MAX */ + opcode = (uint8)opcode1; + if (opcode != WASM_OP_ATOMIC_FENCE) { skip_leb_uint32(p, p_end); /* align */ skip_leb_uint32(p, p_end); /* offset */ @@ -7464,11 +7473,14 @@ re_scan: #if WASM_ENABLE_SHARED_MEMORY != 0 case WASM_OP_ATOMIC_PREFIX: { - opcode = read_uint8(p); + uint32 opcode1; + + read_leb_uint32(p, p_end, opcode1); + #if WASM_ENABLE_FAST_INTERP != 0 - emit_byte(loader_ctx, opcode); + emit_byte(loader_ctx, opcode1); #endif - if (opcode != WASM_OP_ATOMIC_FENCE) { + if (opcode1 != WASM_OP_ATOMIC_FENCE) { CHECK_MEMORY(); read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, mem_offset); /* offset */ @@ -7479,7 +7491,7 @@ re_scan: #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 func->has_memory_operations = true; #endif - switch (opcode) { + switch (opcode1) { case WASM_OP_ATOMIC_NOTIFY: POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); break; diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index f2e5efafd..17c19143c 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -627,8 +627,10 @@ main(int argc, char *argv[]) goto fail1; } - if (get_package_type(wasm_file, wasm_file_size) != Wasm_Module_Bytecode) { - printf("Invalid file type: expected wasm file but got other\n"); + if (wasm_file_size >= 4 /* length of MAGIC NUMBER */ + && get_package_type(wasm_file, wasm_file_size) + != Wasm_Module_Bytecode) { + printf("Invalid wasm file: magic header not detected\n"); goto fail2; }