diff --git a/.clang-format b/.clang-format index f0ecd63bf9..0d945dd697 100644 --- a/.clang-format +++ b/.clang-format @@ -1,5 +1,6 @@ +# using [clang-formt-12 options](https://releases.llvm.org/12.0.0/tools/clang/docs/ClangFormatStyleOptions.html) RawStringFormats: - - Language: Cpp + - Language: Cpp Delimiters: - c - C @@ -13,35 +14,23 @@ RawStringFormats: - h - hpp CanonicalDelimiter: '' - BasedOnStyle: google - - Language: TextProto - Delimiters: - - pb - - PB - - proto - - PROTO - EnclosingFunctions: - - EqualsProto - - EquivToProto - - PARSE_PARTIAL_TEXT_PROTO - - PARSE_TEST_PROTO - - PARSE_TEXT_PROTO - - ParseTextOrDie - - ParseTextProtoOrDie - CanonicalDelimiter: '' - BasedOnStyle: google + BasedOnStyle: Mozilla Language: Cpp BasedOnStyle: Mozilla +# 6.1 IndentWidth: 4 +ContinuationIndentWidth: 4 +# 6.2 +TabWidth: 4 +UseTab: Never +# 6.3 +ColumnLimit: 80 +# 6.9 AlignAfterOpenBracket: Align -AllowAllArgumentsOnNextLine: false -AlignConsecutiveMacros: true -AllowShortBlocksOnASingleLine: true -AlwaysBreakAfterReturnType: All BinPackArguments: true -BinPackParameters: false -BreakBeforeBinaryOperators: NonAssignment +BinPackParameters: true +# 6.10 BreakBeforeBraces: Custom BraceWrapping: AfterCaseLabel: true @@ -60,104 +49,13 @@ BraceWrapping: SplitEmptyFunction: true SplitEmptyRecord: false SplitEmptyNamespace: true -ColumnLimit: 79 -ContinuationIndentWidth: 2 -DerivePointerAlignment: false -IncludeBlocks: Regroup -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 1 - - Regex: ".*" - Priority: 3 -IndentPPDirectives: None -KeepEmptyLinesAtTheStartOfBlocks: false -NamespaceIndentation: None -PointerAlignment: Right -ReflowComments: false -SortIncludes: false -Standard: Auto -StatementMacros: - - Q_UNUSED - - QT_REQUIRE_VERSION - -# AccessModifierOffset: -2 -# AlignConsecutiveAssignments: false -# AlignConsecutiveDeclarations: false -# AlignEscapedNewlines: Right -# AlignOperands: true -# AlignTrailingComments: true -# AllowAllConstructorInitializersOnNextLine: true -# AllowAllParametersOfDeclarationOnNextLine: false -# AllowShortCaseLabelsOnASingleLine: false -# AllowShortFunctionsOnASingleLine: Inline -# AllowShortLambdasOnASingleLine: All -# AllowShortIfStatementsOnASingleLine: Never -# AllowShortLoopsOnASingleLine: false -# AlwaysBreakAfterDefinitionReturnType: TopLevel -# AlwaysBreakAfterReturnType: TopLevel -# AlwaysBreakBeforeMultilineStrings: false -# AlwaysBreakTemplateDeclarations: Yes -# BreakBeforeInheritanceComma: false -# BreakInheritanceList: BeforeComma -# BreakBeforeTernaryOperators: true -# BreakConstructorInitializersBeforeComma: false -# BreakConstructorInitializers: BeforeComma -# BreakAfterJavaFieldAnnotations: false -# BreakStringLiterals: true -# CommentPragmas: '^ IWYU pragma:' -# CompactNamespaces: false -# ConstructorInitializerAllOnOneLineOrOnePerLine: false -# ConstructorInitializerIndentWidth: 2 -# Cpp11BracedListStyle: false -# DisableFormat: false -# ExperimentalAutoDetectBinPacking: false -# FixNamespaceComments: false -# ForEachMacros: -# - foreach -# - Q_FOREACH -# - BOOST_FOREACH -# IncludeIsMainRegex: '(Test)?$' -# IndentCaseLabels: true -# IndentWrappedFunctionNames: false -# JavaScriptQuotes: Leave -# JavaScriptWrapImports: true -# KeepEmptyLinesAtTheStartOfBlocks: true -# MacroBlockBegin: '' -# MacroBlockEnd: '' -# MaxEmptyLinesToKeep: 1 -# ObjCBinPackProtocolList: Auto -# ObjCBlockIndentWidth: 2 -# ObjCSpaceAfterProperty: true -# ObjCSpaceBeforeProtocolList: false -# PenaltyBreakAssignment: 2 -# PenaltyBreakBeforeFirstCallParameter: 19 -# PenaltyBreakComment: 300 -# PenaltyBreakFirstLessLess: 120 -# PenaltyBreakString: 1000 -# PenaltyBreakTemplateDeclaration: 10 -# PenaltyExcessCharacter: 1000000 -# PenaltyReturnTypeOnItsOwnLine: 200 -# SortIncludes: true -# SortUsingDeclarations: true -# SpaceAfterCStyleCast: false -# SpaceAfterLogicalNot: false -# SpaceAfterTemplateKeyword: false -# SpaceBeforeAssignmentOperators: true -# SpaceBeforeCpp11BracedList: false -# SpaceBeforeCtorInitializerColon: true -# SpaceBeforeInheritanceColon: true -# SpaceBeforeParens: ControlStatements -# SpaceBeforeRangeBasedForLoopColon: true -# SpaceInEmptyParentheses: false -# SpacesBeforeTrailingComments: 1 -# SpacesInAngles: false -# SpacesInContainerLiterals: true -# SpacesInCStyleCastParentheses: false -# SpacesInParentheses: false -# SpacesInSquareBrackets: false -# TabWidth: 4 -# UseTab: Never -# ... +# 6.27 +BreakBeforeBinaryOperators: NonAssignment +# additional +AlignEscapedNewlines: Left +AllowAllParametersOfDeclarationOnNextLine: false +AllowAllArgumentsOnNextLine: false +PointerAlignment: Right +SpaceAroundPointerQualifiers: After +SortIncludes: false diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000000..67cd167fc4 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,16 @@ +# refer to https://clang.llvm.org/extra/clang-tidy/checks/list.html + +Checks: '-*, readability-identifier-naming, clang-analyzer-core.*,' +WarningsAsErrors: '-*' +HeaderFilterRegex: '' +FormatStyle: file +InheritParentConfig: false +AnalyzeTemporaryDtors: false +User: wamr +CheckOptions: + - key: readability-identifier-naming.VariableCase + value: lower_case + - key: readability-identifier-naming.ParameterCase + value: lower_case + - key: readability-identifier-naming.MacroDefinitionCase + value: UPPER_CASE diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml deleted file mode 100644 index 9be92ad0a8..0000000000 --- a/.github/workflows/android.yml +++ /dev/null @@ -1,91 +0,0 @@ -# This is a basic workflow to help you get started with Actions - -name: android - -# Controls when the action will run. -on: - # Triggers the workflow on push or pull request events but only for the master branch - push: - branches: [ main ] - pull_request: - branches: [ main ] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on - runs-on: ubuntu-latest - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - - - name: Build iwasm [default] - run: | - cd product-mini/platforms/android - mkdir build && cd build - cmake .. - make - cd .. && rm -rf build - - name: Build iwasm [Classic interp] - run: | - cd product-mini/platforms/android - mkdir build && cd build - cmake .. -DWAMR_BUILD_FAST_INTERP=0 - make - cd .. && rm -rf build - - name: Build iwasm [Multi module] - run: | - cd product-mini/platforms/android - mkdir build && cd build - cmake .. -DWAMR_BUILD_MULTI_MODULE=1 - make - cd .. && rm -rf build - - name: Build iwasm [lib-pthread] - run: | - cd product-mini/platforms/android - mkdir build && cd build - cmake .. -DWAMR_BUILD_LIB_PTHREAD=1 - make - cd .. && rm -rf build - - name: Build iwasm [aot only] - run: | - cd product-mini/platforms/android - mkdir build && cd build - cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0 - make - cd .. && rm -rf build - - name: Build iwasm [interp only] - run: | - cd product-mini/platforms/android - mkdir build && cd build - cmake .. -DWAMR_BUILD_AOT=0 - make - cd .. && rm -rf build - - name: Build iwasm [memory profiling] - run: | - cd product-mini/platforms/android - mkdir build && cd build - cmake .. -DWAMR_BUILD_MEMORY_PROFILING=1 - make - cd .. && rm -rf build - - name: Build iwasm [tail call] - run: | - cd product-mini/platforms/android - mkdir build && cd build - cmake .. -DWAMR_BUILD_TAIL_CALL=1 - make - cd .. && rm -rf build - - name: Build iwasm [custom name section] - run: | - cd product-mini/platforms/android - mkdir build && cd build - cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1 - make - cd .. && rm -rf build diff --git a/.github/workflows/compilation_on_android_ubuntu_macos.yml b/.github/workflows/compilation_on_android_ubuntu_macos.yml new file mode 100644 index 0000000000..d76b810ccc --- /dev/null +++ b/.github/workflows/compilation_on_android_ubuntu_macos.yml @@ -0,0 +1,521 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +name: compilation on android, ubuntu-18.04, ubuntu-20.04, macos-latest + +on: + # will be triggered on PR events + pull_request: + paths-ignore: + - "assembly-script/**" + - "ci/**" + - "doc/**" + - "test-tools/**" + # will be triggered on push events + push: + paths-ignore: + - "assembly-script/**" + - "ci/**" + - "doc/**" + - "test-tools/**" + # allow to be triggered manually + workflow_dispatch: + +# Cancel any in-flight jobs for the same PR/branch so there's only one active +# at a time +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + AOT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" + CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" + FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" + JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0" + LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1" + LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex" + +jobs: + # Cancel any in-flight jobs for the same PR/branch so there's only one active + # at a time + cancel_previous: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + steps: + - name: Cancel Workflow Action + uses: styfle/cancel-workflow-action@0.6.0 + with: + access_token: ${{ github.token }} + + # set different traffic lights based on the current repo and the running OS. + # according to light colors, the workflow will run different jobs + check_repo: + needs: cancel_previous + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + outputs: + traffic_light_on_ubuntu_1804: ${{ steps.do_check_on_ubuntu_1804.outputs.light }} + traffic_light_on_ubuntu_2004: ${{ steps.do_check_on_ubuntu_2004.outputs.light }} + traffic_light_on_macos_latest: ${{ steps.do_check_on_macos_latest.outputs.light }} + steps: + - name: do_check_on_ubuntu_1804 + id: do_check_on_ubuntu_1804 + if: ${{ matrix.os == 'ubuntu-18.04' }} + run: | + if [[ ${{ github.repository }} == */wasm-micro-runtime ]]; then + echo "::set-output name=light::green" + else + echo "::set-output name=light::red" + fi + + - name: do_check_on_ubuntu_2004 + id: do_check_on_ubuntu_2004 + if: ${{ matrix.os == 'ubuntu-20.04' }} + run: | + if [[ ${{ github.repository }} == */wasm-micro-runtime ]]; then + echo "::set-output name=light::green" + else + echo "::set-output name=light::green" + fi + + - name: do_check_on_macos_latest + id: do_check_on_macos_latest + if: ${{ matrix.os == 'macos-latest' }} + run: | + if [[ ${{ github.repository }} == */wasm-micro-runtime ]]; then + echo "::set-output name=light::green" + else + echo "::set-output name=light::red" + fi + + build_llvm_libraries: + needs: check_repo + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + include: + - os: ubuntu-18.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }} + - os: ubuntu-20.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }} + - os: macos-latest + light: ${{ needs.check_repo.outputs.traffic_light_on_macos_latest }} + steps: + - name: light status + run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}" + + - name: checkout + if: ${{ matrix.light == 'green' }} + uses: actions/checkout@v2 + + - name: Cache LLVM libraries + id: cache_llvm + if: ${{ matrix.light == 'green' }} + uses: actions/cache@v2 + with: + path: ./core/deps/llvm/build/LLVM-13.0.0.tar.gz + key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + restore-keys: ${{ matrix.os }}-${{env.LLVM_CACHE_SUFFIX }} + + - name: Build llvm and clang from source on ubuntu + id: build_llvm_ubuntu + if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' && matrix.os != 'macos-latest' }} + run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly --project clang lldb + working-directory: build-scripts + + - name: Build llvm and clang from source on macos + id: build_llvm_macos + if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' && matrix.os == 'macos-latest' }} + run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly + working-directory: build-scripts + + - name: package LLVM + if: ${{ matrix.light == 'green' && (steps.build_llvm_ubuntu.conclusion == 'success' || steps.build_llvm_macos.conclusion == 'success')}} + run: mv LLVM-13.0.0-*.tar.gz LLVM-13.0.0.tar.gz + working-directory: core/deps/llvm/build/ + + build_wamrc: + needs: [build_llvm_libraries, check_repo] + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + include: + - os: ubuntu-18.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }} + - os: ubuntu-20.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }} + - os: macos-latest + light: ${{ needs.check_repo.outputs.traffic_light_on_macos_latest }} + steps: + - name: light status + run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}" + + - name: checkout + if: ${{ matrix.light == 'green' }} + uses: actions/checkout@v2 + + - name: Get LLVM libraries + id: cache_llvm + if: ${{ matrix.light == 'green' }} + uses: actions/cache@v2 + with: + path: ./core/deps/llvm/build/LLVM-13.0.0.tar.gz + key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + restore-keys: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + + - name: Quit if cache miss + if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }} + run: echo "::error::can not get prebuilt llvm libraries" && exit 1 + + - name: Extract the LLVM package + if: ${{ matrix.light == 'green' }} + run: tar xf LLVM-13.0.0.tar.gz --strip-components=1 + working-directory: ./core/deps/llvm/build + + - name: Build wamrc + if: ${{ matrix.light == 'green' }} + run: | + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + working-directory: wamr-compiler + + build_iwasm: + needs: [build_llvm_libraries, check_repo] + runs-on: ${{ matrix.os }} + strategy: + matrix: + make_options_run_mode: [ + # Running mode + $CLASSIC_INTERP_BUILD_OPTIONS, + $FAST_INTERP_BUILD_OPTIONS, + $JIT_BUILD_OPTIONS, + $LAZY_JIT_BUILD_OPTIONS, + $AOT_BUILD_OPTIONS, + ] + make_options_feature: [ + # Features + "-DWAMR_BUILD_CUSTOM_NAME_SECTION=1", + "-DWAMR_BUILD_DEBUG_AOT=1", + "-DWAMR_BUILD_DEBUG_INTERP=1", + "-DWAMR_BUILD_DUMP_CALL_STACK=1", + "-DWAMR_BUILD_LIB_PTHREAD=1", + "-DWAMR_BUILD_MINI_LOADER=1", + "-DWAMR_BUILD_MEMORY_PROFILING=1", + "-DWAMR_BUILD_MULTI_MODULE=1", + "-DWAMR_BUILD_PERF_PROFILING=1", + "-DWAMR_BUILD_REF_TYPES=1", + "-DWAMR_BUILD_SIMD=1", + "-DWAMR_BUILD_TAIL_CALL=1", + "-DWAMR_DISABLE_HW_BOUND_CHECK=1", + ] + os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + platform: [android, linux, darwin] + exclude: + # uncompatiable os and platform + # ubuntu can not go with darwin + - os: ubuntu-18.04 + platform: darwin + - os: ubuntu-20.04 + platform: darwin + # macos can not go with android, linux + - os: macos-latest + platform: android + - os: macos-latest + platform: linux + # uncompatiable feature and platform + - os: macos-latest + make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" + - os: macos-latest + make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1" + # uncompatiable mode and feature + # MULTI_MODULE only on INTERP mode + - make_options_run_mode: $JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" + - make_options_run_mode: $AOT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" + - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" + # SIMD only on JIT/AOT mode + - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_SIMD=1" + - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_SIMD=1" + # DEBUG_INTERP only on CLASSIC INTERP mode + - make_options_run_mode: $AOT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1" + - make_options_run_mode: $JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1" + - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1" + - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1" + # DEBUG_AOT only on JIT/AOT mode + - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" + - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" + # TODO: DEBUG_AOT on JIT + - make_options_run_mode: $JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" + - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" + # MINI_LOADER only on INTERP mode + - make_options_run_mode: $AOT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" + - make_options_run_mode: $JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" + - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" + include: + - os: ubuntu-18.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }} + - os: ubuntu-20.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }} + - os: macos-latest + light: ${{ needs.check_repo.outputs.traffic_light_on_macos_latest }} + steps: + - name: light status + run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}" + + - name: checkout + if: ${{ matrix.light == 'green' }} + uses: actions/checkout@v2 + + - name: Get LLVM libraries + id: cache_llvm + if: ${{ matrix.light == 'green' }} + uses: actions/cache@v2 + with: + path: ./core/deps/llvm/build/LLVM-13.0.0.tar.gz + key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + restore-keys: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + + - name: Quit if cache miss + if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }} + run: echo "::error::can not get prebuilt llvm libraries" && exit 1 + + - name: Extract the LLVM package + if: ${{ matrix.light == 'green' }} + run: tar xf LLVM-13.0.0.tar.gz --strip-components=1 + working-directory: ./core/deps/llvm/build + + - name: Build iwasm + if: ${{ matrix.light == 'green' }} + run: | + mkdir build && cd build + cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} + cmake --build . --config Release --parallel 4 + working-directory: product-mini/platforms/${{ matrix.platform }} + + build_samples_wasm_c_api: + needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo] + runs-on: ${{ matrix.os }} + strategy: + matrix: + make_options: [ + # Running mode + $CLASSIC_INTERP_BUILD_OPTIONS, + $FAST_INTERP_BUILD_OPTIONS, + $JIT_BUILD_OPTIONS, + $LAZY_JIT_BUILD_OPTIONS, + $AOT_BUILD_OPTIONS, + ] + os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + include: + - os: ubuntu-18.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }} + wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz + wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz + - os: ubuntu-20.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }} + wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz + wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz + - os: macos-latest + light: ${{ needs.check_repo.outputs.traffic_light_on_macos_latest }} + wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz + wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz + exclude: + # TODO: a .aot compatiable problem + - os: macos-latest + make_options: $JIT_BUILD_OPTIONS + - os: macos-latest + make_options: $AOT_BUILD_OPTIONS + - os: macos-latest + make_options: $LAZY_JIT_BUILD_OPTIONS + steps: + - name: light status + run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}" + + - name: checkout + if: ${{ matrix.light == 'green' }} + uses: actions/checkout@v2 + + - name: Get LLVM libraries + id: cache_llvm + if: ${{ matrix.light == 'green' }} + uses: actions/cache@v2 + with: + path: ./core/deps/llvm/build/LLVM-13.0.0.tar.gz + key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + restore-keys: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + + - name: Quit if cache miss + if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }} + run: echo "::error::can not get prebuilt llvm libraries" && exit 1 + + - name: Extract the LLVM package + if: ${{ matrix.light == 'green' }} + run: tar xf LLVM-13.0.0.tar.gz --strip-components=1 + working-directory: ./core/deps/llvm/build + + - name: download and install wabt + if: ${{ matrix.light == 'green' }} + run: | + cd /opt + sudo wget ${{ matrix.wabt_release }} + sudo tar -xzf wabt-1.0.24-*.tar.gz + sudo mv wabt-1.0.24 wabt + + - name: Build wamrc + if: ${{ matrix.light == 'green' }} + run: | + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + working-directory: wamr-compiler + + - name: Build Sample [wasm-c-api] + if: ${{ matrix.light == 'green' }} + run: | + mkdir build && cd build + cmake .. ${{ matrix.make_options }} + cmake --build . --config Release --parallel 4 + ./callback + ./callback_chain + ./empty_imports + ./global + ./hello + ./hostref + ./memory + ./reflect + ./table + ./trap + working-directory: samples/wasm-c-api + + build_samples_others: + needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo] + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-18.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }} + wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz + wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz + - os: ubuntu-20.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }} + wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz + wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz + - os: macos-latest + light: ${{ needs.check_repo.outputs.traffic_light_on_macos_latest }} + wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz + wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz + steps: + - name: light status + run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}" + + - name: checkout + if: ${{ matrix.light == 'green' }} + uses: actions/checkout@v2 + + - name: Get LLVM libraries + id: cache_llvm + if: ${{ matrix.light == 'green' }} + uses: actions/cache@v2 + with: + path: ./core/deps/llvm/build/LLVM-13.0.0.tar.gz + key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + restore-keys: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + + - name: Quit if cache miss + if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }} + run: echo "::error::can not get prebuilt llvm libraries" && exit 1 + + - name: Extract the LLVM package + if: ${{ matrix.light == 'green' }} + run: tar xf LLVM-13.0.0.tar.gz --strip-components=1 + working-directory: ./core/deps/llvm/build + + - name: download and install wasi-sdk + if: ${{ matrix.light == 'green' }} + run: | + cd /opt + sudo wget ${{ matrix.wasi_sdk_release }} + sudo tar -xzf wasi-sdk-12.0-*.tar.gz + sudo mv wasi-sdk-12.0 wasi-sdk + + - name: download and install wabt + if: ${{ matrix.light == 'green' }} + run: | + cd /opt + sudo wget ${{ matrix.wabt_release }} + sudo tar -xzf wabt-1.0.24-*.tar.gz + sudo mv wabt-1.0.24 wabt + + - name: Build wamrc + if: ${{ matrix.light == 'green' }} + run: | + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + working-directory: wamr-compiler + + - name: Build Sample [basic] + if: ${{ matrix.light == 'green' }} + run: | + cd samples/basic + ./build.sh + ./run.sh + + - name: Build Sample [multi-thread] + if: ${{ matrix.light == 'green' }} + run: | + cd samples/multi-thread + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + ./iwasm wasm-apps/test.wasm + + - name: Build Sample [multi-module] + if: ${{ matrix.light == 'green' }} + run: | + cd samples/multi-module + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + ./multi_module + + - name: Build Sample [spawn-thread] + if: ${{ matrix.light == 'green' }} + run: | + cd samples/spawn-thread + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + ./spawn_thread + + - name: Build Sample [ref-types] + if: ${{ matrix.light == 'green' }} + run: | + cd samples/ref-types + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + ./hello diff --git a/.github/workflows/compilation_on_windows.yml b/.github/workflows/compilation_on_windows.yml new file mode 100644 index 0000000000..5b875ac8bf --- /dev/null +++ b/.github/workflows/compilation_on_windows.yml @@ -0,0 +1,106 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +name: compilation on windows-latest + +on: + # will be triggered on PR events + pull_request: + paths-ignore: + - "assembly-script/**" + - "ci/**" + - "doc/**" + - "test-tools/**" + # will be triggered on push events + push: + paths-ignore: + - "assembly-script/**" + - "ci/**" + - "doc/**" + - "test-tools/**" + # allow to be triggered manually + workflow_dispatch: + +# Cancel any in-flight jobs for the same PR/branch so there's only one active +# at a time +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + # Cancel any in-flight jobs for the same PR/branch so there's only one active + # at a time + cancel_previous: + runs-on: windows-latest + steps: + - name: Cancel Workflow Action + uses: styfle/cancel-workflow-action@0.6.0 + with: + access_token: ${{ github.token }} + + build: + needs: cancel_previous + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + + - name: clone uvwasi library + run: | + cd core/deps + git clone https://github.com/nodejs/uvwasi.git + - name: Build iwasm [default] + run: | + cd product-mini/platforms/windows + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + cd .. && rm -force -r build + - name: Build iwasm [aot only] + run: | + cd product-mini/platforms/windows + mkdir build && cd build + cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0 + cmake --build . --config Release --parallel 4 + cd .. && rm -force -r build + - name: Build iwasm [interp only] + run: | + cd product-mini/platforms/windows + mkdir build && cd build + cmake .. -DWAMR_BUILD_AOT=0 + cmake --build . --config Release --parallel 4 + cd .. && rm -force -r build + - name: Build iwasm [tail call] + run: | + cd product-mini/platforms/windows + mkdir build && cd build + cmake .. -DWAMR_BUILD_TAIL_CALL=1 + cmake --build . --config Release --parallel 4 + cd .. && rm -force -r build + - name: Build iwasm [custom name section] + run: | + cd product-mini/platforms/windows + mkdir build && cd build + cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1 + cmake --build . --config Release --parallel 4 + cd .. && rm -force -r build + - name: Build iwasm [disable hardware boundary check] + run: | + cd product-mini/platforms/windows + mkdir build && cd build + cmake .. -DWAMR_DISABLE_HW_BOUND_CHECK=1 + cmake --build . --config Release --parallel 4 + cd .. && rm -force -r build + - name: Build iwasm [reference types] + run: | + cd product-mini/platforms/windows + mkdir build && cd build + cmake .. -DWAMR_BUILD_REF_TYPES=1 + cmake --build . --config Release --parallel 4 + cd .. && rm -force -r build + - name: Build iwasm [128-bit SIMD] + run: | + cd product-mini/platforms/windows + mkdir build && cd build + cmake .. -DWAMR_BUILD_SIMD=1 + cmake --build . --config Release --parallel 4 + cd .. && rm -force -r build diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml deleted file mode 100644 index 22d13e57eb..0000000000 --- a/.github/workflows/linux.yml +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -name: Linux - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the main branch -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - - build: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-18.04, ubuntu-20.04] - steps: - - uses: actions/checkout@v2 - - - name: Build iwasm [default] - run: | - cd product-mini/platforms/linux - mkdir build && cd build - cmake .. - make - cd .. && rm -rf build - - name: Build iwasm [Classic interp] - run: | - cd product-mini/platforms/linux - mkdir build && cd build - cmake .. -DWAMR_BUILD_FAST_INTERP=0 - make - cd .. && rm -rf build - - name: Build iwasm [Multi module] - run: | - cd product-mini/platforms/linux - mkdir build && cd build - cmake .. -DWAMR_BUILD_MULTI_MODULE=1 - make - cd .. && rm -rf build - - name: Build iwasm [lib-pthread] - run: | - cd product-mini/platforms/linux - mkdir build && cd build - cmake .. -DWAMR_BUILD_LIB_PTHREAD=1 - make - cd .. && rm -rf build - - name: Build iwasm [aot only] - run: | - cd product-mini/platforms/linux - mkdir build && cd build - cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0 - make - cd .. && rm -rf build - - name: Build iwasm [interp only] - run: | - cd product-mini/platforms/linux - mkdir build && cd build - cmake .. -DWAMR_BUILD_AOT=0 - make - cd .. && rm -rf build - - name: Build iwasm [memory profiling] - run: | - cd product-mini/platforms/linux - mkdir build && cd build - cmake .. -DWAMR_BUILD_MEMORY_PROFILING=1 - make - cd .. && rm -rf build - - name: Build iwasm [tail call] - run: | - cd product-mini/platforms/linux - mkdir build && cd build - cmake .. -DWAMR_BUILD_TAIL_CALL=1 - make - cd .. && rm -rf build - - name: Build iwasm [custom name section] - run: | - cd product-mini/platforms/linux - mkdir build && cd build - cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1 - make - cd .. && rm -rf build - - name: download and install wasi-sdk - run: | - cd /opt - wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-8/wasi-sdk-8.0-linux.tar.gz - tar -xzf wasi-sdk-8.0-linux.tar.gz - mv wasi-sdk-8.0 wasi-sdk - - name: download and install wabt - run: | - cd /opt - wget https://github.com/WebAssembly/wabt/releases/download/1.0.19/wabt-1.0.19-ubuntu.tar.gz - tar -xzf wabt-1.0.19-ubuntu.tar.gz - mv wabt-1.0.19 wabt - - name: Build Sample [wasm-c-api] - run: | - cd samples/wasm-c-api - mkdir build && cd build - cmake .. - make - ./hello - ./global - ./callback - - name: Build Sample [basic] - run: | - cd samples/basic - ./build.sh - ./run.sh - - name: Build Sample [multi-thread] - run: | - cd samples/multi-thread - mkdir build && cd build - cmake .. - make - ./iwasm wasm-apps/test.wasm - - name: Build Sample [multi-module] - run: | - cd samples/multi-module - mkdir build && cd build - cmake .. - make - ./multi_module - - name: Build Sample [spawn-thread] - run: | - cd samples/spawn-thread - mkdir build && cd build - cmake .. - make - ./spawn_thread diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml deleted file mode 100644 index 6c8704b2be..0000000000 --- a/.github/workflows/mac.yml +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -name: Mac - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the main branch -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - - build: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [macos-latest] - steps: - - uses: actions/checkout@v2 - - - name: Build iwasm [default] - run: | - cd product-mini/platforms/darwin - mkdir build && cd build - cmake .. - make - cd .. && rm -rf build - - name: Build iwasm [Classic interp] - run: | - cd product-mini/platforms/darwin - mkdir build && cd build - cmake .. -DWAMR_BUILD_FAST_INTERP=0 - make - cd .. && rm -rf build - - name: Build iwasm [Multi module] - run: | - cd product-mini/platforms/darwin - mkdir build && cd build - cmake .. -DWAMR_BUILD_MULTI_MODULE=1 - make - cd .. && rm -rf build - - name: Build iwasm [lib-pthread] - run: | - cd product-mini/platforms/darwin - mkdir build && cd build - cmake .. -DWAMR_BUILD_LIB_PTHREAD=1 - make - cd .. && rm -rf build - - name: Build iwasm [aot only] - run: | - cd product-mini/platforms/darwin - mkdir build && cd build - cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0 - make - cd .. && rm -rf build - - name: Build iwasm [interp only] - run: | - cd product-mini/platforms/darwin - mkdir build && cd build - cmake .. -DWAMR_BUILD_AOT=0 - make - cd .. && rm -rf build - - name: Build iwasm [memory profiling] - run: | - cd product-mini/platforms/darwin - mkdir build && cd build - cmake .. -DWAMR_BUILD_MEMORY_PROFILING=1 - make - cd .. && rm -rf build - - name: Build iwasm [tail call] - run: | - cd product-mini/platforms/darwin - mkdir build && cd build - cmake .. -DWAMR_BUILD_TAIL_CALL=1 - make - cd .. && rm -rf build - - name: Build iwasm [custom name section] - run: | - cd product-mini/platforms/darwin - mkdir build && cd build - cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1 - make - cd .. && rm -rf build - - name: download and install wabt - run: | - cd /opt - sudo wget https://github.com/WebAssembly/wabt/releases/download/1.0.19/wabt-1.0.19-macos.tar.gz - sudo tar -xzf wabt-1.0.19-macos.tar.gz - sudo mv wabt-1.0.19 wabt - - name: Build Sample [wasm-c-api] - run: | - cd samples/wasm-c-api - mkdir build && cd build - cmake .. - make - ./hello - ./global - ./callback diff --git a/.github/workflows/spec_test.yml b/.github/workflows/spec_test.yml new file mode 100644 index 0000000000..5567db10c7 --- /dev/null +++ b/.github/workflows/spec_test.yml @@ -0,0 +1,109 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +name: Spec tests on non-windows + +on: + # will be triggered on PR events + pull_request: + paths: + - "core/config.h" + - "core/iwasm/**" + - "core/shared/**" + - "wamr-compiler/**" + - "product-mini/**" + # will be triggered on push events + push: + paths: + - "core/config.h" + - "core/iwasm/**" + - "core/shared/**" + - "wamr-compiler/**" + - "product-mini/**" + # allow to be triggered manually + workflow_dispatch: + +# Cancel any in-flight jobs for the same PR/branch so there's only one active +# at a time +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + LLVM_CACHE_SUFFIX: "build-llvm_libraries" + +jobs: + cancel_previous: + runs-on: ubuntu-20.04 + steps: + - name: Cancel Workflow Action + uses: styfle/cancel-workflow-action@0.6.0 + with: + access_token: ${{ github.token }} + + build_llvm_libraries: + needs: cancel_previous + runs-on: ubuntu-20.04 + steps: + - name: checkout + uses: actions/checkout@v2 + + - name: Cache LLVM libraries + id: cache_llvm + uses: actions/cache@v2 + with: + path: ./core/deps/llvm/build/LLVM-13.0.0.tar.gz + key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }} + restore-keys: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }} + + - name: Build llvm and clang from source + id: build_llvm + if: ${{ steps.cache_llvm.outputs.cache-hit != 'true' }} + run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly + working-directory: build-scripts + + - name: package LLVM + if: ${{ steps.build_llvm.conclusion == 'success' }} + run: mv LLVM-13.0.0-*.tar.gz LLVM-13.0.0.tar.gz + working-directory: core/deps/llvm/build/ + + spec_test_on_ubuntu_2004: + needs: build_llvm_libraries + runs-on: ubuntu-20.04 + strategy: + matrix: + test_option: [ + # DEFAULT + "-s spec", + # SIMD + "-s spec -S", + # THREAD + "-s spec -p", + # MULTI_MODULES + "-s spec -M", + ] + steps: + - name: checkout + uses: actions/checkout@v2 + + - name: Get LLVM libraries + id: cache_llvm + uses: actions/cache@v2 + with: + path: ./core/deps/llvm/build/LLVM-13.0.0.tar.gz + key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }} + restore-keys: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }} + + - name: Quit if cache miss + if: steps.cache_llvm.outputs.cache-hit != 'true' + run: echo "::error::can not get prebuilt llvm libraries" && exit 1 + + - name: Extract the LLVM package + run: tar xf LLVM-13.0.0.tar.gz --strip-components=1 + working-directory: ./core/deps/llvm/build + + - name: install Ninja + run: sudo apt install -y ninja-build + + - name: run spec tests + run: ./test_wamr.sh ${{ matrix.test_option }} + working-directory: ./tests/wamr-test-suites diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index 3ae374f902..0000000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -name: Windows - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the main branch -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - - build: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [windows-latest] - steps: - - uses: actions/checkout@v2 - - - name: clone uvwasi library - run: | - cd core/deps - git clone https://github.com/nodejs/uvwasi.git - - name: Build iwasm [default] - run: | - cd product-mini/platforms/windows - mkdir build && cd build - cmake .. - cmake --build . --config Release - cd .. && rm -force -r build - - name: Build iwasm [aot only] - run: | - cd product-mini/platforms/windows - mkdir build && cd build - cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0 - cmake --build . --config Release - cd .. && rm -force -r build - - name: Build iwasm [interp only] - run: | - cd product-mini/platforms/windows - mkdir build && cd build - cmake .. -DWAMR_BUILD_AOT=0 - cmake --build . --config Release - cd .. && rm -force -r build - - name: Build iwasm [tail call] - run: | - cd product-mini/platforms/windows - mkdir build && cd build - cmake .. -DWAMR_BUILD_TAIL_CALL=1 - cmake --build . --config Release - cd .. && rm -force -r build - - name: Build iwasm [custom name section] - run: | - cd product-mini/platforms/windows - mkdir build && cd build - cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1 - cmake --build . --config Release - cd .. && rm -force -r build - diff --git a/.gitignore b/.gitignore index f046482476..36b2b6756e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ test-tools/host-tool/bin/ product-mini/app-samples/hello-world/test.wasm build_out +tests/wamr-test-suites/workspace diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index a2e76403a8..e64c972cd6 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -63,3 +63,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the ### zephyr [LICENSE](./samples/gui/wasm-runtime-wgl/src/platform/zephyr/LICENSE) + +### wac + +[LICENSE](./tests/wamr-test-suites/spec-test-script/LICENSE) diff --git a/README.md b/README.md index d12b5e8b47..bd9418daaf 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ iwasm VM core - [The mechanism for exporting native API's to WASM applications](./doc/export_native_api.md) - [Multiple modules as dependencies](./doc/multi_module.md), ref to [sample](samples/multi-module) - [Thread management and pthread library](./doc/pthread_library.md), ref to [sample](samples/multi-thread) +- [Linux SGX (Intel Software Guard Extension) support](./doc/linux_sgx.md) +- [Source debugging](./doc/source_debugging.md) ### post-MVP features - [Non-trapping float-to-int conversions](https://github.com/WebAssembly/nontrapping-float-to-int-conversions) @@ -48,7 +50,7 @@ The iwasm supports the following architectures: - AArch64 (Cortex-A57 and Cortex-A53 are tested) - MIPS - XTENSA -- RISCV64, RISCV32 (interpreter only) +- RISCV64, RISCV32 (RISC-V LP64 and RISC-V LP64D are tested) Following platforms are supported. Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform. @@ -67,7 +69,7 @@ Both wasm binary file and AoT file are supported by iwasm. The wamrc AoT compile cd wamr-compiler ./build_llvm.sh (or "./build_llvm_xtensa.sh" to support xtensa target) mkdir build && cd build -cmake .. (or "cmake .. -DWAMR_BUILD_TARGET=darwin" for MacOS) +cmake .. (or "cmake .. -DWAMR_BUILD_PLATFORM=darwin" for MacOS) make # wamrc is generated under current directory ``` @@ -76,8 +78,6 @@ For **Windows**: ```shell cd wamr-compiler python build_llvm.py -open LLVM.sln in wasm-micro-runtime\core\deps\llvm\win32build with Visual Studio -build LLVM.sln Release mkdir build && cd build cmake .. cmake --build . --config Release @@ -132,15 +132,15 @@ The WAMR [samples](./samples) integrate the iwasm VM core, application manager a Project Technical Steering Committee ==================================== -The [WAMR PTSC Charter](./TSC_Charter.md) governs the operations of the project TSC. +The [WAMR PTSC Charter](./TSC_Charter.md) governs the operations of the project TSC. The current TSC members: - [lum1n0us](https://github.com/lum1n0us) - **Liang He**, +- [no1wudi](https://github.com/no1wudi) **Qi Huang**, - [qinxk-inter](https://github.com/qinxk-inter) - **Xiaokang Qin**, - [wei-tang](https://github.com/wei-tang) - **Wei Tang**, - [wenyongh](https://github.com/wenyongh) - **Wenyong Huang**, - [xujuntwt95329](https://github.com/xujuntwt95329) - **Jun Xu**, -- [xwang98](https://github.com/xwang98) - **Xin Wang**, - +- [xwang98](https://github.com/xwang98) - **Xin Wang**, (chair) License ======= @@ -153,10 +153,11 @@ Any contributions you make will be under the same license. # More resources -Check out the [Wiki documents ](../../wiki) for more resources: +Check out the [Wiki documents ](https://github.com/bytecodealliance/wasm-micro-runtime/wiki) for more resources: -- [Performance and footprint data](../../wiki/Performance) -- Community news and events -- Roadmap +- [Performance and footprint data](https://github.com/bytecodealliance/wasm-micro-runtime/wiki/Performance) +- [Community news and events](https://github.com/bytecodealliance/wasm-micro-runtime/wiki/Events) +- [Roadmap](https://github.com/bytecodealliance/wasm-micro-runtime/wiki/Roadmap) +- [WAMR TSC meetings](https://github.com/bytecodealliance/wasm-micro-runtime/wiki/TSC-meeting) - Technical documents diff --git a/SConscript b/SConscript index af4c3efef7..7db274184c 100644 --- a/SConscript +++ b/SConscript @@ -14,20 +14,10 @@ cwd = GetCurrentDir() list = os.listdir(cwd) if GetDepend(['PKG_USING_WAMR']): - wamr_entry_sconscript = os.path.join(cwd, "product-mini", "platforms", "rt-thread", 'SConscript') + wamr_entry_sconscript = os.path.join(cwd, "product-mini", "platforms", "rt-thread", 'SConscript') + wamr_runlib_sconscript = os.path.join(cwd, "build-scripts", 'SConscript') - if os.path.isfile(wamr_entry_sconscript): - objs = objs + SConscript(wamr_entry_sconscript) - else: - print("[WAMR] entry script wrong:", wamr_entry_sconscript) - Return('objs') - - wamr_runlib_sconsript = os.path.join(cwd, "build-scripts", 'SConscript') - - if os.path.isfile(wamr_runlib_sconsript): - objs = objs + SConscript(wamr_runlib_sconsript) - else: - print("[WAMR] runtime lib script wrong:", wamr_runlib_sconsript) + objs = objs + SConscript(wamr_entry_sconscript) + objs = objs + SConscript(wamr_runlib_sconscript) Return('objs') - diff --git a/TSC_Charter.md b/TSC_Charter.md index 6cb8ddd282..56c4a024b9 100644 --- a/TSC_Charter.md +++ b/TSC_Charter.md @@ -2,23 +2,23 @@ ## Section 1. Guiding Principle -The WebAssembly Micro Runtime (WAMR) project is part of the -Bytecode Alliance (BA) which operates transparently, openly, -collaboratively, and ethically. Project proposals, timelines, and status +The WebAssembly Micro Runtime (WAMR) project is part of the +Bytecode Alliance (BA) which operates transparently, openly, +collaboratively, and ethically. Project proposals, timelines, and status must not merely be open, but also easily visible to outsiders. ## Section 2. Project Governance under Bytecode Alliance -Technical leadership for the WAMR projects within the Bytecode Alliance -is delegated to the projects through the project charter. Though the BA TSC +Technical leadership for the WAMR projects within the Bytecode Alliance +is delegated to the projects through the project charter. Though the BA TSC will not interfere with day-to-day discussions, votes or meetings of the PTSC, -the BA TSC may request additional amendments to the PTSC charter when +the BA TSC may request additional amendments to the PTSC charter when there is misalignment between the project charter and the BA mission and values. -The PTSC structure described in this document may be overhauled as part of -establishing a BA TSC in order to adhere to constraints or requirements that +The PTSC structure described in this document may be overhauled as part of +establishing a BA TSC in order to adhere to constraints or requirements that TSC will impose on project-level governance. ## Section 3. Establishment of the PTSC @@ -26,7 +26,7 @@ TSC will impose on project-level governance. PTSC memberships are not time-limited. There is no maximum size of the PTSC. The size is expected to vary in order to ensure adequate coverage of important areas of expertise, balanced with the ability to make decisions efficiently. -The PTSC must have at least four members. +The PTSC must have at least four members. There is no specific set of requirements or qualifications for PTSC membership beyond these rules. The PTSC may add additional members to the @@ -77,11 +77,11 @@ The PTSC will define WAMR project’s release vehicles. ## Section 5. WAMR Project Operations -The PTSC will establish and maintain a development process for the WAMR +The PTSC will establish and maintain a development process for the WAMR project. The development process will establish guidelines for how the developers and community will operate. It will, for example, establish appropriate timelines for PTSC review (e.g. agenda items must be -published at least a certain number of hours in advance of a PTSC +published at least a certain number of hours in advance of a PTSC meeting). The PTSC and entire technical community will follow any processes as may @@ -106,7 +106,7 @@ the candidate's election. Elections shall be done within the projects by the Collaborators active in the project. The PTSC will elect from amongst voting PTSC members a PTSC Chairperson to -work on building an agenda for PTSC meetings. The PTSC shall hold annual +work on building an agenda for PTSC meetings. The PTSC shall hold annual elections to select a PTSC Chairperson; there are no limits on the number of terms a PTSC Chairperson may serve. diff --git a/build-scripts/SConscript b/build-scripts/SConscript index a1839642bd..d2bee95818 100644 --- a/build-scripts/SConscript +++ b/build-scripts/SConscript @@ -11,23 +11,16 @@ cwd = GetCurrentDir() objs = [] WAMR_ROOT_DIR = os.path.join(cwd, "..") - - -SHARED_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'shared') - -IWASM_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'iwasm') - -APP_MGR_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'app-mgr') - +SHARED_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'shared') +IWASM_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'iwasm') +APP_MGR_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'app-mgr') APP_FRAMEWORK_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'app-framework') - -DEPS_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'deps') +DEPS_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'deps') if GetDepend(['WAMR_BUILD_INTERP']): script_path = os.path.join(IWASM_DIR, 'interpreter', 'SConscript') objs += SConscript(script_path) - if GetDepend(['WAMR_BUILD_AOT']): script_path = os.path.join(IWASM_DIR, 'aot', 'SConscript') objs += SConscript(script_path) @@ -35,54 +28,32 @@ if GetDepend(['WAMR_BUILD_AOT']): script_path = os.path.join(IWASM_DIR, 'compilation', 'SConscript') objs += SConscript(script_path) - if GetDepend(['WAMR_BUILD_APP_FRAMEWORK']): objs += SConscript(os.path.join(APP_FRAMEWORK_DIR, 'SConscript')) objs += SConscript(os.path.join(SHARED_DIR, 'coap', 'SConscript')) objs += SConscript(os.path.join(APP_MGR_DIR, 'app-manager', 'SConscript')) objs += SConscript(os.path.join(APP_MGR_DIR, 'app-mgr-shared', 'SConscript')) - - if GetDepend(['WAMR_BUILD_LIBC_BUILTIN']): objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-builtin', 'SConscript')) - - if GetDepend(['WAMR_BUILD_LIBC_WASI']): objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-wasi', 'SConscript')) - if GetDepend(['WAMR_BUILD_LIB_PTHREAD']): objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-pthread', 'SConscript')) - # TODO: 这里加一下 - - - -# if (WAMR_BUILD_THREAD_MGR EQUAL 1) -# include (${IWASM_DIR}/libraries/thread-mgr/thread_mgr.cmake) -# endif () if GetDepend(['WAMR_BUILD_THREAD_MGR']): objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'thread-mgr', 'SConscript')) - - -# if (WAMR_BUILD_LIBC_EMCC EQUAL 1) -# include (${IWASM_DIR}/libraries/libc-emcc/libc_emcc.cmake) -# endif() - if GetDepend(['WAMR_BUILD_LIBC_EMCC']): objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-emmc', 'SConscript')) objs += SConscript(os.path.join(cwd, 'SConscript_config')); - objs += SConscript(os.path.join(SHARED_DIR, 'platform', 'rt-thread', 'SConscript')) objs += SConscript(os.path.join(SHARED_DIR, 'mem-alloc', 'SConscript')) objs += SConscript(os.path.join(IWASM_DIR, 'common', 'SConscript')) objs += SConscript(os.path.join(SHARED_DIR, 'utils', 'SConscript')) - - Return('objs') diff --git a/build-scripts/SConscript_config b/build-scripts/SConscript_config index f5fe373dc8..df96940e9d 100644 --- a/build-scripts/SConscript_config +++ b/build-scripts/SConscript_config @@ -11,15 +11,12 @@ from building import * Import('rtconfig') -src = Split(''' -''') +src = [] objs = [] cwd = GetCurrentDir() IWASM_INC_DIR = os.path.join(cwd, '..', 'core', 'iwasm', 'include') -# include_directories (${IWASM_DIR}/include) - CPPPATH = [IWASM_INC_DIR] if rtconfig.BUILD == 'debug': @@ -48,12 +45,11 @@ if rtconfig.ARCH == 'arm': print('[WAMR] using armv4') CPPDEFINES += ['BUILD_TARGET_ARM'] CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_ARMV4'] +elif rtconfig.ARCH == 'ia32': + CPPDEFINES += ['BUILD_TARGET_X86_32', 'RTT_WAMR_BUILD_TARGET_X86_32'] else: print("[WAMR] unknown arch", rtconfig.ARCH) - -LIBS = ['m'] - if GetDepend(['WAMR_BUILD_INTERP']): CPPDEFINES += ['WASM_ENABLE_INTERP=1'] if GetDepend(['WAMR_BUILD_FAST_INTERP']): @@ -114,8 +110,8 @@ if GetDepend(['WAMR_BUILD_TAIL_CALL']): CPPDEFINES += ['WASM_ENABLE_TAIL_CALL=1'] print('[WAMR] Tail call enabledd') +LIBS = ['m'] -group = DefineGroup('wamr_config_common', src, depend = ['PKG_USING_WAMR'], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES, LIBS = LIBS) +group = DefineGroup('wamr', src, depend = ['PKG_USING_WAMR'], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES, LIBS = LIBS) Return('group') - diff --git a/build-scripts/build_llvm.py b/build-scripts/build_llvm.py new file mode 100755 index 0000000000..1a9527995a --- /dev/null +++ b/build-scripts/build_llvm.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import argparse +import os +import pathlib +import shlex +import shutil +import subprocess +import sys + + +def clone_llvm(dst_dir, llvm_repo, llvm_branch): + """ + any error will raise CallProcessError + """ + llvm_dir = dst_dir.joinpath("llvm").resolve() + + if not llvm_dir.exists(): + print(f"Clone llvm to {llvm_dir} ...") + GIT_CLONE_CMD = f"git clone --depth 1 --branch {llvm_branch} {llvm_repo} llvm" + subprocess.check_output(shlex.split(GIT_CLONE_CMD), cwd=dst_dir) + else: + print(f"There is an LLVM local repo in {llvm_dir}, clean and keep using it") + + return llvm_dir + + +def build_llvm(llvm_dir, platform, backends, projects): + LLVM_COMPILE_OPTIONS = [ + '-DCMAKE_BUILD_TYPE:STRING="Release"', + "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", + "-DLLVM_APPEND_VC_REV:BOOL=ON", + "-DLLVM_BUILD_BENCHMARKS:BOOL=OFF", + "-DLLVM_BUILD_DOCS:BOOL=OFF", + "-DLLVM_BUILD_EXAMPLES:BOOL=OFF", + "-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF", + "-DLLVM_BUILD_TESTS:BOOL=OFF", + "-DLLVM_CCACHE_BUILD:BOOL=OFF", + "-DLLVM_ENABLE_BINDINGS:BOOL=OFF", + "-DLLVM_ENABLE_IDE:BOOL=OFF", + "-DLLVM_ENABLE_TERMINFO:BOOL=OFF", + "-DLLVM_ENABLE_ZLIB:BOOL=OFF", + "-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF", + "-DLLVM_INCLUDE_DOCS:BOOL=OFF", + "-DLLVM_INCLUDE_EXAMPLES:BOOL=OFF", + "-DLLVM_INCLUDE_UTILS:BOOL=OFF", + "-DLLVM_INCLUDE_TESTS:BOOL=OFF", + "-DLLVM_BUILD_TESTS:BOOL=OFF", + "-DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON", + ] + + LLVM_EXTRA_COMPILE_OPTIONS = { + "arc": [ + '-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="ARC"', + "-DLLVM_ENABLE_LIBICUUC:BOOL=OFF", + "-DLLVM_ENABLE_LIBICUDATA:BOOL=OFF", + ], + "xtensa": [ + '-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="Xtensa"', + ], + "windows": [ + "-DCMAKE_INSTALL_PREFIX=LLVM-install", + ], + "default": [], + } + + LLVM_TARGETS_TO_BUILD = [ + '-DLLVM_TARGETS_TO_BUILD:STRING="' + ";".join(backends) + '"' + if backends + else '-DLLVM_TARGETS_TO_BUILD:STRING="AArch64;ARM;Mips;RISCV;X86"' + ] + + LLVM_PROJECTS_TO_BUILD = [ + '-DLLVM_ENABLE_PROJECTS:STRING="' + ";".join(projects) + '"' if projects else "" + ] + + # lldb project requires libxml2 + LLVM_LIBXML2_OPTION = [ + "-DLLVM_ENABLE_LIBXML2:BOOL=" + ("ON" if "lldb" in projects else "OFF") + ] + + # enabling LLVM_INCLUDE_TOOLS will increase ~300M to the final package + LLVM_INCLUDE_TOOLS_OPTION = [ + "-DLLVM_INCLUDE_TOOLS:BOOL=ON" if projects else "-DLLVM_INCLUDE_TOOLS:BOOL=OFF" + ] + + if not llvm_dir.exists(): + raise Exception(f"{llvm_dir} doesn't exist") + + build_dir = llvm_dir.joinpath( + "win32build" if "windows" == platform else "build" + ).resolve() + build_dir.mkdir(exist_ok=True) + + lib_llvm_core_library = build_dir.joinpath("lib/libLLVMCore.a").resolve() + if lib_llvm_core_library.exists(): + print(f"Please remove {build_dir} manually and try again") + return + + compile_options = " ".join( + LLVM_COMPILE_OPTIONS + + LLVM_LIBXML2_OPTION + + LLVM_EXTRA_COMPILE_OPTIONS.get( + platform, LLVM_EXTRA_COMPILE_OPTIONS["default"] + ) + + LLVM_TARGETS_TO_BUILD + + LLVM_PROJECTS_TO_BUILD + + LLVM_INCLUDE_TOOLS_OPTION + ) + + CONFIG_CMD = f"cmake {compile_options} ../llvm " + ( + "-A x64" if "windows" == platform else "" + ) + print(f"{CONFIG_CMD}") + subprocess.check_call(shlex.split(CONFIG_CMD), cwd=build_dir) + + BUILD_CMD = f"cmake --build . --target package --parallel {os.cpu_count()}" + ( + " --config Release" if "windows" == platform else "" + ) + subprocess.check_call(shlex.split(BUILD_CMD), cwd=build_dir) + + return build_dir + + +def main(): + parser = argparse.ArgumentParser(description="build necessary LLVM libraries") + parser.add_argument( + "--platform", + type=str, + choices=["android", "arc", "darwin", "linux", "windows", "xtensa"], + help="identify current platform", + ) + parser.add_argument( + "--arch", + nargs="+", + type=str, + choices=[ + "AArch64", + "ARC", + "ARM", + "Mips", + "RISCV", + "WebAssembly", + "X86", + "Xtensa", + ], + help="identify LLVM supported backends, separate by space, like '--arch ARM Mips X86'", + ) + parser.add_argument( + "--project", + nargs="+", + type=str, + default="", + choices=["clang", "lldb"], + help="identify extra LLVM projects, separate by space, like '--project clang lldb'", + ) + options = parser.parse_args() + print(f"options={options}") + + # if the "platform" is not identified in the command line option, + # detect it + if not options.platform: + if sys.platform.startswith("win32") or sys.platform.startswith("msys"): + platform = "windows" + elif sys.platform.startswith("darwin"): + platform = "darwin" + else: + platform = "linux" + else: + platform = options.platform + + print(f"========== Build LLVM for {platform} ==========\n") + + llvm_repo_and_branch = { + "arc": { + "repo": "https://github.com/llvm/llvm-project.git", + "branch": "release/13.x", + }, + "xtensa": { + "repo": "https://github.com/espressif/llvm-project.git", + "branch": "xtensa_release_11.0.0", + }, + "default": { + "repo": "https://github.com/llvm/llvm-project.git", + "branch": "release/13.x", + }, + } + + # retrieve the real file + current_file = pathlib.Path(__file__) + if current_file.is_symlink(): + current_file = pathlib.Path(os.readlink(current_file)) + + current_dir = current_file.parent.resolve() + deps_dir = current_dir.joinpath("../core/deps").resolve() + + print(f"==================== CLONE LLVM ====================") + llvm_info = llvm_repo_and_branch.get(platform, llvm_repo_and_branch["default"]) + llvm_dir = clone_llvm(deps_dir, llvm_info["repo"], llvm_info["branch"]) + + print() + print(f"==================== BUILD LLVM ====================") + build_llvm(llvm_dir, platform, options.arch, options.project) + + print() + + +if __name__ == "__main__": + main() diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 68aad25883..3d94acf540 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -42,6 +42,8 @@ elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISC add_definitions(-DBUILD_TARGET_RISCV32_ILP32D) elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32") add_definitions(-DBUILD_TARGET_RISCV32_ILP32) +elseif (WAMR_BUILD_TARGET STREQUAL "ARC") + add_definitions(-DBUILD_TARGET_ARC) else () message (FATAL_ERROR "-- WAMR build target isn't set") endif () @@ -51,7 +53,8 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug") endif () if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*" OR WAMR_BUILD_TARGET MATCHES "RISCV64.*") + if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" + OR WAMR_BUILD_TARGET MATCHES "AARCH64.*" OR WAMR_BUILD_TARGET MATCHES "RISCV64.*") if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") # Add -fPIC flag if build as 64-bit set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") @@ -80,6 +83,9 @@ endif () if (WAMR_BUILD_JIT EQUAL 1) if (WAMR_BUILD_AOT EQUAL 1) add_definitions("-DWASM_ENABLE_JIT=1") + if (WAMR_BUILD_LAZY_JIT EQUAL 1) + add_definitions("-DWASM_ENABLE_LAZY_JIT=1") + endif () if (NOT DEFINED LLVM_DIR) set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build") @@ -119,6 +125,11 @@ else () endif () if (WAMR_BUILD_JIT EQUAL 1) message (" WAMR JIT enabled") + if (WAMR_BUILD_LAZY_JIT EQUAL 1) + message (" WAMR LazyJIT enabled") + else () + message (" WAMR LazyJIT disabled") + endif () else () message (" WAMR JIT disabled") endif () @@ -134,7 +145,7 @@ elseif (WAMR_BUILD_LIBC_WASI EQUAL 1) else () message (" Libc WASI disabled") endif () -if (WAMR_BUILD_FAST_INTERP EQUAL 1) +if ((WAMR_BUILD_FAST_INTERP EQUAL 1) AND (WAMR_BUILD_INTERP EQUAL 1)) add_definitions (-DWASM_ENABLE_FAST_INTERP=1) message (" Fast interpreter enabled") else () @@ -186,8 +197,12 @@ else () add_definitions (-DWASM_DISABLE_HW_BOUND_CHECK=0) endif () if (WAMR_BUILD_SIMD EQUAL 1) - add_definitions (-DWASM_ENABLE_SIMD=1) - message (" SIMD enabled") + if (NOT WAMR_BUILD_TARGET MATCHES "RISCV64.*") + add_definitions (-DWASM_ENABLE_SIMD=1) + message (" SIMD enabled") + else () + message (" SIMD disabled due to not supported on target RISCV64") + endif () endif () if (WAMR_BUILD_MEMORY_PROFILING EQUAL 1) add_definitions (-DWASM_ENABLE_MEMORY_PROFILING=1) @@ -224,3 +239,9 @@ endif () if (WAMR_DISABLE_APP_ENTRY EQUAL 1) message (" WAMR application entry functions excluded") endif () +if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) + message (" Debug Interpreter enabled") +endif () +if (WAMR_BUILD_DEBUG_AOT EQUAL 1) + message (" Debug AOT enabled") +endif () diff --git a/build-scripts/lldb-wasm.patch b/build-scripts/lldb-wasm.patch new file mode 100644 index 0000000000..1570418bf9 --- /dev/null +++ b/build-scripts/lldb-wasm.patch @@ -0,0 +1,5779 @@ +diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h +index dd7100c4616c..97d70daadbdc 100644 +--- a/lldb/include/lldb/Core/Module.h ++++ b/lldb/include/lldb/Core/Module.h +@@ -41,6 +41,7 @@ + + namespace lldb_private { + class CompilerDeclContext; ++class DWARFEvaluatorFactory; + class Function; + class Log; + class ObjectFile; +@@ -859,6 +860,8 @@ public: + /// Update the ArchSpec to a more specific variant. + bool MergeArchitecture(const ArchSpec &arch_spec); + ++ DWARFEvaluatorFactory *GetDWARFExpressionEvaluatorFactory(); ++ + /// \class LookupInfo Module.h "lldb/Core/Module.h" + /// A class that encapsulates name lookup information. + /// +@@ -985,6 +988,8 @@ protected: + m_first_file_changed_log : 1; /// See if the module was modified after it + /// was initially opened. + ++ std::unique_ptr m_dwarf_evaluator_factory; ++ + /// Resolve a file or load virtual address. + /// + /// Tries to resolve \a vm_addr as a file address (if \a +diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h +index be91929c62e1..8d876fc1fa2f 100644 +--- a/lldb/include/lldb/Core/PluginManager.h ++++ b/lldb/include/lldb/Core/PluginManager.h +@@ -508,6 +508,17 @@ public: + static bool CreateSettingForStructuredDataPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); ++ ++ // DWARFEvaluatorFactory ++ static bool ++ RegisterPlugin(ConstString name, const char *description, ++ DWARFEvaluatorFactoryCreateInstance create_callback); ++ ++ static bool ++ UnregisterPlugin(DWARFEvaluatorFactoryCreateInstance create_callback); ++ ++ static DWARFEvaluatorFactoryCreateInstance ++ GetDWARFEvaluatorFactoryCreateCallbackAtIndex(uint32_t idx); + }; + + } // namespace lldb_private +diff --git a/lldb/include/lldb/Expression/DWARFEvaluator.h b/lldb/include/lldb/Expression/DWARFEvaluator.h +new file mode 100644 +index 000000000000..6811cbeae3d3 +--- /dev/null ++++ b/lldb/include/lldb/Expression/DWARFEvaluator.h +@@ -0,0 +1,110 @@ ++//===-- DWARFEvaluator.h ----------------------------------------*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLDB_EXPRESSION_DWARFEVALUATOR_H ++#define LLDB_EXPRESSION_DWARFEVALUATOR_H ++ ++#include "lldb/lldb-private.h" ++#include ++ ++namespace lldb_private { ++ ++class DWARFExpression; ++ ++/// \class DWARFEvaluator DWARFEvaluator.h ++/// "lldb/Expression/DWARFEvaluator.h" Evaluates DWARF opcodes. ++/// ++class DWARFEvaluator { ++public: ++ /// Crates a DWARF location expression evaluator ++ /// ++ /// \param[in] dwarf_expression ++ /// The DWARF expression to evaluate. ++ /// ++ /// \param[in] exe_ctx ++ /// The execution context in which to evaluate the location ++ /// expression. The location expression may access the target's ++ /// memory, especially if it comes from the expression parser. ++ /// ++ /// \param[in] reg_ctx ++ /// An optional parameter which provides a RegisterContext for use ++ /// when evaluating the expression (i.e. for fetching register values). ++ /// Normally this will come from the ExecutionContext's StackFrame but ++ /// in the case where an expression needs to be evaluated while building ++ /// the stack frame list, this short-cut is available. ++ /// ++ /// \param[in] initial_value_ptr ++ /// A value to put on top of the interpreter stack before evaluating ++ /// the expression, if the expression is parametrized. Can be NULL. ++ /// ++ /// \param[in] object_address_ptr ++ /// ++ DWARFEvaluator(const DWARFExpression &dwarf_expression, ++ ExecutionContext *exe_ctx, RegisterContext *reg_ctx, ++ const Value *initial_value_ptr, ++ const Value *object_address_ptr); ++ ++ /// DWARFEvaluator protocol. ++ /// \{ ++ ++ /// Evaluate the DWARF location expression ++ /// ++ /// \param[in] result ++ /// A value into which the result of evaluating the expression is ++ /// to be placed. ++ /// ++ /// \param[in] error_ptr ++ /// If non-NULL, used to report errors in expression evaluation. ++ /// ++ /// \return ++ /// True on success; false otherwise. If error_ptr is non-NULL, ++ /// details of the failure are provided through it. ++ virtual bool Evaluate(Value &result, Status *error_ptr); ++ ++ /// Evaluate the DWARF location expression with the opcodes specified. ++ /// ++ /// \param[in] opcodes ++ /// The DWARF opcodes to evaluate. ++ /// ++ /// \param[in] result ++ /// A value into which the result of evaluating the expression is ++ /// to be placed. ++ /// ++ /// \param[in] error_ptr ++ /// If non-NULL, used to report errors in expression evaluation. ++ /// ++ /// \return ++ /// True on success; false otherwise. If error_ptr is non-NULL, ++ /// details of the failure are provided through it. ++ virtual bool Evaluate(const DataExtractor &opcodes, Value &result, ++ Status *error_ptr); ++ ++ /// Evaluates a specific DWARF opcode in the context of a DWARF expression ++ virtual bool Evaluate(const uint8_t op, Process *process, StackFrame *frame, ++ std::vector &stack, const DataExtractor &opcodes, ++ lldb::offset_t &offset, Value &pieces, ++ uint64_t &op_piece_offset, Log *log, Status *error_ptr); ++ ++ /// \} ++ ++protected: ++ const DWARFExpression &m_dwarf_expression; ++ ExecutionContext *m_exe_ctx; ++ RegisterContext *m_reg_ctx; ++ const Value *m_initial_value_ptr; ++ const Value *m_object_address_ptr; ++ ++private: ++ DWARFEvaluator(const DWARFEvaluator &); ++ const DWARFEvaluator &operator=(const DWARFEvaluator &) = delete; ++ ++}; ++ ++} // namespace lldb_private ++ ++#endif // LLDB_EXPRESSION_DWARFEVALUATOR_H +diff --git a/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h b/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h +new file mode 100644 +index 000000000000..f3b496c580e4 +--- /dev/null ++++ b/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h +@@ -0,0 +1,56 @@ ++//===-- DWARFEvaluatorFactory.h ---------------------------------*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLDB_EXPRESSION_DWARFEVALUATORFACTORY_H ++#define LLDB_EXPRESSION_DWARFEVALUATORFACTORY_H ++ ++#include "lldb/Core/PluginInterface.h" ++#include "lldb/Utility/ConstString.h" ++#include "lldb/lldb-private.h" ++ ++class DWARFUnit; ++ ++namespace lldb_private { ++ ++class DWARFEvaluator; ++class DWARFExpression; ++ ++/// \class DWARFEvaluatorFactory DWARFEvaluatorFactory.h ++/// "lldb/Expression/DWARFEvaluatorFactory.h" Factory class that allows the ++/// registration of platform-specific DWARF expression evaluators, used to ++/// handle platform-specific DWARF opcodes. ++class DWARFEvaluatorFactory : public PluginInterface { ++public: ++ static std::unique_ptr FindPlugin(Module *module); ++ ++ /// PluginInterface protocol. ++ /// \{ ++ ConstString GetPluginName() override; ++ ++ uint32_t GetPluginVersion() override { return 1; } ++ /// \} ++ ++ DWARFEvaluatorFactory() {} ++ ++ /// DWARFEvaluatorFactory protocol. ++ /// \{ ++ virtual std::unique_ptr ++ CreateDWARFEvaluator(const DWARFExpression &dwarf_expression, ++ ExecutionContext *exe_ctx, RegisterContext *reg_ctx, ++ const Value *initial_value_ptr, ++ const Value *object_address_ptr); ++ /// \} ++ ++private: ++ DWARFEvaluatorFactory(const DWARFEvaluatorFactory &); ++ const DWARFEvaluatorFactory &operator=(const DWARFEvaluatorFactory &) = delete; ++}; ++ ++} // namespace lldb_private ++ ++#endif // LLDB_EXPRESSION_DWARFEVALUATORFACTORY_H +diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h +index 1490ac2d614a..35c741d4e6ba 100644 +--- a/lldb/include/lldb/Expression/DWARFExpression.h ++++ b/lldb/include/lldb/Expression/DWARFExpression.h +@@ -120,6 +120,10 @@ public: + + void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; } + ++ lldb::ModuleSP GetModule() const { return m_module_wp.lock(); } ++ ++ const DWARFUnit *GetDWARFCompileUnit() const { return m_dwarf_cu; } ++ + bool ContainsThreadLocalStorage() const; + + bool LinkThreadLocalStorage( +@@ -140,7 +144,7 @@ public: + lldb::addr_t func_file_addr); + + /// Return the call-frame-info style register kind +- int GetRegisterKind(); ++ lldb::RegisterKind GetRegisterKind() const; + + /// Set the call-frame-info style register kind + /// +@@ -219,6 +223,9 @@ public: + + bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op); + ++ static lldb::addr_t ReadAddressFromDebugAddrSection(const DWARFUnit *dwarf_cu, ++ uint32_t index); ++ + llvm::Optional + GetLocationExpression(lldb::addr_t load_function_start, + lldb::addr_t addr) const; +diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h +index aaa2470d2931..c15f2db52fbc 100644 +--- a/lldb/include/lldb/Target/Process.h ++++ b/lldb/include/lldb/Target/Process.h +@@ -1434,7 +1434,7 @@ public: + /// vm_addr, \a buf, and \a size updated appropriately. Zero is + /// returned in the case of an error. + virtual size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, +- Status &error); ++ Status &error, ExecutionContext *exe_ctx = nullptr); + + /// Read of memory from a process. + /// +diff --git a/lldb/include/lldb/Target/ProcessTrace.h b/lldb/include/lldb/Target/ProcessTrace.h +index 7b9d6b13dd6f..9525fc9750fd 100644 +--- a/lldb/include/lldb/Target/ProcessTrace.h ++++ b/lldb/include/lldb/Target/ProcessTrace.h +@@ -59,7 +59,7 @@ public: + bool WarnBeforeDetach() const override { return false; } + + size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size, +- Status &error) override; ++ Status &error, ExecutionContext *exe_ctx = nullptr) override; + + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + Status &error) override; +diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h +index ad5298151e4a..5a3c0b27a738 100644 +--- a/lldb/include/lldb/lldb-forward.h ++++ b/lldb/include/lldb/lldb-forward.h +@@ -74,6 +74,7 @@ class Disassembler; + class DumpValueObjectOptions; + class DynamicCheckerFunctions; + class DynamicLoader; ++class DWARFEvaluatorFactory; + class Editline; + class EmulateInstruction; + class Environment; +diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h +index 2ed083ec8ae9..f4d500d198e8 100644 +--- a/lldb/include/lldb/lldb-private-interfaces.h ++++ b/lldb/include/lldb/lldb-private-interfaces.h +@@ -113,6 +113,8 @@ typedef lldb::REPLSP (*REPLCreateInstance)(Status &error, + const char *repl_options); + typedef int (*ComparisonFunction)(const void *, const void *); + typedef void (*DebuggerInitializeCallback)(Debugger &debugger); ++typedef DWARFEvaluatorFactory *(*DWARFEvaluatorFactoryCreateInstance)( ++ Module *module); + /// Trace + /// \{ + typedef llvm::Expected (*TraceCreateInstanceForSessionFile)( +diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp +index 19c97be15066..1647f93ec4f3 100644 +--- a/lldb/source/Core/Module.cpp ++++ b/lldb/source/Core/Module.cpp +@@ -16,6 +16,7 @@ + #include "lldb/Core/ModuleSpec.h" + #include "lldb/Core/SearchFilter.h" + #include "lldb/Core/Section.h" ++#include "lldb/Expression/DWARFEvaluatorFactory.h" + #include "lldb/Host/FileSystem.h" + #include "lldb/Host/Host.h" + #include "lldb/Host/HostInfo.h" +@@ -1659,3 +1660,9 @@ bool Module::GetIsDynamicLinkEditor() { + + return false; + } ++ ++DWARFEvaluatorFactory *Module::GetDWARFExpressionEvaluatorFactory() { ++ if (!m_dwarf_evaluator_factory) ++ m_dwarf_evaluator_factory = DWARFEvaluatorFactory::FindPlugin(this); ++ return m_dwarf_evaluator_factory.get(); ++} +diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp +index fcaa868b083e..59a404d4a7e1 100644 +--- a/lldb/source/Core/PluginManager.cpp ++++ b/lldb/source/Core/PluginManager.cpp +@@ -1597,3 +1597,32 @@ bool PluginManager::CreateSettingForStructuredDataPlugin( + ConstString("Settings for structured data plug-ins"), properties_sp, + description, is_global_property); + } ++ ++#pragma mark DWARFEvaluator ++ ++typedef PluginInstance ++ DWARFEvaluatorFactoryInstance; ++typedef PluginInstances ++ DWARFEvaluatorFactoryInstances; ++ ++static DWARFEvaluatorFactoryInstances &GetDWARFEvaluatorFactoryInstances() { ++ static DWARFEvaluatorFactoryInstances g_instances; ++ return g_instances; ++} ++ ++bool PluginManager::RegisterPlugin( ++ ConstString name, const char *description, ++ DWARFEvaluatorFactoryCreateInstance create_callback) { ++ return GetDWARFEvaluatorFactoryInstances().RegisterPlugin(name, description, ++ create_callback); ++} ++ ++bool PluginManager::UnregisterPlugin( ++ DWARFEvaluatorFactoryCreateInstance create_callback) { ++ return GetDWARFEvaluatorFactoryInstances().UnregisterPlugin(create_callback); ++} ++ ++DWARFEvaluatorFactoryCreateInstance ++PluginManager::GetDWARFEvaluatorFactoryCreateCallbackAtIndex(uint32_t idx) { ++ return GetDWARFEvaluatorFactoryInstances().GetCallbackAtIndex(idx); ++} +diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp +index fb57c0fedf04..f92d6a54de94 100644 +--- a/lldb/source/Core/Value.cpp ++++ b/lldb/source/Core/Value.cpp +@@ -538,7 +538,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, + + if (process) { + const size_t bytes_read = +- process->ReadMemory(address, dst, byte_size, error); ++ process->ReadMemory(address, dst, byte_size, error, exe_ctx); + if (bytes_read != byte_size) + error.SetErrorStringWithFormat( + "read memory from 0x%" PRIx64 " failed (%u of %u bytes read)", +diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp +index 9c1ba99da1d0..b15b214b2a2f 100644 +--- a/lldb/source/Core/ValueObject.cpp ++++ b/lldb/source/Core/ValueObject.cpp +@@ -735,7 +735,7 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx, + if (process) { + heap_buf_ptr->SetByteSize(bytes); + size_t bytes_read = process->ReadMemory( +- addr + offset, heap_buf_ptr->GetBytes(), bytes, error); ++ addr + offset, heap_buf_ptr->GetBytes(), bytes, error, &exe_ctx); + if (error.Success() || bytes_read > 0) { + data.SetData(data_sp); + return bytes_read; +diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt +index bf94361dd6c1..4e76d547aeaf 100644 +--- a/lldb/source/Expression/CMakeLists.txt ++++ b/lldb/source/Expression/CMakeLists.txt +@@ -1,5 +1,7 @@ + add_lldb_library(lldbExpression + DiagnosticManager.cpp ++ DWARFEvaluator.cpp ++ DWARFEvaluatorFactory.cpp + DWARFExpression.cpp + Expression.cpp + ExpressionVariable.cpp +diff --git a/lldb/source/Expression/DWARFEvaluator.cpp b/lldb/source/Expression/DWARFEvaluator.cpp +new file mode 100644 +index 000000000000..06107e136197 +--- /dev/null ++++ b/lldb/source/Expression/DWARFEvaluator.cpp +@@ -0,0 +1,1952 @@ ++//===-- DWARFEvaluator.cpp ------------ -----------------------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "lldb/Expression/DWARFEvaluator.h" ++#include "lldb/Expression/DWARFExpression.h" ++ ++#include "lldb/Core/Module.h" ++#include "lldb/Core/Value.h" ++#include "lldb/Core/dwarf.h" ++ ++#include "lldb/Utility/Log.h" ++#include "lldb/Utility/RegisterValue.h" ++ ++#include "lldb/Target/Process.h" ++#include "lldb/Target/RegisterContext.h" ++#include "lldb/Target/StackFrame.h" ++ ++#include "Plugins/SymbolFile/DWARF/DWARFUnit.h" ++ ++using namespace lldb; ++using namespace lldb_private; ++ ++DWARFEvaluator::DWARFEvaluator(const DWARFExpression &dwarf_expression, ++ ExecutionContext *exe_ctx, ++ RegisterContext *reg_ctx, ++ const Value *initial_value_ptr, ++ const Value *object_address_ptr) ++ : m_dwarf_expression(dwarf_expression), m_exe_ctx(exe_ctx), ++ m_reg_ctx(reg_ctx), m_initial_value_ptr(initial_value_ptr), ++ m_object_address_ptr(object_address_ptr) {} ++ ++static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx, ++ lldb::RegisterKind reg_kind, ++ uint32_t reg_num, Status *error_ptr, ++ Value &value) { ++ if (reg_ctx == nullptr) { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat("No register context in frame.\n"); ++ } else { ++ uint32_t native_reg = ++ reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); ++ if (native_reg == LLDB_INVALID_REGNUM) { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat("Unable to convert register " ++ "kind=%u reg_num=%u to a native " ++ "register number.\n", ++ reg_kind, reg_num); ++ } else { ++ const RegisterInfo *reg_info = ++ reg_ctx->GetRegisterInfoAtIndex(native_reg); ++ RegisterValue reg_value; ++ if (reg_ctx->ReadRegister(reg_info, reg_value)) { ++ if (reg_value.GetScalarValue(value.GetScalar())) { ++ value.SetValueType(Value::ValueType::Scalar); ++ value.SetContext(Value::ContextType::RegisterInfo, ++ const_cast(reg_info)); ++ if (error_ptr) ++ error_ptr->Clear(); ++ return true; ++ } else { ++ // If we get this error, then we need to implement a value buffer in ++ // the dwarf expression evaluation function... ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "register %s can't be converted to a scalar value", ++ reg_info->name); ++ } ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat("register %s is not available", ++ reg_info->name); ++ } ++ } ++ } ++ return false; ++} ++ ++static bool Evaluate_DW_OP_entry_value(std::vector &stack, ++ ExecutionContext *exe_ctx, ++ RegisterContext *reg_ctx, ++ const DataExtractor &opcodes, ++ lldb::offset_t &opcode_offset, ++ Status *error_ptr, Log *log) { ++ // DW_OP_entry_value(sub-expr) describes the location a variable had upon ++ // function entry: this variable location is presumed to be optimized out at ++ // the current PC value. The caller of the function may have call site ++ // information that describes an alternate location for the variable (e.g. a ++ // constant literal, or a spilled stack value) in the parent frame. ++ // ++ // Example (this is pseudo-code & pseudo-DWARF, but hopefully illustrative): ++ // ++ // void child(int &sink, int x) { ++ // ... ++ // /* "x" gets optimized out. */ ++ // ++ // /* The location of "x" here is: DW_OP_entry_value($reg2). */ ++ // ++sink; ++ // } ++ // ++ // void parent() { ++ // int sink; ++ // ++ // /* ++ // * The callsite information emitted here is: ++ // * ++ // * DW_TAG_call_site ++ // * DW_AT_return_pc ... (for "child(sink, 123);") ++ // * DW_TAG_call_site_parameter (for "sink") ++ // * DW_AT_location ($reg1) ++ // * DW_AT_call_value ($SP - 8) ++ // * DW_TAG_call_site_parameter (for "x") ++ // * DW_AT_location ($reg2) ++ // * DW_AT_call_value ($literal 123) ++ // * ++ // * DW_TAG_call_site ++ // * DW_AT_return_pc ... (for "child(sink, 456);") ++ // * ... ++ // */ ++ // child(sink, 123); ++ // child(sink, 456); ++ // } ++ // ++ // When the program stops at "++sink" within `child`, the debugger determines ++ // the call site by analyzing the return address. Once the call site is found, ++ // the debugger determines which parameter is referenced by DW_OP_entry_value ++ // and evaluates the corresponding location for that parameter in `parent`. ++ ++ // 1. Find the function which pushed the current frame onto the stack. ++ if ((!exe_ctx || !exe_ctx->HasTargetScope()) || !reg_ctx) { ++ LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no exe/reg context"); ++ return false; ++ } ++ ++ StackFrame *current_frame = exe_ctx->GetFramePtr(); ++ Thread *thread = exe_ctx->GetThreadPtr(); ++ if (!current_frame || !thread) { ++ LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no current frame/thread"); ++ return false; ++ } ++ ++ Target &target = exe_ctx->GetTargetRef(); ++ StackFrameSP parent_frame = nullptr; ++ addr_t return_pc = LLDB_INVALID_ADDRESS; ++ uint32_t current_frame_idx = current_frame->GetFrameIndex(); ++ uint32_t num_frames = thread->GetStackFrameCount(); ++ for (uint32_t parent_frame_idx = current_frame_idx + 1; ++ parent_frame_idx < num_frames; ++parent_frame_idx) { ++ parent_frame = thread->GetStackFrameAtIndex(parent_frame_idx); ++ // Require a valid sequence of frames. ++ if (!parent_frame) ++ break; ++ ++ // Record the first valid return address, even if this is an inlined frame, ++ // in order to look up the associated call edge in the first non-inlined ++ // parent frame. ++ if (return_pc == LLDB_INVALID_ADDRESS) { ++ return_pc = parent_frame->GetFrameCodeAddress().GetLoadAddress(&target); ++ LLDB_LOG(log, ++ "Evaluate_DW_OP_entry_value: immediate ancestor with pc = {0:x}", ++ return_pc); ++ } ++ ++ // If we've found an inlined frame, skip it (these have no call site ++ // parameters). ++ if (parent_frame->IsInlined()) ++ continue; ++ ++ // We've found the first non-inlined parent frame. ++ break; ++ } ++ if (!parent_frame || !parent_frame->GetRegisterContext()) { ++ LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no parent frame with reg ctx"); ++ return false; ++ } ++ ++ Function *parent_func = ++ parent_frame->GetSymbolContext(eSymbolContextFunction).function; ++ if (!parent_func) { ++ LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no parent function"); ++ return false; ++ } ++ ++ // 2. Find the call edge in the parent function responsible for creating the ++ // current activation. ++ Function *current_func = ++ current_frame->GetSymbolContext(eSymbolContextFunction).function; ++ if (!current_func) { ++ LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no current function"); ++ return false; ++ } ++ ++ CallEdge *call_edge = nullptr; ++ ModuleList &modlist = target.GetImages(); ++ ExecutionContext parent_exe_ctx = *exe_ctx; ++ parent_exe_ctx.SetFrameSP(parent_frame); ++ if (!parent_frame->IsArtificial()) { ++ // If the parent frame is not artificial, the current activation may be ++ // produced by an ambiguous tail call. In this case, refuse to proceed. ++ call_edge = parent_func->GetCallEdgeForReturnAddress(return_pc, target); ++ if (!call_edge) { ++ LLDB_LOG(log, ++ "Evaluate_DW_OP_entry_value: no call edge for retn-pc = {0:x} " ++ "in parent frame {1}", ++ return_pc, parent_func->GetName()); ++ return false; ++ } ++ Function *callee_func = call_edge->GetCallee(modlist, parent_exe_ctx); ++ if (callee_func != current_func) { ++ LLDB_LOG(log, "Evaluate_DW_OP_entry_value: ambiguous call sequence, " ++ "can't find real parent frame"); ++ return false; ++ } ++ } else { ++ // The StackFrameList solver machinery has deduced that an unambiguous tail ++ // call sequence that produced the current activation. The first edge in ++ // the parent that points to the current function must be valid. ++ for (auto &edge : parent_func->GetTailCallingEdges()) { ++ if (edge->GetCallee(modlist, parent_exe_ctx) == current_func) { ++ call_edge = edge.get(); ++ break; ++ } ++ } ++ } ++ if (!call_edge) { ++ LLDB_LOG(log, "Evaluate_DW_OP_entry_value: no unambiguous edge from parent " ++ "to current function"); ++ return false; ++ } ++ ++ // 3. Attempt to locate the DW_OP_entry_value expression in the set of ++ // available call site parameters. If found, evaluate the corresponding ++ // parameter in the context of the parent frame. ++ const uint32_t subexpr_len = opcodes.GetULEB128(&opcode_offset); ++ const void *subexpr_data = opcodes.GetData(&opcode_offset, subexpr_len); ++ if (!subexpr_data) { ++ LLDB_LOG(log, "Evaluate_DW_OP_entry_value: subexpr could not be read"); ++ return false; ++ } ++ ++ const CallSiteParameter *matched_param = nullptr; ++ for (const CallSiteParameter ¶m : call_edge->GetCallSiteParameters()) { ++ DataExtractor param_subexpr_extractor; ++ if (!param.LocationInCallee.GetExpressionData(param_subexpr_extractor)) ++ continue; ++ lldb::offset_t param_subexpr_offset = 0; ++ const void *param_subexpr_data = ++ param_subexpr_extractor.GetData(¶m_subexpr_offset, subexpr_len); ++ if (!param_subexpr_data || ++ param_subexpr_extractor.BytesLeft(param_subexpr_offset) != 0) ++ continue; ++ ++ // At this point, the DW_OP_entry_value sub-expression and the callee-side ++ // expression in the call site parameter are known to have the same length. ++ // Check whether they are equal. ++ // ++ // Note that an equality check is sufficient: the contents of the ++ // DW_OP_entry_value subexpression are only used to identify the right call ++ // site parameter in the parent, and do not require any special handling. ++ if (memcmp(subexpr_data, param_subexpr_data, subexpr_len) == 0) { ++ matched_param = ¶m; ++ break; ++ } ++ } ++ if (!matched_param) { ++ LLDB_LOG(log, ++ "Evaluate_DW_OP_entry_value: no matching call site param found"); ++ return false; ++ } ++ ++ // TODO: Add support for DW_OP_push_object_address within a DW_OP_entry_value ++ // subexpresion whenever llvm does. ++ Value result; ++ const DWARFExpression ¶m_expr = matched_param->LocationInCaller; ++ if (!param_expr.Evaluate(&parent_exe_ctx, ++ parent_frame->GetRegisterContext().get(), ++ /*loclist_base_addr=*/LLDB_INVALID_ADDRESS, ++ /*initial_value_ptr=*/nullptr, ++ /*object_address_ptr=*/nullptr, result, error_ptr)) { ++ LLDB_LOG(log, ++ "Evaluate_DW_OP_entry_value: call site param evaluation failed"); ++ return false; ++ } ++ ++ stack.push_back(result); ++ return true; ++} ++ ++bool DWARFEvaluator::Evaluate(Value &result, Status *error_ptr) { ++ DataExtractor opcodes; ++ if (!m_dwarf_expression.GetExpressionData(opcodes)) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "no location, value may have been optimized out"); ++ return false; ++ } ++ return Evaluate(opcodes, result, error_ptr); ++} ++ ++bool DWARFEvaluator::Evaluate(const DataExtractor &opcodes, Value &result, ++ Status *error_ptr) { ++ if (opcodes.GetByteSize() == 0) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "no location, value may have been optimized out"); ++ return false; ++ } ++ std::vector stack; ++ ++ Process *process = nullptr; ++ StackFrame *frame = nullptr; ++ ++ if (m_exe_ctx) { ++ process = m_exe_ctx->GetProcessPtr(); ++ frame = m_exe_ctx->GetFramePtr(); ++ } ++ if (m_reg_ctx == nullptr && frame) ++ m_reg_ctx = frame->GetRegisterContext().get(); ++ ++ if (m_initial_value_ptr) ++ stack.push_back(*m_initial_value_ptr); ++ ++ lldb::offset_t offset = 0; ++ ++ /// Insertion point for evaluating multi-piece expression. ++ uint64_t op_piece_offset = 0; ++ Value pieces; // Used for DW_OP_piece ++ ++ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); ++ ++ uint8_t _opcode = 0; ++ ++ while (opcodes.ValidOffset(offset)) { ++ const lldb::offset_t op_offset = offset; ++ const uint8_t op = opcodes.GetU8(&offset); ++ _opcode = op; ++ ++ if (log && log->GetVerbose()) { ++ size_t count = stack.size(); ++ LLDB_LOGF(log, "Stack before operation has %" PRIu64 " values:", ++ (uint64_t)count); ++ for (size_t i = 0; i < count; ++i) { ++ StreamString new_value; ++ new_value.Printf("[%" PRIu64 "]", (uint64_t)i); ++ stack[i].Dump(&new_value); ++ LLDB_LOGF(log, " %s", new_value.GetData()); ++ } ++ LLDB_LOGF(log, "0x%8.8" PRIx64 ": %s", op_offset, ++ DW_OP_value_to_name(op)); ++ } ++ ++ if (!Evaluate(op, process, frame, stack, opcodes, offset, pieces, ++ op_piece_offset, log, error_ptr)) ++ return false; ++ } ++ ++ if (stack.empty()) { ++ // Nothing on the stack, check if we created a piece value from DW_OP_piece ++ // or DW_OP_bit_piece opcodes ++ if (pieces.GetBuffer().GetByteSize()) ++ result = pieces; ++ else { ++ if (error_ptr) ++ error_ptr->SetErrorString("Stack empty after evaluation."); ++ return false; ++ } ++ } else { ++ if (log && log->GetVerbose()) { ++ size_t count = stack.size(); ++ LLDB_LOGF(log, "Stack after operation has %" PRIu64 " values:", ++ (uint64_t)count); ++ for (size_t i = 0; i < count; ++i) { ++ StreamString new_value; ++ new_value.Printf("[%" PRIu64 "]", (uint64_t)i); ++ stack[i].Dump(&new_value); ++ LLDB_LOGF(log, " %s", new_value.GetData()); ++ } ++ } ++ result = stack.back(); ++ } ++ return true; // Return true on success ++} ++ ++bool DWARFEvaluator::Evaluate(const uint8_t op, Process *process, ++ StackFrame *frame, std::vector &stack, ++ const DataExtractor &opcodes, ++ lldb::offset_t &offset, Value &pieces, ++ uint64_t &op_piece_offset, Log *log, ++ Status *error_ptr) { ++ Value tmp; ++ uint32_t reg_num; ++ ++ lldb::ModuleSP module_sp = m_dwarf_expression.GetModule(); ++ const DWARFUnit *dwarf_cu = m_dwarf_expression.GetDWARFCompileUnit(); ++ const lldb::RegisterKind reg_kind = m_dwarf_expression.GetRegisterKind(); ++ ++ switch (op) { ++ // The DW_OP_addr operation has a single operand that encodes a machine ++ // address and whose size is the size of an address on the target machine. ++ case DW_OP_addr: ++ stack.push_back(Scalar(opcodes.GetAddress(&offset))); ++ stack.back().SetValueType(Value::ValueType::FileAddress); ++ // Convert the file address to a load address, so subsequent ++ // DWARF operators can operate on it. ++ if (frame) ++ stack.back().ConvertToLoadAddress(module_sp.get(), ++ frame->CalculateTarget().get()); ++ break; ++ ++ // The DW_OP_addr_sect_offset4 is used for any location expressions in ++ // shared libraries that have a location like: ++ // DW_OP_addr(0x1000) ++ // If this address resides in a shared library, then this virtual address ++ // won't make sense when it is evaluated in the context of a running ++ // process where shared libraries have been slid. To account for this, this ++ // new address type where we can store the section pointer and a 4 byte ++ // offset. ++ // case DW_OP_addr_sect_offset4: ++ // { ++ // result_type = eResultTypeFileAddress; ++ // lldb::Section *sect = (lldb::Section ++ // *)opcodes.GetMaxU64(&offset, sizeof(void *)); ++ // lldb::addr_t sect_offset = opcodes.GetU32(&offset); ++ // ++ // Address so_addr (sect, sect_offset); ++ // lldb::addr_t load_addr = so_addr.GetLoadAddress(); ++ // if (load_addr != LLDB_INVALID_ADDRESS) ++ // { ++ // // We successfully resolve a file address to a load ++ // // address. ++ // stack.push_back(load_addr); ++ // break; ++ // } ++ // else ++ // { ++ // // We were able ++ // if (error_ptr) ++ // error_ptr->SetErrorStringWithFormat ("Section %s in ++ // %s is not currently loaded.\n", ++ // sect->GetName().AsCString(), ++ // sect->GetModule()->GetFileSpec().GetFilename().AsCString()); ++ // return false; ++ // } ++ // } ++ // break; ++ ++ // OPCODE: DW_OP_deref ++ // OPERANDS: none ++ // DESCRIPTION: Pops the top stack entry and treats it as an address. ++ // The value retrieved from that address is pushed. The size of the data ++ // retrieved from the dereferenced address is the size of an address on the ++ // target machine. ++ case DW_OP_deref: { ++ if (stack.empty()) { ++ if (error_ptr) ++ error_ptr->SetErrorString("Expression stack empty for DW_OP_deref."); ++ return false; ++ } ++ Value::ValueType value_type = stack.back().GetValueType(); ++ switch (value_type) { ++ case Value::ValueType::HostAddress: { ++ void *src = (void *)stack.back().GetScalar().ULongLong(); ++ intptr_t ptr; ++ ::memcpy(&ptr, src, sizeof(void *)); ++ stack.back().GetScalar() = ptr; ++ stack.back().ClearContext(); ++ } break; ++ case Value::ValueType::FileAddress: { ++ auto file_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); ++ if (!module_sp) { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "need module to resolve file address for DW_OP_deref"); ++ return false; ++ } ++ Address so_addr; ++ if (!module_sp->ResolveFileAddress(file_addr, so_addr)) { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "failed to resolve file address in module"); ++ return false; ++ } ++ addr_t load_Addr = so_addr.GetLoadAddress(m_exe_ctx->GetTargetPtr()); ++ if (load_Addr == LLDB_INVALID_ADDRESS) { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat("failed to resolve load address"); ++ return false; ++ } ++ stack.back().GetScalar() = load_Addr; ++ stack.back().SetValueType(Value::ValueType::LoadAddress); ++ // Fall through to load address code below... ++ } ++ LLVM_FALLTHROUGH; ++ case Value::ValueType::LoadAddress: ++ if (m_exe_ctx) { ++ if (process) { ++ lldb::addr_t pointer_addr = ++ stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); ++ Status error; ++ lldb::addr_t pointer_value = ++ process->ReadPointerFromMemory(pointer_addr, error); ++ if (pointer_value != LLDB_INVALID_ADDRESS) { ++ stack.back().GetScalar() = pointer_value; ++ stack.back().ClearContext(); ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "Failed to dereference pointer from 0x%" PRIx64 ++ " for DW_OP_deref: %s\n", ++ pointer_addr, error.AsCString()); ++ return false; ++ } ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "NULL process for DW_OP_deref.\n"); ++ return false; ++ } ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "NULL execution context for DW_OP_deref.\n"); ++ return false; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ } break; ++ ++ // OPCODE: DW_OP_deref_size ++ // OPERANDS: 1 ++ // 1 - uint8_t that specifies the size of the data to dereference. ++ // DESCRIPTION: Behaves like the DW_OP_deref operation: it pops the top ++ // stack entry and treats it as an address. The value retrieved from that ++ // address is pushed. In the DW_OP_deref_size operation, however, the size ++ // in bytes of the data retrieved from the dereferenced address is ++ // specified by the single operand. This operand is a 1-byte unsigned ++ // integral constant whose value may not be larger than the size of an ++ // address on the target machine. The data retrieved is zero extended to ++ // the size of an address on the target machine before being pushed on the ++ // expression stack. ++ case DW_OP_deref_size: { ++ if (stack.empty()) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack empty for DW_OP_deref_size."); ++ return false; ++ } ++ uint8_t size = opcodes.GetU8(&offset); ++ Value::ValueType value_type = stack.back().GetValueType(); ++ switch (value_type) { ++ case Value::ValueType::HostAddress: { ++ void *src = (void *)stack.back().GetScalar().ULongLong(); ++ intptr_t ptr; ++ ::memcpy(&ptr, src, sizeof(void *)); ++ // I can't decide whether the size operand should apply to the bytes in ++ // their ++ // lldb-host endianness or the target endianness.. I doubt this'll ever ++ // come up but I'll opt for assuming big endian regardless. ++ switch (size) { ++ case 1: ++ ptr = ptr & 0xff; ++ break; ++ case 2: ++ ptr = ptr & 0xffff; ++ break; ++ case 3: ++ ptr = ptr & 0xffffff; ++ break; ++ case 4: ++ ptr = ptr & 0xffffffff; ++ break; ++ // the casts are added to work around the case where intptr_t is a 32 ++ // bit quantity; ++ // presumably we won't hit the 5..7 cases if (void*) is 32-bits in this ++ // program. ++ case 5: ++ ptr = (intptr_t)ptr & 0xffffffffffULL; ++ break; ++ case 6: ++ ptr = (intptr_t)ptr & 0xffffffffffffULL; ++ break; ++ case 7: ++ ptr = (intptr_t)ptr & 0xffffffffffffffULL; ++ break; ++ default: ++ break; ++ } ++ stack.back().GetScalar() = ptr; ++ stack.back().ClearContext(); ++ } break; ++ case Value::ValueType::LoadAddress: ++ if (m_exe_ctx) { ++ if (process) { ++ lldb::addr_t pointer_addr = ++ stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); ++ uint8_t addr_bytes[sizeof(lldb::addr_t)]; ++ Status error; ++ if (process->ReadMemory(pointer_addr, &addr_bytes, size, error) == ++ size) { ++ DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), ++ process->GetByteOrder(), size); ++ lldb::offset_t addr_data_offset = 0; ++ switch (size) { ++ case 1: ++ stack.back().GetScalar() = addr_data.GetU8(&addr_data_offset); ++ break; ++ case 2: ++ stack.back().GetScalar() = addr_data.GetU16(&addr_data_offset); ++ break; ++ case 4: ++ stack.back().GetScalar() = addr_data.GetU32(&addr_data_offset); ++ break; ++ case 8: ++ stack.back().GetScalar() = addr_data.GetU64(&addr_data_offset); ++ break; ++ default: ++ stack.back().GetScalar() = ++ addr_data.GetAddress(&addr_data_offset); ++ } ++ stack.back().ClearContext(); ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "Failed to dereference pointer from 0x%" PRIx64 ++ " for DW_OP_deref: %s\n", ++ pointer_addr, error.AsCString()); ++ return false; ++ } ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "NULL process for DW_OP_deref.\n"); ++ return false; ++ } ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "NULL execution context for DW_OP_deref.\n"); ++ return false; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ } break; ++ ++ // OPCODE: DW_OP_xderef_size ++ // OPERANDS: 1 ++ // 1 - uint8_t that specifies the size of the data to dereference. ++ // DESCRIPTION: Behaves like the DW_OP_xderef operation: the entry at ++ // the top of the stack is treated as an address. The second stack entry is ++ // treated as an "address space identifier" for those architectures that ++ // support multiple address spaces. The top two stack elements are popped, ++ // a data item is retrieved through an implementation-defined address ++ // calculation and pushed as the new stack top. In the DW_OP_xderef_size ++ // operation, however, the size in bytes of the data retrieved from the ++ // dereferenced address is specified by the single operand. This operand is ++ // a 1-byte unsigned integral constant whose value may not be larger than ++ // the size of an address on the target machine. The data retrieved is zero ++ // extended to the size of an address on the target machine before being ++ // pushed on the expression stack. ++ case DW_OP_xderef_size: ++ if (error_ptr) ++ error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef_size."); ++ return false; ++ // OPCODE: DW_OP_xderef ++ // OPERANDS: none ++ // DESCRIPTION: Provides an extended dereference mechanism. The entry at ++ // the top of the stack is treated as an address. The second stack entry is ++ // treated as an "address space identifier" for those architectures that ++ // support multiple address spaces. The top two stack elements are popped, ++ // a data item is retrieved through an implementation-defined address ++ // calculation and pushed as the new stack top. The size of the data ++ // retrieved from the dereferenced address is the size of an address on the ++ // target machine. ++ case DW_OP_xderef: ++ if (error_ptr) ++ error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef."); ++ return false; ++ ++ // All DW_OP_constXXX opcodes have a single operand as noted below: ++ // ++ // Opcode Operand 1 ++ // DW_OP_const1u 1-byte unsigned integer constant DW_OP_const1s ++ // 1-byte signed integer constant DW_OP_const2u 2-byte unsigned integer ++ // constant DW_OP_const2s 2-byte signed integer constant DW_OP_const4u ++ // 4-byte unsigned integer constant DW_OP_const4s 4-byte signed integer ++ // constant DW_OP_const8u 8-byte unsigned integer constant DW_OP_const8s ++ // 8-byte signed integer constant DW_OP_constu unsigned LEB128 integer ++ // constant DW_OP_consts signed LEB128 integer constant ++ case DW_OP_const1u: ++ stack.push_back(Scalar((uint8_t)opcodes.GetU8(&offset))); ++ break; ++ case DW_OP_const1s: ++ stack.push_back(Scalar((int8_t)opcodes.GetU8(&offset))); ++ break; ++ case DW_OP_const2u: ++ stack.push_back(Scalar((uint16_t)opcodes.GetU16(&offset))); ++ break; ++ case DW_OP_const2s: ++ stack.push_back(Scalar((int16_t)opcodes.GetU16(&offset))); ++ break; ++ case DW_OP_const4u: ++ stack.push_back(Scalar((uint32_t)opcodes.GetU32(&offset))); ++ break; ++ case DW_OP_const4s: ++ stack.push_back(Scalar((int32_t)opcodes.GetU32(&offset))); ++ break; ++ case DW_OP_const8u: ++ stack.push_back(Scalar((uint64_t)opcodes.GetU64(&offset))); ++ break; ++ case DW_OP_const8s: ++ stack.push_back(Scalar((int64_t)opcodes.GetU64(&offset))); ++ break; ++ case DW_OP_constu: ++ stack.push_back(Scalar(opcodes.GetULEB128(&offset))); ++ break; ++ case DW_OP_consts: ++ stack.push_back(Scalar(opcodes.GetSLEB128(&offset))); ++ break; ++ ++ // OPCODE: DW_OP_dup ++ // OPERANDS: none ++ // DESCRIPTION: duplicates the value at the top of the stack ++ case DW_OP_dup: ++ if (stack.empty()) { ++ if (error_ptr) ++ error_ptr->SetErrorString("Expression stack empty for DW_OP_dup."); ++ return false; ++ } else ++ stack.push_back(stack.back()); ++ break; ++ ++ // OPCODE: DW_OP_drop ++ // OPERANDS: none ++ // DESCRIPTION: pops the value at the top of the stack ++ case DW_OP_drop: ++ if (stack.empty()) { ++ if (error_ptr) ++ error_ptr->SetErrorString("Expression stack empty for DW_OP_drop."); ++ return false; ++ } else ++ stack.pop_back(); ++ break; ++ ++ // OPCODE: DW_OP_over ++ // OPERANDS: none ++ // DESCRIPTION: Duplicates the entry currently second in the stack at ++ // the top of the stack. ++ case DW_OP_over: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_over."); ++ return false; ++ } else ++ stack.push_back(stack[stack.size() - 2]); ++ break; ++ ++ // OPCODE: DW_OP_pick ++ // OPERANDS: uint8_t index into the current stack ++ // DESCRIPTION: The stack entry with the specified index (0 through 255, ++ // inclusive) is pushed on the stack ++ case DW_OP_pick: { ++ uint8_t pick_idx = opcodes.GetU8(&offset); ++ if (pick_idx < stack.size()) ++ stack.push_back(stack[stack.size() - 1 - pick_idx]); ++ else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "Index %u out of range for DW_OP_pick.\n", pick_idx); ++ return false; ++ } ++ } break; ++ ++ // OPCODE: DW_OP_swap ++ // OPERANDS: none ++ // DESCRIPTION: swaps the top two stack entries. The entry at the top ++ // of the stack becomes the second stack entry, and the second entry ++ // becomes the top of the stack ++ case DW_OP_swap: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_swap."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.back() = stack[stack.size() - 2]; ++ stack[stack.size() - 2] = tmp; ++ } ++ break; ++ ++ // OPCODE: DW_OP_rot ++ // OPERANDS: none ++ // DESCRIPTION: Rotates the first three stack entries. The entry at ++ // the top of the stack becomes the third stack entry, the second entry ++ // becomes the top of the stack, and the third entry becomes the second ++ // entry. ++ case DW_OP_rot: ++ if (stack.size() < 3) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 3 items for DW_OP_rot."); ++ return false; ++ } else { ++ size_t last_idx = stack.size() - 1; ++ Value old_top = stack[last_idx]; ++ stack[last_idx] = stack[last_idx - 1]; ++ stack[last_idx - 1] = stack[last_idx - 2]; ++ stack[last_idx - 2] = old_top; ++ } ++ break; ++ ++ // OPCODE: DW_OP_abs ++ // OPERANDS: none ++ // DESCRIPTION: pops the top stack entry, interprets it as a signed ++ // value and pushes its absolute value. If the absolute value can not be ++ // represented, the result is undefined. ++ case DW_OP_abs: ++ if (stack.empty()) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 1 item for DW_OP_abs."); ++ return false; ++ } else if (!stack.back().ResolveValue(m_exe_ctx).AbsoluteValue()) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Failed to take the absolute value of the first stack item."); ++ return false; ++ } ++ break; ++ ++ // OPCODE: DW_OP_and ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack values, performs a bitwise and ++ // operation on the two, and pushes the result. ++ case DW_OP_and: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_and."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) & tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_div ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack values, divides the former second ++ // entry by the former top of the stack using signed division, and pushes ++ // the result. ++ case DW_OP_div: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_div."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ if (tmp.ResolveValue(m_exe_ctx).IsZero()) { ++ if (error_ptr) ++ error_ptr->SetErrorString("Divide by zero."); ++ return false; ++ } else { ++ stack.pop_back(); ++ stack.back() = ++ stack.back().ResolveValue(m_exe_ctx) / tmp.ResolveValue(m_exe_ctx); ++ if (!stack.back().ResolveValue(m_exe_ctx).IsValid()) { ++ if (error_ptr) ++ error_ptr->SetErrorString("Divide failed."); ++ return false; ++ } ++ } ++ } ++ break; ++ ++ // OPCODE: DW_OP_minus ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack values, subtracts the former top ++ // of the stack from the former second entry, and pushes the result. ++ case DW_OP_minus: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_minus."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) - tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_mod ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack values and pushes the result of ++ // the calculation: former second stack entry modulo the former top of the ++ // stack. ++ case DW_OP_mod: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_mod."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) % tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_mul ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack entries, multiplies them ++ // together, and pushes the result. ++ case DW_OP_mul: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_mul."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) * tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_neg ++ // OPERANDS: none ++ // DESCRIPTION: pops the top stack entry, and pushes its negation. ++ case DW_OP_neg: ++ if (stack.empty()) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 1 item for DW_OP_neg."); ++ return false; ++ } else { ++ if (!stack.back().ResolveValue(m_exe_ctx).UnaryNegate()) { ++ if (error_ptr) ++ error_ptr->SetErrorString("Unary negate failed."); ++ return false; ++ } ++ } ++ break; ++ ++ // OPCODE: DW_OP_not ++ // OPERANDS: none ++ // DESCRIPTION: pops the top stack entry, and pushes its bitwise ++ // complement ++ case DW_OP_not: ++ if (stack.empty()) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 1 item for DW_OP_not."); ++ return false; ++ } else { ++ if (!stack.back().ResolveValue(m_exe_ctx).OnesComplement()) { ++ if (error_ptr) ++ error_ptr->SetErrorString("Logical NOT failed."); ++ return false; ++ } ++ } ++ break; ++ ++ // OPCODE: DW_OP_or ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack entries, performs a bitwise or ++ // operation on the two, and pushes the result. ++ case DW_OP_or: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_or."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) | tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_plus ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack entries, adds them together, and ++ // pushes the result. ++ case DW_OP_plus: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_plus."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().GetScalar() += tmp.GetScalar(); ++ } ++ break; ++ ++ // OPCODE: DW_OP_plus_uconst ++ // OPERANDS: none ++ // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128 ++ // constant operand and pushes the result. ++ case DW_OP_plus_uconst: ++ if (stack.empty()) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 1 item for DW_OP_plus_uconst."); ++ return false; ++ } else { ++ const uint64_t uconst_value = opcodes.GetULEB128(&offset); ++ // Implicit conversion from a UINT to a Scalar... ++ stack.back().GetScalar() += uconst_value; ++ if (!stack.back().GetScalar().IsValid()) { ++ if (error_ptr) ++ error_ptr->SetErrorString("DW_OP_plus_uconst failed."); ++ return false; ++ } ++ } ++ break; ++ ++ // OPCODE: DW_OP_shl ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack entries, shifts the former ++ // second entry left by the number of bits specified by the former top of ++ // the stack, and pushes the result. ++ case DW_OP_shl: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_shl."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) <<= tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_shr ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack entries, shifts the former second ++ // entry right logically (filling with zero bits) by the number of bits ++ // specified by the former top of the stack, and pushes the result. ++ case DW_OP_shr: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_shr."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ if (!stack.back().ResolveValue(m_exe_ctx).ShiftRightLogical( ++ tmp.ResolveValue(m_exe_ctx))) { ++ if (error_ptr) ++ error_ptr->SetErrorString("DW_OP_shr failed."); ++ return false; ++ } ++ } ++ break; ++ ++ // OPCODE: DW_OP_shra ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack entries, shifts the former second ++ // entry right arithmetically (divide the magnitude by 2, keep the same ++ // sign for the result) by the number of bits specified by the former top ++ // of the stack, and pushes the result. ++ case DW_OP_shra: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_shra."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) >>= tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_xor ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack entries, performs the bitwise ++ // exclusive-or operation on the two, and pushes the result. ++ case DW_OP_xor: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_xor."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) ^ tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_skip ++ // OPERANDS: int16_t ++ // DESCRIPTION: An unconditional branch. Its single operand is a 2-byte ++ // signed integer constant. The 2-byte constant is the number of bytes of ++ // the DWARF expression to skip forward or backward from the current ++ // operation, beginning after the 2-byte constant. ++ case DW_OP_skip: { ++ int16_t skip_offset = (int16_t)opcodes.GetU16(&offset); ++ lldb::offset_t new_offset = offset + skip_offset; ++ if (opcodes.ValidOffset(new_offset)) ++ offset = new_offset; ++ else { ++ if (error_ptr) ++ error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip."); ++ return false; ++ } ++ } break; ++ ++ // OPCODE: DW_OP_bra ++ // OPERANDS: int16_t ++ // DESCRIPTION: A conditional branch. Its single operand is a 2-byte ++ // signed integer constant. This operation pops the top of stack. If the ++ // value popped is not the constant 0, the 2-byte constant operand is the ++ // number of bytes of the DWARF expression to skip forward or backward from ++ // the current operation, beginning after the 2-byte constant. ++ case DW_OP_bra: ++ if (stack.empty()) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 1 item for DW_OP_bra."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ int16_t bra_offset = (int16_t)opcodes.GetU16(&offset); ++ Scalar zero(0); ++ if (tmp.ResolveValue(m_exe_ctx) != zero) { ++ lldb::offset_t new_offset = offset + bra_offset; ++ if (opcodes.ValidOffset(new_offset)) ++ offset = new_offset; ++ else { ++ if (error_ptr) ++ error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra."); ++ return false; ++ } ++ } ++ } ++ break; ++ ++ // OPCODE: DW_OP_eq ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack values, compares using the ++ // equals (==) operator. ++ // STACK RESULT: push the constant value 1 onto the stack if the result ++ // of the operation is true or the constant value 0 if the result of the ++ // operation is false. ++ case DW_OP_eq: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_eq."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) == tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_ge ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack values, compares using the ++ // greater than or equal to (>=) operator. ++ // STACK RESULT: push the constant value 1 onto the stack if the result ++ // of the operation is true or the constant value 0 if the result of the ++ // operation is false. ++ case DW_OP_ge: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_ge."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) >= tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_gt ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack values, compares using the ++ // greater than (>) operator. ++ // STACK RESULT: push the constant value 1 onto the stack if the result ++ // of the operation is true or the constant value 0 if the result of the ++ // operation is false. ++ case DW_OP_gt: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_gt."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) > tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_le ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack values, compares using the ++ // less than or equal to (<=) operator. ++ // STACK RESULT: push the constant value 1 onto the stack if the result ++ // of the operation is true or the constant value 0 if the result of the ++ // operation is false. ++ case DW_OP_le: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_le."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) <= tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_lt ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack values, compares using the ++ // less than (<) operator. ++ // STACK RESULT: push the constant value 1 onto the stack if the result ++ // of the operation is true or the constant value 0 if the result of the ++ // operation is false. ++ case DW_OP_lt: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_lt."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) < tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_ne ++ // OPERANDS: none ++ // DESCRIPTION: pops the top two stack values, compares using the ++ // not equal (!=) operator. ++ // STACK RESULT: push the constant value 1 onto the stack if the result ++ // of the operation is true or the constant value 0 if the result of the ++ // operation is false. ++ case DW_OP_ne: ++ if (stack.size() < 2) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 2 items for DW_OP_ne."); ++ return false; ++ } else { ++ tmp = stack.back(); ++ stack.pop_back(); ++ stack.back().ResolveValue(m_exe_ctx) = ++ stack.back().ResolveValue(m_exe_ctx) != tmp.ResolveValue(m_exe_ctx); ++ } ++ break; ++ ++ // OPCODE: DW_OP_litn ++ // OPERANDS: none ++ // DESCRIPTION: encode the unsigned literal values from 0 through 31. ++ // STACK RESULT: push the unsigned literal constant value onto the top ++ // of the stack. ++ case DW_OP_lit0: ++ case DW_OP_lit1: ++ case DW_OP_lit2: ++ case DW_OP_lit3: ++ case DW_OP_lit4: ++ case DW_OP_lit5: ++ case DW_OP_lit6: ++ case DW_OP_lit7: ++ case DW_OP_lit8: ++ case DW_OP_lit9: ++ case DW_OP_lit10: ++ case DW_OP_lit11: ++ case DW_OP_lit12: ++ case DW_OP_lit13: ++ case DW_OP_lit14: ++ case DW_OP_lit15: ++ case DW_OP_lit16: ++ case DW_OP_lit17: ++ case DW_OP_lit18: ++ case DW_OP_lit19: ++ case DW_OP_lit20: ++ case DW_OP_lit21: ++ case DW_OP_lit22: ++ case DW_OP_lit23: ++ case DW_OP_lit24: ++ case DW_OP_lit25: ++ case DW_OP_lit26: ++ case DW_OP_lit27: ++ case DW_OP_lit28: ++ case DW_OP_lit29: ++ case DW_OP_lit30: ++ case DW_OP_lit31: ++ stack.push_back(Scalar((uint64_t)(op - DW_OP_lit0))); ++ break; ++ ++ // OPCODE: DW_OP_regN ++ // OPERANDS: none ++ // DESCRIPTION: Push the value in register n on the top of the stack. ++ case DW_OP_reg0: ++ case DW_OP_reg1: ++ case DW_OP_reg2: ++ case DW_OP_reg3: ++ case DW_OP_reg4: ++ case DW_OP_reg5: ++ case DW_OP_reg6: ++ case DW_OP_reg7: ++ case DW_OP_reg8: ++ case DW_OP_reg9: ++ case DW_OP_reg10: ++ case DW_OP_reg11: ++ case DW_OP_reg12: ++ case DW_OP_reg13: ++ case DW_OP_reg14: ++ case DW_OP_reg15: ++ case DW_OP_reg16: ++ case DW_OP_reg17: ++ case DW_OP_reg18: ++ case DW_OP_reg19: ++ case DW_OP_reg20: ++ case DW_OP_reg21: ++ case DW_OP_reg22: ++ case DW_OP_reg23: ++ case DW_OP_reg24: ++ case DW_OP_reg25: ++ case DW_OP_reg26: ++ case DW_OP_reg27: ++ case DW_OP_reg28: ++ case DW_OP_reg29: ++ case DW_OP_reg30: ++ case DW_OP_reg31: { ++ reg_num = op - DW_OP_reg0; ++ ++ if (ReadRegisterValueAsScalar(m_reg_ctx, reg_kind, reg_num, error_ptr, tmp)) ++ stack.push_back(tmp); ++ else ++ return false; ++ } break; ++ // OPCODE: DW_OP_regx ++ // OPERANDS: ++ // ULEB128 literal operand that encodes the register. ++ // DESCRIPTION: Push the value in register on the top of the stack. ++ case DW_OP_regx: { ++ reg_num = opcodes.GetULEB128(&offset); ++ if (ReadRegisterValueAsScalar(m_reg_ctx, reg_kind, reg_num, error_ptr, tmp)) ++ stack.push_back(tmp); ++ else ++ return false; ++ } break; ++ ++ // OPCODE: DW_OP_bregN ++ // OPERANDS: ++ // SLEB128 offset from register N ++ // DESCRIPTION: Value is in memory at the address specified by register ++ // N plus an offset. ++ case DW_OP_breg0: ++ case DW_OP_breg1: ++ case DW_OP_breg2: ++ case DW_OP_breg3: ++ case DW_OP_breg4: ++ case DW_OP_breg5: ++ case DW_OP_breg6: ++ case DW_OP_breg7: ++ case DW_OP_breg8: ++ case DW_OP_breg9: ++ case DW_OP_breg10: ++ case DW_OP_breg11: ++ case DW_OP_breg12: ++ case DW_OP_breg13: ++ case DW_OP_breg14: ++ case DW_OP_breg15: ++ case DW_OP_breg16: ++ case DW_OP_breg17: ++ case DW_OP_breg18: ++ case DW_OP_breg19: ++ case DW_OP_breg20: ++ case DW_OP_breg21: ++ case DW_OP_breg22: ++ case DW_OP_breg23: ++ case DW_OP_breg24: ++ case DW_OP_breg25: ++ case DW_OP_breg26: ++ case DW_OP_breg27: ++ case DW_OP_breg28: ++ case DW_OP_breg29: ++ case DW_OP_breg30: ++ case DW_OP_breg31: { ++ reg_num = op - DW_OP_breg0; ++ ++ if (ReadRegisterValueAsScalar(m_reg_ctx, reg_kind, reg_num, error_ptr, ++ tmp)) { ++ int64_t breg_offset = opcodes.GetSLEB128(&offset); ++ tmp.ResolveValue(m_exe_ctx) += (uint64_t)breg_offset; ++ tmp.ClearContext(); ++ stack.push_back(tmp); ++ stack.back().SetValueType(Value::ValueType::LoadAddress); ++ } else ++ return false; ++ } break; ++ // OPCODE: DW_OP_bregx ++ // OPERANDS: 2 ++ // ULEB128 literal operand that encodes the register. ++ // SLEB128 offset from register N ++ // DESCRIPTION: Value is in memory at the address specified by register ++ // N plus an offset. ++ case DW_OP_bregx: { ++ reg_num = opcodes.GetULEB128(&offset); ++ ++ if (ReadRegisterValueAsScalar(m_reg_ctx, reg_kind, reg_num, error_ptr, ++ tmp)) { ++ int64_t breg_offset = opcodes.GetSLEB128(&offset); ++ tmp.ResolveValue(m_exe_ctx) += (uint64_t)breg_offset; ++ tmp.ClearContext(); ++ stack.push_back(tmp); ++ stack.back().SetValueType(Value::ValueType::LoadAddress); ++ } else ++ return false; ++ } break; ++ ++ case DW_OP_fbreg: ++ if (m_exe_ctx) { ++ if (frame) { ++ Scalar value; ++ if (frame->GetFrameBaseValue(value, error_ptr)) { ++ int64_t fbreg_offset = opcodes.GetSLEB128(&offset); ++ value += fbreg_offset; ++ stack.push_back(value); ++ stack.back().SetValueType(Value::ValueType::LoadAddress); ++ } else ++ return false; ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Invalid stack frame in context for DW_OP_fbreg opcode."); ++ return false; ++ } ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "NULL execution context for DW_OP_fbreg.\n"); ++ return false; ++ } ++ ++ break; ++ ++ // OPCODE: DW_OP_nop ++ // OPERANDS: none ++ // DESCRIPTION: A place holder. It has no effect on the location stack ++ // or any of its values. ++ case DW_OP_nop: ++ break; ++ ++ // OPCODE: DW_OP_piece ++ // OPERANDS: 1 ++ // ULEB128: byte size of the piece ++ // DESCRIPTION: The operand describes the size in bytes of the piece of ++ // the object referenced by the DWARF expression whose result is at the top ++ // of the stack. If the piece is located in a register, but does not occupy ++ // the entire register, the placement of the piece within that register is ++ // defined by the ABI. ++ // ++ // Many compilers store a single variable in sets of registers, or store a ++ // variable partially in memory and partially in registers. DW_OP_piece ++ // provides a way of describing how large a part of a variable a particular ++ // DWARF expression refers to. ++ case DW_OP_piece: { ++ const uint64_t piece_byte_size = opcodes.GetULEB128(&offset); ++ ++ if (piece_byte_size > 0) { ++ Value curr_piece; ++ ++ if (stack.empty()) { ++ // In a multi-piece expression, this means that the current piece is ++ // not available. Fill with zeros for now by resizing the data and ++ // appending it ++ curr_piece.ResizeData(piece_byte_size); ++ // Note that "0" is not a correct value for the unknown bits. ++ // It would be better to also return a mask of valid bits together ++ // with the expression result, so the debugger can print missing ++ // members as "" or something. ++ ::memset(curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size); ++ pieces.AppendDataToHostBuffer(curr_piece); ++ } else { ++ Status error; ++ // Extract the current piece into "curr_piece" ++ Value curr_piece_source_value(stack.back()); ++ stack.pop_back(); ++ ++ const Value::ValueType curr_piece_source_value_type = ++ curr_piece_source_value.GetValueType(); ++ switch (curr_piece_source_value_type) { ++ case Value::ValueType::LoadAddress: ++ if (process) { ++ if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) { ++ lldb::addr_t load_addr = ++ curr_piece_source_value.GetScalar().ULongLong( ++ LLDB_INVALID_ADDRESS); ++ if (process->ReadMemory( ++ load_addr, curr_piece.GetBuffer().GetBytes(), ++ piece_byte_size, error) != piece_byte_size) { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "failed to read memory DW_OP_piece(%" PRIu64 ++ ") from 0x%" PRIx64, ++ piece_byte_size, load_addr); ++ return false; ++ } ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "failed to resize the piece memory buffer for " ++ "DW_OP_piece(%" PRIu64 ")", ++ piece_byte_size); ++ return false; ++ } ++ } ++ break; ++ ++ case Value::ValueType::FileAddress: ++ case Value::ValueType::HostAddress: ++ if (error_ptr) { ++ lldb::addr_t addr = curr_piece_source_value.GetScalar().ULongLong( ++ LLDB_INVALID_ADDRESS); ++ error_ptr->SetErrorStringWithFormat( ++ "failed to read memory DW_OP_piece(%" PRIu64 ++ ") from %s address 0x%" PRIx64, ++ piece_byte_size, ++ curr_piece_source_value.GetValueType() == ++ Value::ValueType::FileAddress ++ ? "file" ++ : "host", ++ addr); ++ } ++ return false; ++ ++ case Value::ValueType::Scalar: { ++ uint32_t bit_size = piece_byte_size * 8; ++ uint32_t bit_offset = 0; ++ Scalar &scalar = curr_piece_source_value.GetScalar(); ++ if (!scalar.ExtractBitfield(bit_size, bit_offset)) { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "unable to extract %" PRIu64 " bytes from a %" PRIu64 ++ " byte scalar value.", ++ piece_byte_size, ++ (uint64_t)curr_piece_source_value.GetScalar().GetByteSize()); ++ return false; ++ } ++ // Create curr_piece with bit_size. By default Scalar ++ // grows to the nearest host integer type. ++ llvm::APInt fail_value(1, 0, false); ++ llvm::APInt ap_int = scalar.UInt128(fail_value); ++ assert(ap_int.getBitWidth() >= bit_size); ++ llvm::ArrayRef buf{ap_int.getRawData(), ++ ap_int.getNumWords()}; ++ curr_piece.GetScalar() = Scalar(llvm::APInt(bit_size, buf)); ++ } break; ++ } ++ ++ // Check if this is the first piece? ++ if (op_piece_offset == 0) { ++ // This is the first piece, we should push it back onto the stack ++ // so subsequent pieces will be able to access this piece and add ++ // to it. ++ if (pieces.AppendDataToHostBuffer(curr_piece) == 0) { ++ if (error_ptr) ++ error_ptr->SetErrorString("failed to append piece data"); ++ return false; ++ } ++ } else { ++ // If this is the second or later piece there should be a value on ++ // the stack. ++ if (pieces.GetBuffer().GetByteSize() != op_piece_offset) { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "DW_OP_piece for offset %" PRIu64 ++ " but top of stack is of size %" PRIu64, ++ op_piece_offset, pieces.GetBuffer().GetByteSize()); ++ return false; ++ } ++ ++ if (pieces.AppendDataToHostBuffer(curr_piece) == 0) { ++ if (error_ptr) ++ error_ptr->SetErrorString("failed to append piece data"); ++ return false; ++ } ++ } ++ } ++ op_piece_offset += piece_byte_size; ++ } ++ } break; ++ ++ case DW_OP_bit_piece: // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3); ++ if (stack.size() < 1) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 1 item for DW_OP_bit_piece."); ++ return false; ++ } else { ++ const uint64_t piece_bit_size = opcodes.GetULEB128(&offset); ++ const uint64_t piece_bit_offset = opcodes.GetULEB128(&offset); ++ switch (stack.back().GetValueType()) { ++ case Value::ValueType::Scalar: { ++ if (!stack.back().GetScalar().ExtractBitfield(piece_bit_size, ++ piece_bit_offset)) { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "unable to extract %" PRIu64 " bit value with %" PRIu64 ++ " bit offset from a %" PRIu64 " bit scalar value.", ++ piece_bit_size, piece_bit_offset, ++ (uint64_t)(stack.back().GetScalar().GetByteSize() * 8)); ++ return false; ++ } ++ } break; ++ ++ case Value::ValueType::FileAddress: ++ case Value::ValueType::LoadAddress: ++ case Value::ValueType::HostAddress: ++ if (error_ptr) { ++ error_ptr->SetErrorStringWithFormat( ++ "unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 ++ ", bit_offset = %" PRIu64 ") from an address value.", ++ piece_bit_size, piece_bit_offset); ++ } ++ return false; ++ } ++ } ++ break; ++ ++ // OPCODE: DW_OP_push_object_address ++ // OPERANDS: none ++ // DESCRIPTION: Pushes the address of the object currently being ++ // evaluated as part of evaluation of a user presented expression. This ++ // object may correspond to an independent variable described by its own ++ // DIE or it may be a component of an array, structure, or class whose ++ // address has been dynamically determined by an earlier step during user ++ // expression evaluation. ++ case DW_OP_push_object_address: ++ if (m_object_address_ptr) ++ stack.push_back(*m_object_address_ptr); ++ else { ++ if (error_ptr) ++ error_ptr->SetErrorString("DW_OP_push_object_address used without " ++ "specifying an object address"); ++ return false; ++ } ++ break; ++ ++ // OPCODE: DW_OP_call2 ++ // OPERANDS: ++ // uint16_t compile unit relative offset of a DIE ++ // DESCRIPTION: Performs subroutine calls during evaluation ++ // of a DWARF expression. The operand is the 2-byte unsigned offset of a ++ // debugging information entry in the current compilation unit. ++ // ++ // Operand interpretation is exactly like that for DW_FORM_ref2. ++ // ++ // This operation transfers control of DWARF expression evaluation to the ++ // DW_AT_location attribute of the referenced DIE. If there is no such ++ // attribute, then there is no effect. Execution of the DWARF expression of ++ // a DW_AT_location attribute may add to and/or remove from values on the ++ // stack. Execution returns to the point following the call when the end of ++ // the attribute is reached. Values on the stack at the time of the call ++ // may be used as parameters by the called expression and values left on ++ // the stack by the called expression may be used as return values by prior ++ // agreement between the calling and called expressions. ++ case DW_OP_call2: ++ if (error_ptr) ++ error_ptr->SetErrorString("Unimplemented opcode DW_OP_call2."); ++ return false; ++ // OPCODE: DW_OP_call4 ++ // OPERANDS: 1 ++ // uint32_t compile unit relative offset of a DIE ++ // DESCRIPTION: Performs a subroutine call during evaluation of a DWARF ++ // expression. For DW_OP_call4, the operand is a 4-byte unsigned offset of ++ // a debugging information entry in the current compilation unit. ++ // ++ // Operand interpretation DW_OP_call4 is exactly like that for ++ // DW_FORM_ref4. ++ // ++ // This operation transfers control of DWARF expression evaluation to the ++ // DW_AT_location attribute of the referenced DIE. If there is no such ++ // attribute, then there is no effect. Execution of the DWARF expression of ++ // a DW_AT_location attribute may add to and/or remove from values on the ++ // stack. Execution returns to the point following the call when the end of ++ // the attribute is reached. Values on the stack at the time of the call ++ // may be used as parameters by the called expression and values left on ++ // the stack by the called expression may be used as return values by prior ++ // agreement between the calling and called expressions. ++ case DW_OP_call4: ++ if (error_ptr) ++ error_ptr->SetErrorString("Unimplemented opcode DW_OP_call4."); ++ return false; ++ ++ // OPCODE: DW_OP_stack_value ++ // OPERANDS: None ++ // DESCRIPTION: Specifies that the object does not exist in memory but ++ // rather is a constant value. The value from the top of the stack is the ++ // value to be used. This is the actual object value and not the location. ++ case DW_OP_stack_value: ++ if (stack.empty()) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 1 item for DW_OP_stack_value."); ++ return false; ++ } ++ stack.back().SetValueType(Value::ValueType::Scalar); ++ break; ++ ++ // OPCODE: DW_OP_convert ++ // OPERANDS: 1 ++ // A ULEB128 that is either a DIE offset of a ++ // DW_TAG_base_type or 0 for the generic (pointer-sized) type. ++ // ++ // DESCRIPTION: Pop the top stack element, convert it to a ++ // different type, and push the result. ++ case DW_OP_convert: { ++ if (stack.size() < 1) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Expression stack needs at least 1 item for DW_OP_convert."); ++ return false; ++ } ++ const uint64_t die_offset = opcodes.GetULEB128(&offset); ++ uint64_t bit_size; ++ bool sign; ++ if (die_offset == 0) { ++ // The generic type has the size of an address on the target ++ // machine and an unspecified signedness. Scalar has no ++ // "unspecified signedness", so we use unsigned types. ++ if (!module_sp) { ++ if (error_ptr) ++ error_ptr->SetErrorString("No module"); ++ return false; ++ } ++ sign = false; ++ bit_size = module_sp->GetArchitecture().GetAddressByteSize() * 8; ++ if (!bit_size) { ++ if (error_ptr) ++ error_ptr->SetErrorString("unspecified architecture"); ++ return false; ++ } ++ } else { ++ // Retrieve the type DIE that the value is being converted to. ++ // FIXME: the constness has annoying ripple effects. ++ DWARFDIE die = const_cast(dwarf_cu)->GetDIE(die_offset); ++ if (!die) { ++ if (error_ptr) ++ error_ptr->SetErrorString("Cannot resolve DW_OP_convert type DIE"); ++ return false; ++ } ++ uint64_t encoding = ++ die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user); ++ bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; ++ if (!bit_size) ++ bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0); ++ if (!bit_size) { ++ if (error_ptr) ++ error_ptr->SetErrorString("Unsupported type size in DW_OP_convert"); ++ return false; ++ } ++ switch (encoding) { ++ case DW_ATE_signed: ++ case DW_ATE_signed_char: ++ sign = true; ++ break; ++ case DW_ATE_unsigned: ++ case DW_ATE_unsigned_char: ++ sign = false; ++ break; ++ default: ++ if (error_ptr) ++ error_ptr->SetErrorString("Unsupported encoding in DW_OP_convert"); ++ return false; ++ } ++ } ++ Scalar &top = stack.back().ResolveValue(m_exe_ctx); ++ top.TruncOrExtendTo(bit_size, sign); ++ break; ++ } ++ ++ // OPCODE: DW_OP_call_frame_cfa ++ // OPERANDS: None ++ // DESCRIPTION: Specifies a DWARF expression that pushes the value of ++ // the canonical frame address consistent with the call frame information ++ // located in .debug_frame (or in the FDEs of the eh_frame section). ++ case DW_OP_call_frame_cfa: ++ if (frame) { ++ // Note that we don't have to parse FDEs because this DWARF expression ++ // is commonly evaluated with a valid stack frame. ++ StackID id = frame->GetStackID(); ++ addr_t cfa = id.GetCallFrameAddress(); ++ if (cfa != LLDB_INVALID_ADDRESS) { ++ stack.push_back(Scalar(cfa)); ++ stack.back().SetValueType(Value::ValueType::LoadAddress); ++ } else if (error_ptr) ++ error_ptr->SetErrorString("Stack frame does not include a canonical " ++ "frame address for DW_OP_call_frame_cfa " ++ "opcode."); ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorString("Invalid stack frame in context for " ++ "DW_OP_call_frame_cfa opcode."); ++ return false; ++ } ++ break; ++ ++ // OPCODE: DW_OP_form_tls_address (or the old pre-DWARFv3 vendor extension ++ // opcode, DW_OP_GNU_push_tls_address) ++ // OPERANDS: none ++ // DESCRIPTION: Pops a TLS offset from the stack, converts it to ++ // an address in the current thread's thread-local storage block, and ++ // pushes it on the stack. ++ case DW_OP_form_tls_address: ++ case DW_OP_GNU_push_tls_address: { ++ if (stack.size() < 1) { ++ if (error_ptr) { ++ if (op == DW_OP_form_tls_address) ++ error_ptr->SetErrorString( ++ "DW_OP_form_tls_address needs an argument."); ++ else ++ error_ptr->SetErrorString( ++ "DW_OP_GNU_push_tls_address needs an argument."); ++ } ++ return false; ++ } ++ ++ if (!m_exe_ctx || !module_sp) { ++ if (error_ptr) ++ error_ptr->SetErrorString("No context to evaluate TLS within."); ++ return false; ++ } ++ ++ Thread *thread = m_exe_ctx->GetThreadPtr(); ++ if (!thread) { ++ if (error_ptr) ++ error_ptr->SetErrorString("No thread to evaluate TLS within."); ++ return false; ++ } ++ ++ // Lookup the TLS block address for this thread and module. ++ const addr_t tls_file_addr = ++ stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); ++ const addr_t tls_load_addr = ++ thread->GetThreadLocalData(module_sp, tls_file_addr); ++ ++ if (tls_load_addr == LLDB_INVALID_ADDRESS) { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "No TLS data currently exists for this thread."); ++ return false; ++ } ++ ++ stack.back().GetScalar() = tls_load_addr; ++ stack.back().SetValueType(Value::ValueType::LoadAddress); ++ } break; ++ ++ // OPCODE: DW_OP_addrx (DW_OP_GNU_addr_index is the legacy name.) ++ // OPERANDS: 1 ++ // ULEB128: index to the .debug_addr section ++ // DESCRIPTION: Pushes an address to the stack from the .debug_addr ++ // section with the base address specified by the DW_AT_addr_base attribute ++ // and the 0 based index is the ULEB128 encoded index. ++ case DW_OP_addrx: ++ case DW_OP_GNU_addr_index: { ++ if (!dwarf_cu) { ++ if (error_ptr) ++ error_ptr->SetErrorString("DW_OP_GNU_addr_index found without a " ++ "compile unit being specified"); ++ return false; ++ } ++ uint64_t index = opcodes.GetULEB128(&offset); ++ lldb::addr_t value = ++ DWARFExpression::ReadAddressFromDebugAddrSection(dwarf_cu, index); ++ stack.push_back(Scalar(value)); ++ stack.back().SetValueType(Value::ValueType::FileAddress); ++ } break; ++ ++ // OPCODE: DW_OP_GNU_const_index ++ // OPERANDS: 1 ++ // ULEB128: index to the .debug_addr section ++ // DESCRIPTION: Pushes an constant with the size of a machine address to ++ // the stack from the .debug_addr section with the base address specified ++ // by the DW_AT_addr_base attribute and the 0 based index is the ULEB128 ++ // encoded index. ++ case DW_OP_GNU_const_index: { ++ if (!dwarf_cu) { ++ if (error_ptr) ++ error_ptr->SetErrorString("DW_OP_GNU_const_index found without a " ++ "compile unit being specified"); ++ return false; ++ } ++ uint64_t index = opcodes.GetULEB128(&offset); ++ lldb::addr_t value = ++ DWARFExpression::ReadAddressFromDebugAddrSection(dwarf_cu, index); ++ stack.push_back(Scalar(value)); ++ } break; ++ ++ case DW_OP_entry_value: { ++ if (!Evaluate_DW_OP_entry_value(stack, m_exe_ctx, m_reg_ctx, opcodes, ++ offset, error_ptr, log)) { ++ LLDB_ERRORF(error_ptr, "Could not evaluate %s.", DW_OP_value_to_name(op)); ++ return false; ++ } ++ break; ++ } ++ ++ default: ++ LLDB_LOGF(log, "Unhandled opcode %s in DWARFExpression.", ++ DW_OP_value_to_name(op)); ++ break; ++ } ++ ++ return true; ++} +diff --git a/lldb/source/Expression/DWARFEvaluatorFactory.cpp b/lldb/source/Expression/DWARFEvaluatorFactory.cpp +new file mode 100644 +index 000000000000..c0612641204a +--- /dev/null ++++ b/lldb/source/Expression/DWARFEvaluatorFactory.cpp +@@ -0,0 +1,57 @@ ++//===-- DWARFEvaluatorFactory.cpp -----------------------------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "lldb/Expression/DWARFEvaluatorFactory.h" ++#include "lldb/Expression/DWARFEvaluator.h" ++ ++#include "lldb/Core/PluginManager.h" ++#include "lldb/Core/Value.h" ++#include "lldb/Target/RegisterContext.h" ++ ++using namespace lldb; ++using namespace lldb_private; ++ ++// PluginInterface protocol ++lldb_private::ConstString DWARFEvaluatorFactory::GetPluginName() { ++ static ConstString g_name("vendor-default"); ++ return g_name; ++} ++ ++// FindPlugin ++// ++// Platforms can register a callback to use when creating DWARF expression ++// evaluators to allow handling platform-specific DWARF codes. ++std::unique_ptr ++DWARFEvaluatorFactory::FindPlugin(Module *module) { ++ std::unique_ptr instance_up; ++ DWARFEvaluatorFactoryCreateInstance create_callback; ++ ++ for (size_t idx = 0; ++ (create_callback = ++ PluginManager::GetDWARFEvaluatorFactoryCreateCallbackAtIndex( ++ idx)) != nullptr; ++ ++idx) { ++ instance_up.reset(create_callback(module)); ++ ++ if (instance_up) { ++ return instance_up; ++ } ++ } ++ ++ instance_up.reset(new DWARFEvaluatorFactory()); ++ return instance_up; ++} ++ ++std::unique_ptr DWARFEvaluatorFactory::CreateDWARFEvaluator( ++ const DWARFExpression &dwarf_expression, ExecutionContext *exe_ctx, ++ RegisterContext *reg_ctx, const Value *initial_value_ptr, ++ const Value *object_address_ptr) { ++ return std::make_unique(dwarf_expression, exe_ctx, reg_ctx, ++ initial_value_ptr, ++ object_address_ptr); ++} +diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp +index a10546c1deae..4d13e4642af3 100644 +--- a/lldb/source/Expression/DWARFExpression.cpp ++++ b/lldb/source/Expression/DWARFExpression.cpp +@@ -15,6 +15,8 @@ + #include "lldb/Core/Module.h" + #include "lldb/Core/Value.h" + #include "lldb/Core/dwarf.h" ++#include "lldb/Expression/DWARFEvaluator.h" ++#include "lldb/Expression/DWARFEvaluatorFactory.h" + #include "lldb/Utility/DataEncoder.h" + #include "lldb/Utility/Log.h" + #include "lldb/Utility/RegisterValue.h" +@@ -41,8 +43,8 @@ + using namespace lldb; + using namespace lldb_private; + +-static lldb::addr_t +-ReadAddressFromDebugAddrSection(const DWARFUnit *dwarf_cu, ++lldb::addr_t ++DWARFExpression::ReadAddressFromDebugAddrSection(const DWARFUnit *dwarf_cu, + uint32_t index) { + uint32_t index_size = dwarf_cu->GetAddressByteSize(); + dw_offset_t addr_base = dwarf_cu->GetAddrBase(); +@@ -96,7 +98,7 @@ void DWARFExpression::SetLocationListAddresses(addr_t cu_file_addr, + m_loclist_addresses = LoclistAddresses{cu_file_addr, func_file_addr}; + } + +-int DWARFExpression::GetRegisterKind() { return m_reg_kind; } ++RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; } + + void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) { + m_reg_kind = reg_kind; +@@ -150,52 +152,6 @@ void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level, + } + } + +-static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx, +- lldb::RegisterKind reg_kind, +- uint32_t reg_num, Status *error_ptr, +- Value &value) { +- if (reg_ctx == nullptr) { +- if (error_ptr) +- error_ptr->SetErrorString("No register context in frame.\n"); +- } else { +- uint32_t native_reg = +- reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); +- if (native_reg == LLDB_INVALID_REGNUM) { +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat("Unable to convert register " +- "kind=%u reg_num=%u to a native " +- "register number.\n", +- reg_kind, reg_num); +- } else { +- const RegisterInfo *reg_info = +- reg_ctx->GetRegisterInfoAtIndex(native_reg); +- RegisterValue reg_value; +- if (reg_ctx->ReadRegister(reg_info, reg_value)) { +- if (reg_value.GetScalarValue(value.GetScalar())) { +- value.SetValueType(Value::ValueType::Scalar); +- value.SetContext(Value::ContextType::RegisterInfo, +- const_cast(reg_info)); +- if (error_ptr) +- error_ptr->Clear(); +- return true; +- } else { +- // If we get this error, then we need to implement a value buffer in +- // the dwarf expression evaluation function... +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat( +- "register %s can't be converted to a scalar value", +- reg_info->name); +- } +- } else { +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat("register %s is not available", +- reg_info->name); +- } +- } +- } +- return false; +-} +- + /// Return the length in bytes of the set of operands for \p op. No guarantees + /// are made on the state of \p data after this call. + static offset_t GetOpcodeDataSize(const DataExtractor &data, +@@ -955,1719 +911,17 @@ bool DWARFExpression::Evaluate( + const Value *initial_value_ptr, const Value *object_address_ptr, + Value &result, Status *error_ptr) { + +- if (opcodes.GetByteSize() == 0) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "no location, value may have been optimized out"); +- return false; +- } +- std::vector stack; +- +- Process *process = nullptr; +- StackFrame *frame = nullptr; +- +- if (exe_ctx) { +- process = exe_ctx->GetProcessPtr(); +- frame = exe_ctx->GetFramePtr(); +- } +- if (reg_ctx == nullptr && frame) +- reg_ctx = frame->GetRegisterContext().get(); +- +- if (initial_value_ptr) +- stack.push_back(*initial_value_ptr); +- +- lldb::offset_t offset = 0; +- Value tmp; +- uint32_t reg_num; +- +- /// Insertion point for evaluating multi-piece expression. +- uint64_t op_piece_offset = 0; +- Value pieces; // Used for DW_OP_piece +- +- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); +- // A generic type is "an integral type that has the size of an address and an +- // unspecified signedness". For now, just use the signedness of the operand. +- // TODO: Implement a real typed stack, and store the genericness of the value +- // there. +- auto to_generic = [&](auto v) { +- bool is_signed = std::is_signed::value; +- return Scalar(llvm::APSInt( +- llvm::APInt(8 * opcodes.GetAddressByteSize(), v, is_signed), +- !is_signed)); +- }; +- +- // The default kind is a memory location. This is updated by any +- // operation that changes this, such as DW_OP_stack_value, and reset +- // by composition operations like DW_OP_piece. +- LocationDescriptionKind dwarf4_location_description_kind = Memory; +- +- while (opcodes.ValidOffset(offset)) { +- const lldb::offset_t op_offset = offset; +- const uint8_t op = opcodes.GetU8(&offset); +- +- if (log && log->GetVerbose()) { +- size_t count = stack.size(); +- LLDB_LOGF(log, "Stack before operation has %" PRIu64 " values:", +- (uint64_t)count); +- for (size_t i = 0; i < count; ++i) { +- StreamString new_value; +- new_value.Printf("[%" PRIu64 "]", (uint64_t)i); +- stack[i].Dump(&new_value); +- LLDB_LOGF(log, " %s", new_value.GetData()); +- } +- LLDB_LOGF(log, "0x%8.8" PRIx64 ": %s", op_offset, +- DW_OP_value_to_name(op)); +- } +- +- switch (op) { +- // The DW_OP_addr operation has a single operand that encodes a machine +- // address and whose size is the size of an address on the target machine. +- case DW_OP_addr: +- stack.push_back(Scalar(opcodes.GetAddress(&offset))); +- stack.back().SetValueType(Value::ValueType::FileAddress); +- // Convert the file address to a load address, so subsequent +- // DWARF operators can operate on it. +- if (frame) +- stack.back().ConvertToLoadAddress(module_sp.get(), +- frame->CalculateTarget().get()); +- break; +- +- // The DW_OP_addr_sect_offset4 is used for any location expressions in +- // shared libraries that have a location like: +- // DW_OP_addr(0x1000) +- // If this address resides in a shared library, then this virtual address +- // won't make sense when it is evaluated in the context of a running +- // process where shared libraries have been slid. To account for this, this +- // new address type where we can store the section pointer and a 4 byte +- // offset. +- // case DW_OP_addr_sect_offset4: +- // { +- // result_type = eResultTypeFileAddress; +- // lldb::Section *sect = (lldb::Section +- // *)opcodes.GetMaxU64(&offset, sizeof(void *)); +- // lldb::addr_t sect_offset = opcodes.GetU32(&offset); +- // +- // Address so_addr (sect, sect_offset); +- // lldb::addr_t load_addr = so_addr.GetLoadAddress(); +- // if (load_addr != LLDB_INVALID_ADDRESS) +- // { +- // // We successfully resolve a file address to a load +- // // address. +- // stack.push_back(load_addr); +- // break; +- // } +- // else +- // { +- // // We were able +- // if (error_ptr) +- // error_ptr->SetErrorStringWithFormat ("Section %s in +- // %s is not currently loaded.\n", +- // sect->GetName().AsCString(), +- // sect->GetModule()->GetFileSpec().GetFilename().AsCString()); +- // return false; +- // } +- // } +- // break; +- +- // OPCODE: DW_OP_deref +- // OPERANDS: none +- // DESCRIPTION: Pops the top stack entry and treats it as an address. +- // The value retrieved from that address is pushed. The size of the data +- // retrieved from the dereferenced address is the size of an address on the +- // target machine. +- case DW_OP_deref: { +- if (stack.empty()) { +- if (error_ptr) +- error_ptr->SetErrorString("Expression stack empty for DW_OP_deref."); +- return false; +- } +- Value::ValueType value_type = stack.back().GetValueType(); +- switch (value_type) { +- case Value::ValueType::HostAddress: { +- void *src = (void *)stack.back().GetScalar().ULongLong(); +- intptr_t ptr; +- ::memcpy(&ptr, src, sizeof(void *)); +- stack.back().GetScalar() = ptr; +- stack.back().ClearContext(); +- } break; +- case Value::ValueType::FileAddress: { +- auto file_addr = stack.back().GetScalar().ULongLong( +- LLDB_INVALID_ADDRESS); +- if (!module_sp) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "need module to resolve file address for DW_OP_deref"); +- return false; +- } +- Address so_addr; +- if (!module_sp->ResolveFileAddress(file_addr, so_addr)) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "failed to resolve file address in module"); +- return false; +- } +- addr_t load_Addr = so_addr.GetLoadAddress(exe_ctx->GetTargetPtr()); +- if (load_Addr == LLDB_INVALID_ADDRESS) { +- if (error_ptr) +- error_ptr->SetErrorString("failed to resolve load address"); +- return false; +- } +- stack.back().GetScalar() = load_Addr; +- // Fall through to load address promotion code below. +- } LLVM_FALLTHROUGH; +- case Value::ValueType::Scalar: +- // Promote Scalar to LoadAddress and fall through. +- stack.back().SetValueType(Value::ValueType::LoadAddress); +- LLVM_FALLTHROUGH; +- case Value::ValueType::LoadAddress: +- if (exe_ctx) { +- if (process) { +- lldb::addr_t pointer_addr = +- stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); +- Status error; +- lldb::addr_t pointer_value = +- process->ReadPointerFromMemory(pointer_addr, error); +- if (pointer_value != LLDB_INVALID_ADDRESS) { +- if (ABISP abi_sp = process->GetABI()) +- pointer_value = abi_sp->FixCodeAddress(pointer_value); +- stack.back().GetScalar() = pointer_value; +- stack.back().ClearContext(); +- } else { +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat( +- "Failed to dereference pointer from 0x%" PRIx64 +- " for DW_OP_deref: %s\n", +- pointer_addr, error.AsCString()); +- return false; +- } +- } else { +- if (error_ptr) +- error_ptr->SetErrorString("NULL process for DW_OP_deref.\n"); +- return false; +- } +- } else { +- if (error_ptr) +- error_ptr->SetErrorString( +- "NULL execution context for DW_OP_deref.\n"); +- return false; +- } +- break; +- +- case Value::ValueType::Invalid: +- if (error_ptr) +- error_ptr->SetErrorString("Invalid value type for DW_OP_deref.\n"); +- return false; +- } +- +- } break; +- +- // OPCODE: DW_OP_deref_size +- // OPERANDS: 1 +- // 1 - uint8_t that specifies the size of the data to dereference. +- // DESCRIPTION: Behaves like the DW_OP_deref operation: it pops the top +- // stack entry and treats it as an address. The value retrieved from that +- // address is pushed. In the DW_OP_deref_size operation, however, the size +- // in bytes of the data retrieved from the dereferenced address is +- // specified by the single operand. This operand is a 1-byte unsigned +- // integral constant whose value may not be larger than the size of an +- // address on the target machine. The data retrieved is zero extended to +- // the size of an address on the target machine before being pushed on the +- // expression stack. +- case DW_OP_deref_size: { +- if (stack.empty()) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack empty for DW_OP_deref_size."); +- return false; +- } +- uint8_t size = opcodes.GetU8(&offset); +- Value::ValueType value_type = stack.back().GetValueType(); +- switch (value_type) { +- case Value::ValueType::HostAddress: { +- void *src = (void *)stack.back().GetScalar().ULongLong(); +- intptr_t ptr; +- ::memcpy(&ptr, src, sizeof(void *)); +- // I can't decide whether the size operand should apply to the bytes in +- // their +- // lldb-host endianness or the target endianness.. I doubt this'll ever +- // come up but I'll opt for assuming big endian regardless. +- switch (size) { +- case 1: +- ptr = ptr & 0xff; +- break; +- case 2: +- ptr = ptr & 0xffff; +- break; +- case 3: +- ptr = ptr & 0xffffff; +- break; +- case 4: +- ptr = ptr & 0xffffffff; +- break; +- // the casts are added to work around the case where intptr_t is a 32 +- // bit quantity; +- // presumably we won't hit the 5..7 cases if (void*) is 32-bits in this +- // program. +- case 5: +- ptr = (intptr_t)ptr & 0xffffffffffULL; +- break; +- case 6: +- ptr = (intptr_t)ptr & 0xffffffffffffULL; +- break; +- case 7: +- ptr = (intptr_t)ptr & 0xffffffffffffffULL; +- break; +- default: +- break; +- } +- stack.back().GetScalar() = ptr; +- stack.back().ClearContext(); +- } break; +- case Value::ValueType::Scalar: +- case Value::ValueType::LoadAddress: +- if (exe_ctx) { +- if (process) { +- lldb::addr_t pointer_addr = +- stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); +- uint8_t addr_bytes[sizeof(lldb::addr_t)]; +- Status error; +- if (process->ReadMemory(pointer_addr, &addr_bytes, size, error) == +- size) { +- DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), +- process->GetByteOrder(), size); +- lldb::offset_t addr_data_offset = 0; +- switch (size) { +- case 1: +- stack.back().GetScalar() = addr_data.GetU8(&addr_data_offset); +- break; +- case 2: +- stack.back().GetScalar() = addr_data.GetU16(&addr_data_offset); +- break; +- case 4: +- stack.back().GetScalar() = addr_data.GetU32(&addr_data_offset); +- break; +- case 8: +- stack.back().GetScalar() = addr_data.GetU64(&addr_data_offset); +- break; +- default: +- stack.back().GetScalar() = +- addr_data.GetAddress(&addr_data_offset); +- } +- stack.back().ClearContext(); +- } else { +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat( +- "Failed to dereference pointer from 0x%" PRIx64 +- " for DW_OP_deref: %s\n", +- pointer_addr, error.AsCString()); +- return false; +- } +- } else { +- if (error_ptr) +- error_ptr->SetErrorString("NULL process for DW_OP_deref_size.\n"); +- return false; +- } +- } else { +- if (error_ptr) +- error_ptr->SetErrorString( +- "NULL execution context for DW_OP_deref_size.\n"); +- return false; +- } +- break; +- +- case Value::ValueType::FileAddress: +- case Value::ValueType::Invalid: +- if (error_ptr) +- error_ptr->SetErrorString("Invalid value for DW_OP_deref_size.\n"); +- return false; +- } +- +- } break; +- +- // OPCODE: DW_OP_xderef_size +- // OPERANDS: 1 +- // 1 - uint8_t that specifies the size of the data to dereference. +- // DESCRIPTION: Behaves like the DW_OP_xderef operation: the entry at +- // the top of the stack is treated as an address. The second stack entry is +- // treated as an "address space identifier" for those architectures that +- // support multiple address spaces. The top two stack elements are popped, +- // a data item is retrieved through an implementation-defined address +- // calculation and pushed as the new stack top. In the DW_OP_xderef_size +- // operation, however, the size in bytes of the data retrieved from the +- // dereferenced address is specified by the single operand. This operand is +- // a 1-byte unsigned integral constant whose value may not be larger than +- // the size of an address on the target machine. The data retrieved is zero +- // extended to the size of an address on the target machine before being +- // pushed on the expression stack. +- case DW_OP_xderef_size: +- if (error_ptr) +- error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef_size."); +- return false; +- // OPCODE: DW_OP_xderef +- // OPERANDS: none +- // DESCRIPTION: Provides an extended dereference mechanism. The entry at +- // the top of the stack is treated as an address. The second stack entry is +- // treated as an "address space identifier" for those architectures that +- // support multiple address spaces. The top two stack elements are popped, +- // a data item is retrieved through an implementation-defined address +- // calculation and pushed as the new stack top. The size of the data +- // retrieved from the dereferenced address is the size of an address on the +- // target machine. +- case DW_OP_xderef: +- if (error_ptr) +- error_ptr->SetErrorString("Unimplemented opcode: DW_OP_xderef."); +- return false; +- +- // All DW_OP_constXXX opcodes have a single operand as noted below: +- // +- // Opcode Operand 1 +- // DW_OP_const1u 1-byte unsigned integer constant +- // DW_OP_const1s 1-byte signed integer constant +- // DW_OP_const2u 2-byte unsigned integer constant +- // DW_OP_const2s 2-byte signed integer constant +- // DW_OP_const4u 4-byte unsigned integer constant +- // DW_OP_const4s 4-byte signed integer constant +- // DW_OP_const8u 8-byte unsigned integer constant +- // DW_OP_const8s 8-byte signed integer constant +- // DW_OP_constu unsigned LEB128 integer constant +- // DW_OP_consts signed LEB128 integer constant +- case DW_OP_const1u: +- stack.push_back(to_generic(opcodes.GetU8(&offset))); +- break; +- case DW_OP_const1s: +- stack.push_back(to_generic((int8_t)opcodes.GetU8(&offset))); +- break; +- case DW_OP_const2u: +- stack.push_back(to_generic(opcodes.GetU16(&offset))); +- break; +- case DW_OP_const2s: +- stack.push_back(to_generic((int16_t)opcodes.GetU16(&offset))); +- break; +- case DW_OP_const4u: +- stack.push_back(to_generic(opcodes.GetU32(&offset))); +- break; +- case DW_OP_const4s: +- stack.push_back(to_generic((int32_t)opcodes.GetU32(&offset))); +- break; +- case DW_OP_const8u: +- stack.push_back(to_generic(opcodes.GetU64(&offset))); +- break; +- case DW_OP_const8s: +- stack.push_back(to_generic((int64_t)opcodes.GetU64(&offset))); +- break; +- // These should also use to_generic, but we can't do that due to a +- // producer-side bug in llvm. See llvm.org/pr48087. +- case DW_OP_constu: +- stack.push_back(Scalar(opcodes.GetULEB128(&offset))); +- break; +- case DW_OP_consts: +- stack.push_back(Scalar(opcodes.GetSLEB128(&offset))); +- break; +- +- // OPCODE: DW_OP_dup +- // OPERANDS: none +- // DESCRIPTION: duplicates the value at the top of the stack +- case DW_OP_dup: +- if (stack.empty()) { +- if (error_ptr) +- error_ptr->SetErrorString("Expression stack empty for DW_OP_dup."); +- return false; +- } else +- stack.push_back(stack.back()); +- break; +- +- // OPCODE: DW_OP_drop +- // OPERANDS: none +- // DESCRIPTION: pops the value at the top of the stack +- case DW_OP_drop: +- if (stack.empty()) { +- if (error_ptr) +- error_ptr->SetErrorString("Expression stack empty for DW_OP_drop."); +- return false; +- } else +- stack.pop_back(); +- break; +- +- // OPCODE: DW_OP_over +- // OPERANDS: none +- // DESCRIPTION: Duplicates the entry currently second in the stack at +- // the top of the stack. +- case DW_OP_over: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_over."); +- return false; +- } else +- stack.push_back(stack[stack.size() - 2]); +- break; +- +- // OPCODE: DW_OP_pick +- // OPERANDS: uint8_t index into the current stack +- // DESCRIPTION: The stack entry with the specified index (0 through 255, +- // inclusive) is pushed on the stack +- case DW_OP_pick: { +- uint8_t pick_idx = opcodes.GetU8(&offset); +- if (pick_idx < stack.size()) +- stack.push_back(stack[stack.size() - 1 - pick_idx]); +- else { +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat( +- "Index %u out of range for DW_OP_pick.\n", pick_idx); +- return false; +- } +- } break; +- +- // OPCODE: DW_OP_swap +- // OPERANDS: none +- // DESCRIPTION: swaps the top two stack entries. The entry at the top +- // of the stack becomes the second stack entry, and the second entry +- // becomes the top of the stack +- case DW_OP_swap: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_swap."); +- return false; +- } else { +- tmp = stack.back(); +- stack.back() = stack[stack.size() - 2]; +- stack[stack.size() - 2] = tmp; +- } +- break; +- +- // OPCODE: DW_OP_rot +- // OPERANDS: none +- // DESCRIPTION: Rotates the first three stack entries. The entry at +- // the top of the stack becomes the third stack entry, the second entry +- // becomes the top of the stack, and the third entry becomes the second +- // entry. +- case DW_OP_rot: +- if (stack.size() < 3) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 3 items for DW_OP_rot."); +- return false; +- } else { +- size_t last_idx = stack.size() - 1; +- Value old_top = stack[last_idx]; +- stack[last_idx] = stack[last_idx - 1]; +- stack[last_idx - 1] = stack[last_idx - 2]; +- stack[last_idx - 2] = old_top; +- } +- break; +- +- // OPCODE: DW_OP_abs +- // OPERANDS: none +- // DESCRIPTION: pops the top stack entry, interprets it as a signed +- // value and pushes its absolute value. If the absolute value can not be +- // represented, the result is undefined. +- case DW_OP_abs: +- if (stack.empty()) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 1 item for DW_OP_abs."); +- return false; +- } else if (!stack.back().ResolveValue(exe_ctx).AbsoluteValue()) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Failed to take the absolute value of the first stack item."); +- return false; +- } +- break; +- +- // OPCODE: DW_OP_and +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack values, performs a bitwise and +- // operation on the two, and pushes the result. +- case DW_OP_and: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_and."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) & tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_div +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack values, divides the former second +- // entry by the former top of the stack using signed division, and pushes +- // the result. +- case DW_OP_div: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_div."); +- return false; +- } else { +- tmp = stack.back(); +- if (tmp.ResolveValue(exe_ctx).IsZero()) { +- if (error_ptr) +- error_ptr->SetErrorString("Divide by zero."); +- return false; +- } else { +- stack.pop_back(); +- stack.back() = +- stack.back().ResolveValue(exe_ctx) / tmp.ResolveValue(exe_ctx); +- if (!stack.back().ResolveValue(exe_ctx).IsValid()) { +- if (error_ptr) +- error_ptr->SetErrorString("Divide failed."); +- return false; +- } +- } +- } +- break; +- +- // OPCODE: DW_OP_minus +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack values, subtracts the former top +- // of the stack from the former second entry, and pushes the result. +- case DW_OP_minus: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_minus."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) - tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_mod +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack values and pushes the result of +- // the calculation: former second stack entry modulo the former top of the +- // stack. +- case DW_OP_mod: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_mod."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) % tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_mul +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack entries, multiplies them +- // together, and pushes the result. +- case DW_OP_mul: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_mul."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) * tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_neg +- // OPERANDS: none +- // DESCRIPTION: pops the top stack entry, and pushes its negation. +- case DW_OP_neg: +- if (stack.empty()) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 1 item for DW_OP_neg."); +- return false; +- } else { +- if (!stack.back().ResolveValue(exe_ctx).UnaryNegate()) { +- if (error_ptr) +- error_ptr->SetErrorString("Unary negate failed."); +- return false; +- } +- } +- break; +- +- // OPCODE: DW_OP_not +- // OPERANDS: none +- // DESCRIPTION: pops the top stack entry, and pushes its bitwise +- // complement +- case DW_OP_not: +- if (stack.empty()) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 1 item for DW_OP_not."); +- return false; +- } else { +- if (!stack.back().ResolveValue(exe_ctx).OnesComplement()) { +- if (error_ptr) +- error_ptr->SetErrorString("Logical NOT failed."); +- return false; +- } +- } +- break; +- +- // OPCODE: DW_OP_or +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack entries, performs a bitwise or +- // operation on the two, and pushes the result. +- case DW_OP_or: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_or."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) | tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_plus +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack entries, adds them together, and +- // pushes the result. +- case DW_OP_plus: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_plus."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().GetScalar() += tmp.GetScalar(); +- } +- break; +- +- // OPCODE: DW_OP_plus_uconst +- // OPERANDS: none +- // DESCRIPTION: pops the top stack entry, adds it to the unsigned LEB128 +- // constant operand and pushes the result. +- case DW_OP_plus_uconst: +- if (stack.empty()) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 1 item for DW_OP_plus_uconst."); +- return false; +- } else { +- const uint64_t uconst_value = opcodes.GetULEB128(&offset); +- // Implicit conversion from a UINT to a Scalar... +- stack.back().GetScalar() += uconst_value; +- if (!stack.back().GetScalar().IsValid()) { +- if (error_ptr) +- error_ptr->SetErrorString("DW_OP_plus_uconst failed."); +- return false; +- } +- } +- break; +- +- // OPCODE: DW_OP_shl +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack entries, shifts the former +- // second entry left by the number of bits specified by the former top of +- // the stack, and pushes the result. +- case DW_OP_shl: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_shl."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) <<= tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_shr +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack entries, shifts the former second +- // entry right logically (filling with zero bits) by the number of bits +- // specified by the former top of the stack, and pushes the result. +- case DW_OP_shr: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_shr."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- if (!stack.back().ResolveValue(exe_ctx).ShiftRightLogical( +- tmp.ResolveValue(exe_ctx))) { +- if (error_ptr) +- error_ptr->SetErrorString("DW_OP_shr failed."); +- return false; +- } +- } +- break; +- +- // OPCODE: DW_OP_shra +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack entries, shifts the former second +- // entry right arithmetically (divide the magnitude by 2, keep the same +- // sign for the result) by the number of bits specified by the former top +- // of the stack, and pushes the result. +- case DW_OP_shra: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_shra."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) >>= tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_xor +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack entries, performs the bitwise +- // exclusive-or operation on the two, and pushes the result. +- case DW_OP_xor: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_xor."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) ^ tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_skip +- // OPERANDS: int16_t +- // DESCRIPTION: An unconditional branch. Its single operand is a 2-byte +- // signed integer constant. The 2-byte constant is the number of bytes of +- // the DWARF expression to skip forward or backward from the current +- // operation, beginning after the 2-byte constant. +- case DW_OP_skip: { +- int16_t skip_offset = (int16_t)opcodes.GetU16(&offset); +- lldb::offset_t new_offset = offset + skip_offset; +- if (opcodes.ValidOffset(new_offset)) +- offset = new_offset; +- else { +- if (error_ptr) +- error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip."); +- return false; +- } +- } break; +- +- // OPCODE: DW_OP_bra +- // OPERANDS: int16_t +- // DESCRIPTION: A conditional branch. Its single operand is a 2-byte +- // signed integer constant. This operation pops the top of stack. If the +- // value popped is not the constant 0, the 2-byte constant operand is the +- // number of bytes of the DWARF expression to skip forward or backward from +- // the current operation, beginning after the 2-byte constant. +- case DW_OP_bra: +- if (stack.empty()) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 1 item for DW_OP_bra."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- int16_t bra_offset = (int16_t)opcodes.GetU16(&offset); +- Scalar zero(0); +- if (tmp.ResolveValue(exe_ctx) != zero) { +- lldb::offset_t new_offset = offset + bra_offset; +- if (opcodes.ValidOffset(new_offset)) +- offset = new_offset; +- else { +- if (error_ptr) +- error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra."); +- return false; +- } +- } +- } +- break; +- +- // OPCODE: DW_OP_eq +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack values, compares using the +- // equals (==) operator. +- // STACK RESULT: push the constant value 1 onto the stack if the result +- // of the operation is true or the constant value 0 if the result of the +- // operation is false. +- case DW_OP_eq: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_eq."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) == tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_ge +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack values, compares using the +- // greater than or equal to (>=) operator. +- // STACK RESULT: push the constant value 1 onto the stack if the result +- // of the operation is true or the constant value 0 if the result of the +- // operation is false. +- case DW_OP_ge: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_ge."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) >= tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_gt +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack values, compares using the +- // greater than (>) operator. +- // STACK RESULT: push the constant value 1 onto the stack if the result +- // of the operation is true or the constant value 0 if the result of the +- // operation is false. +- case DW_OP_gt: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_gt."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) > tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_le +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack values, compares using the +- // less than or equal to (<=) operator. +- // STACK RESULT: push the constant value 1 onto the stack if the result +- // of the operation is true or the constant value 0 if the result of the +- // operation is false. +- case DW_OP_le: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_le."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) <= tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_lt +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack values, compares using the +- // less than (<) operator. +- // STACK RESULT: push the constant value 1 onto the stack if the result +- // of the operation is true or the constant value 0 if the result of the +- // operation is false. +- case DW_OP_lt: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_lt."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) < tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_ne +- // OPERANDS: none +- // DESCRIPTION: pops the top two stack values, compares using the +- // not equal (!=) operator. +- // STACK RESULT: push the constant value 1 onto the stack if the result +- // of the operation is true or the constant value 0 if the result of the +- // operation is false. +- case DW_OP_ne: +- if (stack.size() < 2) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 2 items for DW_OP_ne."); +- return false; +- } else { +- tmp = stack.back(); +- stack.pop_back(); +- stack.back().ResolveValue(exe_ctx) = +- stack.back().ResolveValue(exe_ctx) != tmp.ResolveValue(exe_ctx); +- } +- break; +- +- // OPCODE: DW_OP_litn +- // OPERANDS: none +- // DESCRIPTION: encode the unsigned literal values from 0 through 31. +- // STACK RESULT: push the unsigned literal constant value onto the top +- // of the stack. +- case DW_OP_lit0: +- case DW_OP_lit1: +- case DW_OP_lit2: +- case DW_OP_lit3: +- case DW_OP_lit4: +- case DW_OP_lit5: +- case DW_OP_lit6: +- case DW_OP_lit7: +- case DW_OP_lit8: +- case DW_OP_lit9: +- case DW_OP_lit10: +- case DW_OP_lit11: +- case DW_OP_lit12: +- case DW_OP_lit13: +- case DW_OP_lit14: +- case DW_OP_lit15: +- case DW_OP_lit16: +- case DW_OP_lit17: +- case DW_OP_lit18: +- case DW_OP_lit19: +- case DW_OP_lit20: +- case DW_OP_lit21: +- case DW_OP_lit22: +- case DW_OP_lit23: +- case DW_OP_lit24: +- case DW_OP_lit25: +- case DW_OP_lit26: +- case DW_OP_lit27: +- case DW_OP_lit28: +- case DW_OP_lit29: +- case DW_OP_lit30: +- case DW_OP_lit31: +- stack.push_back(to_generic(op - DW_OP_lit0)); +- break; +- +- // OPCODE: DW_OP_regN +- // OPERANDS: none +- // DESCRIPTION: Push the value in register n on the top of the stack. +- case DW_OP_reg0: +- case DW_OP_reg1: +- case DW_OP_reg2: +- case DW_OP_reg3: +- case DW_OP_reg4: +- case DW_OP_reg5: +- case DW_OP_reg6: +- case DW_OP_reg7: +- case DW_OP_reg8: +- case DW_OP_reg9: +- case DW_OP_reg10: +- case DW_OP_reg11: +- case DW_OP_reg12: +- case DW_OP_reg13: +- case DW_OP_reg14: +- case DW_OP_reg15: +- case DW_OP_reg16: +- case DW_OP_reg17: +- case DW_OP_reg18: +- case DW_OP_reg19: +- case DW_OP_reg20: +- case DW_OP_reg21: +- case DW_OP_reg22: +- case DW_OP_reg23: +- case DW_OP_reg24: +- case DW_OP_reg25: +- case DW_OP_reg26: +- case DW_OP_reg27: +- case DW_OP_reg28: +- case DW_OP_reg29: +- case DW_OP_reg30: +- case DW_OP_reg31: { +- dwarf4_location_description_kind = Register; +- reg_num = op - DW_OP_reg0; +- +- if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp)) +- stack.push_back(tmp); +- else +- return false; +- } break; +- // OPCODE: DW_OP_regx +- // OPERANDS: +- // ULEB128 literal operand that encodes the register. +- // DESCRIPTION: Push the value in register on the top of the stack. +- case DW_OP_regx: { +- dwarf4_location_description_kind = Register; +- reg_num = opcodes.GetULEB128(&offset); +- if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, tmp)) +- stack.push_back(tmp); +- else +- return false; +- } break; +- +- // OPCODE: DW_OP_bregN +- // OPERANDS: +- // SLEB128 offset from register N +- // DESCRIPTION: Value is in memory at the address specified by register +- // N plus an offset. +- case DW_OP_breg0: +- case DW_OP_breg1: +- case DW_OP_breg2: +- case DW_OP_breg3: +- case DW_OP_breg4: +- case DW_OP_breg5: +- case DW_OP_breg6: +- case DW_OP_breg7: +- case DW_OP_breg8: +- case DW_OP_breg9: +- case DW_OP_breg10: +- case DW_OP_breg11: +- case DW_OP_breg12: +- case DW_OP_breg13: +- case DW_OP_breg14: +- case DW_OP_breg15: +- case DW_OP_breg16: +- case DW_OP_breg17: +- case DW_OP_breg18: +- case DW_OP_breg19: +- case DW_OP_breg20: +- case DW_OP_breg21: +- case DW_OP_breg22: +- case DW_OP_breg23: +- case DW_OP_breg24: +- case DW_OP_breg25: +- case DW_OP_breg26: +- case DW_OP_breg27: +- case DW_OP_breg28: +- case DW_OP_breg29: +- case DW_OP_breg30: +- case DW_OP_breg31: { +- reg_num = op - DW_OP_breg0; +- +- if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, +- tmp)) { +- int64_t breg_offset = opcodes.GetSLEB128(&offset); +- tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset; +- tmp.ClearContext(); +- stack.push_back(tmp); +- stack.back().SetValueType(Value::ValueType::LoadAddress); +- } else +- return false; +- } break; +- // OPCODE: DW_OP_bregx +- // OPERANDS: 2 +- // ULEB128 literal operand that encodes the register. +- // SLEB128 offset from register N +- // DESCRIPTION: Value is in memory at the address specified by register +- // N plus an offset. +- case DW_OP_bregx: { +- reg_num = opcodes.GetULEB128(&offset); +- +- if (ReadRegisterValueAsScalar(reg_ctx, reg_kind, reg_num, error_ptr, +- tmp)) { +- int64_t breg_offset = opcodes.GetSLEB128(&offset); +- tmp.ResolveValue(exe_ctx) += (uint64_t)breg_offset; +- tmp.ClearContext(); +- stack.push_back(tmp); +- stack.back().SetValueType(Value::ValueType::LoadAddress); +- } else +- return false; +- } break; +- +- case DW_OP_fbreg: +- if (exe_ctx) { +- if (frame) { +- Scalar value; +- if (frame->GetFrameBaseValue(value, error_ptr)) { +- int64_t fbreg_offset = opcodes.GetSLEB128(&offset); +- value += fbreg_offset; +- stack.push_back(value); +- stack.back().SetValueType(Value::ValueType::LoadAddress); +- } else +- return false; +- } else { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Invalid stack frame in context for DW_OP_fbreg opcode."); +- return false; +- } +- } else { +- if (error_ptr) +- error_ptr->SetErrorString( +- "NULL execution context for DW_OP_fbreg.\n"); +- return false; +- } +- +- break; +- +- // OPCODE: DW_OP_nop +- // OPERANDS: none +- // DESCRIPTION: A place holder. It has no effect on the location stack +- // or any of its values. +- case DW_OP_nop: +- break; +- +- // OPCODE: DW_OP_piece +- // OPERANDS: 1 +- // ULEB128: byte size of the piece +- // DESCRIPTION: The operand describes the size in bytes of the piece of +- // the object referenced by the DWARF expression whose result is at the top +- // of the stack. If the piece is located in a register, but does not occupy +- // the entire register, the placement of the piece within that register is +- // defined by the ABI. +- // +- // Many compilers store a single variable in sets of registers, or store a +- // variable partially in memory and partially in registers. DW_OP_piece +- // provides a way of describing how large a part of a variable a particular +- // DWARF expression refers to. +- case DW_OP_piece: { +- LocationDescriptionKind piece_locdesc = dwarf4_location_description_kind; +- // Reset for the next piece. +- dwarf4_location_description_kind = Memory; +- +- const uint64_t piece_byte_size = opcodes.GetULEB128(&offset); +- +- if (piece_byte_size > 0) { +- Value curr_piece; +- +- if (stack.empty()) { +- UpdateValueTypeFromLocationDescription( +- log, dwarf_cu, LocationDescriptionKind::Empty); +- // In a multi-piece expression, this means that the current piece is +- // not available. Fill with zeros for now by resizing the data and +- // appending it +- curr_piece.ResizeData(piece_byte_size); +- // Note that "0" is not a correct value for the unknown bits. +- // It would be better to also return a mask of valid bits together +- // with the expression result, so the debugger can print missing +- // members as "" or something. +- ::memset(curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size); +- pieces.AppendDataToHostBuffer(curr_piece); +- } else { +- Status error; +- // Extract the current piece into "curr_piece" +- Value curr_piece_source_value(stack.back()); +- stack.pop_back(); +- UpdateValueTypeFromLocationDescription(log, dwarf_cu, piece_locdesc, +- &curr_piece_source_value); +- +- const Value::ValueType curr_piece_source_value_type = +- curr_piece_source_value.GetValueType(); +- switch (curr_piece_source_value_type) { +- case Value::ValueType::Invalid: +- return false; +- case Value::ValueType::LoadAddress: +- if (process) { +- if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) { +- lldb::addr_t load_addr = +- curr_piece_source_value.GetScalar().ULongLong( +- LLDB_INVALID_ADDRESS); +- if (process->ReadMemory( +- load_addr, curr_piece.GetBuffer().GetBytes(), +- piece_byte_size, error) != piece_byte_size) { +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat( +- "failed to read memory DW_OP_piece(%" PRIu64 +- ") from 0x%" PRIx64, +- piece_byte_size, load_addr); +- return false; +- } +- } else { +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat( +- "failed to resize the piece memory buffer for " +- "DW_OP_piece(%" PRIu64 ")", +- piece_byte_size); +- return false; +- } +- } +- break; +- +- case Value::ValueType::FileAddress: +- case Value::ValueType::HostAddress: +- if (error_ptr) { +- lldb::addr_t addr = curr_piece_source_value.GetScalar().ULongLong( +- LLDB_INVALID_ADDRESS); +- error_ptr->SetErrorStringWithFormat( +- "failed to read memory DW_OP_piece(%" PRIu64 +- ") from %s address 0x%" PRIx64, +- piece_byte_size, curr_piece_source_value.GetValueType() == +- Value::ValueType::FileAddress +- ? "file" +- : "host", +- addr); +- } +- return false; +- +- case Value::ValueType::Scalar: { +- uint32_t bit_size = piece_byte_size * 8; +- uint32_t bit_offset = 0; +- Scalar &scalar = curr_piece_source_value.GetScalar(); +- if (!scalar.ExtractBitfield( +- bit_size, bit_offset)) { +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat( +- "unable to extract %" PRIu64 " bytes from a %" PRIu64 +- " byte scalar value.", +- piece_byte_size, +- (uint64_t)curr_piece_source_value.GetScalar() +- .GetByteSize()); +- return false; +- } +- // Create curr_piece with bit_size. By default Scalar +- // grows to the nearest host integer type. +- llvm::APInt fail_value(1, 0, false); +- llvm::APInt ap_int = scalar.UInt128(fail_value); +- assert(ap_int.getBitWidth() >= bit_size); +- llvm::ArrayRef buf{ap_int.getRawData(), +- ap_int.getNumWords()}; +- curr_piece.GetScalar() = Scalar(llvm::APInt(bit_size, buf)); +- } break; +- } +- +- // Check if this is the first piece? +- if (op_piece_offset == 0) { +- // This is the first piece, we should push it back onto the stack +- // so subsequent pieces will be able to access this piece and add +- // to it. +- if (pieces.AppendDataToHostBuffer(curr_piece) == 0) { +- if (error_ptr) +- error_ptr->SetErrorString("failed to append piece data"); +- return false; +- } +- } else { +- // If this is the second or later piece there should be a value on +- // the stack. +- if (pieces.GetBuffer().GetByteSize() != op_piece_offset) { +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat( +- "DW_OP_piece for offset %" PRIu64 +- " but top of stack is of size %" PRIu64, +- op_piece_offset, pieces.GetBuffer().GetByteSize()); +- return false; +- } +- +- if (pieces.AppendDataToHostBuffer(curr_piece) == 0) { +- if (error_ptr) +- error_ptr->SetErrorString("failed to append piece data"); +- return false; +- } +- } +- } +- op_piece_offset += piece_byte_size; +- } +- } break; +- +- case DW_OP_bit_piece: // 0x9d ULEB128 bit size, ULEB128 bit offset (DWARF3); +- if (stack.size() < 1) { +- UpdateValueTypeFromLocationDescription(log, dwarf_cu, +- LocationDescriptionKind::Empty); +- // Reset for the next piece. +- dwarf4_location_description_kind = Memory; +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 1 item for DW_OP_bit_piece."); +- return false; +- } else { +- UpdateValueTypeFromLocationDescription( +- log, dwarf_cu, dwarf4_location_description_kind, &stack.back()); +- // Reset for the next piece. +- dwarf4_location_description_kind = Memory; +- const uint64_t piece_bit_size = opcodes.GetULEB128(&offset); +- const uint64_t piece_bit_offset = opcodes.GetULEB128(&offset); +- switch (stack.back().GetValueType()) { +- case Value::ValueType::Invalid: +- return false; +- case Value::ValueType::Scalar: { +- if (!stack.back().GetScalar().ExtractBitfield(piece_bit_size, +- piece_bit_offset)) { +- if (error_ptr) +- error_ptr->SetErrorStringWithFormat( +- "unable to extract %" PRIu64 " bit value with %" PRIu64 +- " bit offset from a %" PRIu64 " bit scalar value.", +- piece_bit_size, piece_bit_offset, +- (uint64_t)(stack.back().GetScalar().GetByteSize() * 8)); +- return false; +- } +- } break; +- +- case Value::ValueType::FileAddress: +- case Value::ValueType::LoadAddress: +- case Value::ValueType::HostAddress: +- if (error_ptr) { +- error_ptr->SetErrorStringWithFormat( +- "unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 +- ", bit_offset = %" PRIu64 ") from an address value.", +- piece_bit_size, piece_bit_offset); +- } +- return false; +- } +- } +- break; +- +- // OPCODE: DW_OP_implicit_value +- // OPERANDS: 2 +- // ULEB128 size of the value block in bytes +- // uint8_t* block bytes encoding value in target's memory +- // representation +- // DESCRIPTION: Value is immediately stored in block in the debug info with +- // the memory representation of the target. +- case DW_OP_implicit_value: { +- dwarf4_location_description_kind = Implicit; +- +- const uint32_t len = opcodes.GetULEB128(&offset); +- const void *data = opcodes.GetData(&offset, len); +- +- if (!data) { +- LLDB_LOG(log, "Evaluate_DW_OP_implicit_value: could not be read data"); +- LLDB_ERRORF(error_ptr, "Could not evaluate %s.", +- DW_OP_value_to_name(op)); +- return false; +- } +- +- Value result(data, len); +- stack.push_back(result); +- break; +- } +- +- case DW_OP_implicit_pointer: { +- dwarf4_location_description_kind = Implicit; +- LLDB_ERRORF(error_ptr, "Could not evaluate %s.", DW_OP_value_to_name(op)); +- return false; +- } +- +- // OPCODE: DW_OP_push_object_address +- // OPERANDS: none +- // DESCRIPTION: Pushes the address of the object currently being +- // evaluated as part of evaluation of a user presented expression. This +- // object may correspond to an independent variable described by its own +- // DIE or it may be a component of an array, structure, or class whose +- // address has been dynamically determined by an earlier step during user +- // expression evaluation. +- case DW_OP_push_object_address: +- if (object_address_ptr) +- stack.push_back(*object_address_ptr); +- else { +- if (error_ptr) +- error_ptr->SetErrorString("DW_OP_push_object_address used without " +- "specifying an object address"); +- return false; +- } +- break; +- +- // OPCODE: DW_OP_call2 +- // OPERANDS: +- // uint16_t compile unit relative offset of a DIE +- // DESCRIPTION: Performs subroutine calls during evaluation +- // of a DWARF expression. The operand is the 2-byte unsigned offset of a +- // debugging information entry in the current compilation unit. +- // +- // Operand interpretation is exactly like that for DW_FORM_ref2. +- // +- // This operation transfers control of DWARF expression evaluation to the +- // DW_AT_location attribute of the referenced DIE. If there is no such +- // attribute, then there is no effect. Execution of the DWARF expression of +- // a DW_AT_location attribute may add to and/or remove from values on the +- // stack. Execution returns to the point following the call when the end of +- // the attribute is reached. Values on the stack at the time of the call +- // may be used as parameters by the called expression and values left on +- // the stack by the called expression may be used as return values by prior +- // agreement between the calling and called expressions. +- case DW_OP_call2: +- if (error_ptr) +- error_ptr->SetErrorString("Unimplemented opcode DW_OP_call2."); +- return false; +- // OPCODE: DW_OP_call4 +- // OPERANDS: 1 +- // uint32_t compile unit relative offset of a DIE +- // DESCRIPTION: Performs a subroutine call during evaluation of a DWARF +- // expression. For DW_OP_call4, the operand is a 4-byte unsigned offset of +- // a debugging information entry in the current compilation unit. +- // +- // Operand interpretation DW_OP_call4 is exactly like that for +- // DW_FORM_ref4. +- // +- // This operation transfers control of DWARF expression evaluation to the +- // DW_AT_location attribute of the referenced DIE. If there is no such +- // attribute, then there is no effect. Execution of the DWARF expression of +- // a DW_AT_location attribute may add to and/or remove from values on the +- // stack. Execution returns to the point following the call when the end of +- // the attribute is reached. Values on the stack at the time of the call +- // may be used as parameters by the called expression and values left on +- // the stack by the called expression may be used as return values by prior +- // agreement between the calling and called expressions. +- case DW_OP_call4: +- if (error_ptr) +- error_ptr->SetErrorString("Unimplemented opcode DW_OP_call4."); +- return false; +- +- // OPCODE: DW_OP_stack_value +- // OPERANDS: None +- // DESCRIPTION: Specifies that the object does not exist in memory but +- // rather is a constant value. The value from the top of the stack is the +- // value to be used. This is the actual object value and not the location. +- case DW_OP_stack_value: +- dwarf4_location_description_kind = Implicit; +- if (stack.empty()) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 1 item for DW_OP_stack_value."); +- return false; +- } +- stack.back().SetValueType(Value::ValueType::Scalar); +- break; +- +- // OPCODE: DW_OP_convert +- // OPERANDS: 1 +- // A ULEB128 that is either a DIE offset of a +- // DW_TAG_base_type or 0 for the generic (pointer-sized) type. +- // +- // DESCRIPTION: Pop the top stack element, convert it to a +- // different type, and push the result. +- case DW_OP_convert: { +- if (stack.size() < 1) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "Expression stack needs at least 1 item for DW_OP_convert."); +- return false; +- } +- const uint64_t die_offset = opcodes.GetULEB128(&offset); +- uint64_t bit_size; +- bool sign; +- if (die_offset == 0) { +- // The generic type has the size of an address on the target +- // machine and an unspecified signedness. Scalar has no +- // "unspecified signedness", so we use unsigned types. +- if (!module_sp) { +- if (error_ptr) +- error_ptr->SetErrorString("No module"); +- return false; +- } +- sign = false; +- bit_size = module_sp->GetArchitecture().GetAddressByteSize() * 8; +- if (!bit_size) { +- if (error_ptr) +- error_ptr->SetErrorString("unspecified architecture"); +- return false; +- } +- } else { +- // Retrieve the type DIE that the value is being converted to. +- // FIXME: the constness has annoying ripple effects. +- DWARFDIE die = const_cast(dwarf_cu)->GetDIE(die_offset); +- if (!die) { +- if (error_ptr) +- error_ptr->SetErrorString("Cannot resolve DW_OP_convert type DIE"); +- return false; +- } +- uint64_t encoding = +- die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user); +- bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; +- if (!bit_size) +- bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0); +- if (!bit_size) { +- if (error_ptr) +- error_ptr->SetErrorString("Unsupported type size in DW_OP_convert"); +- return false; +- } +- switch (encoding) { +- case DW_ATE_signed: +- case DW_ATE_signed_char: +- sign = true; +- break; +- case DW_ATE_unsigned: +- case DW_ATE_unsigned_char: +- sign = false; +- break; +- default: +- if (error_ptr) +- error_ptr->SetErrorString("Unsupported encoding in DW_OP_convert"); +- return false; +- } +- } +- Scalar &top = stack.back().ResolveValue(exe_ctx); +- top.TruncOrExtendTo(bit_size, sign); +- break; +- } +- +- // OPCODE: DW_OP_call_frame_cfa +- // OPERANDS: None +- // DESCRIPTION: Specifies a DWARF expression that pushes the value of +- // the canonical frame address consistent with the call frame information +- // located in .debug_frame (or in the FDEs of the eh_frame section). +- case DW_OP_call_frame_cfa: +- if (frame) { +- // Note that we don't have to parse FDEs because this DWARF expression +- // is commonly evaluated with a valid stack frame. +- StackID id = frame->GetStackID(); +- addr_t cfa = id.GetCallFrameAddress(); +- if (cfa != LLDB_INVALID_ADDRESS) { +- stack.push_back(Scalar(cfa)); +- stack.back().SetValueType(Value::ValueType::LoadAddress); +- } else if (error_ptr) +- error_ptr->SetErrorString("Stack frame does not include a canonical " +- "frame address for DW_OP_call_frame_cfa " +- "opcode."); +- } else { +- if (error_ptr) +- error_ptr->SetErrorString("Invalid stack frame in context for " +- "DW_OP_call_frame_cfa opcode."); +- return false; +- } +- break; +- +- // OPCODE: DW_OP_form_tls_address (or the old pre-DWARFv3 vendor extension +- // opcode, DW_OP_GNU_push_tls_address) +- // OPERANDS: none +- // DESCRIPTION: Pops a TLS offset from the stack, converts it to +- // an address in the current thread's thread-local storage block, and +- // pushes it on the stack. +- case DW_OP_form_tls_address: +- case DW_OP_GNU_push_tls_address: { +- if (stack.size() < 1) { +- if (error_ptr) { +- if (op == DW_OP_form_tls_address) +- error_ptr->SetErrorString( +- "DW_OP_form_tls_address needs an argument."); +- else +- error_ptr->SetErrorString( +- "DW_OP_GNU_push_tls_address needs an argument."); +- } +- return false; +- } +- +- if (!exe_ctx || !module_sp) { +- if (error_ptr) +- error_ptr->SetErrorString("No context to evaluate TLS within."); +- return false; +- } +- +- Thread *thread = exe_ctx->GetThreadPtr(); +- if (!thread) { +- if (error_ptr) +- error_ptr->SetErrorString("No thread to evaluate TLS within."); +- return false; +- } +- +- // Lookup the TLS block address for this thread and module. +- const addr_t tls_file_addr = +- stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS); +- const addr_t tls_load_addr = +- thread->GetThreadLocalData(module_sp, tls_file_addr); +- +- if (tls_load_addr == LLDB_INVALID_ADDRESS) { +- if (error_ptr) +- error_ptr->SetErrorString( +- "No TLS data currently exists for this thread."); +- return false; +- } +- +- stack.back().GetScalar() = tls_load_addr; +- stack.back().SetValueType(Value::ValueType::LoadAddress); +- } break; +- +- // OPCODE: DW_OP_addrx (DW_OP_GNU_addr_index is the legacy name.) +- // OPERANDS: 1 +- // ULEB128: index to the .debug_addr section +- // DESCRIPTION: Pushes an address to the stack from the .debug_addr +- // section with the base address specified by the DW_AT_addr_base attribute +- // and the 0 based index is the ULEB128 encoded index. +- case DW_OP_addrx: +- case DW_OP_GNU_addr_index: { +- if (!dwarf_cu) { +- if (error_ptr) +- error_ptr->SetErrorString("DW_OP_GNU_addr_index found without a " +- "compile unit being specified"); +- return false; +- } +- uint64_t index = opcodes.GetULEB128(&offset); +- lldb::addr_t value = ReadAddressFromDebugAddrSection(dwarf_cu, index); +- stack.push_back(Scalar(value)); +- stack.back().SetValueType(Value::ValueType::FileAddress); +- } break; +- +- // OPCODE: DW_OP_GNU_const_index +- // OPERANDS: 1 +- // ULEB128: index to the .debug_addr section +- // DESCRIPTION: Pushes an constant with the size of a machine address to +- // the stack from the .debug_addr section with the base address specified +- // by the DW_AT_addr_base attribute and the 0 based index is the ULEB128 +- // encoded index. +- case DW_OP_GNU_const_index: { +- if (!dwarf_cu) { +- if (error_ptr) +- error_ptr->SetErrorString("DW_OP_GNU_const_index found without a " +- "compile unit being specified"); +- return false; +- } +- uint64_t index = opcodes.GetULEB128(&offset); +- lldb::addr_t value = ReadAddressFromDebugAddrSection(dwarf_cu, index); +- stack.push_back(Scalar(value)); +- } break; +- +- case DW_OP_GNU_entry_value: +- case DW_OP_entry_value: { +- if (!Evaluate_DW_OP_entry_value(stack, exe_ctx, reg_ctx, opcodes, offset, +- error_ptr, log)) { +- LLDB_ERRORF(error_ptr, "Could not evaluate %s.", +- DW_OP_value_to_name(op)); +- return false; +- } +- break; +- } +- +- default: +- if (error_ptr) +- error_ptr->SetErrorStringWithFormatv( +- "Unhandled opcode {0} in DWARFExpression", LocationAtom(op)); +- return false; +- } +- } +- +- if (stack.empty()) { +- // Nothing on the stack, check if we created a piece value from DW_OP_piece +- // or DW_OP_bit_piece opcodes +- if (pieces.GetBuffer().GetByteSize()) { +- result = pieces; +- return true; +- } +- if (error_ptr) +- error_ptr->SetErrorString("Stack empty after evaluation."); +- return false; +- } +- +- UpdateValueTypeFromLocationDescription( +- log, dwarf_cu, dwarf4_location_description_kind, &stack.back()); +- +- if (log && log->GetVerbose()) { +- size_t count = stack.size(); +- LLDB_LOGF(log, +- "Stack after operation has %" PRIu64 " values:", (uint64_t)count); +- for (size_t i = 0; i < count; ++i) { +- StreamString new_value; +- new_value.Printf("[%" PRIu64 "]", (uint64_t)i); +- stack[i].Dump(&new_value); +- LLDB_LOGF(log, " %s", new_value.GetData()); +- } +- } +- result = stack.back(); +- return true; // Return true on success ++ DWARFExpression expr(module_sp, opcodes, dwarf_cu); ++ expr.SetRegisterKind(reg_kind); ++ ++ // Use the DWARF expression evaluator registered for this module (or ++ // DWARFEvaluator by default). ++ DWARFEvaluatorFactory *evaluator_factory = ++ module_sp->GetDWARFExpressionEvaluatorFactory(); ++ std::unique_ptr evaluator = ++ evaluator_factory->CreateDWARFEvaluator( ++ expr, exe_ctx, reg_ctx, initial_value_ptr, object_address_ptr); ++ return evaluator->Evaluate(result, error_ptr); + } + + static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc, +diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp +index 00e9ccb762c3..2137a1ac8324 100644 +--- a/lldb/source/Interpreter/CommandInterpreter.cpp ++++ b/lldb/source/Interpreter/CommandInterpreter.cpp +@@ -759,6 +759,24 @@ void CommandInterpreter::LoadCommandDictionary() { + } + } + ++ std::unique_ptr connect_wasm_cmd_up( ++ new CommandObjectRegexCommand( ++ *this, "wasm", ++ "Connect to a WebAssembly process via remote GDB server. " ++ "If no host is specifed, localhost is assumed.", ++ "wasm [:]", 2, 0, false)); ++ if (connect_wasm_cmd_up) { ++ if (connect_wasm_cmd_up->AddRegexCommand( ++ "^([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)$", ++ "process connect --plugin wasm connect://%1:%2") && ++ connect_wasm_cmd_up->AddRegexCommand( ++ "^([[:digit:]]+)$", ++ "process connect --plugin wasm connect://localhost:%1")) { ++ CommandObjectSP command_sp(connect_wasm_cmd_up.release()); ++ m_command_dict[std::string(command_sp->GetCommandName())] = command_sp; ++ } ++ } ++ + std::unique_ptr connect_kdp_remote_cmd_up( + new CommandObjectRegexCommand( + *this, "kdp-remote", +diff --git a/lldb/source/Plugins/CMakeLists.txt b/lldb/source/Plugins/CMakeLists.txt +index 9181a4e47675..2be6ec3657c0 100644 +--- a/lldb/source/Plugins/CMakeLists.txt ++++ b/lldb/source/Plugins/CMakeLists.txt +@@ -2,6 +2,7 @@ add_subdirectory(ABI) + add_subdirectory(Architecture) + add_subdirectory(Disassembler) + add_subdirectory(DynamicLoader) ++add_subdirectory(DWARFEvaluator) + add_subdirectory(ExpressionParser) + add_subdirectory(Instruction) + add_subdirectory(InstrumentationRuntime) +@@ -32,6 +33,7 @@ set(LLDB_ENUM_PLUGINS "") + # FIXME: ProcessWindowsCommon needs to be initialized after all other process + # plugins but before ProcessGDBRemote. + set(LLDB_PROCESS_WINDOWS_PLUGIN "") ++set(LLDB_PROCESS_WASM_PLUGIN "") + set(LLDB_PROCESS_GDB_PLUGIN "") + + foreach(p ${LLDB_ALL_PLUGINS}) +@@ -43,6 +45,8 @@ foreach(p ${LLDB_ALL_PLUGINS}) + set(LLDB_PROCESS_WINDOWS_PLUGIN "LLDB_PLUGIN(${pStripped})\n") + elseif(${pStripped} STREQUAL "ProcessGDBRemote") + set(LLDB_PROCESS_GDB_PLUGIN "LLDB_PLUGIN(${pStripped})\n") ++ elseif(${pStripped} STREQUAL "ProcessWasm") ++ set(LLDB_PROCESS_WASM_PLUGIN "LLDB_PLUGIN(${pStripped})\n") + else() + set(LLDB_ENUM_PLUGINS "${LLDB_ENUM_PLUGINS}LLDB_PLUGIN(${pStripped})\n") + endif() +diff --git a/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt b/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt +new file mode 100644 +index 000000000000..73fad41e1a72 +--- /dev/null ++++ b/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt +@@ -0,0 +1 @@ ++add_subdirectory(wasm) +diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt b/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt +new file mode 100644 +index 000000000000..e50b1bef7e69 +--- /dev/null ++++ b/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt +@@ -0,0 +1,10 @@ ++add_lldb_library(lldbPluginWasmDWARFEvaluatorFactory PLUGIN ++ WasmDWARFEvaluator.cpp ++ WasmDWARFEvaluatorFactory.cpp ++ ++ LINK_LIBS ++ lldbCore ++ lldbHost ++ lldbSymbol ++ lldbPluginObjectFileWasm ++ ) +diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp +new file mode 100644 +index 000000000000..fdda1991d19f +--- /dev/null ++++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp +@@ -0,0 +1,126 @@ ++//===-- WasmDWARFEvaluator.cpp --------------------------------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "WasmDWARFEvaluator.h" ++ ++#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h" ++#include "Plugins/Process/wasm/ProcessWasm.h" ++#include "lldb/Core/Module.h" ++#include "lldb/Core/PluginManager.h" ++#include "lldb/Core/Value.h" ++#include "lldb/Core/dwarf.h" ++#include "lldb/Expression/DWARFExpression.h" ++ ++using namespace lldb; ++using namespace lldb_private; ++using namespace lldb_private::wasm; ++ ++bool WasmDWARFEvaluator::Evaluate(const uint8_t op, Process *process, ++ StackFrame *frame, std::vector &stack, ++ const DataExtractor &opcodes, ++ lldb::offset_t &offset, Value &pieces, ++ uint64_t &op_piece_offset, Log *log, ++ Status *error_ptr) { ++ lldb::ModuleSP module_sp = m_dwarf_expression.GetModule(); ++ ++ switch (op) { ++ case DW_OP_WASM_location: { ++ if (frame) { ++ const llvm::Triple::ArchType machine = ++ frame->CalculateTarget()->GetArchitecture().GetMachine(); ++ if (machine != llvm::Triple::wasm32) { ++ if (error_ptr) ++ error_ptr->SetErrorString("Invalid target architecture for " ++ "DW_OP_WASM_location opcode."); ++ return false; ++ } ++ ++ ProcessWasm *wasm_process = ++ static_cast(frame->CalculateProcess().get()); ++ int frame_index = frame->GetConcreteFrameIndex(); ++ uint64_t wasm_op = opcodes.GetULEB128(&offset); ++ uint64_t index = opcodes.GetULEB128(&offset); ++ uint8_t buf[16]; ++ size_t size = 0; ++ switch (wasm_op) { ++ case 0: // Local ++ if (!wasm_process->GetWasmLocal(frame_index, index, buf, 16, size)) { ++ return false; ++ } ++ break; ++ case 1: // Global ++ if (!wasm_process->GetWasmGlobal(frame_index, index, buf, 16, size)) { ++ return false; ++ } ++ break; ++ case 2: // Operand Stack ++ if (!wasm_process->GetWasmStackValue(frame_index, index, buf, 16, ++ size)) { ++ return false; ++ } ++ break; ++ default: ++ return false; ++ } ++ ++ if (size == sizeof(uint32_t)) { ++ uint32_t value; ++ memcpy(&value, buf, size); ++ stack.push_back(Scalar(value)); ++ } else if (size == sizeof(uint64_t)) { ++ uint64_t value; ++ memcpy(&value, buf, size); ++ stack.push_back(Scalar(value)); ++ } else ++ return false; ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorString("Invalid stack frame in context for " ++ "DW_OP_WASM_location opcode."); ++ return false; ++ } ++ } break; ++ ++ case DW_OP_addr: { ++ /// {addr} is an offset in the module Data section. ++ lldb::addr_t addr = opcodes.GetAddress(&offset); ++ stack.push_back(Scalar(addr)); ++ stack.back().SetValueType(Value::ValueType::LoadAddress); ++ } break; ++ ++ case DW_OP_fbreg: ++ if (m_exe_ctx) { ++ if (frame) { ++ Scalar value; ++ if (frame->GetFrameBaseValue(value, error_ptr)) { ++ // The value is an address in the Wasm Memory space. ++ int64_t fbreg_offset = opcodes.GetSLEB128(&offset); ++ stack.push_back(Scalar(value.ULong() + fbreg_offset)); ++ stack.back().SetValueType(Value::ValueType::LoadAddress); ++ } else ++ return false; ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorString( ++ "Invalid stack frame in context for DW_OP_fbreg opcode."); ++ return false; ++ } ++ } else { ++ if (error_ptr) ++ error_ptr->SetErrorStringWithFormat( ++ "NULL execution context for DW_OP_fbreg.\n"); ++ return false; ++ } ++ break; ++ ++ default: ++ return DWARFEvaluator::Evaluate(op, process, frame, stack, opcodes, offset, ++ pieces, op_piece_offset, log, error_ptr); ++ } ++ return true; ++} +diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h +new file mode 100644 +index 000000000000..a01159064a39 +--- /dev/null ++++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h +@@ -0,0 +1,47 @@ ++//===-- WasmDWARFEvaluator.h ------------------------------------*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATOR_H ++#define LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATOR_H ++ ++#include "lldb/Expression/DWARFEvaluator.h" ++#include "lldb/lldb-private.h" ++ ++namespace lldb_private { ++namespace wasm { ++ ++/// \class WasmDWARFEvaluator evaluates DWARF expressions in the context of a ++/// WebAssembly process. ++/// ++class WasmDWARFEvaluator : public DWARFEvaluator { ++public: ++ WasmDWARFEvaluator(const DWARFExpression &dwarf_expression, ++ ExecutionContext *exe_ctx, RegisterContext *reg_ctx, ++ const Value *initial_value_ptr, ++ const Value *object_address_ptr) ++ : DWARFEvaluator(dwarf_expression, exe_ctx, reg_ctx, initial_value_ptr, ++ object_address_ptr) {} ++ ++ /// DWARFEvaluator protocol. ++ /// \{ ++ bool Evaluate(const uint8_t op, Process *process, StackFrame *frame, ++ std::vector &stack, const DataExtractor &opcodes, ++ lldb::offset_t &offset, Value &pieces, ++ uint64_t &op_piece_offset, Log *log, ++ Status *error_ptr) override; ++ /// \} ++ ++private: ++ WasmDWARFEvaluator(const WasmDWARFEvaluator &); ++ const WasmDWARFEvaluator &operator=(const WasmDWARFEvaluator &) = delete; ++}; ++ ++} // namespace wasm ++} // namespace lldb_private ++ ++#endif // LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATOR_H +diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp +new file mode 100644 +index 000000000000..d43e96a34d37 +--- /dev/null ++++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp +@@ -0,0 +1,64 @@ ++//===-- WasmDWARFEvaluatorFactory.cpp -------------------------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "WasmDWARFEvaluatorFactory.h" ++#include "WasmDWARFEvaluator.h" ++ ++#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h" ++#include "lldb/Core/Module.h" ++#include "lldb/Core/PluginManager.h" ++ ++using namespace lldb; ++using namespace lldb_private; ++using namespace lldb_private::wasm; ++ ++LLDB_PLUGIN_DEFINE(WasmDWARFEvaluatorFactory) ++ ++void WasmDWARFEvaluatorFactory::Initialize() { ++ PluginManager::RegisterPlugin(GetPluginNameStatic(), ++ GetPluginDescriptionStatic(), CreateInstance); ++} ++ ++void WasmDWARFEvaluatorFactory::Terminate() { ++ PluginManager::UnregisterPlugin(CreateInstance); ++} ++ ++lldb_private::ConstString WasmDWARFEvaluatorFactory::GetPluginNameStatic() { ++ static ConstString g_name("WASM"); ++ return g_name; ++} ++ ++const char *WasmDWARFEvaluatorFactory::GetPluginDescriptionStatic() { ++ return "DWARF expression evaluator factory for WASM."; ++} ++ ++// CreateInstance ++// ++// Platforms can register a callback to use when creating DWARF expression ++// evaluators to allow handling platform-specific DWARF codes. ++DWARFEvaluatorFactory * ++WasmDWARFEvaluatorFactory::CreateInstance(Module *module) { ++ if (!module) ++ return nullptr; ++ ++ ObjectFileWasm *obj_file = ++ llvm::dyn_cast_or_null(module->GetObjectFile()); ++ if (!obj_file) ++ return nullptr; ++ ++ return new WasmDWARFEvaluatorFactory(); ++} ++ ++std::unique_ptr WasmDWARFEvaluatorFactory::CreateDWARFEvaluator( ++ const DWARFExpression &dwarf_expression, ExecutionContext *exe_ctx, ++ RegisterContext *reg_ctx, const Value *initial_value_ptr, ++ const Value *object_address_ptr) { ++ return std::make_unique(dwarf_expression, exe_ctx, ++ reg_ctx, initial_value_ptr, ++ object_address_ptr); ++} +diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h +new file mode 100644 +index 000000000000..8a946592a09a +--- /dev/null ++++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h +@@ -0,0 +1,55 @@ ++//===-- WasmDWARFEvaluatorFactory.h -----------------------------*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATORFACTORY_H ++#define LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATORFACTORY_H ++ ++#include "lldb/Expression/DWARFEvaluatorFactory.h" ++ ++namespace lldb_private { ++namespace wasm { ++ ++/// \class WasmDWARFEvaluatorFactory creates DWARF evaluators specialized to ++/// manage DWARF-specific opcodes. ++class WasmDWARFEvaluatorFactory : public DWARFEvaluatorFactory { ++public: ++ static void Initialize(); ++ static void Terminate(); ++ static lldb_private::ConstString GetPluginNameStatic(); ++ static const char *GetPluginDescriptionStatic(); ++ ++ static lldb_private::DWARFEvaluatorFactory *CreateInstance(Module *module); ++ ++ /// PluginInterface protocol. ++ /// \{ ++ lldb_private::ConstString GetPluginName() override { ++ return GetPluginNameStatic(); ++ } ++ uint32_t GetPluginVersion() override { return 1; } ++ /// \} ++ ++ WasmDWARFEvaluatorFactory() {} ++ ++ /// DWARFEvaluatorFactory protocol. ++ /// \{ ++ std::unique_ptr ++ CreateDWARFEvaluator(const DWARFExpression &dwarf_expression, ++ ExecutionContext *exe_ctx, RegisterContext *reg_ctx, ++ const Value *initial_value_ptr, ++ const Value *object_address_ptr) override; ++ /// \} ++ ++private: ++ WasmDWARFEvaluatorFactory(const WasmDWARFEvaluatorFactory &); ++ const WasmDWARFEvaluatorFactory &operator=(const WasmDWARFEvaluatorFactory &) = delete; ++}; ++ ++} // namespace wasm ++} // namespace lldb_private ++ ++#endif // LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATORFACTORY_H +diff --git a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp +index ae7e011eaa52..24ea75d1971c 100644 +--- a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp ++++ b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp +@@ -62,6 +62,15 @@ void DynamicLoaderWasmDYLD::DidAttach() { + // Ask the process for the list of loaded WebAssembly modules. + auto error = m_process->LoadModules(); + LLDB_LOG_ERROR(log, std::move(error), "Couldn't load modules: {0}"); ++ ++ // TODO: multi-modules support ? ++ Target &target = m_process->GetTarget(); ++ const ModuleList &modules = target.GetImages(); ++ ModuleSP module_sp(modules.GetModuleAtIndex(0)); ++ // module_sp is nullptr if without libxml2 ++ if(module_sp) { ++ module_sp->PreloadSymbols(); ++ } + } + + ThreadPlanSP DynamicLoaderWasmDYLD::GetStepThroughTrampolinePlan(Thread &thread, +diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp +index 5272da9ab33a..abc5523bfd70 100644 +--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp ++++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp +@@ -23,6 +23,7 @@ + #include "llvm/BinaryFormat/Wasm.h" + #include "llvm/Support/Endian.h" + #include "llvm/Support/Format.h" ++#include "Plugins/Process/wasm/ProcessWasm.h" + + using namespace lldb; + using namespace lldb_private; +@@ -341,6 +342,8 @@ void ObjectFileWasm::CreateSections(SectionList &unified_section_list) { + 0, // Alignment of the section + 0, // Flags for this section. + 1)); // Number of host bytes per target byte ++ if (section_type == eSectionTypeCode) ++ section_sp->SetPermissions(ePermissionsReadable|ePermissionsExecutable); + m_sections_up->AddSection(section_sp); + unified_section_list.AddSection(section_sp); + } +@@ -367,6 +370,7 @@ bool ObjectFileWasm::SetLoadAddress(Target &target, lldb::addr_t load_address, + assert(m_memory_addr == LLDB_INVALID_ADDRESS || + m_memory_addr == load_address); + ++ lldb::addr_t adjust_addr; + ModuleSP module_sp = GetModule(); + if (!module_sp) + return false; +@@ -381,8 +385,9 @@ bool ObjectFileWasm::SetLoadAddress(Target &target, lldb::addr_t load_address, + const size_t num_sections = section_list->GetSize(); + for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) { + SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); ++ adjust_addr = load_address; + if (target.SetSectionLoadAddress( +- section_sp, load_address | section_sp->GetFileOffset())) { ++ section_sp, adjust_addr | section_sp->GetFileOffset())) { + ++num_loaded_sections; + } + } +diff --git a/lldb/source/Plugins/Platform/CMakeLists.txt b/lldb/source/Plugins/Platform/CMakeLists.txt +index 5f284e517dca..6084cbc9378d 100644 +--- a/lldb/source/Plugins/Platform/CMakeLists.txt ++++ b/lldb/source/Plugins/Platform/CMakeLists.txt +@@ -15,3 +15,4 @@ + add_subdirectory(POSIX) + add_subdirectory(gdb-server) + add_subdirectory(Android) ++add_subdirectory(wasm-remote) +diff --git a/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt b/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt +new file mode 100644 +index 000000000000..4a65765a5659 +--- /dev/null ++++ b/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt +@@ -0,0 +1,10 @@ ++add_lldb_library(lldbPluginPlatformWasm PLUGIN ++ PlatformRemoteWasmServer.cpp ++ ++ LINK_LIBS ++ lldbBreakpoint ++ lldbCore ++ lldbHost ++ lldbTarget ++ lldbPluginProcessUtility ++ ) +diff --git a/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp +new file mode 100644 +index 000000000000..f26d11f00e5c +--- /dev/null ++++ b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp +@@ -0,0 +1,139 @@ ++#include "PlatformRemoteWasmServer.h" ++#include "lldb/Host/Config.h" ++ ++#include "lldb/Breakpoint/BreakpointLocation.h" ++#include "lldb/Core/Debugger.h" ++#include "lldb/Core/Module.h" ++#include "lldb/Core/ModuleList.h" ++#include "lldb/Core/ModuleSpec.h" ++#include "lldb/Core/PluginManager.h" ++#include "lldb/Core/StreamFile.h" ++#include "lldb/Host/ConnectionFileDescriptor.h" ++#include "lldb/Host/Host.h" ++#include "lldb/Host/HostInfo.h" ++#include "lldb/Host/PosixApi.h" ++#include "lldb/Target/Process.h" ++#include "lldb/Target/Target.h" ++#include "lldb/Utility/FileSpec.h" ++#include "lldb/Utility/Log.h" ++#include "lldb/Utility/ProcessInfo.h" ++#include "lldb/Utility/Status.h" ++#include "lldb/Utility/StreamString.h" ++#include "lldb/Utility/UriParser.h" ++ ++#include "Plugins/Process/Utility/GDBRemoteSignals.h" ++ ++using namespace lldb; ++using namespace lldb_private; ++using namespace lldb_private::platform_wasm_server; ++ ++LLDB_PLUGIN_DEFINE_ADV(PlatformRemoteWASMServer, PlatformWasm) ++ ++static bool g_initialized = false; ++ ++void PlatformRemoteWASMServer::Initialize() { ++ Platform::Initialize(); ++ ++ if (!g_initialized) { ++ g_initialized = true; ++ PluginManager::RegisterPlugin( ++ PlatformRemoteWASMServer::GetPluginNameStatic(), ++ PlatformRemoteWASMServer::GetDescriptionStatic(), ++ PlatformRemoteWASMServer::CreateInstance); ++ } ++} ++ ++void PlatformRemoteWASMServer::Terminate() { ++ if (g_initialized) { ++ g_initialized = false; ++ PluginManager::UnregisterPlugin(PlatformRemoteWASMServer::CreateInstance); ++ } ++ ++ Platform::Terminate(); ++} ++ ++PlatformSP PlatformRemoteWASMServer::CreateInstance(bool force, ++ const ArchSpec *arch) { ++ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); ++ if (log) { ++ const char *arch_name; ++ if (arch && arch->GetArchitectureName()) ++ arch_name = arch->GetArchitectureName(); ++ else ++ arch_name = ""; ++ ++ const char *triple_cstr = ++ arch ? arch->GetTriple().getTriple().c_str() : ""; ++ ++ LLDB_LOGF(log, "PlatformRemoteWASMServer::%s(force=%s, arch={%s,%s})", ++ __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); ++ } ++ ++ bool create = force; ++ if (!create && arch && arch->IsValid()) { ++ const llvm::Triple &triple = arch->GetTriple(); ++ if (arch->GetMachine() == llvm::Triple::wasm32 && ++ triple.getOS() == llvm::Triple::WASI) { ++ create = true; ++ } ++ } ++ ++ if (create) { ++ if (log) ++ LLDB_LOGF(log, "PlatformRemoteWASMServer::%s() creating platform", ++ __FUNCTION__); ++ return PlatformSP(new PlatformRemoteWASMServer()); ++ } ++ ++ if (log) ++ LLDB_LOGF(log, ++ "PlatformRemoteWASMServer::%s() aborting creation of platform", ++ __FUNCTION__); ++ return PlatformSP(); ++} ++ ++ConstString PlatformRemoteWASMServer::GetPluginNameStatic() { ++ static ConstString g_name("remote-wasm-server"); ++ return g_name; ++} ++ ++ConstString PlatformRemoteWASMServer::GetPluginName() { ++ return GetPluginNameStatic(); ++} ++ ++const char *PlatformRemoteWASMServer::GetDescriptionStatic() { ++ return "A platform that uses the GDB remote protocol as the communication " ++ "transport for Wasm Runtime"; ++} ++ ++size_t PlatformRemoteWASMServer::ConnectToWaitingProcesses(Debugger &debugger, ++ Status &error) { ++ std::vector connection_urls; ++ GetPendingGdbServerList(connection_urls); ++ ++ for (size_t i = 0; i < connection_urls.size(); ++i) { ++ ConnectProcess(connection_urls[i].c_str(), "wasm", debugger, nullptr, error); ++ if (error.Fail()) ++ return i; // We already connected to i process succsessfully ++ } ++ return connection_urls.size(); ++} ++ ++bool PlatformRemoteWASMServer::GetSupportedArchitectureAtIndex(uint32_t idx, ++ ArchSpec &arch) { ++ ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture(); ++ if (idx == 0) { ++ arch = remote_arch; ++ return arch.IsValid(); ++ } else if (idx == 1 && remote_arch.IsValid() && ++ remote_arch.GetTriple().getOS() == llvm::Triple::WASI) { ++ return arch.IsValid(); ++ } ++ return false; ++} ++ ++/// Default Constructor ++PlatformRemoteWASMServer::PlatformRemoteWASMServer() ++ : PlatformRemoteGDBServer() ++ { ++ } +\ No newline at end of file +diff --git a/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h +new file mode 100644 +index 000000000000..f306a79d3f4f +--- /dev/null ++++ b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h +@@ -0,0 +1,37 @@ ++#ifndef LLDB_SOURCE_PLUGINS_PLATFORM_GDB_SERVER_PLATFORMREMOTEWASMSERVER_H ++#define LLDB_SOURCE_PLUGINS_PLATFORM_GDB_SERVER_PLATFORMREMOTEWASMSERVER_H ++ ++#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" ++#include "lldb/Target/Platform.h" ++ ++namespace lldb_private { ++namespace platform_wasm_server { ++ ++class PlatformRemoteWASMServer : public lldb_private::platform_gdb_server::PlatformRemoteGDBServer{ ++ ++public: ++ static void Initialize(); ++ ++ static void Terminate(); ++ ++ static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); ++ ++ static ConstString GetPluginNameStatic(); ++ ++ static const char *GetDescriptionStatic(); ++ ++ size_t ConnectToWaitingProcesses(lldb_private::Debugger &debugger, ++ lldb_private::Status &error) override; ++ ++ bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override; ++ ++ ConstString GetPluginName() override; ++ ++ PlatformRemoteWASMServer(); ++ ++}; ++ ++} // namespace platform_wasm_server ++} // namespace lldb_private ++ ++#endif +\ No newline at end of file +diff --git a/lldb/source/Plugins/Plugins.def.in b/lldb/source/Plugins/Plugins.def.in +index bf54598fb2f3..b0bd7b9965fe 100644 +--- a/lldb/source/Plugins/Plugins.def.in ++++ b/lldb/source/Plugins/Plugins.def.in +@@ -31,6 +31,7 @@ + + @LLDB_ENUM_PLUGINS@ + @LLDB_PROCESS_WINDOWS_PLUGIN@ ++@LLDB_PROCESS_WASM_PLUGIN@ + @LLDB_PROCESS_GDB_PLUGIN@ + + #undef LLDB_PLUGIN +diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt +index bea5bac9eb21..7a0855e02ca2 100644 +--- a/lldb/source/Plugins/Process/CMakeLists.txt ++++ b/lldb/source/Plugins/Process/CMakeLists.txt +@@ -18,3 +18,4 @@ add_subdirectory(Utility) + add_subdirectory(elf-core) + add_subdirectory(mach-core) + add_subdirectory(minidump) ++add_subdirectory(wasm) +diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +index 12bc7390c729..707ab85e5615 100644 +--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp ++++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +@@ -285,7 +285,7 @@ bool ProcessElfCore::IsAlive() { return true; } + + // Process Memory + size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size, +- Status &error) { ++ Status &error, ExecutionContext *exe_ctx) { + // Don't allow the caching that lldb_private::Process::ReadMemory does since + // in core files we have it all cached our our core file anyway. + return DoReadMemory(addr, buf, size, error); +diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +index d8e3cc9ae3e1..f0bf9c4d3b00 100644 +--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h ++++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +@@ -84,7 +84,8 @@ public: + + // Process Memory + size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size, +- lldb_private::Status &error) override; ++ lldb_private::Status &error, ++ lldb_private::ExecutionContext *exe_ctx = nullptr) override; + + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Status &error) override; +diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +index 6914b37348ea..bb8a056049f3 100644 +--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp ++++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +@@ -334,6 +334,11 @@ ConstString ProcessGDBRemote::GetPluginName() { return GetPluginNameStatic(); } + + uint32_t ProcessGDBRemote::GetPluginVersion() { return 1; } + ++std::shared_ptr ++ProcessGDBRemote::CreateThread(lldb::tid_t tid) { ++ return std::make_shared(*this, tid); ++} ++ + bool ProcessGDBRemote::ParsePythonTargetDefinition( + const FileSpec &target_definition_fspec) { + ScriptInterpreter *interpreter = +@@ -1626,7 +1631,7 @@ bool ProcessGDBRemote::DoUpdateThreadList(ThreadList &old_thread_list, + ThreadSP thread_sp( + old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); + if (!thread_sp) { +- thread_sp = std::make_shared(*this, tid); ++ thread_sp = CreateThread(tid); + LLDB_LOGV(log, "Making new thread: {0} for thread ID: {1:x}.", + thread_sp.get(), thread_sp->GetID()); + } else { +@@ -1742,7 +1747,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( + + if (!thread_sp) { + // Create the thread if we need to +- thread_sp = std::make_shared(*this, tid); ++ thread_sp = CreateThread(tid); + m_thread_list_real.AddThread(thread_sp); + } + } +diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +index fe04cdddd0f5..e4a14c64579a 100644 +--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h ++++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +@@ -237,6 +237,8 @@ protected: + + bool SupportsMemoryTagging() override; + ++ virtual std::shared_ptr CreateThread(lldb::tid_t tid); ++ + /// Broadcaster event bits definitions. + enum { + eBroadcastBitAsyncContinue = (1 << 0), +diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +index 84548edb5caa..0ae6f7e4a177 100644 +--- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp ++++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +@@ -596,7 +596,7 @@ bool ProcessMachCore::WarnBeforeDetach() const { return false; } + + // Process Memory + size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size, +- Status &error) { ++ Status &error, ExecutionContext *exe_ctx) { + // Don't allow the caching that lldb_private::Process::ReadMemory does since + // in core files we have it all cached our our core file anyway. + return DoReadMemory(addr, buf, size, error); +diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h +index db77e96f1072..1c930896c743 100644 +--- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h ++++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h +@@ -65,7 +65,8 @@ public: + + // Process Memory + size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size, +- lldb_private::Status &error) override; ++ lldb_private::Status &error, ++ lldb_private::ExecutionContext *exe_ctx = nullptr) override; + + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + lldb_private::Status &error) override; +diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +index 385557422758..d8bb21581086 100644 +--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp ++++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +@@ -374,7 +374,7 @@ bool ProcessMinidump::IsAlive() { return true; } + bool ProcessMinidump::WarnBeforeDetach() const { return false; } + + size_t ProcessMinidump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, +- Status &error) { ++ Status &error, ExecutionContext *exe_ctx) { + // Don't allow the caching that lldb_private::Process::ReadMemory does since + // we have it all cached in our dump file anyway. + return DoReadMemory(addr, buf, size, error); +diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h +index 27b0da0047a5..e94ecab430c1 100644 +--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h ++++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h +@@ -69,8 +69,8 @@ public: + + bool WarnBeforeDetach() const override; + +- size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size, +- Status &error) override; ++ size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size, Status &error, ++ ExecutionContext *exe_ctx = nullptr) override; + + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + Status &error) override; +diff --git a/lldb/source/Plugins/Process/wasm/CMakeLists.txt b/lldb/source/Plugins/Process/wasm/CMakeLists.txt +new file mode 100644 +index 000000000000..61efb933fa62 +--- /dev/null ++++ b/lldb/source/Plugins/Process/wasm/CMakeLists.txt +@@ -0,0 +1,12 @@ ++ ++add_lldb_library(lldbPluginProcessWasm PLUGIN ++ ProcessWasm.cpp ++ ThreadWasm.cpp ++ UnwindWasm.cpp ++ ++ LINK_LIBS ++ lldbCore ++ ${LLDB_PLUGINS} ++ LINK_COMPONENTS ++ Support ++ ) +diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp +new file mode 100644 +index 000000000000..b8ffcac12df2 +--- /dev/null ++++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp +@@ -0,0 +1,256 @@ ++//===-- ProcessWasm.cpp ---------------------------------------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "ProcessWasm.h" ++#include "ThreadWasm.h" ++#include "lldb/Core/Module.h" ++#include "lldb/Core/PluginManager.h" ++#include "lldb/Utility/DataBufferHeap.h" ++ ++using namespace lldb; ++using namespace lldb_private; ++using namespace lldb_private::process_gdb_remote; ++using namespace lldb_private::wasm; ++ ++LLDB_PLUGIN_DEFINE(ProcessWasm) ++ ++// ProcessGDBRemote constructor ++ProcessWasm::ProcessWasm(lldb::TargetSP target_sp, ListenerSP listener_sp) ++ : ProcessGDBRemote(target_sp, listener_sp) {} ++ ++void ProcessWasm::Initialize() { ++ static llvm::once_flag g_once_flag; ++ ++ llvm::call_once(g_once_flag, []() { ++ PluginManager::RegisterPlugin(GetPluginNameStatic(), ++ GetPluginDescriptionStatic(), CreateInstance, ++ DebuggerInitialize); ++ }); ++} ++ ++void ProcessWasm::DebuggerInitialize(Debugger &debugger) { ++ ProcessGDBRemote::DebuggerInitialize(debugger); ++} ++ ++// PluginInterface ++ConstString ProcessWasm::GetPluginName() { return GetPluginNameStatic(); } ++ ++uint32_t ProcessWasm::GetPluginVersion() { return 1; } ++ ++ConstString ProcessWasm::GetPluginNameStatic() { ++ static ConstString g_name("wasm"); ++ return g_name; ++} ++ ++const char *ProcessWasm::GetPluginDescriptionStatic() { ++ return "GDB Remote protocol based WebAssembly debugging plug-in."; ++} ++ ++void ProcessWasm::Terminate() { ++ PluginManager::UnregisterPlugin(ProcessWasm::CreateInstance); ++} ++ ++lldb::ProcessSP ProcessWasm::CreateInstance(lldb::TargetSP target_sp, ++ ListenerSP listener_sp, ++ const FileSpec *crash_file_path, ++ bool can_connect) { ++ lldb::ProcessSP process_sp; ++ if (crash_file_path == nullptr) ++ process_sp = std::make_shared(target_sp, listener_sp); ++ return process_sp; ++} ++ ++bool ProcessWasm::CanDebug(lldb::TargetSP target_sp, ++ bool plugin_specified_by_name) { ++ if (plugin_specified_by_name) ++ return true; ++ ++ Module *exe_module = target_sp->GetExecutableModulePointer(); ++ if (exe_module) { ++ ObjectFile *exe_objfile = exe_module->GetObjectFile(); ++ return exe_objfile->GetArchitecture().GetMachine() == llvm::Triple::wasm32; ++ } ++ // However, if there is no wasm module, we return false, otherwise, ++ // we might use ProcessWasm to attach gdb remote. ++ return false; ++} ++ ++ ++ ++std::shared_ptr ProcessWasm::CreateThread(lldb::tid_t tid) { ++ return std::make_shared(*this, tid); ++} ++ ++size_t ProcessWasm::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, ++ Status &error, ExecutionContext *exe_ctx) { ++ wasm_addr_t wasm_addr(vm_addr); ++ size_t nread = 0; ++ ++ switch (wasm_addr.GetType()) { ++ case WasmAddressType::Memory: ++ case WasmAddressType::Object: ++ return ProcessGDBRemote::ReadMemory(vm_addr, buf, size, error); ++ case WasmAddressType::Invalid: ++ default: ++ error.SetErrorStringWithFormat( ++ "Wasm read failed for invalid address 0x%" PRIx64, vm_addr); ++ return 0; ++ } ++} ++ ++size_t ProcessWasm::WasmReadMemory(uint32_t wasm_module_id, lldb::addr_t addr, ++ void *buf, size_t buffer_size) { ++ char packet[64]; ++ int packet_len = ++ ::snprintf(packet, sizeof(packet), "qWasmMem:%d;%" PRIx64 ";%" PRIx64, ++ wasm_module_id, static_cast(addr), ++ static_cast(buffer_size)); ++ assert(packet_len + 1 < (int)sizeof(packet)); ++ UNUSED_IF_ASSERT_DISABLED(packet_len); ++ StringExtractorGDBRemote response; ++ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, GetInterruptTimeout()) == ++ GDBRemoteCommunication::PacketResult::Success) { ++ if (response.IsNormalResponse()) { ++ return response.GetHexBytes(llvm::MutableArrayRef( ++ static_cast(buf), buffer_size), ++ '\xdd'); ++ } ++ } ++ return 0; ++} ++ ++size_t ProcessWasm::WasmReadData(uint32_t wasm_module_id, lldb::addr_t addr, ++ void *buf, size_t buffer_size) { ++ char packet[64]; ++ int packet_len = ++ ::snprintf(packet, sizeof(packet), "qWasmData:%d;%" PRIx64 ";%" PRIx64, ++ wasm_module_id, static_cast(addr), ++ static_cast(buffer_size)); ++ assert(packet_len + 1 < (int)sizeof(packet)); ++ UNUSED_IF_ASSERT_DISABLED(packet_len); ++ StringExtractorGDBRemote response; ++ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, GetInterruptTimeout()) == ++ GDBRemoteCommunication::PacketResult::Success) { ++ if (response.IsNormalResponse()) { ++ return response.GetHexBytes(llvm::MutableArrayRef( ++ static_cast(buf), buffer_size), ++ '\xdd'); ++ } ++ } ++ return 0; ++} ++ ++bool ProcessWasm::GetWasmLocal(int frame_index, int index, void *buf, ++ size_t buffer_size, size_t &size) { ++ StreamString packet; ++ packet.Printf("qWasmLocal:"); ++ packet.Printf("%d;%d", frame_index, index); ++ StringExtractorGDBRemote response; ++ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != ++ GDBRemoteCommunication::PacketResult::Success) { ++ return false; ++ } ++ ++ if (!response.IsNormalResponse()) { ++ return false; ++ } ++ ++ DataBufferSP buffer_sp( ++ new DataBufferHeap(response.GetStringRef().size() / 2, 0)); ++ response.GetHexBytes(buffer_sp->GetData(), '\xcc'); ++ size = buffer_sp->GetByteSize(); ++ if (size <= buffer_size) { ++ memcpy(buf, buffer_sp->GetBytes(), size); ++ return true; ++ } ++ ++ return false; ++} ++ ++bool ProcessWasm::GetWasmGlobal(int frame_index, int index, void *buf, ++ size_t buffer_size, size_t &size) { ++ StreamString packet; ++ packet.PutCString("qWasmGlobal:"); ++ packet.Printf("%d;%d", frame_index, index); ++ StringExtractorGDBRemote response; ++ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != ++ GDBRemoteCommunication::PacketResult::Success) { ++ return false; ++ } ++ ++ if (!response.IsNormalResponse()) { ++ return false; ++ } ++ ++ DataBufferSP buffer_sp( ++ new DataBufferHeap(response.GetStringRef().size() / 2, 0)); ++ response.GetHexBytes(buffer_sp->GetData(), '\xcc'); ++ size = buffer_sp->GetByteSize(); ++ if (size <= buffer_size) { ++ memcpy(buf, buffer_sp->GetBytes(), size); ++ return true; ++ } ++ ++ return false; ++} ++ ++bool ProcessWasm::GetWasmStackValue(int frame_index, int index, void *buf, ++ size_t buffer_size, size_t &size) { ++ StreamString packet; ++ packet.PutCString("qWasmStackValue:"); ++ packet.Printf("%d;%d", frame_index, index); ++ StringExtractorGDBRemote response; ++ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != ++ GDBRemoteCommunication::PacketResult::Success) { ++ return false; ++ } ++ ++ if (!response.IsNormalResponse()) { ++ return false; ++ } ++ ++ DataBufferSP buffer_sp( ++ new DataBufferHeap(response.GetStringRef().size() / 2, 0)); ++ response.GetHexBytes(buffer_sp->GetData(), '\xcc'); ++ size = buffer_sp->GetByteSize(); ++ if (size <= buffer_size) { ++ memcpy(buf, buffer_sp->GetBytes(), size); ++ return true; ++ } ++ ++ return false; ++} ++ ++bool ProcessWasm::GetWasmCallStack(lldb::tid_t tid, ++ std::vector &call_stack_pcs) { ++ call_stack_pcs.clear(); ++ StreamString packet; ++ packet.Printf("qWasmCallStack:"); ++ packet.Printf("%lx", tid); ++ StringExtractorGDBRemote response; ++ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != ++ GDBRemoteCommunication::PacketResult::Success) { ++ return false; ++ } ++ ++ if (!response.IsNormalResponse()) { ++ return false; ++ } ++ ++ addr_t buf[1024 / sizeof(addr_t)]; ++ size_t bytes = response.GetHexBytes( ++ llvm::MutableArrayRef((uint8_t *)buf, sizeof(buf)), '\xdd'); ++ if (bytes == 0) { ++ return false; ++ } ++ ++ for (size_t i = 0; i < bytes / sizeof(addr_t); i++) { ++ call_stack_pcs.push_back(buf[i]); ++ } ++ return true; ++} +diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h +new file mode 100644 +index 000000000000..d3aece7a6554 +--- /dev/null ++++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h +@@ -0,0 +1,128 @@ ++//===-- ProcessWasm.h -------------------------------------------*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H ++#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H ++ ++#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" ++#include "lldb/Target/RegisterContext.h" ++ ++namespace lldb_private { ++namespace wasm { ++ ++// Each WebAssembly module has separated address spaces for Code and Memory. ++// A WebAssembly module also has a Data section which, when the module is ++// loaded, gets mapped into a region in the module Memory. ++// For the purpose of debugging, we can represent all these separated 32-bit ++// address spaces with a single virtual 64-bit address space. ++// ++// Struct wasm_addr_t provides this encoding using bitfields ++// ++enum WasmAddressType { ++ Memory = 0x00, ++ Object = 0x01, ++ Invalid = 0x03 ++}; ++struct wasm_addr_t { ++ uint64_t offset : 32; ++ uint64_t module_id : 30; ++ uint64_t type : 2; ++ ++ wasm_addr_t(lldb::addr_t addr) ++ : type(addr >> 62), module_id((addr & 0x00ffffff00000000) >> 32), ++ offset(addr & 0x00000000ffffffff) {} ++ ++ wasm_addr_t(WasmAddressType type_, uint32_t module_id_, uint32_t offset_) ++ : type(type_), module_id(module_id_), offset(offset_) {} ++ ++ WasmAddressType GetType() { return static_cast(type); } ++ operator lldb::addr_t() { return *(uint64_t *)this; } ++}; ++ ++/// ProcessWasm provides the access to the Wasm program state ++/// retrieved from the Wasm engine. ++class ProcessWasm : public process_gdb_remote::ProcessGDBRemote { ++public: ++ ProcessWasm(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); ++ ~ProcessWasm() override = default; ++ ++ static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, ++ lldb::ListenerSP listener_sp, ++ const FileSpec *crash_file_path, ++ bool can_connect); ++ ++ static void Initialize(); ++ static void DebuggerInitialize(Debugger &debugger); ++ static void Terminate(); ++ static ConstString GetPluginNameStatic(); ++ static const char *GetPluginDescriptionStatic(); ++ ++ /// PluginInterface protocol. ++ /// \{ ++ ConstString GetPluginName() override; ++ uint32_t GetPluginVersion() override; ++ /// \} ++ ++ /// Process protocol. ++ /// \{ ++ size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Status &error, ++ ExecutionContext *exe_ctx = nullptr) override; ++ /// \} ++ ++ /// Query the value of a WebAssembly local variable from the WebAssembly ++ /// remote process. ++ bool GetWasmLocal(int frame_index, int index, void *buf, size_t buffer_size, ++ size_t &size); ++ ++ /// Query the value of a WebAssembly global variable from the WebAssembly ++ /// remote process. ++ bool GetWasmGlobal(int frame_index, int index, void *buf, size_t buffer_size, ++ size_t &size); ++ ++ /// Query the value of an item in the WebAssembly operand stack from the ++ /// WebAssembly remote process. ++ bool GetWasmStackValue(int frame_index, int index, void *buf, ++ size_t buffer_size, size_t &size); ++ ++ /// Read from the WebAssembly Memory space. ++ size_t WasmReadMemory(uint32_t wasm_module_id, lldb::addr_t addr, void *buf, ++ size_t buffer_size); ++ ++ /// Read from the WebAssembly Data space. ++ size_t WasmReadData(uint32_t wasm_module_id, lldb::addr_t addr, void *buf, ++ size_t buffer_size); ++ ++ /// Retrieve the current call stack from the WebAssembly remote process. ++ bool GetWasmCallStack(lldb::tid_t tid, ++ std::vector &call_stack_pcs); ++ ++ // Check if a given Process ++ bool CanDebug(lldb::TargetSP target_sp, ++ bool plugin_specified_by_name) override; ++ ++protected: ++ /// ProcessGDBRemote protocol. ++ /// \{ ++ std::shared_ptr ++ CreateThread(lldb::tid_t tid) override; ++ /// \} ++ ++private: ++ friend class UnwindWasm; ++ process_gdb_remote::GDBRemoteDynamicRegisterInfoSP &GetRegisterInfo() { ++ return m_register_info_sp; ++ } ++ ++ ProcessWasm(const ProcessWasm &); ++ const ProcessWasm &operator=(const ProcessWasm &) = delete; ++}; ++ ++} // namespace wasm ++} // namespace lldb_private ++ ++#endif // LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H +diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp +new file mode 100644 +index 000000000000..fa02073e7a52 +--- /dev/null ++++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp +@@ -0,0 +1,35 @@ ++//===-- ThreadWasm.cpp ----------------------------------------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "ThreadWasm.h" ++ ++#include "ProcessWasm.h" ++#include "UnwindWasm.h" ++#include "lldb/Target/Target.h" ++ ++using namespace lldb; ++using namespace lldb_private; ++using namespace lldb_private::wasm; ++ ++Unwind &ThreadWasm::GetUnwinder() { ++ if (!m_unwinder_up) { ++ assert(CalculateTarget()->GetArchitecture().GetMachine() == ++ llvm::Triple::wasm32); ++ m_unwinder_up.reset(new wasm::UnwindWasm(*this)); ++ } ++ return *m_unwinder_up; ++} ++ ++bool ThreadWasm::GetWasmCallStack(std::vector &call_stack_pcs) { ++ ProcessSP process_sp(GetProcess()); ++ if (process_sp) { ++ ProcessWasm *wasm_process = static_cast(process_sp.get()); ++ return wasm_process->GetWasmCallStack(GetID(), call_stack_pcs); ++ } ++ return false; ++} +diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.h b/lldb/source/Plugins/Process/wasm/ThreadWasm.h +new file mode 100644 +index 000000000000..0a33c07de994 +--- /dev/null ++++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.h +@@ -0,0 +1,41 @@ ++//===-- ThreadWasm.h --------------------------------------------*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLDB_SOURCE_PLUGINS_PROCESS_WASM_THREADWASM_H ++#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_THREADWASM_H ++ ++#include "Plugins/Process/gdb-remote/ThreadGDBRemote.h" ++ ++namespace lldb_private { ++namespace wasm { ++ ++/// ProcessWasm provides the access to the Wasm program state ++/// retrieved from the Wasm engine. ++class ThreadWasm : public process_gdb_remote::ThreadGDBRemote { ++public: ++ ThreadWasm(Process &process, lldb::tid_t tid) ++ : process_gdb_remote::ThreadGDBRemote(process, tid) {} ++ ~ThreadWasm() override = default; ++ ++ /// Retrieve the current call stack from the WebAssembly remote process. ++ bool GetWasmCallStack(std::vector &call_stack_pcs); ++ ++protected: ++ /// Thread protocol. ++ /// \{ ++ Unwind &GetUnwinder() override; ++ /// \} ++ ++ ThreadWasm(const ThreadWasm &); ++ const ThreadWasm &operator=(const ThreadWasm &) = delete; ++}; ++ ++} // namespace wasm ++} // namespace lldb_private ++ ++#endif // LLDB_SOURCE_PLUGINS_PROCESS_WASM_THREADWASM_H +diff --git a/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp b/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp +new file mode 100644 +index 000000000000..1a195cb9361a +--- /dev/null ++++ b/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp +@@ -0,0 +1,74 @@ ++//===-- UnwindWasm.cpp ----------------------------------------------------===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#include "UnwindWasm.h" ++#include "Plugins/Process/gdb-remote/ThreadGDBRemote.h" ++#include "Plugins/Process/wasm/ProcessWasm.h" ++#include "Plugins/Process/wasm/ThreadWasm.h" ++ ++using namespace lldb; ++using namespace lldb_private; ++using namespace process_gdb_remote; ++using namespace wasm; ++ ++class WasmGDBRemoteRegisterContext : public GDBRemoteRegisterContext { ++public: ++ WasmGDBRemoteRegisterContext(ThreadGDBRemote &thread, ++ uint32_t concrete_frame_idx, ++ GDBRemoteDynamicRegisterInfoSP ®_info_sp, ++ uint64_t pc) ++ : GDBRemoteRegisterContext(thread, concrete_frame_idx, reg_info_sp, false, ++ false) { ++ PrivateSetRegisterValue(0, pc); ++ } ++}; ++ ++lldb::RegisterContextSP ++UnwindWasm::DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) { ++ if (m_frames.size() <= frame->GetFrameIndex()) { ++ return lldb::RegisterContextSP(); ++ } ++ ++ ThreadSP thread = frame->GetThread(); ++ ThreadGDBRemote *gdb_thread = static_cast(thread.get()); ++ ProcessWasm *wasm_process = ++ static_cast(thread->GetProcess().get()); ++ std::shared_ptr reg_ctx_sp = ++ std::make_shared( ++ *gdb_thread, frame->GetConcreteFrameIndex(), ++ wasm_process->GetRegisterInfo(), m_frames[frame->GetFrameIndex()]); ++ return reg_ctx_sp; ++} ++ ++uint32_t UnwindWasm::DoGetFrameCount() { ++ if (!m_unwind_complete) { ++ m_unwind_complete = true; ++ m_frames.clear(); ++ ++ ThreadWasm &wasm_thread = static_cast(GetThread()); ++ if (!wasm_thread.GetWasmCallStack(m_frames)) ++ m_frames.clear(); ++ } ++ return m_frames.size(); ++} ++ ++bool UnwindWasm::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, ++ lldb::addr_t &pc, ++ bool &behaves_like_zeroth_frame) { ++ if (m_frames.size() == 0) { ++ DoGetFrameCount(); ++ } ++ ++ if (frame_idx < m_frames.size()) { ++ behaves_like_zeroth_frame = (frame_idx == 0); ++ cfa = 0; ++ pc = m_frames[frame_idx]; ++ return true; ++ } ++ return false; ++} +\ No newline at end of file +diff --git a/lldb/source/Plugins/Process/wasm/UnwindWasm.h b/lldb/source/Plugins/Process/wasm/UnwindWasm.h +new file mode 100644 +index 000000000000..9bd1dac9a98a +--- /dev/null ++++ b/lldb/source/Plugins/Process/wasm/UnwindWasm.h +@@ -0,0 +1,55 @@ ++//===-- UnwindWasm.h --------------------------------------------*- C++ -*-===// ++// ++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. ++// See https://llvm.org/LICENSE.txt for license information. ++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef lldb_UnwindWasm_h_ ++#define lldb_UnwindWasm_h_ ++ ++#include "lldb/Target/RegisterContext.h" ++#include "lldb/Target/Unwind.h" ++#include ++ ++namespace lldb_private { ++namespace wasm { ++ ++/// UnwindWasm manages stack unwinding for a WebAssembly process. ++class UnwindWasm : public lldb_private::Unwind { ++public: ++ UnwindWasm(lldb_private::Thread &thread) ++ : Unwind(thread), m_frames(), m_unwind_complete(false) {} ++ ~UnwindWasm() override = default; ++ ++protected: ++ /// Unwind protocol. ++ /// \{ ++ void DoClear() override { ++ m_frames.clear(); ++ m_unwind_complete = false; ++ } ++ ++ uint32_t DoGetFrameCount() override; ++ ++ bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, ++ lldb::addr_t &pc, ++ bool &behaves_like_zeroth_frame) override; ++ ++ lldb::RegisterContextSP ++ DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; ++ /// \} ++ ++private: ++ std::vector m_frames; ++ bool m_unwind_complete; ++ ++ UnwindWasm(const UnwindWasm &); ++ const UnwindWasm &operator=(const UnwindWasm &) = delete; ++}; ++ ++} // namespace wasm ++} // namespace lldb_private ++ ++#endif // lldb_UnwindWasm_h_ +diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +index ccaf31317d75..c3ef5aebd46d 100644 +--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp ++++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +@@ -3212,8 +3212,13 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, + GetDWARFDeclContext(die).GetQualifiedNameAsConstString().GetCString(); + } + +- if (tag == DW_TAG_formal_parameter) ++ if (tag == DW_TAG_formal_parameter) { + scope = eValueTypeVariableArgument; ++ // For Wasm dwarft, pamameter may don't have location attr, ++ // so set module here ++ if (!location.GetModule()) ++ location.SetModule(module); ++ } + else { + // DWARF doesn't specify if a DW_TAG_variable is a local, global + // or static variable, so we have to do a little digging: +diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp +index a77ecddfbab6..e257f93508f6 100644 +--- a/lldb/source/Target/Platform.cpp ++++ b/lldb/source/Target/Platform.cpp +@@ -1970,6 +1970,12 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target, + trap_opcode_size = sizeof(g_i386_opcode); + } break; + ++ case llvm::Triple::wasm32: { ++ static const uint8_t g_wasm_opcode[] = {0x00}; // unreachable ++ trap_opcode = g_wasm_opcode; ++ trap_opcode_size = sizeof(g_wasm_opcode); ++ } break; ++ + default: + return 0; + } +diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp +index 8ecc66b592ea..f148987915de 100644 +--- a/lldb/source/Target/Process.cpp ++++ b/lldb/source/Target/Process.cpp +@@ -1892,7 +1892,8 @@ Status Process::DisableSoftwareBreakpoint(BreakpointSite *bp_site) { + // code + //#define VERIFY_MEMORY_READS + +-size_t Process::ReadMemory(addr_t addr, void *buf, size_t size, Status &error) { ++size_t Process::ReadMemory(addr_t addr, void *buf, size_t size, Status &error, ++ ExecutionContext *exe_ctx) { + error.Clear(); + if (!GetDisableMemoryCache()) { + #if defined(VERIFY_MEMORY_READS) +diff --git a/lldb/source/Target/ProcessTrace.cpp b/lldb/source/Target/ProcessTrace.cpp +index c878a2ac4eb9..ad5945b0ad1f 100644 +--- a/lldb/source/Target/ProcessTrace.cpp ++++ b/lldb/source/Target/ProcessTrace.cpp +@@ -88,7 +88,7 @@ void ProcessTrace::RefreshStateAfterStop() {} + Status ProcessTrace::DoDestroy() { return Status(); } + + size_t ProcessTrace::ReadMemory(addr_t addr, void *buf, size_t size, +- Status &error) { ++ Status &error, ExecutionContext *exe_ctx) { + // Don't allow the caching that lldb_private::Process::ReadMemory does since + // we have it all cached in the trace files. + return DoReadMemory(addr, buf, size, error); diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index b647219d60..2ef197fc7d 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -52,11 +52,6 @@ if (WAMR_BUILD_INTERP EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1) include (${IWASM_DIR}/interpreter/iwasm_interp.cmake) endif () -if (WAMR_BUILD_TARGET MATCHES "RISCV.*" AND WAMR_BUILD_AOT EQUAL 1) - set (WAMR_BUILD_AOT 0) - message ("-- WAMR AOT disabled as it isn't supported by riscv currently") -endif () - if (WAMR_BUILD_AOT EQUAL 1) include (${IWASM_DIR}/aot/iwasm_aot.cmake) if (WAMR_BUILD_JIT EQUAL 1) @@ -89,6 +84,11 @@ if (WAMR_BUILD_LIB_PTHREAD EQUAL 1) set (WAMR_BUILD_SHARED_MEMORY 1) endif () +if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) + set (WAMR_BUILD_THREAD_MGR 1) + include (${IWASM_DIR}/libraries/debug-engine/debug_engine.cmake) +endif () + if (WAMR_BUILD_THREAD_MGR EQUAL 1) include (${IWASM_DIR}/libraries/thread-mgr/thread_mgr.cmake) endif () @@ -137,6 +137,7 @@ set (source_all ${LIB_PTHREAD_SOURCE} ${THREAD_MGR_SOURCE} ${LIBC_EMCC_SOURCE} + ${DEBUG_ENGINE_SOURCE} ) set (WAMR_RUNTIME_LIB_SOURCE ${source_all}) diff --git a/ci/Dockerfile b/ci/Dockerfile index 7c3bed58a7..1a176d3529 100644 --- a/ci/Dockerfile +++ b/ci/Dockerfile @@ -1,18 +1,83 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -FROM ubuntu:18.04 +ARG VARIANT=need_to_assign +FROM ubuntu:${VARIANT} + +ARG DEBIAN_FRONTEND=noninteractive +ENV TZ=Asian/Shanghai RUN apt update \ && apt install -y apt-transport-https ca-certificates gnupg \ - software-properties-common wget lsb-release curl build-essential + tzdata lsb-release software-properties-common build-essential \ + apt-utils curl wget git tree unzip zip vim # # CMAKE (https://apt.kitware.com/) -RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null \ - && apt purge --auto-remove cmake \ - && apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' \ +RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg > /dev/null \ + && echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ bionic main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null \ && apt update \ - && apt-get install -y kitware-archive-keyring \ - && rm /etc/apt/trusted.gpg.d/kitware.gpg \ - && apt-get install -y cmake + && rm /usr/share/keyrings/kitware-archive-keyring.gpg \ + && apt install -y kitware-archive-keyring \ + && apt install -y cmake + +# +# install emsdk (may not necessary ?) +RUN cd /opt \ + && git clone https://github.com/emscripten-core/emsdk.git +RUN cd /opt/emsdk \ + && git pull \ + && ./emsdk install 2.0.26 \ + && ./emsdk activate 2.0.26 \ + && echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc + +# +#install wabt +ARG WABT_VER=1.0.23 +RUN wget -c https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -P /opt +RUN tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \ + && ln -fs /opt/wabt-${WABT_VER} /opt/wabt +RUN rm /opt/wabt-${WABT_VER}-ubuntu.tar.gz + +# +# install binaryen +ARG BINARYEN_VER=version_101 +RUN wget -c https://github.com/WebAssembly/binaryen/releases/download/${BINARYEN_VER}/binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz -P /opt +RUN tar xf /opt/binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz -C /opt \ + && ln -fs /opt/binaryen-${BINARYEN_VER} /opt/binaryen +RUN rm /opt/binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz + + +# +# install bazelisk +ARG BAZELISK_VER=1.10.1 +RUN mkdir /opt/bazelisk +RUN wget -c https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -P /opt/bazelisk +RUN chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \ + && ln -fs /opt/bazelisk/bazelisk-linux-amd64 /opt/bazelisk/bazel + +# set path +RUN echo "PATH=/opt/clang_llvm/bin:/opt/wasi-sdk/bin:/opt/wabt/bin:/opt/binaryen/bin:/opt/bazelisk:${PATH}" >> /root/.bashrc + +# +# install +RUN apt update \ + && apt install -y ninja-build python2.7 valgrind + +# +# ocaml +RUN apt update \ + && apt install -y ocaml ocamlbuild + +# +# PS +RUN echo "PS1='\n[ \u@wamr-dev-docker \W ]\n$ '" >> /root/.bashrc + +# Clean up +RUN apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/* + +VOLUME workspace +WORKDIR workspace diff --git a/ci/build_wamr.sh b/ci/build_wamr.sh index 9d02aba84d..9b944662e6 100755 --- a/ci/build_wamr.sh +++ b/ci/build_wamr.sh @@ -1,24 +1,33 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -docker build -t wamr_dev:0.1 -f Dockerfile . \ - && docker run --rm -it \ - --name wamr_building \ - --mount type=bind,src=$(realpath .)/..,dst=/source \ - --workdir /source \ - wamr_dev:0.1 \ - /bin/bash -c "\ - pushd product-mini/platforms/linux \ - && mkdir -p build \ - && pushd build \ - && rm -rf * \ - && cmake .. \ - && make \ - && popd \ - && popd \ - && echo 'Copying binary for image build' \ - && mkdir -p build_out \ - && rm build_out/* \ - && cp -f product-mini/platforms/linux/build/iwasm build_out/iwasm" +readonly CURRENT_PATH=$(dirname "$(realpath "$0")") +readonly ROOT=$(realpath "${CURRENT_PATH}/..") +readonly VARIANT=$(lsb_release -c | awk '{print $2}') + +docker build \ + --build-arg VARIANT=${VARIANT} \ + --memory=4G --cpu-quota=50000 \ + -t wamr_dev_${VARIANT}:0.1 -f "${CURRENT_PATH}"/Dockerfile "${CURRENT_PATH}" && + docker run --rm -it \ + --cpus=".5" \ + --memory=4G \ + --name wamr_build_env \ + --mount type=bind,src="${ROOT}",dst=/workspace \ + wamr_dev_${VARIANT}:0.1 \ + /bin/bash -c "\ + pwd \ + && pushd product-mini/platforms/linux \ + && rm -rf build \ + && mkdir build \ + && pushd build \ + && cmake .. \ + && make \ + && popd \ + && popd \ + && echo 'Copying the binary ...' \ + && rm -rf build_out \ + && mkdir build_out \ + && cp product-mini/platforms/linux/build/iwasm build_out/iwasm" diff --git a/ci/run_pre_commit_check.py b/ci/run_pre_commit_check.py new file mode 100644 index 0000000000..41f907bd82 --- /dev/null +++ b/ci/run_pre_commit_check.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import json +import os +import pathlib +import queue +import re +import shlex +import shutil +import subprocess +import sys + +CLANG_CMD = "clang-13" +CLANG_CPP_CMD = "clang-cpp-13" +CLANG_FORMAT_CMD = "clang-format-13" +CLANG_TIDY_CMD = "clang-tidy-13" +CMAKE_CMD = "cmake" + + +# glob style patterns +EXCLUDE_PATHS = [ + "**/.git/", + "**/.github/", + "**/.vscode/", + "**/assembly-script/", + "**/build/", + "**/build-scripts/", + "**/ci/", + "**/core/deps/", + "**/doc/", + "**/samples/workload/", + "**/test-tools/", + "**/wamr-sdk/", + "**/wamr-dev/", + "**/wamr-dev-simd/", +] + +C_SUFFIXES = [".c", ".h"] + +VALID_DIR_NAME = r"([a-zA-Z0-9]+\-*)+[a-zA-Z0-9]*" +VALID_FILE_NAME = r"\.?([a-zA-Z0-9]+\_*)+[a-zA-Z0-9]*\.*\w*" + + +def locate_command(command): + if not shutil.which(command): + print(f"Command '{command}'' not found") + return False + + return True + + +def is_excluded(path): + for exclude_path in EXCLUDE_PATHS: + if path.match(exclude_path): + return True + return False + + +def pre_flight_check(root): + def check_clang_foramt(root): + if not locate_command(CLANG_FORMAT_CMD): + return False + + # Quick syntax check for .clang-format + try: + subprocess.check_call( + shlex.split(f"{CLANG_FORMAT_CMD} --dump-config"), cwd=root + ) + except subprocess.CalledProcessError: + print(f"Might have a typo in .clang-format") + return False + return True + + def check_clang_tidy(root): + if not locate_command(CLANG_TIDY_CMD): + return False + + if ( + not locate_command(CLANG_CMD) + or not locate_command(CLANG_CPP_CMD) + or not locate_command(CMAKE_CMD) + ): + return False + + # Quick syntax check for .clang-format + try: + subprocess.check_call( + shlex.split("{CLANG_TIDY_CMD} --dump-config"), cwd=root + ) + except subprocess.CalledProcessError: + print(f"Might have a typo in .clang-tidy") + return False + + # looking for compile command database + return True + + def check_aspell(root): + return True + + return check_clang_foramt(root) and check_clang_tidy(root) and check_aspell(root) + + +def run_clang_format(file_path, root): + try: + subprocess.check_call( + shlex.split( + f"{CLANG_FORMAT_CMD} --style=file --Werror --dry-run {file_path}" + ), + cwd=root, + ) + return True + except subprocess.CalledProcessError: + print(f"{file_path} failed the check of {CLANG_FORMAT_CMD}") + return False + + +def generate_compile_commands(compile_command_database, root): + CMD = f"{CMAKE_CMD} -DCMAKE_C_COMPILER={shutil.which(CLANG_CMD)} -DCMAKE_CXX_COMPILER={shutil.which(CLANG_CPP_CMD)} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .." + + try: + linux_mini_build = root.joinpath("product-mini/platforms/linux/build").resolve() + linux_mini_build.mkdir(exist_ok=True) + if subprocess.check_call(shlex.split(CMD), cwd=linux_mini_build): + return False + + wamrc_build = root.joinpath("wamr-compiler/build").resolve() + wamrc_build.mkdir(exist_ok=True) + + if subprocess.check_call(shlex.split(CMD), cwd=wamrc_build): + return False + + with open(linux_mini_build.joinpath("compile_commands.json"), "r") as f: + iwasm_compile_commands = json.load(f) + + with open(wamrc_build.joinpath("compile_commands.json"), "r") as f: + wamrc_compile_commands = json.load(f) + + all_compile_commands = iwasm_compile_commands + wamrc_compile_commands + # TODO: duplication items ? + with open(compile_command_database, "w") as f: + json.dump(all_compile_commands, f) + + return True + except subprocess.CalledProcessError: + return False + + +def run_clang_tidy(file_path, root): + # preparatoin + compile_command_database = pathlib.Path("/tmp/compile_commands.json") + if not compile_command_database.exists() and not generate_compile_commands( + compile_command_database, root + ): + return False + + try: + if subprocess.check_call( + shlex.split(f"{CLANG_TIDY_CMD} -p={compile_command_database} {file_path}"), + cwd=root, + ): + print(f"{file_path} failed the check of {CLANG_TIDY_CMD}") + except subprocess.CalledProcessError: + print(f"{file_path} failed the check of {CLANG_TIDY_CMD}") + return False + return True + + +def run_aspell(file_path, root): + return True + + +def check_dir_name(path, root): + # since we don't want to check the path beyond root. + # we hope "-" only will be used in a dir name as separators + return all( + [ + re.match(VALID_DIR_NAME, path_part) + for path_part in path.relative_to(root).parts + ] + ) + + +def check_file_name(path): + # since we don't want to check the path beyond root. + # we hope "_" only will be used in a file name as separators + return re.match(VALID_FILE_NAME, path.name) is not None + + +def run_pre_commit_check(path, root=None): + path = path.resolve() + if path.is_dir(): + if not check_dir_name(path, root): + print(f"{path} is not a valid directory name") + return False + else: + return True + + if path.is_file(): + if not check_file_name(path): + print(f"{path} is not a valid file name") + return False + + if not path.suffix in C_SUFFIXES: + return True + + return ( + run_clang_format(path, root) + and run_clang_tidy(path, root) + and run_aspell(path, root) + ) + + print(f"{path} neither a file nor a directory") + return False + + +def main(): + wamr_root = pathlib.Path(__file__).parent.joinpath("..").resolve() + + if not pre_flight_check(wamr_root): + return False + + invalid_file, invalid_directory = 0, 0 + + # in order to skip exclude directories ASAP, + # will not yield Path. + # since we will create every object + dirs = queue.Queue() + dirs.put(wamr_root) + while not dirs.empty(): + qsize = dirs.qsize() + while qsize: + current_dir = dirs.get() + + for path in current_dir.iterdir(): + path = path.resolve() + + if path.is_symlink(): + continue + + if path.is_dir() and not is_excluded(path): + invalid_directory += ( + 0 if run_pre_commit_check(path, wamr_root) else 1 + ) + dirs.put(path) + + if not path.is_file(): + continue + + invalid_file += 0 if run_pre_commit_check(path) else 1 + + else: + qsize -= 1 + + print(f"invalid_directory={invalid_directory}, invalid_file={invalid_file}") + return True + + +if __name__ == "__main__": + main() diff --git a/core/app-framework/app-native-shared/restful_utils.c b/core/app-framework/app-native-shared/restful_utils.c index 5268b22a7a..74bd59a52a 100644 --- a/core/app-framework/app-native-shared/restful_utils.c +++ b/core/app-framework/app-native-shared/restful_utils.c @@ -32,29 +32,44 @@ #define REQUES_PACKET_VER 1 #define REQUEST_PACKET_FIX_PART_LEN 18 #define REQUEST_PACKET_URL_OFFSET REQUEST_PACKET_FIX_PART_LEN -#define REQUEST_PACKET_URL_LEN *((uint16*)( (char*) buffer + 12))) //!!! to ensure little endian -#define REQUEST_PACKET_PAYLOAD_LEN *((uint32*)( (char*) buffer + 14))) //!!! to ensure little endian +#define REQUEST_PACKET_URL_LEN *((uint16*)((char*) buffer + 12)) /* to ensure little endian */ +#define REQUEST_PACKET_PAYLOAD_LEN *((uint32*)((char*) buffer + 14)) /* to ensure little endian */ #define REQUEST_PACKET_URL(buffer) ((char*) buffer + REQUEST_PACKET_URL_OFFSET) #define REQUEST_PACKET_PAYLOAD(buffer) ((char*) buffer + REQUEST_PACKET_URL_OFFSET + REQUEST_PACKET_URL_LEN(buffer)) #define RESPONSE_PACKET_FIX_PART_LEN 16 -char * pack_request(request_t *request, int * size) +char * +pack_request(request_t *request, int *size) { int url_len = strlen(request->url) + 1; int len = REQUEST_PACKET_FIX_PART_LEN + url_len + request->payload_len; - char * packet = (char*) WA_MALLOC(len); - if (packet == NULL) + uint16 u16; + uint32 u32; + char *packet; + + if ((packet = (char*) WA_MALLOC(len)) == NULL) return NULL; - // TODO: ensure little endian for words and dwords + /* TODO: ensure little endian for words and dwords */ *packet = REQUES_PACKET_VER; *((uint8*) (packet + 1)) = request->action; - *((uint16*) (packet + 2)) = htons(request->fmt); - *((uint32*) (packet + 4)) = htonl(request->mid); - *((uint32*) (packet + 8)) = htonl(request->sender); - *((uint16*) (packet + 12)) = htons(url_len); - *((uint32*) (packet + 14)) = htonl(request->payload_len); + + u16 = htons(request->fmt); + memcpy(packet + 2, &u16, 2); + + u32 = htonl(request->mid); + memcpy(packet + 4, &u32, 4); + + u32 = htonl(request->sender); + memcpy(packet + 8, &u32, 4); + + u16 = htons(url_len); + memcpy(packet + 12, &u16, 2); + + u32 = htonl(request->payload_len); + memcpy(packet + 14, &u32, 4); + strcpy(packet + REQUEST_PACKET_URL_OFFSET, request->url); memcpy(packet + REQUEST_PACKET_URL_OFFSET + url_len, request->payload, request->payload_len); @@ -63,35 +78,53 @@ char * pack_request(request_t *request, int * size) return packet; } -void free_req_resp_packet(char * packet) +void +free_req_resp_packet(char *packet) { WA_FREE(packet); } -request_t * unpack_request(char * packet, int size, request_t * request) +request_t * +unpack_request(char *packet, int size, request_t *request) { + uint16 url_len, u16; + uint32 payload_len, u32; + if (*packet != REQUES_PACKET_VER) { return NULL; } if (size < REQUEST_PACKET_FIX_PART_LEN) { return NULL; } - uint16 url_len = ntohs(*((uint16*) (packet + 12))); - uint32 payload_len = ntohl(*((uint32*) (packet + 14))); - if (size != ( REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len)) { + memcpy(&u16, packet + 12, 2); + url_len = ntohs(u16); + + memcpy(&u32, packet + 14, 4); + payload_len = ntohl(u32); + + if (size != (REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len)) { return NULL; } + if (*(packet + REQUEST_PACKET_FIX_PART_LEN + url_len - 1) != 0) { return NULL; } request->action = *((uint8*) (packet + 1)); - request->fmt = ntohs(*((uint16*) (packet + 2))); - request->mid = ntohl(*((uint32*) (packet + 4))); - request->sender = ntohl(*((uint32*) (packet + 8))); + + memcpy(&u16, packet + 2, 2); + request->fmt = ntohs(u16); + + memcpy(&u32, packet + 4, 4); + request->mid = ntohl(u32); + + memcpy(&u32, packet + 8, 4); + request->sender = ntohl(u32); + request->payload_len = payload_len; request->url = REQUEST_PACKET_URL(packet); + if (payload_len > 0) request->payload = packet + REQUEST_PACKET_URL_OFFSET + url_len; else @@ -100,20 +133,33 @@ request_t * unpack_request(char * packet, int size, request_t * request) return request; } -char * pack_response(response_t *response, int * size) +char * +pack_response(response_t *response, int *size) { int len = RESPONSE_PACKET_FIX_PART_LEN + response->payload_len; - char * packet = (char*) WA_MALLOC(len); - if (packet == NULL) + uint16 u16; + uint32 u32; + char *packet; + + if ((packet = (char*) WA_MALLOC(len)) == NULL) return NULL; - // TODO: ensure little endian for words and dwords + /* TODO: ensure little endian for words and dwords */ *packet = REQUES_PACKET_VER; *((uint8*) (packet + 1)) = response->status; - *((uint16*) (packet + 2)) = htons(response->fmt); - *((uint32*) (packet + 4)) = htonl(response->mid); - *((uint32*) (packet + 8)) = htonl(response->reciever); - *((uint32*) (packet + 12)) = htonl(response->payload_len); + + u16 = htons(response->fmt); + memcpy(packet + 2, &u16, 2); + + u32 = htonl(response->mid); + memcpy(packet + 4, &u32, 4); + + u32 = htonl(response->reciever); + memcpy(packet + 8, &u32, 4); + + u32 = htonl(response->payload_len); + memcpy(packet + 12, &u32, 4); + memcpy(packet + RESPONSE_PACKET_FIX_PART_LEN, response->payload, response->payload_len); @@ -121,20 +167,34 @@ char * pack_response(response_t *response, int * size) return packet; } -response_t * unpack_response(char * packet, int size, response_t * response) +response_t * +unpack_response(char *packet, int size, response_t *response) { + uint16 u16; + uint32 payload_len, u32; + if (*packet != REQUES_PACKET_VER) return NULL; + if (size < RESPONSE_PACKET_FIX_PART_LEN) return NULL; - uint32 payload_len = ntohl(*((uint32*) (packet + 12))); - if (size != ( RESPONSE_PACKET_FIX_PART_LEN + payload_len)) + + memcpy(&u32, packet + 12, 4); + payload_len = ntohl(u32); + if (size != (RESPONSE_PACKET_FIX_PART_LEN + payload_len)) return NULL; response->status = *((uint8*) (packet + 1)); - response->fmt = ntohs(*((uint16*) (packet + 2))); - response->mid = ntohl(*((uint32*) (packet + 4))); - response->reciever = ntohl(*((uint32*) (packet + 8))); + + memcpy(&u16, packet + 2, 2); + response->fmt = ntohs(u16); + + memcpy(&u32, packet + 4, 4); + response->mid = ntohl(u32); + + memcpy(&u32, packet + 8, 4); + response->reciever = ntohl(u32); + response->payload_len = payload_len; if (payload_len > 0) response->payload = packet + RESPONSE_PACKET_FIX_PART_LEN; @@ -144,7 +204,8 @@ response_t * unpack_response(char * packet, int size, response_t * response) return response; } -request_t *clone_request(request_t *request) +request_t * +clone_request(request_t *request) { /* deep clone */ request_t *req = (request_t *) WA_MALLOC(sizeof(request_t)); @@ -164,12 +225,14 @@ request_t *clone_request(request_t *request) req->payload_len = request->payload_len; if (request->payload_len) { - req->payload = (char *) WA_MALLOC(request->payload_len); + req->payload = (char *)WA_MALLOC(request->payload_len); if (!req->payload) goto fail; memcpy(req->payload, request->payload, request->payload_len); - } else { - // when payload_len is 0, the payload may be used for carrying some handle or integer + } + else { + /* when payload_len is 0, the payload may be used for + carrying some handle or integer */ req->payload = request->payload; } @@ -180,7 +243,8 @@ request_t *clone_request(request_t *request) return NULL; } -void request_cleaner(request_t *request) +void +request_cleaner(request_t *request) { if (request->url != NULL) WA_FREE(request->url); @@ -190,7 +254,8 @@ void request_cleaner(request_t *request) WA_FREE(request); } -void response_cleaner(response_t * response) +void +response_cleaner(response_t *response) { if (response->payload != NULL && response->payload_len > 0) WA_FREE(response->payload); @@ -198,9 +263,11 @@ void response_cleaner(response_t * response) WA_FREE(response); } -response_t * clone_response(response_t * response) +response_t * +clone_response(response_t *response) { - response_t *clone = (response_t *) WA_MALLOC(sizeof(response_t)); + response_t *clone = (response_t *)WA_MALLOC(sizeof(response_t)); + if (clone == NULL) return NULL; @@ -215,8 +282,10 @@ response_t * clone_response(response_t * response) if (!clone->payload) goto fail; memcpy(clone->payload, response->payload, response->payload_len); - } else { - // when payload_len is 0, the payload may be used for carrying some handle or integer + } + else { + /* when payload_len is 0, the payload may be used for + carrying some handle or integer */ clone->payload = response->payload; } return clone; @@ -226,8 +295,9 @@ response_t * clone_response(response_t * response) return NULL; } -response_t * set_response(response_t * response, int status, int fmt, - const char *payload, int payload_len) +response_t * +set_response(response_t *response, int status, int fmt, + const char *payload, int payload_len) { response->payload = (void *)payload; response->payload_len = payload_len; @@ -236,8 +306,9 @@ response_t * set_response(response_t * response, int status, int fmt, return response; } -response_t * make_response_for_request(request_t * request, - response_t * response) +response_t * +make_response_for_request(request_t *request, + response_t *response) { response->mid = request->mid; response->reciever = request->sender; @@ -245,10 +316,12 @@ response_t * make_response_for_request(request_t * request, return response; } -request_t * init_request(request_t * request, char *url, int action, int fmt, - void *payload, int payload_len) +static unsigned int mid = 0; + +request_t * +init_request(request_t *request, char *url, int action, int fmt, + void *payload, int payload_len) { - static unsigned int mid = 0; request->url = url; request->action = action; request->fmt = fmt; @@ -269,7 +342,8 @@ request_t * init_request(request_t * request, char *url, int action, int fmt, 3. it ensure the leading_str "/abc" can pass "/abc?cde */ -int check_url_start(const char* url, int url_len, const char * leading_str) +int +check_url_start(const char *url, int url_len, const char *leading_str) { int offset = 0; if (*leading_str == '/') @@ -284,28 +358,27 @@ int check_url_start(const char* url, int url_len, const char * leading_str) if (len == 0) return 0; - // ensure leading_str not end with "/" + /* ensure leading_str not end with "/" */ if (leading_str[len - 1] == '/') { len--; if (len == 0) return 0; } - // equal length + /* equal length */ if (url_len == len) { if (memcmp(url, leading_str, url_len) == 0) { return (offset + len); - } else { + } + else { return 0; } } if (url_len < len) return 0; - else if (memcmp(url, leading_str, len) != 0) return 0; - else if (url[len] != '/' && url[len] != '?') return 0; else @@ -318,7 +391,8 @@ int check_url_start(const char* url, int url_len, const char * leading_str) // * sample 3: /abcd*, match any url started with "/abcd" // * sample 4: /abcd/*, exclude "/abcd" -bool match_url(char * pattern, char * matched) +bool +match_url(char *pattern, char *matched) { if (*pattern == '/') pattern++; @@ -352,17 +426,19 @@ bool match_url(char * pattern, char * matched) return false; - } else if (pattern[len - 1] == '*') { + } + else if (pattern[len - 1] == '*') { if (pattern[len - 2] == '/') { if (strncmp(pattern, matched, len - 1) == 0) return true; - else return false; - } else { + } + else { return (strncmp(pattern, matched, len - 1) == 0); } - } else { + } + else { return (strcmp(pattern, matched) == 0); } } @@ -371,10 +447,11 @@ bool match_url(char * pattern, char * matched) * get the value of the key from following format buffer: * key1=value1;key2=value2;key3=value3 */ -char * find_key_value(char * buffer, int buffer_len, char * key, char * value, - int value_len, char delimiter) +char * +find_key_value(char *buffer, int buffer_len, char *key, char *value, + int value_len, char delimiter) { - char * p = buffer; + char *p = buffer; int remaining = buffer_len; int key_len = strlen(key); @@ -387,13 +464,13 @@ char * find_key_value(char * buffer, int buffer_len, char * key, char * value, if (remaining <= key_len) return NULL; - // find the key + /* find the key */ if (0 == strncmp(p, key, key_len) && p[key_len] == '=') { p += (key_len + 1); remaining -= (key_len + 1); char * v = value; memset(value, 0, value_len); - value_len--; // ensure last char is 0 + value_len--; /* ensure last char is 0 */ while (*p != delimiter && remaining > 0 && value_len > 0) { *v++ = *p++; remaining--; @@ -402,7 +479,7 @@ char * find_key_value(char * buffer, int buffer_len, char * key, char * value, return value; } - // goto next key + /* goto next key */ while (*p != delimiter && remaining > 0) { p++; remaining--; diff --git a/core/app-mgr/app-manager/module_wasm_app.c b/core/app-mgr/app-manager/module_wasm_app.c index a7d993ade1..f7752bd5bf 100644 --- a/core/app-mgr/app-manager/module_wasm_app.c +++ b/core/app-mgr/app-manager/module_wasm_app.c @@ -13,7 +13,9 @@ #include "event.h" #include "watchdog.h" #include "runtime_lib.h" +#if WASM_ENABLE_INTERP != 0 #include "wasm.h" +#endif #if WASM_ENABLE_AOT != 0 #include "aot_export.h" #endif @@ -163,6 +165,15 @@ module_interface wasm_app_module_interface = { wasm_app_module_on_install_request_byte_arrive }; +#if WASM_ENABLE_INTERP == 0 +static unsigned +align_uint(unsigned v, unsigned b) +{ + unsigned m = b - 1; + return (v + m) & ~m; +} +#endif + static void exchange_uint32(uint8 *p_data) { @@ -577,7 +588,7 @@ wasm_app_module_install(request_t * msg) char m_name[APP_NAME_MAX_LEN] = { 0 }; char timeout_str[MAX_INT_STR_LEN] = { 0 }; char heap_size_str[MAX_INT_STR_LEN] = { 0 }; - char timers_str[MAX_INT_STR_LEN] = { 0 }, err[256]; + char timers_str[MAX_INT_STR_LEN] = { 0 }, err[128], err_resp[256]; #if WASM_ENABLE_LIBC_WASI != 0 char wasi_dir_buf[PATH_MAX] = { 0 }; const char *wasi_dir_list[] = { wasi_dir_buf }; @@ -642,7 +653,8 @@ wasm_app_module_install(request_t * msg) AOT_SECTION_TYPE_FUNCTION, AOT_SECTION_TYPE_EXPORT, AOT_SECTION_TYPE_RELOCATION, - AOT_SECTION_TYPE_SIGANATURE + AOT_SECTION_TYPE_SIGANATURE, + AOT_SECTION_TYPE_CUSTOM, }; aot_file = &wasm_app_file->u.aot; @@ -651,8 +663,9 @@ wasm_app_module_install(request_t * msg) module = wasm_runtime_load_from_sections(aot_file->sections, true, err, err_size); if (!module) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: load WASM file failed."); + snprintf(err_resp, sizeof(err_resp), + "Install WASM app failed: %s", err); + SEND_ERR_RESPONSE(msg->mid, err_resp); goto fail; } /* Destroy useless sections from list after load */ @@ -677,8 +690,9 @@ wasm_app_module_install(request_t * msg) /* Instantiate the AOT module */ inst = wasm_runtime_instantiate(module, 0, heap_size, err, err_size); if (!inst) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: instantiate wasm runtime failed."); + snprintf(err_resp, sizeof(err_resp), + "Install WASM app failed: %s", err); + SEND_ERR_RESPONSE(msg->mid, err); goto fail; } break; @@ -715,8 +729,9 @@ wasm_app_module_install(request_t * msg) module = wasm_runtime_load_from_sections(bytecode_file->sections, false, err, err_size); if (!module) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: load WASM file failed."); + snprintf(err_resp, sizeof(err_resp), + "Install WASM app failed: %s", err); + SEND_ERR_RESPONSE(msg->mid, err_resp); goto fail; } @@ -742,8 +757,9 @@ wasm_app_module_install(request_t * msg) /* Instantiate the wasm module */ inst = wasm_runtime_instantiate(module, 0, heap_size, err, err_size); if (!inst) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: instantiate wasm runtime failed."); + snprintf(err_resp, sizeof(err_resp), + "Install WASM app failed: %s", err); + SEND_ERR_RESPONSE(msg->mid, err_resp); goto fail; } @@ -1360,7 +1376,8 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, /* Notes: integers are always little endian encoded in AOT file */ if (!is_little_endian()) exchange_uint32(p); - if (cur_section->section_type < AOT_SECTION_TYPE_SIGANATURE) { + if (cur_section->section_type < AOT_SECTION_TYPE_SIGANATURE + || cur_section->section_type == AOT_SECTION_TYPE_CUSTOM) { recv_ctx.phase = Phase_AOT_Section_Size; recv_ctx.size_in_phase = 0; } @@ -1395,7 +1412,8 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, if (section->section_type == AOT_SECTION_TYPE_TEXT) { int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC; -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_RISCV64_LP64D) || defined(BUILD_TARGET_RISCV64_LP64) /* aot code and data in x86_64 must be in range 0 to 2G due to relocation for R_X86_64_32/32S/PC32 */ int map_flags = MMAP_MAP_32BIT; @@ -1673,7 +1691,7 @@ wasm_set_wasi_root_dir(const char *root_dir) if (!(path = realpath(root_dir, resolved_path))) return false; - strncpy(wasi_root_dir, path, sizeof(wasi_root_dir)); + snprintf(wasi_root_dir, sizeof(wasi_root_dir), "%s", path); return true; } diff --git a/core/app-mgr/app-manager/module_wasm_app.h b/core/app-mgr/app-manager/module_wasm_app.h index 7a967e220d..8965a975fd 100644 --- a/core/app-mgr/app-manager/module_wasm_app.h +++ b/core/app-mgr/app-manager/module_wasm_app.h @@ -29,12 +29,13 @@ extern "C" { typedef enum AOTSectionType { AOT_SECTION_TYPE_TARGET_INFO = 0, - AOT_SECTION_TYPE_INIT_DATA, - AOT_SECTION_TYPE_TEXT, - AOT_SECTION_TYPE_FUNCTION, - AOT_SECTION_TYPE_EXPORT, - AOT_SECTION_TYPE_RELOCATION, - AOT_SECTION_TYPE_SIGANATURE + AOT_SECTION_TYPE_INIT_DATA = 1, + AOT_SECTION_TYPE_TEXT = 2, + AOT_SECTION_TYPE_FUNCTION = 3, + AOT_SECTION_TYPE_EXPORT = 4, + AOT_SECTION_TYPE_RELOCATION = 5, + AOT_SECTION_TYPE_SIGANATURE = 6, + AOT_SECTION_TYPE_CUSTOM = 100, } AOTSectionType; enum { diff --git a/core/config.h b/core/config.h index 7f0c017890..aebddaa296 100644 --- a/core/config.h +++ b/core/config.h @@ -6,6 +6,7 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ +/* clang-format off */ #if !defined(BUILD_TARGET_X86_64) \ && !defined(BUILD_TARGET_AMD_64) \ && !defined(BUILD_TARGET_AARCH64) \ @@ -19,7 +20,9 @@ && !defined(BUILD_TARGET_RISCV64_LP64D) \ && !defined(BUILD_TARGET_RISCV64_LP64) \ && !defined(BUILD_TARGET_RISCV32_ILP32D) \ - && !defined(BUILD_TARGET_RISCV32_ILP32) + && !defined(BUILD_TARGET_RISCV32_ILP32) \ + && !defined(BUILD_TARGET_ARC) +/* clang-format on */ #if defined(__x86_64__) || defined(__x86_64) #define BUILD_TARGET_X86_64 #elif defined(__amd64__) || defined(__amd64) @@ -42,6 +45,8 @@ #define BUILD_TARGET_RISCV64_LP64D #elif defined(__riscv) && (__riscv_xlen == 32) #define BUILD_TARGET_RISCV32_ILP32D +#elif defined(__arc__) +#define BUILD_TARGET_ARC #else #error "Build target isn't set" #endif @@ -51,7 +56,7 @@ #define BH_DEBUG 0 #endif -#define MEM_ALLOCATOR_EMS 0 +#define MEM_ALLOCATOR_EMS 0 #define MEM_ALLOCATOR_TLSF 1 /* Default memory allocator */ @@ -72,10 +77,17 @@ #define WASM_ENABLE_JIT 0 #endif +#ifndef WASM_ENABLE_LAZY_JIT +#define WASM_ENABLE_LAZY_JIT 0 +#endif + #if (WASM_ENABLE_AOT == 0) && (WASM_ENABLE_JIT != 0) -/* JIT can only be enabled when AOT is enabled */ +/* LazyJIT or MCJIT can only be enabled when AOT is enabled */ #undef WASM_ENABLE_JIT #define WASM_ENABLE_JIT 0 + +#undef WASM_ENABLE_LAZY_JIT +#define WASM_ENABLE_LAZY_JIT 0 #endif #ifndef WASM_ENABLE_WAMR_COMPILER @@ -237,7 +249,9 @@ #define APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT 1 / 3 /* Default min/max heap size of each app */ +#ifndef APP_HEAP_SIZE_DEFAULT #define APP_HEAP_SIZE_DEFAULT (8 * 1024) +#endif #define APP_HEAP_SIZE_MIN (256) #define APP_HEAP_SIZE_MAX (512 * 1024 * 1024) @@ -251,13 +265,16 @@ #define WASM_THREAD_AUX_STACK_SIZE_MIN (256) /* Default/min/max stack size of each app thread */ -#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \ - && !defined(BH_PLATFORM_ESP_IDF) && !defined(BH_PLATFORM_OPENRTOS) -#define APP_THREAD_STACK_SIZE_DEFAULT (32 * 1024) -#define APP_THREAD_STACK_SIZE_MIN (24 * 1024) -#else +#if defined(BH_PLATFORM_ZEPHYR) || defined(BH_PLATFORM_ALIOS_THINGS) \ + || defined(BH_PLATFORM_ESP_IDF) || defined(BH_PLATFORM_OPENRTOS) #define APP_THREAD_STACK_SIZE_DEFAULT (6 * 1024) #define APP_THREAD_STACK_SIZE_MIN (4 * 1024) +#elif defined(PTHREAD_STACK_DEFAULT) && defined(PTHREAD_STACK_MIN) +#define APP_THREAD_STACK_SIZE_DEFAULT PTHREAD_STACK_DEFAULT +#define APP_THREAD_STACK_SIZE_MIN PTHREAD_STACK_MIN +#else +#define APP_THREAD_STACK_SIZE_DEFAULT (32 * 1024) +#define APP_THREAD_STACK_SIZE_MIN (24 * 1024) #endif #if !defined(APP_THREAD_STACK_SIZE_MAX) #define APP_THREAD_STACK_SIZE_MAX (8 * 1024 * 1024) @@ -297,4 +314,3 @@ #endif #endif /* end of _CONFIG_H_ */ - diff --git a/core/iwasm/aot/SConscript b/core/iwasm/aot/SConscript index c1a3c96e75..790f284041 100644 --- a/core/iwasm/aot/SConscript +++ b/core/iwasm/aot/SConscript @@ -13,6 +13,7 @@ cwd = GetCurrentDir() src = Split(''' aot_loader.c aot_runtime.c +aot_intrinsic.c ''') if rtconfig.ARCH == 'arm': @@ -20,7 +21,8 @@ if rtconfig.ARCH == 'arm': src += ['arch/aot_reloc_thumb.c'] elif re.match('^cortex-a.*', rtconfig.CPU): src += ['arch/aot_reloc_arm.c'] - +elif rtconfig.ARCH == 'ia32': + src += ['arch/aot_reloc_x86_32.c'] CPPPATH = [cwd, cwd + '/../include'] diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c new file mode 100644 index 0000000000..ba02dca0ba --- /dev/null +++ b/core/iwasm/aot/aot_intrinsic.c @@ -0,0 +1,613 @@ +/* + * Copyright (C) 2021 XiaoMi Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_intrinsic.h" + +typedef struct { + const char *llvm_intrinsic; + const char *native_intrinsic; + uint64 flag; +} aot_intrinsic; + +/* clang-format off */ +static const aot_intrinsic g_intrinsic_mapping[] = { + { "llvm.experimental.constrained.fadd.f32", "aot_intrinsic_fadd_f32", AOT_INTRINSIC_FLAG_F32_FADD }, + { "llvm.experimental.constrained.fadd.f64", "aot_intrinsic_fadd_f64", AOT_INTRINSIC_FLAG_F64_FADD }, + { "llvm.experimental.constrained.fsub.f32", "aot_intrinsic_fsub_f32", AOT_INTRINSIC_FLAG_F32_FSUB }, + { "llvm.experimental.constrained.fsub.f64", "aot_intrinsic_fsub_f64", AOT_INTRINSIC_FLAG_F64_FSUB }, + { "llvm.experimental.constrained.fmul.f32", "aot_intrinsic_fmul_f32", AOT_INTRINSIC_FLAG_F32_FMUL }, + { "llvm.experimental.constrained.fmul.f64", "aot_intrinsic_fmul_f64", AOT_INTRINSIC_FLAG_F64_FMUL }, + { "llvm.experimental.constrained.fdiv.f32", "aot_intrinsic_fdiv_f32", AOT_INTRINSIC_FLAG_F32_FDIV }, + { "llvm.experimental.constrained.fdiv.f64", "aot_intrinsic_fdiv_f64", AOT_INTRINSIC_FLAG_F64_FDIV }, + { "llvm.fabs.f32", "aot_intrinsic_fabs_f32", AOT_INTRINSIC_FLAG_F32_FABS }, + { "llvm.fabs.f64", "aot_intrinsic_fabs_f64", AOT_INTRINSIC_FLAG_F64_FABS }, + { "llvm.ceil.f32", "aot_intrinsic_ceil_f32", AOT_INTRINSIC_FLAG_F32_CEIL }, + { "llvm.ceil.f64", "aot_intrinsic_ceil_f64", AOT_INTRINSIC_FLAG_F64_CEIL }, + { "llvm.floor.f32", "aot_intrinsic_floor_f32", AOT_INTRINSIC_FLAG_F32_FLOOR }, + { "llvm.floor.f64", "aot_intrinsic_floor_f64", AOT_INTRINSIC_FLAG_F64_FLOOR }, + { "llvm.trunc.f32", "aot_intrinsic_trunc_f32", AOT_INTRINSIC_FLAG_F32_TRUNC }, + { "llvm.trunc.f64", "aot_intrinsic_trunc_f64", AOT_INTRINSIC_FLAG_F64_TRUNC }, + { "llvm.rint.f32", "aot_intrinsic_rint_f32", AOT_INTRINSIC_FLAG_F32_RINT }, + { "llvm.rint.f64", "aot_intrinsic_rint_f64", AOT_INTRINSIC_FLAG_F64_RINT }, + { "llvm.sqrt.f32", "aot_intrinsic_sqrt_f32", AOT_INTRINSIC_FLAG_F32_SQRT }, + { "llvm.sqrt.f64", "aot_intrinsic_sqrt_f64", AOT_INTRINSIC_FLAG_F64_SQRT }, + { "llvm.copysign.f32", "aot_intrinsic_copysign_f32", AOT_INTRINSIC_FLAG_F32_COPYSIGN }, + { "llvm.copysign.f64", "aot_intrinsic_copysign_f64", AOT_INTRINSIC_FLAG_F64_COPYSIGN }, + { "llvm.minnum.f32", "aot_intrinsic_fmin_f32", AOT_INTRINSIC_FLAG_F32_MIN }, + { "llvm.minnum.f64", "aot_intrinsic_fmin_f64", AOT_INTRINSIC_FLAG_F64_MIN }, + { "llvm.maxnum.f32", "aot_intrinsic_fmax_f32", AOT_INTRINSIC_FLAG_F32_MAX }, + { "llvm.maxnum.f64", "aot_intrinsic_fmax_f64", AOT_INTRINSIC_FLAG_F64_MAX }, + { "llvm.ctlz.i32", "aot_intrinsic_clz_i32", AOT_INTRINSIC_FLAG_I32_CLZ }, + { "llvm.ctlz.i64", "aot_intrinsic_clz_i64", AOT_INTRINSIC_FLAG_I64_CLZ }, + { "llvm.cttz.i32", "aot_intrinsic_ctz_i32", AOT_INTRINSIC_FLAG_I32_CTZ }, + { "llvm.cttz.i64", "aot_intrinsic_ctz_i64", AOT_INTRINSIC_FLAG_I64_CTZ }, + { "llvm.ctpop.i32", "aot_intrinsic_popcnt_i32", AOT_INTRINSIC_FLAG_I32_POPCNT }, + { "llvm.ctpop.i64", "aot_intrinsic_popcnt_i64", AOT_INTRINSIC_FLAG_I64_POPCNT }, + { "f64_convert_i32_s", "aot_intrinsic_i32_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 }, + { "f64_convert_i32_u", "aot_intrinsic_u32_to_f64", AOT_INTRINSIC_FLAG_U32_TO_F64 }, + { "f32_convert_i32_s", "aot_intrinsic_i32_to_f32", AOT_INTRINSIC_FLAG_I32_TO_F32 }, + { "f32_convert_i32_u", "aot_intrinsic_u32_to_f32", AOT_INTRINSIC_FLAG_U32_TO_F32 }, + { "f64_convert_i64_s", "aot_intrinsic_i64_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 }, + { "f64_convert_i64_u", "aot_intrinsic_u64_to_f64", AOT_INTRINSIC_FLAG_U64_TO_F64 }, + { "f32_convert_i64_s", "aot_intrinsic_i64_to_f32", AOT_INTRINSIC_FLAG_I64_TO_F32 }, + { "f32_convert_i64_u", "aot_intrinsic_u64_to_f32", AOT_INTRINSIC_FLAG_U64_TO_F32 }, + { "i32_trunc_f64_u", "aot_intrinsic_f64_to_u32", AOT_INTRINSIC_FLAG_I32_TO_F64 }, + { "f32_demote_f64", "aot_intrinsic_f64_to_f32", AOT_INTRINSIC_FLAG_F64_TO_F32 }, + { "f64_promote_f32", "aot_intrinsic_f32_to_f64", AOT_INTRINSIC_FLAG_F32_TO_F64 }, + { "f32_cmp", "aot_intrinsic_f32_cmp", AOT_INTRINSIC_FLAG_F32_CMP }, + { "f64_cmp", "aot_intrinsic_f64_cmp", AOT_INTRINSIC_FLAG_F64_CMP }, +}; +/* clang-format on */ + +static const uint32 g_intrinsic_count = + sizeof(g_intrinsic_mapping) / sizeof(aot_intrinsic); + +float32 +aot_intrinsic_fadd_f32(float32 a, float32 b) +{ + return a + b; +} + +float64 +aot_intrinsic_fadd_f64(float64 a, float64 b) +{ + return a + b; +} + +float32 +aot_intrinsic_fsub_f32(float32 a, float32 b) +{ + return a - b; +} + +float64 +aot_intrinsic_fsub_f64(float64 a, float64 b) +{ + return a - b; +} + +float32 +aot_intrinsic_fmul_f32(float32 a, float32 b) +{ + return a * b; +} + +float64 +aot_intrinsic_fmul_f64(float64 a, float64 b) +{ + return a * b; +} + +float32 +aot_intrinsic_fdiv_f32(float32 a, float32 b) +{ + return a / b; +} + +float64 +aot_intrinsic_fdiv_f64(float64 a, float64 b) +{ + return a / b; +} + +float32 +aot_intrinsic_fabs_f32(float32 a) +{ + return (float32)fabs(a); +} + +float64 +aot_intrinsic_fabs_f64(float64 a) +{ + return fabs(a); +} + +float32 +aot_intrinsic_ceil_f32(float32 a) +{ + return (float32)ceilf(a); +} + +float64 +aot_intrinsic_ceil_f64(float64 a) +{ + return ceil(a); +} + +float32 +aot_intrinsic_floor_f32(float32 a) +{ + return (float32)floorf(a); +} + +float64 +aot_intrinsic_floor_f64(float64 a) +{ + return floor(a); +} + +float32 +aot_intrinsic_trunc_f32(float32 a) +{ + return (float32)trunc(a); +} + +float64 +aot_intrinsic_trunc_f64(float64 a) +{ + return trunc(a); +} + +float32 +aot_intrinsic_rint_f32(float32 a) +{ + return (float32)rint(a); +} + +float64 +aot_intrinsic_rint_f64(float64 a) +{ + return rint(a); +} + +float32 +aot_intrinsic_sqrt_f32(float32 a) +{ + return (float32)sqrt(a); +} + +float64 +aot_intrinsic_sqrt_f64(float64 a) +{ + return sqrt(a); +} + +float32 +aot_intrinsic_copysign_f32(float32 a, float32 b) +{ + return signbit(b) ? (float32)-fabs(a) : (float32)fabs(a); +} + +float64 +aot_intrinsic_copysign_f64(float64 a, float64 b) +{ + return signbit(b) ? -fabs(a) : fabs(a); +} + +float32 +aot_intrinsic_fmin_f32(float32 a, float32 b) +{ + if (isnan(a)) + return a; + else if (isnan(b)) + return b; + else + return (float32)fmin(a, b); +} + +float64 +aot_intrinsic_fmin_f64(float64 a, float64 b) +{ + float64 c = fmin(a, b); + if (c == 0 && a == b) + return signbit(a) ? a : b; + return c; +} + +float32 +aot_intrinsic_fmax_f32(float32 a, float32 b) +{ + if (isnan(a)) + return a; + else if (isnan(b)) + return b; + else + return (float32)fmax(a, b); +} + +float64 +aot_intrinsic_fmax_f64(float64 a, float64 b) +{ + float64 c = fmax(a, b); + if (c == 0 && a == b) + return signbit(a) ? b : a; + return c; +} + +uint32 +aot_intrinsic_clz_i32(uint32 type) +{ + uint32 num = 0; + if (type == 0) + return 32; + while (!(type & 0x80000000)) { + num++; + type <<= 1; + } + return num; +} + +uint32 +aot_intrinsic_clz_i64(uint64 type) +{ + uint32 num = 0; + if (type == 0) + return 64; + while (!(type & 0x8000000000000000LL)) { + num++; + type <<= 1; + } + return num; +} + +uint32 +aot_intrinsic_ctz_i32(uint32 type) +{ + uint32 num = 0; + if (type == 0) + return 32; + while (!(type & 1)) { + num++; + type >>= 1; + } + return num; +} + +uint32 +aot_intrinsic_ctz_i64(uint64 type) +{ + uint32 num = 0; + if (type == 0) + return 64; + while (!(type & 1)) { + num++; + type >>= 1; + } + return num; +} + +uint32 +aot_intrinsic_popcnt_i32(uint32 u) +{ + uint32 ret = 0; + while (u) { + u = (u & (u - 1)); + ret++; + } + return ret; +} + +uint32 +aot_intrinsic_popcnt_i64(uint64 u) +{ + uint32 ret = 0; + while (u) { + u = (u & (u - 1)); + ret++; + } + return ret; +} + +float32 +aot_intrinsic_i32_to_f32(int32 i) +{ + return (float32)i; +} + +float32 +aot_intrinsic_u32_to_f32(uint32 u) +{ + return (float32)u; +} + +float64 +aot_intrinsic_i32_to_f64(int32 i) +{ + return (float64)i; +} + +float64 +aot_intrinsic_u32_to_f64(uint32 u) +{ + return (float64)u; +} + +float32 +aot_intrinsic_i64_to_f32(int64 i) +{ + return (float32)i; +} + +float32 +aot_intrinsic_u64_to_f32(uint64 u) +{ + return (float32)u; +} + +float64 +aot_intrinsic_i64_to_f64(int64 i) +{ + return (float64)i; +} + +float64 +aot_intrinsic_u64_to_f64(uint64 u) +{ + return (float64)u; +} + +int32 +aot_intrinsic_f32_to_i32(float32 f) +{ + return (int32)f; +} + +uint32 +aot_intrinsic_f32_to_u32(float32 f) +{ + return (uint32)f; +} + +int64 +aot_intrinsic_f32_to_i64(float32 f) +{ + return (int64)f; +} + +uint64 +aot_intrinsic_f32_to_u64(float32 f) +{ + return (uint64)f; +} + +int32 +aot_intrinsic_f64_to_i32(float64 f) +{ + return (int32)f; +} + +uint32 +aot_intrinsic_f64_to_u32(float64 f) +{ + return (uint32)f; +} + +int64 +aot_intrinsic_f64_to_i64(float64 f) +{ + return (int64)f; +} + +uint64 +aot_intrinsic_f64_to_u64(float64 f) +{ + return (uint64)f; +} + +float64 +aot_intrinsic_f32_to_f64(float32 f) +{ + return (float64)f; +} + +float32 +aot_intrinsic_f64_to_f32(float64 f) +{ + return (float32)f; +} + +int32 +aot_intrinsic_f32_cmp(AOTFloatCond cond, float32 lhs, float32 rhs) +{ + switch (cond) { + case FLOAT_LT: + return lhs < rhs ? 1 : 0; + + case FLOAT_GT: + return lhs > rhs ? 1 : 0; + + case FLOAT_LE: + return lhs <= rhs ? 1 : 0; + + case FLOAT_GE: + return lhs >= rhs ? 1 : 0; + + case FLOAT_NE: + return (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0; + + case FLOAT_UNO: + return (isnan(lhs) || isnan(rhs)) ? 1 : 0; + + default: + break; + } + return 0; +} + +int32 +aot_intrinsic_f64_cmp(AOTFloatCond cond, float64 lhs, float64 rhs) +{ + switch (cond) { + case FLOAT_LT: + return lhs < rhs ? 1 : 0; + + case FLOAT_GT: + return lhs > rhs ? 1 : 0; + + case FLOAT_LE: + return lhs <= rhs ? 1 : 0; + + case FLOAT_GE: + return lhs >= rhs ? 1 : 0; + + case FLOAT_NE: + return (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0; + + case FLOAT_UNO: + return (isnan(lhs) || isnan(rhs)) ? 1 : 0; + + default: + break; + } + return 0; +} + +const char * +aot_intrinsic_get_symbol(const char *llvm_intrinsic) +{ + uint32 cnt; + for (cnt = 0; cnt < g_intrinsic_count; cnt++) { + if (!strcmp(llvm_intrinsic, g_intrinsic_mapping[cnt].llvm_intrinsic)) { + return g_intrinsic_mapping[cnt].native_intrinsic; + } + } + return NULL; +} + +#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 + +static void +add_intrinsic_capability(AOTCompContext *comp_ctx, uint64 flag) +{ + uint64 group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag); + if (group < sizeof(comp_ctx->flags) / sizeof(uint64)) { + comp_ctx->flags[group] |= flag; + } + else { + bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__, + "intrinsic exceeds max limit."); + } +} + +static void +add_f32_common_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FABS); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FADD); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FSUB); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FMUL); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FDIV); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_SQRT); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CMP); +} + +static void +add_f64_common_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FABS); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FADD); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FSUB); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FMUL); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FDIV); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_SQRT); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CMP); +} + +static void +add_common_float_integer_convertion(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F64); + + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F64); + + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U64); + + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I64); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U64); + + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_F32); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_F64); +} + +bool +aot_intrinsic_check_capability(const AOTCompContext *comp_ctx, + const char *llvm_intrinsic) +{ + uint32 cnt; + uint64 flag; + uint64 group; + + for (cnt = 0; cnt < g_intrinsic_count; cnt++) { + if (!strcmp(llvm_intrinsic, g_intrinsic_mapping[cnt].llvm_intrinsic)) { + flag = g_intrinsic_mapping[cnt].flag; + group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag); + flag &= AOT_INTRINSIC_FLAG_MASK; + if (group < sizeof(comp_ctx->flags) / sizeof(uint64)) { + if (comp_ctx->flags[group] & flag) { + return true; + } + } + else { + bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__, + "intrinsic exceeds max limit."); + } + } + } + return false; +} + +void +aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx) +{ + memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags)); + + if (!comp_ctx->target_cpu) + return; + + if (!strncmp(comp_ctx->target_arch, "thumb", 5)) { + if (!strcmp(comp_ctx->target_cpu, "cortex-m7")) { + } + else if (!strcmp(comp_ctx->target_cpu, "cortex-m4")) { + add_f64_common_intrinsics(comp_ctx); + } + else { + add_f32_common_intrinsics(comp_ctx); + add_f64_common_intrinsics(comp_ctx); + add_common_float_integer_convertion(comp_ctx); + } + } + else if (!strncmp(comp_ctx->target_arch, "riscv", 5)) { + /* + * Note: Use builtin intrinsics since hardware float operation + * will cause rodata relocation + */ + add_f32_common_intrinsics(comp_ctx); + add_f64_common_intrinsics(comp_ctx); + add_common_float_integer_convertion(comp_ctx); + } +} + +#endif /* WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 */ diff --git a/core/iwasm/aot/aot_intrinsic.h b/core/iwasm/aot/aot_intrinsic.h new file mode 100644 index 0000000000..3446ad558c --- /dev/null +++ b/core/iwasm/aot/aot_intrinsic.h @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2021 XiaoMi Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_INTRINSIC_H +#define _AOT_INTRINSIC_H + +#include "aot_runtime.h" +#if WASM_ENABLE_WAMR_COMPILER != 0 +#include "aot_llvm.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define AOT_INTRINSIC_GROUPS 2 + +/* Use uint64 as flag container: + * - The upper 16 bits are the intrinsic group number + * - The lower 48 bits are the intrinsic capability mask + */ + +#define AOT_INTRINSIC_FLAG(group, number) \ + ((((uint64)(group & 0xffffLL)) << 48) | ((uint64)1 << number)) + +#define AOT_INTRINSIC_FLAG_MASK (0x0000ffffffffffffLL) + +#define AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag) \ + ((((uint64)flag) >> 48) & 0xffffLL) + +/* clang-format off */ +#define AOT_INTRINSIC_FLAG_F32_FADD AOT_INTRINSIC_FLAG(0, 0) +#define AOT_INTRINSIC_FLAG_F32_FSUB AOT_INTRINSIC_FLAG(0, 1) +#define AOT_INTRINSIC_FLAG_F32_FMUL AOT_INTRINSIC_FLAG(0, 2) +#define AOT_INTRINSIC_FLAG_F32_FDIV AOT_INTRINSIC_FLAG(0, 3) +#define AOT_INTRINSIC_FLAG_F32_FABS AOT_INTRINSIC_FLAG(0, 4) +#define AOT_INTRINSIC_FLAG_F32_CEIL AOT_INTRINSIC_FLAG(0, 5) +#define AOT_INTRINSIC_FLAG_F32_FLOOR AOT_INTRINSIC_FLAG(0, 6) +#define AOT_INTRINSIC_FLAG_F32_TRUNC AOT_INTRINSIC_FLAG(0, 7) +#define AOT_INTRINSIC_FLAG_F32_RINT AOT_INTRINSIC_FLAG(0, 8) +#define AOT_INTRINSIC_FLAG_F32_SQRT AOT_INTRINSIC_FLAG(0, 9) +#define AOT_INTRINSIC_FLAG_F32_COPYSIGN AOT_INTRINSIC_FLAG(0, 10) +#define AOT_INTRINSIC_FLAG_F32_MIN AOT_INTRINSIC_FLAG(0, 11) +#define AOT_INTRINSIC_FLAG_F32_MAX AOT_INTRINSIC_FLAG(0, 12) +#define AOT_INTRINSIC_FLAG_I32_CLZ AOT_INTRINSIC_FLAG(0, 13) +#define AOT_INTRINSIC_FLAG_I32_CTZ AOT_INTRINSIC_FLAG(0, 14) +#define AOT_INTRINSIC_FLAG_I32_POPCNT AOT_INTRINSIC_FLAG(0, 15) +#define AOT_INTRINSIC_FLAG_I32_TO_F32 AOT_INTRINSIC_FLAG(0, 16) +#define AOT_INTRINSIC_FLAG_U32_TO_F32 AOT_INTRINSIC_FLAG(0, 17) +#define AOT_INTRINSIC_FLAG_I32_TO_F64 AOT_INTRINSIC_FLAG(0, 18) +#define AOT_INTRINSIC_FLAG_U32_TO_F64 AOT_INTRINSIC_FLAG(0, 19) +#define AOT_INTRINSIC_FLAG_F32_TO_I32 AOT_INTRINSIC_FLAG(0, 20) +#define AOT_INTRINSIC_FLAG_F32_TO_U32 AOT_INTRINSIC_FLAG(0, 21) +#define AOT_INTRINSIC_FLAG_F32_TO_I64 AOT_INTRINSIC_FLAG(0, 22) +#define AOT_INTRINSIC_FLAG_F32_TO_U64 AOT_INTRINSIC_FLAG(0, 23) +#define AOT_INTRINSIC_FLAG_F32_TO_F64 AOT_INTRINSIC_FLAG(0, 24) +#define AOT_INTRINSIC_FLAG_F32_CMP AOT_INTRINSIC_FLAG(0, 25) + +#define AOT_INTRINSIC_FLAG_F64_FADD AOT_INTRINSIC_FLAG(1, 0) +#define AOT_INTRINSIC_FLAG_F64_FSUB AOT_INTRINSIC_FLAG(1, 1) +#define AOT_INTRINSIC_FLAG_F64_FMUL AOT_INTRINSIC_FLAG(1, 2) +#define AOT_INTRINSIC_FLAG_F64_FDIV AOT_INTRINSIC_FLAG(1, 3) +#define AOT_INTRINSIC_FLAG_F64_FABS AOT_INTRINSIC_FLAG(1, 4) +#define AOT_INTRINSIC_FLAG_F64_CEIL AOT_INTRINSIC_FLAG(1, 5) +#define AOT_INTRINSIC_FLAG_F64_FLOOR AOT_INTRINSIC_FLAG(1, 6) +#define AOT_INTRINSIC_FLAG_F64_TRUNC AOT_INTRINSIC_FLAG(1, 7) +#define AOT_INTRINSIC_FLAG_F64_RINT AOT_INTRINSIC_FLAG(1, 8) +#define AOT_INTRINSIC_FLAG_F64_SQRT AOT_INTRINSIC_FLAG(1, 9) +#define AOT_INTRINSIC_FLAG_F64_COPYSIGN AOT_INTRINSIC_FLAG(1, 10) +#define AOT_INTRINSIC_FLAG_F64_MIN AOT_INTRINSIC_FLAG(1, 11) +#define AOT_INTRINSIC_FLAG_F64_MAX AOT_INTRINSIC_FLAG(1, 12) +#define AOT_INTRINSIC_FLAG_I64_CLZ AOT_INTRINSIC_FLAG(1, 13) +#define AOT_INTRINSIC_FLAG_I64_CTZ AOT_INTRINSIC_FLAG(1, 14) +#define AOT_INTRINSIC_FLAG_I64_POPCNT AOT_INTRINSIC_FLAG(1, 15) +#define AOT_INTRINSIC_FLAG_I64_TO_F32 AOT_INTRINSIC_FLAG(1, 16) +#define AOT_INTRINSIC_FLAG_U64_TO_F32 AOT_INTRINSIC_FLAG(1, 17) +#define AOT_INTRINSIC_FLAG_I64_TO_F64 AOT_INTRINSIC_FLAG(1, 18) +#define AOT_INTRINSIC_FLAG_U64_TO_F64 AOT_INTRINSIC_FLAG(1, 19) +#define AOT_INTRINSIC_FLAG_F64_TO_I32 AOT_INTRINSIC_FLAG(1, 20) +#define AOT_INTRINSIC_FLAG_F64_TO_U32 AOT_INTRINSIC_FLAG(1, 21) +#define AOT_INTRINSIC_FLAG_F64_TO_I64 AOT_INTRINSIC_FLAG(1, 22) +#define AOT_INTRINSIC_FLAG_F64_TO_U64 AOT_INTRINSIC_FLAG(1, 23) +#define AOT_INTRINSIC_FLAG_F64_TO_F32 AOT_INTRINSIC_FLAG(1, 24) +#define AOT_INTRINSIC_FLAG_F64_CMP AOT_INTRINSIC_FLAG(1, 25) +/* clang-format on */ + +float32 +aot_intrinsic_fadd_f32(float32 a, float32 b); + +float64 +aot_intrinsic_fadd_f64(float64 a, float64 b); + +float32 +aot_intrinsic_fsub_f32(float32 a, float32 b); + +float64 +aot_intrinsic_fsub_f64(float64 a, float64 b); + +float32 +aot_intrinsic_fmul_f32(float32 a, float32 b); + +float64 +aot_intrinsic_fmul_f64(float64 a, float64 b); + +float32 +aot_intrinsic_fdiv_f32(float32 a, float32 b); + +float64 +aot_intrinsic_fdiv_f64(float64 a, float64 b); + +float32 +aot_intrinsic_fabs_f32(float32 a); + +float64 +aot_intrinsic_fabs_f64(float64 a); + +float32 +aot_intrinsic_ceil_f32(float32 a); + +float64 +aot_intrinsic_ceil_f64(float64 a); + +float32 +aot_intrinsic_floor_f32(float32 a); + +float64 +aot_intrinsic_floor_f64(float64 a); + +float32 +aot_intrinsic_trunc_f32(float32 a); + +float64 +aot_intrinsic_trunc_f64(float64 a); + +float32 +aot_intrinsic_rint_f32(float32 a); + +float64 +aot_intrinsic_rint_f64(float64 a); + +float32 +aot_intrinsic_sqrt_f32(float32 a); + +float64 +aot_intrinsic_sqrt_f64(float64 a); + +float32 +aot_intrinsic_copysign_f32(float32 a, float32 b); + +float64 +aot_intrinsic_copysign_f64(float64 a, float64 b); + +float32 +aot_intrinsic_fmin_f32(float32 a, float32 b); + +float64 +aot_intrinsic_fmin_f64(float64 a, float64 b); + +float32 +aot_intrinsic_fmax_f32(float32 a, float32 b); + +float64 +aot_intrinsic_fmax_f64(float64 a, float64 b); + +uint32 +aot_intrinsic_clz_i32(uint32 type); + +uint32 +aot_intrinsic_clz_i64(uint64 type); + +uint32 +aot_intrinsic_ctz_i32(uint32 type); + +uint32 +aot_intrinsic_ctz_i64(uint64 type); + +uint32 +aot_intrinsic_popcnt_i32(uint32 u); + +uint32 +aot_intrinsic_popcnt_i64(uint64 u); + +float32 +aot_intrinsic_i32_to_f32(int32 i); + +float32 +aot_intrinsic_u32_to_f32(uint32 u); + +float64 +aot_intrinsic_i32_to_f64(int32 i); + +float64 +aot_intrinsic_u32_to_f64(uint32 u); + +float32 +aot_intrinsic_i64_to_f32(int64 i); + +float32 +aot_intrinsic_u64_to_f32(uint64 u); + +float64 +aot_intrinsic_i64_to_f64(int64 i); + +float64 +aot_intrinsic_u64_to_f64(uint64 u); + +int32 +aot_intrinsic_f32_to_i32(float32 f); + +uint32 +aot_intrinsic_f32_to_u32(float32 f); + +int64 +aot_intrinsic_f32_to_i64(float32 f); + +uint64 +aot_intrinsic_f32_to_u64(float32 f); + +int32 +aot_intrinsic_f64_to_i32(float64 f); + +uint32 +aot_intrinsic_f64_to_u32(float64 f); + +int64 +aot_intrinsic_f64_to_i64(float64 f); + +uint64 +aot_intrinsic_f64_to_u64(float64 f); + +float64 +aot_intrinsic_f32_to_f64(float32 f); + +float32 +aot_intrinsic_f64_to_f32(float64 f); + +int32 +aot_intrinsic_f32_cmp(AOTFloatCond cond, float32 lhs, float32 rhs); + +int32 +aot_intrinsic_f64_cmp(AOTFloatCond cond, float64 lhs, float64 rhs); + +const char * +aot_intrinsic_get_symbol(const char *llvm_intrinsic); + +#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 +bool +aot_intrinsic_check_capability(const AOTCompContext *comp_ctx, + const char *llvm_intrinsic); + +void +aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of _AOT_INTRINSIC_H */ diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 5f21d1ff4c..1923a6a2d9 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -14,6 +14,10 @@ #include "../compilation/aot_llvm.h" #include "../interpreter/wasm_loader.h" #endif +#if WASM_ENABLE_DEBUG_AOT != 0 +#include "debug/elf_parser.h" +#include "debug/jit_debug.h" +#endif #define XMM_PLT_PREFIX "__xmm@" #define REAL_PLT_PREFIX "__real@" @@ -22,14 +26,13 @@ static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) { if (error_buf != NULL) { - snprintf(error_buf, error_buf_size, - "AOT module load failed: %s", string); + snprintf(error_buf, error_buf_size, "AOT module load failed: %s", + string); } } static void -set_error_buf_v(char *error_buf, uint32 error_buf_size, - const char *format, ...) +set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...) { va_list args; char buf[128]; @@ -38,8 +41,7 @@ set_error_buf_v(char *error_buf, uint32 error_buf_size, va_start(args, format); vsnprintf(buf, sizeof(buf), format, args); va_end(args); - snprintf(error_buf, error_buf_size, - "AOT module load failed: %s", buf); + snprintf(error_buf, error_buf_size, "AOT module load failed: %s", buf); } } @@ -95,107 +97,113 @@ check_buf(const uint8 *buf, const uint8 *buf_end, uint32 length, return true; } -#define CHECK_BUF(buf, buf_end, length) do { \ - if (!check_buf(buf, buf_end, length, \ - error_buf, error_buf_size)) { \ - goto fail; \ - } \ -} while (0) +#define CHECK_BUF(buf, buf_end, length) \ + do { \ + if (!check_buf(buf, buf_end, length, error_buf, error_buf_size)) { \ + goto fail; \ + } \ + } while (0) -static uint8* +static uint8 * align_ptr(const uint8 *p, uint32 b) { uintptr_t v = (uintptr_t)p; uintptr_t m = b - 1; - return (uint8*)((v + m) & ~m); + return (uint8 *)((v + m) & ~m); } static inline uint64 GET_U64_FROM_ADDR(uint32 *addr) { - union { uint64 val; uint32 parts[2]; } u; + union { + uint64 val; + uint32 parts[2]; + } u; u.parts[0] = addr[0]; u.parts[1] = addr[1]; return u.val; } -#define TEMPLATE_READ(p, p_end, res, type) do { \ - if (sizeof(type) != sizeof(uint64)) \ - p = (uint8*)align_ptr(p, sizeof(type)); \ - else \ - /* align 4 bytes if type is uint64 */ \ - p = (uint8*)align_ptr(p, sizeof(uint32)); \ - CHECK_BUF(p, p_end, sizeof(type)); \ - if (sizeof(type) != sizeof(uint64)) \ - res = *(type*)p; \ - else \ - res = (type)GET_U64_FROM_ADDR((uint32*)p); \ - if (!is_little_endian()) \ - exchange_##type((uint8*)&res); \ - p += sizeof(type); \ - } while (0) +#define TEMPLATE_READ(p, p_end, res, type) \ + do { \ + if (sizeof(type) != sizeof(uint64)) \ + p = (uint8 *)align_ptr(p, sizeof(type)); \ + else \ + /* align 4 bytes if type is uint64 */ \ + p = (uint8 *)align_ptr(p, sizeof(uint32)); \ + CHECK_BUF(p, p_end, sizeof(type)); \ + if (sizeof(type) != sizeof(uint64)) \ + res = *(type *)p; \ + else \ + res = (type)GET_U64_FROM_ADDR((uint32 *)p); \ + if (!is_little_endian()) \ + exchange_##type((uint8 *)&res); \ + p += sizeof(type); \ + } while (0) #define read_uint8(p, p_end, res) TEMPLATE_READ(p, p_end, res, uint8) #define read_uint16(p, p_end, res) TEMPLATE_READ(p, p_end, res, uint16) #define read_uint32(p, p_end, res) TEMPLATE_READ(p, p_end, res, uint32) #define read_uint64(p, p_end, res) TEMPLATE_READ(p, p_end, res, uint64) -#define read_byte_array(p, p_end, addr, len) do { \ - CHECK_BUF(p, p_end, len); \ - memcpy(addr, p, len); \ - p += len; \ - } while (0) - -#define read_string(p, p_end, str) do { \ - uint16 str_len; \ - read_uint16(p, p_end, str_len); \ - CHECK_BUF(p, p_end, str_len); \ - if (!(str = const_str_set_insert \ - (p, str_len, module, \ - error_buf, error_buf_size))) { \ - goto fail; \ - } \ - p += str_len; \ - } while (0) +#define read_byte_array(p, p_end, addr, len) \ + do { \ + CHECK_BUF(p, p_end, len); \ + memcpy(addr, p, len); \ + p += len; \ + } while (0) + +#define read_string(p, p_end, str) \ + do { \ + uint16 str_len; \ + read_uint16(p, p_end, str_len); \ + CHECK_BUF(p, p_end, str_len); \ + if (!(str = const_str_set_insert(p, str_len, module, error_buf, \ + error_buf_size))) { \ + goto fail; \ + } \ + p += str_len; \ + } while (0) /* Legal values for bin_type */ -#define BIN_TYPE_ELF32L 0 /* 32-bit little endian */ -#define BIN_TYPE_ELF32B 1 /* 32-bit big endian */ -#define BIN_TYPE_ELF64L 2 /* 64-bit little endian */ -#define BIN_TYPE_ELF64B 3 /* 64-bit big endian */ -#define BIN_TYPE_COFF64 6 /* 64-bit little endian */ +#define BIN_TYPE_ELF32L 0 /* 32-bit little endian */ +#define BIN_TYPE_ELF32B 1 /* 32-bit big endian */ +#define BIN_TYPE_ELF64L 2 /* 64-bit little endian */ +#define BIN_TYPE_ELF64B 3 /* 64-bit big endian */ +#define BIN_TYPE_COFF64 6 /* 64-bit little endian */ /* Legal values for e_type (object file type). */ -#define E_TYPE_NONE 0 /* No file type */ -#define E_TYPE_REL 1 /* Relocatable file */ -#define E_TYPE_EXEC 2 /* Executable file */ -#define E_TYPE_DYN 3 /* Shared object file */ +#define E_TYPE_NONE 0 /* No file type */ +#define E_TYPE_REL 1 /* Relocatable file */ +#define E_TYPE_EXEC 2 /* Executable file */ +#define E_TYPE_DYN 3 /* Shared object file */ /* Legal values for e_machine (architecture). */ -#define E_MACHINE_386 3 /* Intel 80386 */ -#define E_MACHINE_MIPS 8 /* MIPS R3000 big-endian */ -#define E_MACHINE_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ -#define E_MACHINE_ARM 40 /* ARM/Thumb */ -#define E_MACHINE_AARCH64 183 /* AArch64 */ -#define E_MACHINE_ARC 45 /* Argonaut RISC Core */ -#define E_MACHINE_IA_64 50 /* Intel Merced */ -#define E_MACHINE_MIPS_X 51 /* Stanford MIPS-X */ -#define E_MACHINE_X86_64 62 /* AMD x86-64 architecture */ -#define E_MACHINE_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define E_MACHINE_386 3 /* Intel 80386 */ +#define E_MACHINE_MIPS 8 /* MIPS R3000 big-endian */ +#define E_MACHINE_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ +#define E_MACHINE_ARM 40 /* ARM/Thumb */ +#define E_MACHINE_AARCH64 183 /* AArch64 */ +#define E_MACHINE_ARC 45 /* Argonaut RISC Core */ +#define E_MACHINE_IA_64 50 /* Intel Merced */ +#define E_MACHINE_MIPS_X 51 /* Stanford MIPS-X */ +#define E_MACHINE_X86_64 62 /* AMD x86-64 architecture */ +#define E_MACHINE_ARC_COMPACT 93 /* ARC International ARCompact */ +#define E_MACHINE_ARC_COMPACT2 195 /* Synopsys ARCompact V2 */ +#define E_MACHINE_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define E_MACHINE_RISCV 243 /* RISC-V 32/64 */ #define E_MACHINE_WIN_X86_64 0x8664 /* Windowx x86-64 architecture */ /* Legal values for e_version */ -#define E_VERSION_CURRENT 1 /* Current version */ +#define E_VERSION_CURRENT 1 /* Current version */ static void * loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) { void *mem; - if (size >= UINT32_MAX - || !(mem = wasm_runtime_malloc((uint32)size))) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); return NULL; } @@ -203,15 +211,14 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) return mem; } -static char* +static char * const_str_set_insert(const uint8 *str, int32 len, AOTModule *module, - char* error_buf, uint32 error_buf_size) + char *error_buf, uint32 error_buf_size) { HashMap *set = module->const_str_set; char *c_str, *value; - if (!(c_str = loader_malloc((uint32)len + 1, - error_buf, error_buf_size))) { + if (!(c_str = loader_malloc((uint32)len + 1, error_buf, error_buf_size))) { return NULL; } @@ -234,9 +241,9 @@ const_str_set_insert(const uint8 *str, int32 len, AOTModule *module, } static bool -get_aot_file_target(AOTTargetInfo *target_info, - char *target_buf, uint32 target_buf_size, - char *error_buf, uint32 error_buf_size) +get_aot_file_target(AOTTargetInfo *target_info, char *target_buf, + uint32 target_buf_size, char *error_buf, + uint32 error_buf_size) { char *machine_type = NULL; switch (target_info->e_machine) { @@ -257,16 +264,23 @@ get_aot_file_target(AOTTargetInfo *target_info, case E_MACHINE_XTENSA: machine_type = "xtensa"; break; + case E_MACHINE_RISCV: + machine_type = "riscv"; + break; + case E_MACHINE_ARC_COMPACT: + case E_MACHINE_ARC_COMPACT2: + machine_type = "arc"; + break; default: set_error_buf_v(error_buf, error_buf_size, - "unknown machine type %d", - target_info->e_machine); + "unknown machine type %d", target_info->e_machine); return false; } if (strncmp(target_info->arch, machine_type, strlen(machine_type))) { - set_error_buf_v(error_buf, error_buf_size, - "machine type (%s) isn't consistent with target type (%s)", - machine_type, target_info->arch); + set_error_buf_v( + error_buf, error_buf_size, + "machine type (%s) isn't consistent with target type (%s)", + machine_type, target_info->arch); return false; } snprintf(target_buf, target_buf_size, "%s", target_info->arch); @@ -274,8 +288,8 @@ get_aot_file_target(AOTTargetInfo *target_info, } static bool -check_machine_info(AOTTargetInfo *target_info, - char *error_buf, uint32 error_buf_size) +check_machine_info(AOTTargetInfo *target_info, char *error_buf, + uint32 error_buf_size) { char target_expected[32], target_got[32]; @@ -297,8 +311,8 @@ check_machine_info(AOTTargetInfo *target_info, static bool load_target_info_section(const uint8 *buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, + uint32 error_buf_size) { AOTTargetInfo target_info; const uint8 *p = buf, *p_end = buf_end; @@ -311,12 +325,10 @@ load_target_info_section(const uint8 *buf, const uint8 *buf_end, read_uint32(p, p_end, target_info.e_version); read_uint32(p, p_end, target_info.e_flags); read_uint32(p, p_end, target_info.reserved); - read_byte_array(p, p_end, - target_info.arch, sizeof(target_info.arch)); + read_byte_array(p, p_end, target_info.arch, sizeof(target_info.arch)); if (p != buf_end) { - set_error_buf(error_buf, error_buf_size, - "invalid section size"); + set_error_buf(error_buf, error_buf_size, "invalid section size"); return false; } @@ -326,16 +338,17 @@ load_target_info_section(const uint8 *buf, const uint8 *buf_end, set_error_buf_v(error_buf, error_buf_size, "invalid target endian type, expected %s but got %s", is_little_endian() ? "little endian" : "big endian", - is_target_little_endian ? "little endian" : "big endian"); + is_target_little_endian ? "little endian" + : "big endian"); return false; } /* Check target bit width */ is_target_64_bit = target_info.bin_type & 2 ? true : false; - if ((sizeof(void*) == 8 ? true : false) != is_target_64_bit) { + if ((sizeof(void *) == 8 ? true : false) != is_target_64_bit) { set_error_buf_v(error_buf, error_buf_size, "invalid target bit width, expected %s but got %s", - sizeof(void*) == 8 ? "64-bit" : "32-bit", + sizeof(void *) == 8 ? "64-bit" : "32-bit", is_target_64_bit ? "64-bit" : "32-bit"); return false; } @@ -354,8 +367,7 @@ load_target_info_section(const uint8 *buf, const uint8 *buf_end, } if (target_info.e_version != E_VERSION_CURRENT) { - set_error_buf(error_buf, error_buf_size, - "invalid elf file version"); + set_error_buf(error_buf, error_buf_size, "invalid elf file version"); return false; } @@ -364,9 +376,91 @@ load_target_info_section(const uint8 *buf, const uint8 *buf_end, return false; } +static void * +get_native_symbol_by_name(const char *name) +{ + void *func = NULL; + uint32 symnum = 0; + SymbolMap *sym = NULL; + + sym = get_target_symbol_map(&symnum); + + while (symnum--) { + if (strcmp(sym->symbol_name, name) == 0) { + func = sym->symbol_addr; + break; + } + sym++; + } + + return func; +} + +static bool +load_native_symbol_section(const uint8 *buf, const uint8 *buf_end, + AOTModule *module, char *error_buf, + uint32 error_buf_size) +{ + const uint8 *p = buf, *p_end = buf_end; + uint32 cnt; + int32 i; + const char *symbol; + + read_uint32(p, p_end, cnt); + + module->native_symbol_count = cnt; + + if (cnt > 0) { + module->native_symbol_list = wasm_runtime_malloc(cnt * sizeof(void *)); + if (module->native_symbol_list == NULL) { + set_error_buf(error_buf, error_buf_size, + "malloc native symbol list failed"); + goto fail; + } + + for (i = cnt - 1; i >= 0; i--) { + read_string(p, p_end, symbol); + module->native_symbol_list[i] = get_native_symbol_by_name(symbol); + if (module->native_symbol_list[i] == NULL) { + set_error_buf_v(error_buf, error_buf_size, + "missing native symbol: %s", symbol); + goto fail; + } + } + } + + return true; +fail: + return false; +} + +static bool +load_custom_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *p = buf, *p_end = buf_end; + uint32 sub_section_type; + + read_uint32(p, p_end, sub_section_type); + buf = p; + + switch (sub_section_type) { + case AOT_CUSTOM_SECTION_NATIVE_SYMBOL: + if (!load_native_symbol_section(buf, buf_end, module, error_buf, + error_buf_size)) + goto fail; + break; + default: + break; + } + + return true; +fail: + return false; +} + static void -destroy_import_memories(AOTImportMemory *import_memories, - bool is_jit_mode) +destroy_import_memories(AOTImportMemory *import_memories, bool is_jit_mode) { if (!is_jit_mode) wasm_runtime_free(import_memories); @@ -387,8 +481,8 @@ destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count, static bool load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *buf = *p_buf; AOTMemInitData **data_list; @@ -398,7 +492,7 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTMemInitData *) * (uint64)module->mem_init_data_count; if (!(module->mem_init_data_list = data_list = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -415,8 +509,7 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, read_uint64(buf, buf_end, init_expr_value); read_uint32(buf, buf_end, byte_count); size = offsetof(AOTMemInitData, bytes) + (uint64)byte_count; - if (!(data_list[i] = loader_malloc - (size, error_buf, error_buf_size))) { + if (!(data_list[i] = loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -428,8 +521,8 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, data_list[i]->offset.init_expr_type = (uint8)init_expr_type; data_list[i]->offset.u.i64 = (int64)init_expr_value; data_list[i]->byte_count = byte_count; - read_byte_array(buf, buf_end, - data_list[i]->bytes, data_list[i]->byte_count); + read_byte_array(buf, buf_end, data_list[i]->bytes, + data_list[i]->byte_count); } *p_buf = buf; @@ -439,8 +532,7 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, } static bool -load_memory_info(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, +load_memory_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, char *error_buf, uint32 error_buf_size) { uint32 i; @@ -454,7 +546,7 @@ load_memory_info(const uint8 **p_buf, const uint8 *buf_end, read_uint32(buf, buf_end, module->memory_count); total_size = sizeof(AOTMemory) * (uint64)module->memory_count; if (!(module->memories = - loader_malloc(total_size, error_buf, error_buf_size))) { + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -469,8 +561,8 @@ load_memory_info(const uint8 **p_buf, const uint8 *buf_end, /* load memory init data list */ if (module->mem_init_data_count > 0 - && !load_mem_init_data_list(&buf, buf_end, module, - error_buf, error_buf_size)) + && !load_mem_init_data_list(&buf, buf_end, module, error_buf, + error_buf_size)) return false; *p_buf = buf; @@ -507,10 +599,8 @@ destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count, } static bool -load_import_table_list(const uint8 **p_buf, - const uint8 *buf_end, - AOTModule *module, - char *error_buf, +load_import_table_list(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; @@ -521,7 +611,7 @@ load_import_table_list(const uint8 **p_buf, /* Allocate memory */ size = sizeof(AOTImportTable) * (uint64)module->import_table_count; if (!(module->import_tables = import_table = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -540,8 +630,8 @@ load_import_table_list(const uint8 **p_buf, } static bool -load_table_list(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, char *error_buf, uint32 error_buf_size) +load_table_list(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, + char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; AOTTable *table; @@ -551,7 +641,7 @@ load_table_list(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTTable) * (uint64)module->table_count; if (!(module->tables = table = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -573,8 +663,8 @@ load_table_list(const uint8 **p_buf, const uint8 *buf_end, static bool load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *buf = *p_buf; AOTTableInitData **data_list; @@ -584,7 +674,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTTableInitData *) * (uint64)module->table_init_data_count; if (!(module->table_init_data_list = data_list = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -603,8 +693,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end, size1 = sizeof(uint32) * (uint64)func_index_count; size = offsetof(AOTTableInitData, func_indexes) + size1; - if (!(data_list[i] = loader_malloc - (size, error_buf, error_buf_size))) { + if (!(data_list[i] = loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -615,7 +704,8 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end, data_list[i]->offset.init_expr_type = (uint8)init_expr_type; data_list[i]->offset.u.i64 = (int64)init_expr_value; data_list[i]->func_index_count = func_index_count; - read_byte_array(buf, buf_end, data_list[i]->func_indexes, (uint32)size1); + read_byte_array(buf, buf_end, data_list[i]->func_indexes, + (uint32)size1); } *p_buf = buf; @@ -625,8 +715,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end, } static bool -load_table_info(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, +load_table_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; @@ -646,8 +735,8 @@ load_table_info(const uint8 **p_buf, const uint8 *buf_end, /* load table init data list */ if (module->table_init_data_count > 0 - && !load_table_init_data_list(&buf, buf_end, module, - error_buf, error_buf_size)) + && !load_table_init_data_list(&buf, buf_end, module, error_buf, + error_buf_size)) return false; *p_buf = buf; @@ -669,8 +758,7 @@ destroy_func_types(AOTFuncType **func_types, uint32 count, bool is_jit_mode) } static bool -load_func_types(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, +load_func_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; @@ -680,8 +768,8 @@ load_func_types(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTFuncType *) * (uint64)module->func_type_count; - if (!(module->func_types = func_types = loader_malloc - (size, error_buf, error_buf_size))) { + if (!(module->func_types = func_types = + loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -702,8 +790,7 @@ load_func_types(const uint8 **p_buf, const uint8 *buf_end, size1 = (uint64)param_count + (uint64)result_count; size = offsetof(AOTFuncType, types) + size1; - if (!(func_types[i] = loader_malloc - (size, error_buf, error_buf_size))) { + if (!(func_types[i] = loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -712,8 +799,8 @@ load_func_types(const uint8 **p_buf, const uint8 *buf_end, read_byte_array(buf, buf_end, func_types[i]->types, (uint32)size1); param_cell_num = wasm_get_cell_num(func_types[i]->types, param_count); - ret_cell_num = wasm_get_cell_num(func_types[i]->types + param_count, - result_count); + ret_cell_num = + wasm_get_cell_num(func_types[i]->types + param_count, result_count); if (param_cell_num > UINT16_MAX || ret_cell_num > UINT16_MAX) { set_error_buf(error_buf, error_buf_size, "param count or result count too large"); @@ -732,8 +819,7 @@ load_func_types(const uint8 **p_buf, const uint8 *buf_end, static bool load_func_type_info(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; @@ -759,8 +845,7 @@ destroy_import_globals(AOTImportGlobal *import_globals, bool is_jit_mode) static bool load_import_globals(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; AOTImportGlobal *import_globals; @@ -773,13 +858,13 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count; if (!(module->import_globals = import_globals = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { return false; } /* Create each import global */ for (i = 0; i < module->import_global_count; i++) { - buf = (uint8*)align_ptr(buf, 2); + buf = (uint8 *)align_ptr(buf, 2); read_uint8(buf, buf_end, import_globals[i].type); read_uint8(buf, buf_end, import_globals[i].is_mutable); read_string(buf, buf_end, import_globals[i].module_name); @@ -787,9 +872,8 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end, #if WASM_ENABLE_LIBC_BUILTIN != 0 if (wasm_native_lookup_libc_builtin_global( - import_globals[i].module_name, - import_globals[i].global_name, - &tmp_global)) { + import_globals[i].module_name, import_globals[i].global_name, + &tmp_global)) { if (tmp_global.type != import_globals[i].type || tmp_global.is_mutable != import_globals[i].is_mutable) { set_error_buf(error_buf, error_buf_size, @@ -797,7 +881,7 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end, return false; } import_globals[i].global_data_linked = - tmp_global.global_data_linked; + tmp_global.global_data_linked; } #endif @@ -815,8 +899,8 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end, static bool load_import_global_info(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *buf = *p_buf; @@ -824,8 +908,8 @@ load_import_global_info(const uint8 **p_buf, const uint8 *buf_end, /* load import globals */ if (module->import_global_count > 0 - && !load_import_globals(&buf, buf_end, module, - error_buf, error_buf_size)) + && !load_import_globals(&buf, buf_end, module, error_buf, + error_buf_size)) return false; *p_buf = buf; @@ -842,8 +926,7 @@ destroy_globals(AOTGlobal *globals, bool is_jit_mode) } static bool -load_globals(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, +load_globals(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; @@ -854,16 +937,16 @@ load_globals(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTGlobal) * (uint64)module->global_count; - if (!(module->globals = globals = loader_malloc - (size, error_buf, error_buf_size))) { + if (!(module->globals = globals = + loader_malloc(size, error_buf, error_buf_size))) { return false; } if (module->import_global_count > 0) { last_import_global = &module->import_globals[module->import_global_count - 1]; - data_offset = last_import_global->data_offset - + last_import_global->size; + data_offset = + last_import_global->data_offset + last_import_global->size; } /* Create each global */ @@ -899,8 +982,7 @@ load_globals(const uint8 **p_buf, const uint8 *buf_end, } static bool -load_global_info(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, +load_global_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; @@ -919,16 +1001,14 @@ load_global_info(const uint8 **p_buf, const uint8 *buf_end, } static void -destroy_import_funcs(AOTImportFunc *import_funcs, - bool is_jit_mode) +destroy_import_funcs(AOTImportFunc *import_funcs, bool is_jit_mode) { if (!is_jit_mode) wasm_runtime_free(import_funcs); } static bool -load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, +load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, char *error_buf, uint32 error_buf_size) { const char *module_name, *field_name; @@ -940,7 +1020,7 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTImportFunc) * (uint64)module->import_func_count; if (!(module->import_funcs = import_funcs = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -951,18 +1031,17 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, set_error_buf(error_buf, error_buf_size, "unknown type"); return false; } - import_funcs[i].func_type = module->func_types[import_funcs[i].func_type_index]; + import_funcs[i].func_type = + module->func_types[import_funcs[i].func_type_index]; read_string(buf, buf_end, import_funcs[i].module_name); read_string(buf, buf_end, import_funcs[i].func_name); module_name = import_funcs[i].module_name; field_name = import_funcs[i].func_name; - import_funcs[i].func_ptr_linked = - wasm_native_resolve_symbol(module_name, field_name, - import_funcs[i].func_type, - &import_funcs[i].signature, - &import_funcs[i].attachment, - &import_funcs[i].call_conv_raw); + import_funcs[i].func_ptr_linked = wasm_native_resolve_symbol( + module_name, field_name, import_funcs[i].func_type, + &import_funcs[i].signature, &import_funcs[i].attachment, + &import_funcs[i].call_conv_raw); #if WASM_ENABLE_LIBC_WASI != 0 if (!strcmp(import_funcs[i].module_name, "wasi_unstable") @@ -979,8 +1058,7 @@ load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, static bool load_import_func_info(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; @@ -988,8 +1066,7 @@ load_import_func_info(const uint8 **p_buf, const uint8 *buf_end, /* load import funcs */ if (module->import_func_count > 0 - && !load_import_funcs(&buf, buf_end, module, - error_buf, error_buf_size)) + && !load_import_funcs(&buf, buf_end, module, error_buf, error_buf_size)) return false; *p_buf = buf; @@ -1012,8 +1089,8 @@ destroy_object_data_sections(AOTObjectDataSection *data_sections, static bool load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *buf = *p_buf; AOTObjectDataSection *data_sections; @@ -1023,14 +1100,16 @@ load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTObjectDataSection) * (uint64)module->data_section_count; if (!(module->data_sections = data_sections = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { return false; } /* Create each data section */ for (i = 0; i < module->data_section_count; i++) { int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE; -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_RISCV64_LP64D) \ + || defined(BUILD_TARGET_RISCV64_LP64) /* aot code and data in x86_64 must be in range 0 to 2G due to relocation for R_X86_64_32/32S/PC32 */ int map_flags = MMAP_MAP_32BIT; @@ -1043,10 +1122,9 @@ load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory for data */ if (data_sections[i].size > 0 - && !(data_sections[i].data = - os_mmap(NULL, data_sections[i].size, map_prot, map_flags))) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + && !(data_sections[i].data = os_mmap(NULL, data_sections[i].size, + map_prot, map_flags))) { + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); return false; } #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) @@ -1058,8 +1136,8 @@ load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end, #endif #endif - read_byte_array(buf, buf_end, - data_sections[i].data, data_sections[i].size); + read_byte_array(buf, buf_end, data_sections[i].data, + data_sections[i].size); } *p_buf = buf; @@ -1070,8 +1148,8 @@ load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end, static bool load_object_data_sections_info(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *buf = *p_buf; @@ -1079,8 +1157,8 @@ load_object_data_sections_info(const uint8 **p_buf, const uint8 *buf_end, /* load object data sections */ if (module->data_section_count > 0 - && !load_object_data_sections(&buf, buf_end, module, - error_buf, error_buf_size)) + && !load_object_data_sections(&buf, buf_end, module, error_buf, + error_buf_size)) return false; *p_buf = buf; @@ -1091,15 +1169,16 @@ load_object_data_sections_info(const uint8 **p_buf, const uint8 *buf_end, static bool load_init_data_section(const uint8 *buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; if (!load_memory_info(&p, p_end, module, error_buf, error_buf_size) || !load_table_info(&p, p_end, module, error_buf, error_buf_size) || !load_func_type_info(&p, p_end, module, error_buf, error_buf_size) - || !load_import_global_info(&p, p_end, module, error_buf, error_buf_size) + || !load_import_global_info(&p, p_end, module, error_buf, + error_buf_size) || !load_global_info(&p, p_end, module, error_buf, error_buf_size) || !load_import_func_info(&p, p_end, module, error_buf, error_buf_size)) return false; @@ -1110,8 +1189,8 @@ load_init_data_section(const uint8 *buf, const uint8 *buf_end, /* check start function index */ if (module->start_func_index != (uint32)-1 - && (module->start_func_index >= module->import_func_count - + module->func_count)) { + && (module->start_func_index + >= module->import_func_count + module->func_count)) { set_error_buf(error_buf, error_buf_size, "invalid start function index"); return false; @@ -1125,8 +1204,8 @@ load_init_data_section(const uint8 *buf, const uint8 *buf_end, read_uint32(p, p_end, module->aux_stack_bottom); read_uint32(p, p_end, module->aux_stack_size); - if (!load_object_data_sections_info(&p, p_end, module, - error_buf, error_buf_size)) + if (!load_object_data_sections_info(&p, p_end, module, error_buf, + error_buf_size)) return false; if (p != p_end) { @@ -1136,21 +1215,18 @@ load_init_data_section(const uint8 *buf, const uint8 *buf_end, } return true; - fail: return false; } static bool -load_text_section(const uint8 *buf, const uint8 *buf_end, - AOTModule *module, +load_text_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, char *error_buf, uint32 error_buf_size) { uint8 *plt_base; if (module->func_count > 0 && buf_end == buf) { - set_error_buf(error_buf, error_buf_size, - "invalid code size"); + set_error_buf(error_buf, error_buf_size, "invalid code size"); return false; } @@ -1158,23 +1234,40 @@ load_text_section(const uint8 *buf, const uint8 *buf_end, read_uint32(buf, buf_end, module->literal_size); /* literal data is at begining of the text section */ - module->literal = (uint8*)buf; - module->code = (void*)(buf + module->literal_size); - module->code_size = (uint32)(buf_end - (uint8*)module->code); + module->literal = (uint8 *)buf; + module->code = (void *)(buf + module->literal_size); + module->code_size = (uint32)(buf_end - (uint8 *)module->code); + +#if WASM_ENABLE_DEBUG_AOT != 0 + module->elf_size = module->code_size; + + if (is_ELF(module->code)) { + /* Now code points to an ELF object, we pull it down to .text section */ + uint64 offset; + uint64 size; + char *buf = module->code; + module->elf_hdr = buf; + if (!get_text_section(buf, &offset, &size)) { + set_error_buf(error_buf, error_buf_size, + "get text section of ELF failed"); + return false; + } + module->code = buf + offset; + module->code_size -= (uint32)offset; + } +#endif - if (module->code_size > 0) { - plt_base = (uint8*)buf_end - get_plt_table_size(); + if ((module->code_size > 0) && (module->native_symbol_count == 0)) { + plt_base = (uint8 *)buf_end - get_plt_table_size(); init_plt_table(plt_base); } return true; - fail: return false; } static bool -load_function_section(const uint8 *buf, const uint8 *buf_end, - AOTModule *module, +load_function_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; @@ -1188,29 +1281,29 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, #endif #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) - unwind_info= (AOTUnwindInfo *)((uint8*)module->code + module->code_size - - sizeof(AOTUnwindInfo)); + unwind_info = (AOTUnwindInfo *)((uint8 *)module->code + module->code_size + - sizeof(AOTUnwindInfo)); unwind_info->Version = 1; unwind_info->Flags = UNW_FLAG_NHANDLER; - *(uint32*)&unwind_info->UnwindCode[0] = unwind_code_offset; + *(uint32 *)&unwind_info->UnwindCode[0] = unwind_code_offset; size = sizeof(RUNTIME_FUNCTION) * (uint64)module->func_count; if (size > 0 && !(rtl_func_table = module->rtl_func_table = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { return false; } #endif - size = sizeof(void*) * (uint64)module->func_count; + size = sizeof(void *) * (uint64)module->func_count; if (size > 0 - && !(module->func_ptrs = loader_malloc - (size, error_buf, error_buf_size))) { + && !(module->func_ptrs = + loader_malloc(size, error_buf, error_buf_size))) { return false; } for (i = 0; i < module->func_count; i++) { - if (sizeof(void*) == 8) { + if (sizeof(void *) == 8) { read_uint64(p, p_end, text_offset); } else { @@ -1223,10 +1316,10 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, "invalid function code offset"); return false; } - module->func_ptrs[i] = (uint8*)module->code + text_offset; + module->func_ptrs[i] = (uint8 *)module->code + text_offset; #if defined(BUILD_TARGET_THUMB) || defined(BUILD_TARGET_THUMB_VFP) /* bits[0] of thumb function address must be 1 */ - module->func_ptrs[i] = (void*)((uintptr_t)module->func_ptrs[i] | 1); + module->func_ptrs[i] = (void *)((uintptr_t)module->func_ptrs[i] | 1); #endif #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) rtl_func_table[i].BeginAddress = (DWORD)text_offset; @@ -1240,7 +1333,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) if (module->func_count > 0) { rtl_func_table[module->func_count - 1].EndAddress = - (DWORD)(module->code_size - get_plt_table_size()); + (DWORD)(module->code_size - get_plt_table_size()); if (!RtlAddFunctionTable(rtl_func_table, module->func_count, (DWORD64)(uintptr_t)module->code)) { @@ -1257,7 +1350,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, if (module->start_func_index >= module->import_func_count) module->start_function = module->func_ptrs[module->start_func_index - - module->import_func_count]; + - module->import_func_count]; else /* TODO: fix start function can be import function issue */ module->start_function = NULL; @@ -1268,8 +1361,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, size = sizeof(uint32) * (uint64)module->func_count; if (size > 0 - && !(module->func_type_indexes = loader_malloc - (size, error_buf, error_buf_size))) { + && !(module->func_type_indexes = + loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -1300,8 +1393,8 @@ destroy_exports(AOTExport *exports, bool is_jit_mode) } static bool -load_exports(const uint8 **p_buf, const uint8 *buf_end, - AOTModule *module, char *error_buf, uint32 error_buf_size) +load_exports(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module, + char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; AOTExport *exports; @@ -1311,7 +1404,7 @@ load_exports(const uint8 **p_buf, const uint8 *buf_end, /* Allocate memory */ size = sizeof(AOTExport) * (uint64)module->export_count; if (!(module->exports = exports = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { return false; } @@ -1337,8 +1430,7 @@ load_exports(const uint8 **p_buf, const uint8 *buf_end, } static bool -load_export_section(const uint8 *buf, const uint8 *buf_end, - AOTModule *module, +load_export_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; @@ -1350,18 +1442,15 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, return false; if (p != p_end) { - set_error_buf(error_buf, error_buf_size, - "invalid export section size"); + set_error_buf(error_buf, error_buf_size, "invalid export section size"); return false; } return true; - fail: return false; } - static void * get_data_section_addr(AOTModule *module, const char *section_name, uint32 *p_data_size) @@ -1386,8 +1475,8 @@ resolve_target_sym(const char *symbol, int32 *p_index) uint32 i, num = 0; SymbolMap *target_sym_map; - if (!(target_sym_map = get_target_symbol_map(&num))) - return NULL; + if (!(target_sym_map = get_target_symbol_map(&num))) + return NULL; for (i = 0; i < num; i++) if (!strcmp(target_sym_map[i].symbol_name, symbol)) { @@ -1452,18 +1541,18 @@ str2uint64(const char *buf, uint64 *p_res) #endif static bool -do_text_relocation(AOTModule *module, - AOTRelocationGroup *group, +do_text_relocation(AOTModule *module, AOTRelocationGroup *group, char *error_buf, uint32 error_buf_size) { bool is_literal = is_literal_relocation(group->section_name); uint8 *aot_text = is_literal ? module->literal : module->code; - uint32 aot_text_size = is_literal ? module->literal_size : module->code_size; + uint32 aot_text_size = + is_literal ? module->literal_size : module->code_size; uint32 i, func_index, symbol_len; #if defined(BH_PLATFORM_WINDOWS) uint32 xmm_plt_index = 0, real_plt_index = 0, float_plt_index = 0; #endif - char symbol_buf[128] = { 0 }, *symbol, *p; + char symbol_buf[128] = { 0 }, *symbol, *p; void *symbol_addr; AOTRelocation *relocation = group->relocations; @@ -1479,8 +1568,8 @@ do_text_relocation(AOTModule *module, if (symbol_len + 1 <= sizeof(symbol_buf)) symbol = symbol_buf; else { - if (!(symbol = loader_malloc(symbol_len + 1, - error_buf, error_buf_size))) { + if (!(symbol = loader_malloc(symbol_len + 1, error_buf, + error_buf_size))) { return false; } } @@ -1500,7 +1589,7 @@ do_text_relocation(AOTModule *module, else if (!strcmp(symbol, ".text")) { symbol_addr = module->code; } - else if (!strcmp(symbol, ".data") + else if (!strcmp(symbol, ".data") || !strcmp(symbol, ".sdata") || !strcmp(symbol, ".rdata") || !strcmp(symbol, ".rodata") /* ".rodata.cst4/8/16/.." */ @@ -1529,7 +1618,7 @@ do_text_relocation(AOTModule *module, symbol_addr = module->extra_plt_data + xmm_plt_index * 16; bh_memcpy_s(xmm_buf, sizeof(xmm_buf), symbol + strlen(XMM_PLT_PREFIX) + 16, 16); - if (!str2uint64(xmm_buf, (uint64*)symbol_addr)) { + if (!str2uint64(xmm_buf, (uint64 *)symbol_addr)) { set_error_buf_v(error_buf, error_buf_size, "resolve symbol %s failed", symbol); goto check_symbol_fail; @@ -1537,7 +1626,7 @@ do_text_relocation(AOTModule *module, bh_memcpy_s(xmm_buf, sizeof(xmm_buf), symbol + strlen(XMM_PLT_PREFIX), 16); - if (!str2uint64(xmm_buf, (uint64*)((uint8*)symbol_addr + 8))) { + if (!str2uint64(xmm_buf, (uint64 *)((uint8 *)symbol_addr + 8))) { set_error_buf_v(error_buf, error_buf_size, "resolve symbol %s failed", symbol); goto check_symbol_fail; @@ -1553,7 +1642,7 @@ do_text_relocation(AOTModule *module, + real_plt_index * 8; bh_memcpy_s(real_buf, sizeof(real_buf), symbol + strlen(REAL_PLT_PREFIX), 16); - if (!str2uint64(real_buf, (uint64*)symbol_addr)) { + if (!str2uint64(real_buf, (uint64 *)symbol_addr)) { set_error_buf_v(error_buf, error_buf_size, "resolve symbol %s failed", symbol); goto check_symbol_fail; @@ -1569,7 +1658,7 @@ do_text_relocation(AOTModule *module, + module->real_plt_count * 8 + float_plt_index * 4; bh_memcpy_s(float_buf, sizeof(float_buf), symbol + strlen(REAL_PLT_PREFIX), 8); - if (!str2uint32(float_buf, (uint32*)symbol_addr)) { + if (!str2uint32(float_buf, (uint32 *)symbol_addr)) { set_error_buf_v(error_buf, error_buf_size, "resolve symbol %s failed", symbol); goto check_symbol_fail; @@ -1586,13 +1675,10 @@ do_text_relocation(AOTModule *module, if (symbol != symbol_buf) wasm_runtime_free(symbol); - if (!apply_relocation(module, - aot_text, aot_text_size, - relocation->relocation_offset, - relocation->relocation_addend, - relocation->relocation_type, - symbol_addr, symbol_index, - error_buf, error_buf_size)) + if (!apply_relocation( + module, aot_text, aot_text_size, relocation->relocation_offset, + relocation->relocation_addend, relocation->relocation_type, + symbol_addr, symbol_index, error_buf, error_buf_size)) return false; } @@ -1605,8 +1691,7 @@ do_text_relocation(AOTModule *module, } static bool -do_data_relocation(AOTModule *module, - AOTRelocationGroup *group, +do_data_relocation(AOTModule *module, AOTRelocationGroup *group, char *error_buf, uint32 error_buf_size) { @@ -1631,8 +1716,7 @@ do_data_relocation(AOTModule *module, return false; } - data_addr = get_data_section_addr(module, data_section_name, - &data_size); + data_addr = get_data_section_addr(module, data_section_name, &data_size); if (group->relocation_count > 0 && !data_addr) { set_error_buf(error_buf, error_buf_size, @@ -1651,13 +1735,10 @@ do_data_relocation(AOTModule *module, return false; } - if (!apply_relocation(module, - data_addr, data_size, - relocation->relocation_offset, - relocation->relocation_addend, - relocation->relocation_type, - symbol_addr, -1, - error_buf, error_buf_size)) + if (!apply_relocation( + module, data_addr, data_size, relocation->relocation_offset, + relocation->relocation_addend, relocation->relocation_type, + symbol_addr, -1, error_buf, error_buf_size)) return false; } @@ -1665,8 +1746,7 @@ do_data_relocation(AOTModule *module, } static bool -validate_symbol_table(uint8 *buf, uint8 *buf_end, - uint32 *offsets, uint32 count, +validate_symbol_table(uint8 *buf, uint8 *buf_end, uint32 *offsets, uint32 count, char *error_buf, uint32 error_buf_size) { uint32 i, str_len_addr = 0; @@ -1680,7 +1760,7 @@ validate_symbol_table(uint8 *buf, uint8 *buf_end, str_len_addr += (uint32)sizeof(uint16) + str_len; str_len_addr = align_uint(str_len_addr, 2); buf += str_len; - buf = (uint8*)align_ptr(buf, 2); + buf = (uint8 *)align_ptr(buf, 2); } if (buf == buf_end) @@ -1691,8 +1771,8 @@ validate_symbol_table(uint8 *buf, uint8 *buf_end, static bool load_relocation_section(const uint8 *buf, const uint8 *buf_end, - AOTModule *module, - char *error_buf, uint32 error_buf_size) + AOTModule *module, char *error_buf, + uint32 error_buf_size) { AOTRelocationGroup *groups = NULL, *group; uint32 symbol_count = 0; @@ -1715,9 +1795,8 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, symbol_buf = (uint8 *)buf; symbol_buf_end = symbol_buf + total_string_len; - if (!validate_symbol_table(symbol_buf, symbol_buf_end, - symbol_offsets, symbol_count, - error_buf, error_buf_size)) { + if (!validate_symbol_table(symbol_buf, symbol_buf_end, symbol_offsets, + symbol_count, error_buf, error_buf_size)) { set_error_buf(error_buf, error_buf_size, "validate symbol table failed"); goto fail; @@ -1733,7 +1812,7 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, uint8 *group_name; /* section name address is 4 bytes aligned. */ - buf = (uint8*)align_ptr(buf, sizeof(uint32)); + buf = (uint8 *)align_ptr(buf, sizeof(uint32)); read_uint32(buf, buf_end, name_index); if (name_index >= symbol_count) { @@ -1814,8 +1893,8 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, map_flags = MMAP_MAP_32BIT; if (size > UINT32_MAX - || !(module->extra_plt_data = os_mmap(NULL, (uint32)size, - map_prot, map_flags))) { + || !(module->extra_plt_data = + os_mmap(NULL, (uint32)size, map_prot, map_flags))) { set_error_buf(error_buf, error_buf_size, "mmap memory failed"); goto fail; } @@ -1841,7 +1920,7 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, uint8 *name_addr; /* section name address is 4 bytes aligned. */ - buf = (uint8*)align_ptr(buf, sizeof(uint32)); + buf = (uint8 *)align_ptr(buf, sizeof(uint32)); read_uint32(buf, buf_end, name_index); if (name_index >= symbol_count) { @@ -1853,10 +1932,9 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, name_addr = symbol_buf + symbol_offsets[name_index]; str_len = *(uint16 *)name_addr; - if (!(group->section_name = - const_str_set_insert(name_addr + sizeof(uint16), - (int32)str_len, module, - error_buf, error_buf_size))) { + if (!(group->section_name = const_str_set_insert( + name_addr + sizeof(uint16), (int32)str_len, module, error_buf, + error_buf_size))) { goto fail; } @@ -1865,7 +1943,7 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, /* Allocate memory for relocations */ size = sizeof(AOTRelocation) * (uint64)group->relocation_count; if (!(group->relocations = relocation = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { ret = false; goto fail; } @@ -1899,10 +1977,9 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, symbol_addr = symbol_buf + symbol_offsets[symbol_index]; str_len = *(uint16 *)symbol_addr; - if (!(relocation->symbol_name = - const_str_set_insert(symbol_addr + sizeof(uint16), - (int32)str_len, module, - error_buf, error_buf_size))) { + if (!(relocation->symbol_name = const_str_set_insert( + symbol_addr + sizeof(uint16), (int32)str_len, module, + error_buf, error_buf_size))) { goto fail; } } @@ -1913,7 +1990,14 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, #ifdef BH_PLATFORM_WINDOWS || !strcmp(group->section_name, ".text") #endif - ) { + ) { + if (module->native_symbol_count > 0) { + set_error_buf(error_buf, error_buf_size, + "cannot apply relocation to text section " + "for aot file generated with " + "\"--enable-indirect-mode\" flag"); + goto fail; + } if (!do_text_relocation(module, group, error_buf, error_buf_size)) goto fail; } @@ -1929,8 +2013,8 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, if (module->code) { /* The layout is: literal size + literal + code (with plt table) */ uint8 *mmap_addr = module->literal - sizeof(uint32); - uint32 total_size = sizeof(uint32) - + module->literal_size + module->code_size; + uint32 total_size = + sizeof(uint32) + module->literal_size + module->code_size; os_mprotect(mmap_addr, total_size, map_prot); } @@ -1969,8 +2053,8 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, } static bool -load_from_sections(AOTModule *module, AOTSection *sections, - char *error_buf, uint32 error_buf_size) +load_from_sections(AOTModule *module, AOTSection *sections, char *error_buf, + uint32 error_buf_size) { AOTSection *section = sections; const uint8 *buf, *buf_end; @@ -1987,41 +2071,46 @@ load_from_sections(AOTModule *module, AOTSection *sections, if ((last_section_type == (uint32)-1 && section_type != AOT_SECTION_TYPE_TARGET_INFO) || (last_section_type != (uint32)-1 - && section_type != last_section_type + 1)) { - set_error_buf(error_buf, error_buf_size, - "invalid section order"); + && (section_type != last_section_type + 1 + && section_type != AOT_SECTION_TYPE_CUSTOM))) { + set_error_buf(error_buf, error_buf_size, "invalid section order"); return false; } last_section_type = section_type; switch (section_type) { case AOT_SECTION_TYPE_TARGET_INFO: - if (!load_target_info_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_target_info_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case AOT_SECTION_TYPE_INIT_DATA: - if (!load_init_data_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_init_data_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case AOT_SECTION_TYPE_TEXT: - if (!load_text_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_text_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case AOT_SECTION_TYPE_FUNCTION: - if (!load_function_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_function_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case AOT_SECTION_TYPE_EXPORT: - if (!load_export_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_export_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case AOT_SECTION_TYPE_RELOCATION: - if (!load_relocation_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_relocation_section(buf, buf_end, module, error_buf, + error_buf_size)) + return false; + break; + case AOT_SECTION_TYPE_CUSTOM: + if (!load_custom_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; default: @@ -2033,9 +2122,9 @@ load_from_sections(AOTModule *module, AOTSection *sections, section = section->next; } - if (last_section_type != AOT_SECTION_TYPE_RELOCATION) { - set_error_buf(error_buf, error_buf_size, - "section missing"); + if (last_section_type != AOT_SECTION_TYPE_RELOCATION + && last_section_type != AOT_SECTION_TYPE_CUSTOM) { + set_error_buf(error_buf, error_buf_size, "section missing"); return false; } @@ -2052,8 +2141,7 @@ load_from_sections(AOTModule *module, AOTSection *sections, func_index = exports[i].index - module->import_func_count; func_type_index = module->func_type_indexes[func_index]; func_type = module->func_types[func_type_index]; - if (func_type->param_count == 1 - && func_type->result_count == 1 + if (func_type->param_count == 1 && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32) { bh_assert(module->malloc_func_index == (uint32)-1); @@ -2066,8 +2154,7 @@ load_from_sections(AOTModule *module, AOTSection *sections, func_index = exports[i].index - module->import_func_count; func_type_index = module->func_type_indexes[func_index]; func_type = module->func_types[func_type_index]; - if (func_type->param_count == 2 - && func_type->result_count == 1 + if (func_type->param_count == 2 && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32 && func_type->types[2] == VALUE_TYPE_I32) { @@ -2086,21 +2173,22 @@ load_from_sections(AOTModule *module, AOTSection *sections, if ((export_tmp->kind == EXPORT_KIND_FUNC) && (!strcmp(export_tmp->name, "__retain") || !strcmp(export_tmp->name, "__pin"))) { - func_index = export_tmp->index - - module->import_func_count; + func_index = + export_tmp->index - module->import_func_count; func_type_index = - module->func_type_indexes[func_index]; + module->func_type_indexes[func_index]; func_type = module->func_types[func_type_index]; if (func_type->param_count == 1 && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32) { - bh_assert( - module->retain_func_index == (uint32)-1); + bh_assert(module->retain_func_index + == (uint32)-1); module->retain_func_index = export_tmp->index; - LOG_VERBOSE( - "Found retain function, name: %s, index: %u", - export_tmp->name, export_tmp->index); + LOG_VERBOSE("Found retain function, name: %s, " + "index: %u", + export_tmp->name, + export_tmp->index); break; } } @@ -2118,8 +2206,7 @@ load_from_sections(AOTModule *module, AOTSection *sections, func_index = exports[i].index - module->import_func_count; func_type_index = module->func_type_indexes[func_index]; func_type = module->func_types[func_type_index]; - if (func_type->param_count == 1 - && func_type->result_count == 0 + if (func_type->param_count == 1 && func_type->result_count == 0 && func_type->types[0] == VALUE_TYPE_I32) { bh_assert(module->free_func_index == (uint32)-1); module->free_func_index = func_index; @@ -2135,12 +2222,20 @@ load_from_sections(AOTModule *module, AOTSection *sections, os_dcache_flush(); #if WASM_ENABLE_MEMORY_TRACING != 0 - wasm_runtime_dump_module_mem_consumption((WASMModuleCommon*)module); + wasm_runtime_dump_module_mem_consumption((WASMModuleCommon *)module); +#endif + +#if WASM_ENABLE_DEBUG_AOT != 0 + if (!jit_code_entry_create(module->elf_hdr, module->elf_size)) { + set_error_buf(error_buf, error_buf_size, + "create jit code entry failed"); + return false; + } #endif return true; } -static AOTModule* +static AOTModule * create_module(char *error_buf, uint32 error_buf_size) { AOTModule *module = @@ -2152,12 +2247,9 @@ create_module(char *error_buf, uint32 error_buf_size) module->module_type = Wasm_Module_AoT; - if (!(module->const_str_set = - bh_hash_map_create(32, false, - (HashFunc)wasm_string_hash, - (KeyEqualFunc)wasm_string_equal, - NULL, - wasm_runtime_free))) { + if (!(module->const_str_set = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, NULL, wasm_runtime_free))) { set_error_buf(error_buf, error_buf_size, "create const string set failed"); wasm_runtime_free(module); @@ -2167,17 +2259,16 @@ create_module(char *error_buf, uint32 error_buf_size) return module; } -AOTModule* -aot_load_from_sections(AOTSection *section_list, - char *error_buf, uint32 error_buf_size) +AOTModule * +aot_load_from_sections(AOTSection *section_list, char *error_buf, + uint32 error_buf_size) { AOTModule *module = create_module(error_buf, error_buf_size); if (!module) return NULL; - if (!load_from_sections(module, section_list, - error_buf, error_buf_size)) { + if (!load_from_sections(module, section_list, error_buf, error_buf_size)) { aot_unload(module); return NULL; } @@ -2192,57 +2283,106 @@ destroy_sections(AOTSection *section_list, bool destroy_aot_text) AOTSection *section = section_list, *next; while (section) { next = section->next; - if (destroy_aot_text - && section->section_type == AOT_SECTION_TYPE_TEXT + if (destroy_aot_text && section->section_type == AOT_SECTION_TYPE_TEXT && section->section_body) - os_munmap((uint8*)section->section_body, section->section_body_size); + os_munmap((uint8 *)section->section_body, + section->section_body_size); wasm_runtime_free(section); section = next; } } static bool -create_sections(const uint8 *buf, uint32 size, - AOTSection **p_section_list, - char *error_buf, uint32 error_buf_size) +resolve_native_symbols(const uint8 *buf, uint32 size, uint32 *p_count, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *p = buf, *p_end = buf + size; + uint32 section_type; + uint32 section_size = 0; + + p += 8; + while (p < p_end) { + read_uint32(p, p_end, section_type); + if (section_type <= AOT_SECTION_TYPE_SIGANATURE + || section_type == AOT_SECTION_TYPE_CUSTOM) { + read_uint32(p, p_end, section_size); + CHECK_BUF(p, p_end, section_size); + if (section_type == AOT_SECTION_TYPE_CUSTOM) { + read_uint32(p, p_end, section_type); + if (section_type == AOT_CUSTOM_SECTION_NATIVE_SYMBOL) { + /* Read the count of native symbol */ + read_uint32(p, p_end, *p_count); + return true; + } + p -= sizeof(uint32); + } + } + else if (section_type > AOT_SECTION_TYPE_SIGANATURE) { + set_error_buf(error_buf, error_buf_size, + "resolve native symbol failed"); + break; + } + p += section_size; + } + return true; +fail: + return false; +} + +static bool +create_sections(AOTModule *module, const uint8 *buf, uint32 size, + AOTSection **p_section_list, char *error_buf, + uint32 error_buf_size) { AOTSection *section_list = NULL, *section_list_end = NULL, *section; const uint8 *p = buf, *p_end = buf + size; + bool destory_aot_text = false; + uint32 native_symbol_count = 0; uint32 section_type; uint32 section_size; uint64 total_size; uint8 *aot_text; + if (!resolve_native_symbols(buf, size, &native_symbol_count, error_buf, + error_buf_size)) { + goto fail; + } + + module->native_symbol_count = native_symbol_count; + p += 8; while (p < p_end) { read_uint32(p, p_end, section_type); - if (section_type < AOT_SECTION_TYPE_SIGANATURE) { + if (section_type < AOT_SECTION_TYPE_SIGANATURE + || section_type == AOT_SECTION_TYPE_CUSTOM) { read_uint32(p, p_end, section_size); CHECK_BUF(p, p_end, section_size); - if (!(section = - loader_malloc(sizeof(AOTSection), - error_buf, error_buf_size))) { + if (!(section = loader_malloc(sizeof(AOTSection), error_buf, + error_buf_size))) { goto fail; } memset(section, 0, sizeof(AOTSection)); section->section_type = (int32)section_type; - section->section_body = (uint8*)p; + section->section_body = (uint8 *)p; section->section_body_size = section_size; if (section_type == AOT_SECTION_TYPE_TEXT) { - if (section_size > 0) { - int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE - | MMAP_PROT_EXEC; -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) - /* aot code and data in x86_64 must be in range 0 to 2G due to - relocation for R_X86_64_32/32S/PC32 */ + if ((section_size > 0) && (native_symbol_count == 0)) { + int map_prot = + MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC; +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_RISCV64_LP64D) \ + || defined(BUILD_TARGET_RISCV64_LP64) + /* aot code and data in x86_64 must be in range 0 to 2G due + to relocation for R_X86_64_32/32S/PC32 */ int map_flags = MMAP_MAP_32BIT; #else int map_flags = MMAP_MAP_NONE; #endif - total_size = (uint64)section_size + aot_get_plt_table_size(); + total_size = + (uint64)section_size + aot_get_plt_table_size(); total_size = (total_size + 3) & ~((uint64)3); if (total_size >= UINT32_MAX || !(aot_text = os_mmap(NULL, (uint32)total_size, @@ -2263,15 +2403,14 @@ create_sections(const uint8 *buf, uint32 size, bh_memcpy_s(aot_text, (uint32)total_size, section->section_body, (uint32)section_size); section->section_body = aot_text; + destory_aot_text = true; if ((uint32)total_size > section->section_body_size) { - memset(aot_text + (uint32)section_size, - 0, (uint32)total_size - section_size); + memset(aot_text + (uint32)section_size, 0, + (uint32)total_size - section_size); section->section_body_size = (uint32)total_size; } } - else - section->section_body = NULL; } if (!section_list) @@ -2284,15 +2423,13 @@ create_sections(const uint8 *buf, uint32 size, p += section_size; } else { - set_error_buf(error_buf, error_buf_size, - "invalid section id"); + set_error_buf(error_buf, error_buf_size, "invalid section id"); goto fail; } } if (!section_list) { - set_error_buf(error_buf, error_buf_size, - "create section list failed"); + set_error_buf(error_buf, error_buf_size, "create section list failed"); return false; } @@ -2300,13 +2437,13 @@ create_sections(const uint8 *buf, uint32 size, return true; fail: if (section_list) - destroy_sections(section_list, true); + destroy_sections(section_list, destory_aot_text); return false; } static bool -load(const uint8 *buf, uint32 size, AOTModule *module, - char *error_buf, uint32 error_buf_size) +load(const uint8 *buf, uint32 size, AOTModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *buf_end = buf + size; const uint8 *p = buf, *p_end = buf_end; @@ -2326,14 +2463,16 @@ load(const uint8 *buf, uint32 size, AOTModule *module, return false; } - if (!create_sections(buf, size, §ion_list, error_buf, error_buf_size)) + if (!create_sections(module, buf, size, §ion_list, error_buf, + error_buf_size)) return false; ret = load_from_sections(module, section_list, error_buf, error_buf_size); if (!ret) { /* If load_from_sections() fails, then aot text is destroyed in destroy_sections() */ - destroy_sections(section_list, true); + destroy_sections(section_list, + module->native_symbol_count == 0 ? true : false); /* aot_unload() won't destroy aot text again */ module->code = NULL; } @@ -2347,9 +2486,9 @@ load(const uint8 *buf, uint32 size, AOTModule *module, return false; } -AOTModule* -aot_load_from_aot_file(const uint8 *buf, uint32 size, - char *error_buf, uint32 error_buf_size) +AOTModule * +aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf, + uint32 error_buf_size) { AOTModule *module = create_module(error_buf, error_buf_size); @@ -2366,7 +2505,7 @@ aot_load_from_aot_file(const uint8 *buf, uint32 size, } #if WASM_ENABLE_JIT != 0 -static AOTModule* +static AOTModule * aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, char *error_buf, uint32 error_buf_size) { @@ -2375,9 +2514,16 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, char func_name[32]; AOTModule *module; +#if WASM_ENABLE_LAZY_JIT != 0 + LLVMOrcThreadSafeModuleRef ts_module; + LLVMOrcJITDylibRef main_dylib; + LLVMErrorRef error; + LLVMOrcJITTargetAddress func_addr = 0; +#endif + /* Allocate memory for module */ if (!(module = - loader_malloc(sizeof(AOTModule), error_buf, error_buf_size))) { + loader_malloc(sizeof(AOTModule), error_buf, error_buf_size))) { return NULL; } @@ -2390,12 +2536,12 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, if (module->memory_count) { size = sizeof(AOTMemory) * (uint64)module->memory_count; if (!(module->memories = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { goto fail1; } - bh_memcpy_s(module->memories, (uint32)size, - comp_data->memories, (uint32)size); + bh_memcpy_s(module->memories, (uint32)size, comp_data->memories, + (uint32)size); } module->mem_init_data_list = comp_data->mem_init_data_list; @@ -2433,28 +2579,69 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, size = (uint64)module->func_count * sizeof(void *); if (size > 0 && !(module->func_ptrs = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { goto fail2; } +#if WASM_ENABLE_LAZY_JIT != 0 + bh_assert(comp_ctx->lazy_orcjit); + + main_dylib = LLVMOrcLLLazyJITGetMainJITDylib(comp_ctx->lazy_orcjit); + if (!main_dylib) { + set_error_buf(error_buf, error_buf_size, + "failed to get dynmaic library reference"); + goto fail3; + } + + ts_module = LLVMOrcCreateNewThreadSafeModule(comp_ctx->module, + comp_ctx->ts_context); + if (!ts_module) { + set_error_buf(error_buf, error_buf_size, + "failed to create thread safe module"); + goto fail3; + } + + if ((error = LLVMOrcLLLazyJITAddLLVMIRModule(comp_ctx->lazy_orcjit, + main_dylib, ts_module))) { + /* + * If adding the ThreadSafeModule fails then we need to clean it up + * ourselves. If adding it succeeds the JIT will manage the memory. + */ + aot_handle_llvm_errmsg(error_buf, error_buf_size, + "failed to addIRModule: ", error); + goto fail4; + } + + for (i = 0; i < comp_data->func_count; i++) { + snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i); + if ((error = LLVMOrcLLLazyJITLookup(comp_ctx->lazy_orcjit, &func_addr, + func_name))) { + aot_handle_llvm_errmsg(error_buf, error_buf_size, + "cannot lookup: ", error); + goto fail3; + } + module->func_ptrs[i] = (void *)func_addr; + func_addr = 0; + } +#else /* Resolve function addresses */ bh_assert(comp_ctx->exec_engine); for (i = 0; i < comp_data->func_count; i++) { snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i); - if (!(module->func_ptrs[i] = - (void *)LLVMGetFunctionAddress(comp_ctx->exec_engine, - func_name))) { + if (!(module->func_ptrs[i] = (void *)LLVMGetFunctionAddress( + comp_ctx->exec_engine, func_name))) { set_error_buf(error_buf, error_buf_size, "get function address failed"); goto fail3; } } +#endif /* WASM_ENABLE_LAZY_JIT != 0 */ /* Allocation memory for function type indexes */ size = (uint64)module->func_count * sizeof(uint32); if (size > 0 && !(module->func_type_indexes = - loader_malloc(size, error_buf, error_buf_size))) { + loader_malloc(size, error_buf, error_buf_size))) { goto fail3; } for (i = 0; i < comp_data->func_count; i++) @@ -2465,8 +2652,8 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, module->start_func_index = comp_data->start_func_index; if (comp_data->start_func_index != (uint32)-1) { - bh_assert(comp_data->start_func_index < module->import_func_count - + module->func_count); + bh_assert(comp_data->start_func_index + < module->import_func_count + module->func_count); /* TODO: fix issue that start func cannot be import func */ if (comp_data->start_func_index >= module->import_func_count) { module->start_function = @@ -2502,6 +2689,11 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, return module; +#if WASM_ENABLE_LAZY_JIT != 0 +fail4: + LLVMOrcDisposeThreadSafeModule(ts_module); +#endif + fail3: if (module->func_ptrs) wasm_runtime_free(module->func_ptrs); @@ -2513,9 +2705,9 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, return NULL; } -AOTModule* -aot_convert_wasm_module(WASMModule *wasm_module, - char *error_buf, uint32 error_buf_size) +AOTModule * +aot_convert_wasm_module(WASMModule *wasm_module, char *error_buf, + uint32 error_buf_size) { AOTCompData *comp_data; AOTCompContext *comp_ctx; @@ -2567,8 +2759,8 @@ aot_convert_wasm_module(WASMModule *wasm_module, goto fail2; } - aot_module = aot_load_from_comp_data(comp_data, comp_ctx, - error_buf, error_buf_size); + aot_module = + aot_load_from_comp_data(comp_data, comp_ctx, error_buf, error_buf_size); if (!aot_module) { goto fail2; } @@ -2598,8 +2790,7 @@ aot_unload(AOTModule *module) #endif if (module->import_memories) - destroy_import_memories(module->import_memories, - module->is_jit_mode); + destroy_import_memories(module->import_memories, module->is_jit_mode); if (module->memories) wasm_runtime_free(module->memories); @@ -2609,9 +2800,11 @@ aot_unload(AOTModule *module) module->mem_init_data_count, module->is_jit_mode); + if (module->native_symbol_list) + wasm_runtime_free(module->native_symbol_list); + if (module->import_tables) - destroy_import_tables(module->import_tables, - module->is_jit_mode); + destroy_import_tables(module->import_tables, module->is_jit_mode); if (module->tables) destroy_tables(module->tables, module->is_jit_mode); @@ -2622,25 +2815,20 @@ aot_unload(AOTModule *module) module->is_jit_mode); if (module->func_types) - destroy_func_types(module->func_types, - module->func_type_count, + destroy_func_types(module->func_types, module->func_type_count, module->is_jit_mode); if (module->import_globals) - destroy_import_globals(module->import_globals, - module->is_jit_mode); + destroy_import_globals(module->import_globals, module->is_jit_mode); if (module->globals) - destroy_globals(module->globals, - module->is_jit_mode); + destroy_globals(module->globals, module->is_jit_mode); if (module->import_funcs) - destroy_import_funcs(module->import_funcs, - module->is_jit_mode); + destroy_import_funcs(module->import_funcs, module->is_jit_mode); if (module->exports) - destroy_exports(module->exports, - module->is_jit_mode); + destroy_exports(module->exports, module->is_jit_mode); if (module->func_type_indexes) wasm_runtime_free(module->func_type_indexes); @@ -2651,11 +2839,11 @@ aot_unload(AOTModule *module) if (module->const_str_set) bh_hash_map_destroy(module->const_str_set); - if (module->code) { + if (module->code && (module->native_symbol_count == 0)) { /* The layout is: literal size + literal + code (with plt table) */ uint8 *mmap_addr = module->literal - sizeof(uint32); - uint32 total_size = sizeof(uint32) - + module->literal_size + module->code_size; + uint32 total_size = + sizeof(uint32) + module->literal_size + module->code_size; os_munmap(mmap_addr, total_size); } @@ -2676,6 +2864,9 @@ aot_unload(AOTModule *module) if (module->data_sections) destroy_object_data_sections(module->data_sections, module->data_section_count); +#if WASM_ENABLE_DEBUG_AOT != 0 + jit_code_entry_destroy(module->elf_hdr); +#endif wasm_runtime_free(module); } @@ -2685,4 +2876,3 @@ aot_get_plt_table_size() { return get_plt_table_size(); } - diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 7c1673cf7e..f2296ba545 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -3,14 +3,23 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#ifndef _AOT_RELOC_H_ +#define _AOT_RELOC_H_ + #include "aot_runtime.h" +#include "aot_intrinsic.h" + +#ifdef __cplusplus +extern "C" { +#endif typedef struct { const char *symbol_name; void *symbol_addr; } SymbolMap; -#define REG_SYM(symbol) { #symbol, (void*)symbol } +/* clang-format off */ +#define REG_SYM(symbol) { #symbol, (void *)symbol } #if WASM_ENABLE_BULK_MEMORY != 0 #define REG_BULK_MEMORY_SYM() \ @@ -48,6 +57,53 @@ typedef struct { #define REG_AOT_TRACE_SYM() #endif +#define REG_INTRINSIC_SYM() \ + REG_SYM(aot_intrinsic_fabs_f32), \ + REG_SYM(aot_intrinsic_fabs_f64), \ + REG_SYM(aot_intrinsic_floor_f32), \ + REG_SYM(aot_intrinsic_floor_f64), \ + REG_SYM(aot_intrinsic_ceil_f32), \ + REG_SYM(aot_intrinsic_ceil_f64), \ + REG_SYM(aot_intrinsic_trunc_f32), \ + REG_SYM(aot_intrinsic_trunc_f64), \ + REG_SYM(aot_intrinsic_rint_f32), \ + REG_SYM(aot_intrinsic_rint_f64), \ + REG_SYM(aot_intrinsic_sqrt_f32), \ + REG_SYM(aot_intrinsic_sqrt_f64), \ + REG_SYM(aot_intrinsic_copysign_f32), \ + REG_SYM(aot_intrinsic_copysign_f64), \ + REG_SYM(aot_intrinsic_fadd_f32), \ + REG_SYM(aot_intrinsic_fadd_f64), \ + REG_SYM(aot_intrinsic_fsub_f32), \ + REG_SYM(aot_intrinsic_fsub_f64), \ + REG_SYM(aot_intrinsic_fmul_f32), \ + REG_SYM(aot_intrinsic_fmul_f64), \ + REG_SYM(aot_intrinsic_fdiv_f32), \ + REG_SYM(aot_intrinsic_fdiv_f64), \ + REG_SYM(aot_intrinsic_fmin_f32), \ + REG_SYM(aot_intrinsic_fmin_f64), \ + REG_SYM(aot_intrinsic_fmax_f32), \ + REG_SYM(aot_intrinsic_fmax_f64), \ + REG_SYM(aot_intrinsic_clz_i32), \ + REG_SYM(aot_intrinsic_clz_i64), \ + REG_SYM(aot_intrinsic_ctz_i32), \ + REG_SYM(aot_intrinsic_ctz_i64), \ + REG_SYM(aot_intrinsic_popcnt_i32), \ + REG_SYM(aot_intrinsic_popcnt_i64), \ + REG_SYM(aot_intrinsic_i32_to_f32), \ + REG_SYM(aot_intrinsic_u32_to_f32), \ + REG_SYM(aot_intrinsic_i32_to_f64), \ + REG_SYM(aot_intrinsic_u32_to_f64), \ + REG_SYM(aot_intrinsic_i64_to_f32), \ + REG_SYM(aot_intrinsic_u64_to_f32), \ + REG_SYM(aot_intrinsic_i64_to_f64), \ + REG_SYM(aot_intrinsic_u64_to_f64), \ + REG_SYM(aot_intrinsic_f64_to_f32), \ + REG_SYM(aot_intrinsic_f64_to_u32), \ + REG_SYM(aot_intrinsic_f32_to_f64), \ + REG_SYM(aot_intrinsic_f32_cmp), \ + REG_SYM(aot_intrinsic_f64_cmp), \ + #define REG_COMMON_SYMBOLS \ REG_SYM(aot_set_exception_with_id), \ REG_SYM(aot_invoke_native), \ @@ -71,12 +127,14 @@ typedef struct { REG_BULK_MEMORY_SYM() \ REG_ATOMIC_WAIT_SYM() \ REG_REF_TYPES_SYM() \ - REG_AOT_TRACE_SYM() + REG_AOT_TRACE_SYM() \ + REG_INTRINSIC_SYM() \ -#define CHECK_RELOC_OFFSET(data_size) do { \ - if (!check_reloc_offset(target_section_size, reloc_offset, data_size, \ - error_buf, error_buf_size)) \ - return false; \ +#define CHECK_RELOC_OFFSET(data_size) do { \ + if (!check_reloc_offset(target_section_size, \ + reloc_offset, data_size, \ + error_buf, error_buf_size)) \ + return false; \ } while (0) SymbolMap * @@ -97,4 +155,10 @@ apply_relocation(AOTModule *module, uint64 reloc_offset, uint64 reloc_addend, uint32 reloc_type, void *symbol_addr, int32 symbol_index, char *error_buf, uint32 error_buf_size); +/* clang-format off */ + +#ifdef __cplusplus +} +#endif +#endif /* end of _AOT_RELOC_H_ */ diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 90139788ca..28db2878e6 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -18,14 +18,13 @@ static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) { if (error_buf != NULL) { - snprintf(error_buf, error_buf_size, - "AOT module instantiate failed: %s", string); + snprintf(error_buf, error_buf_size, "AOT module instantiate failed: %s", + string); } } static void -set_error_buf_v(char *error_buf, uint32 error_buf_size, - const char *format, ...) +set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...) { va_list args; char buf[128]; @@ -34,8 +33,8 @@ set_error_buf_v(char *error_buf, uint32 error_buf_size, va_start(args, format); vsnprintf(buf, sizeof(buf), format, args); va_end(args); - snprintf(error_buf, error_buf_size, - "AOT module instantiate failed: %s", buf); + snprintf(error_buf, error_buf_size, "AOT module instantiate failed: %s", + buf); } } @@ -44,10 +43,8 @@ runtime_malloc(uint64 size, char *error_buf, uint32 error_buf_size) { void *mem; - if (size >= UINT32_MAX - || !(mem = wasm_runtime_malloc((uint32)size))) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); return NULL; } @@ -60,8 +57,8 @@ check_global_init_expr(const AOTModule *module, uint32 global_index, char *error_buf, uint32 error_buf_size) { if (global_index >= module->import_global_count + module->global_count) { - set_error_buf_v(error_buf, error_buf_size, - "unknown global %d", global_index); + set_error_buf_v(error_buf, error_buf_size, "unknown global %d", + global_index); return false; } @@ -83,8 +80,7 @@ check_global_init_expr(const AOTModule *module, uint32 global_index, } static void -init_global_data(uint8 *global_data, uint8 type, - WASMValue *initial_value) +init_global_data(uint8 *global_data, uint8 type, WASMValue *initial_value) { switch (type) { case VALUE_TYPE_I32: @@ -93,17 +89,17 @@ init_global_data(uint8 *global_data, uint8 type, case VALUE_TYPE_FUNCREF: case VALUE_TYPE_EXTERNREF: #endif - *(int32*)global_data = initial_value->i32; + *(int32 *)global_data = initial_value->i32; break; case VALUE_TYPE_I64: case VALUE_TYPE_F64: - bh_memcpy_s(global_data, sizeof(int64), - &initial_value->i64, sizeof(int64)); + bh_memcpy_s(global_data, sizeof(int64), &initial_value->i64, + sizeof(int64)); break; #if WASM_ENABLE_SIMD != 0 case VALUE_TYPE_V128: - bh_memcpy_s(global_data, sizeof(V128), - &initial_value->i64, sizeof(V128)); + bh_memcpy_s(global_data, sizeof(V128), &initial_value->i64, + sizeof(V128)); break; #endif default: @@ -117,14 +113,14 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, { uint32 i; InitializerExpression *init_expr; - uint8 *p = (uint8*)module_inst->global_data.ptr; + uint8 *p = (uint8 *)module_inst->global_data.ptr; AOTImportGlobal *import_global = module->import_globals; AOTGlobal *global = module->globals; /* Initialize import global data */ for (i = 0; i < module->import_global_count; i++, import_global++) { - bh_assert(import_global->data_offset == - (uint32)(p - (uint8*)module_inst->global_data.ptr)); + bh_assert(import_global->data_offset + == (uint32)(p - (uint8 *)module_inst->global_data.ptr)); init_global_data(p, import_global->type, &import_global->global_data_linked); p += import_global->size; @@ -132,8 +128,8 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, /* Initialize defined global data */ for (i = 0; i < module->global_count; i++, global++) { - bh_assert(global->data_offset == - (uint32)(p - (uint8*)module_inst->global_data.ptr)); + bh_assert(global->data_offset + == (uint32)(p - (uint8 *)module_inst->global_data.ptr)); init_expr = &global->init_expr; switch (init_expr->init_expr_type) { case INIT_EXPR_TYPE_GET_GLOBAL: @@ -142,9 +138,10 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, error_buf, error_buf_size)) { return false; } - init_global_data(p, global->type, - &module->import_globals[init_expr->u.global_index] - .global_data_linked); + init_global_data( + p, global->type, + &module->import_globals[init_expr->u.global_index] + .global_data_linked); break; } #if WASM_ENABLE_REF_TYPES != 0 @@ -163,8 +160,8 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, p += global->size; } - bh_assert(module_inst->global_data_size == - (uint32)(p - (uint8*)module_inst->global_data.ptr)); + bh_assert(module_inst->global_data_size + == (uint32)(p - (uint8 *)module_inst->global_data.ptr)); return true; } @@ -180,7 +177,7 @@ static inline AOTTableInstance * aot_get_table_inst(const AOTModuleInstance *module_inst, uint32 tbl_idx) { uint32 i = 0; - AOTTableInstance *tbl_inst = (AOTTableInstance*)module_inst->tables.ptr; + AOTTableInstance *tbl_inst = (AOTTableInstance *)module_inst->tables.ptr; while (i != tbl_idx) { tbl_inst = aot_next_tbl_inst(tbl_inst); @@ -196,7 +193,7 @@ table_instantiate(AOTModuleInstance *module_inst, AOTModule *module, { uint32 i, global_index, global_data_offset, base_offset, length; AOTTableInitData *table_seg; - AOTTableInstance *tbl_inst = (AOTTableInstance*)module_inst->tables.ptr; + AOTTableInstance *tbl_inst = (AOTTableInstance *)module_inst->tables.ptr; /* * treat import table like a local one until we enable module linking @@ -209,8 +206,7 @@ table_instantiate(AOTModuleInstance *module_inst, AOTModule *module, tbl_inst->max_size = aot_get_imp_tbl_data_slots(import_table); } else { - AOTTable *table = - module->tables + (i - module->import_table_count); + AOTTable *table = module->tables + (i - module->import_table_count); tbl_inst->cur_size = table->table_init_size; tbl_inst->max_size = aot_get_tbl_data_slots(table); } @@ -235,34 +231,30 @@ table_instantiate(AOTModuleInstance *module_inst, AOTModule *module, bh_assert(tbl_inst); bh_assert( - table_seg->offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST - || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL + table_seg->offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST + || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL #if WASM_ENABLE_REF_TYPES != 0 - || table_seg->offset.init_expr_type - == INIT_EXPR_TYPE_FUNCREF_CONST - || table_seg->offset.init_expr_type - == INIT_EXPR_TYPE_REFNULL_CONST + || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST + || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST #endif ); /* Resolve table data base offset */ - if (table_seg->offset.init_expr_type - == INIT_EXPR_TYPE_GET_GLOBAL) { + if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { global_index = table_seg->offset.u.global_index; - if (!check_global_init_expr(module, global_index, - error_buf, error_buf_size)) { + if (!check_global_init_expr(module, global_index, error_buf, + error_buf_size)) { return false; } if (global_index < module->import_global_count) global_data_offset = - module->import_globals[global_index].data_offset; + module->import_globals[global_index].data_offset; else global_data_offset = - module - ->globals[global_index - module->import_global_count] - .data_offset; + module->globals[global_index - module->import_global_count] + .data_offset; base_offset = *(uint32 *)((uint8 *)module_inst->global_data.ptr + global_data_offset); @@ -319,9 +311,8 @@ memories_deinstantiate(AOTModuleInstance *module_inst) if (memory_inst) { #if WASM_ENABLE_SHARED_MEMORY != 0 if (memory_inst->is_shared) { - int32 ref_count = - shared_memory_dec_reference( - (WASMModuleCommon *)module_inst->aot_module.ptr); + int32 ref_count = shared_memory_dec_reference( + (WASMModuleCommon *)module_inst->aot_module.ptr); bh_assert(ref_count >= 0); /* if the reference count is not zero, @@ -342,9 +333,9 @@ memories_deinstantiate(AOTModuleInstance *module_inst) #ifdef BH_PLATFORM_WINDOWS os_mem_decommit(memory_inst->memory_data.ptr, memory_inst->num_bytes_per_page - * memory_inst->cur_page_count); + * memory_inst->cur_page_count); #endif - os_munmap((uint8*)memory_inst->memory_data.ptr, + os_munmap((uint8 *)memory_inst->memory_data.ptr, 8 * (uint64)BH_GB); #endif } @@ -353,7 +344,7 @@ memories_deinstantiate(AOTModuleInstance *module_inst) wasm_runtime_free(module_inst->memories.ptr); } -static AOTMemoryInstance* +static AOTMemoryInstance * memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, AOTMemoryInstance *memory_inst, AOTMemory *memory, uint32 heap_size, char *error_buf, uint32 error_buf_size) @@ -364,7 +355,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, uint32 max_page_count = memory->mem_max_page_count; uint32 inc_page_count, aux_heap_base, global_idx; uint32 bytes_of_last_page, bytes_to_page_end; - uint32 heap_offset = num_bytes_per_page *init_page_count; + uint32 heap_offset = num_bytes_per_page * init_page_count; uint64 total_size; uint8 *p = NULL, *global_addr; #ifdef OS_ENABLE_HW_BOUND_CHECK @@ -385,11 +376,10 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, return the memory instance directly */ if (node) { uint32 ref_count; - ref_count = shared_memory_inc_reference( - (WASMModuleCommon *)module); + ref_count = shared_memory_inc_reference((WASMModuleCommon *)module); bh_assert(ref_count > 0); shared_memory_instance = - (AOTMemoryInstance *)shared_memory_get_memory_inst(node); + (AOTMemoryInstance *)shared_memory_get_memory_inst(node); bh_assert(shared_memory_instance); (void)ref_count; @@ -398,8 +388,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, } #endif - if (heap_size > 0 - && module->malloc_func_index != (uint32)-1 + if (heap_size > 0 && module->malloc_func_index != (uint32)-1 && module->free_func_index != (uint32)-1) { /* Disable app heap, use malloc/free function exported by wasm app to allocate/free memory instead */ @@ -420,16 +409,16 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, } else if (heap_size > 0) { if (module->aux_heap_base_global_index != (uint32)-1 - && module->aux_heap_base < num_bytes_per_page - * init_page_count) { + && module->aux_heap_base < num_bytes_per_page * init_page_count) { /* Insert app heap before __heap_base */ aux_heap_base = module->aux_heap_base; bytes_of_last_page = aux_heap_base % num_bytes_per_page; if (bytes_of_last_page == 0) bytes_of_last_page = num_bytes_per_page; bytes_to_page_end = num_bytes_per_page - bytes_of_last_page; - inc_page_count = (heap_size - bytes_to_page_end - + num_bytes_per_page - 1) / num_bytes_per_page; + inc_page_count = + (heap_size - bytes_to_page_end + num_bytes_per_page - 1) + / num_bytes_per_page; heap_offset = aux_heap_base; aux_heap_base += heap_size; @@ -445,15 +434,15 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, /* Adjust __heap_base global value */ global_idx = module->aux_heap_base_global_index - module->import_global_count; - global_addr = (uint8*)module_inst->global_data.ptr + - module->globals[global_idx].data_offset; + global_addr = (uint8 *)module_inst->global_data.ptr + + module->globals[global_idx].data_offset; *(uint32 *)global_addr = aux_heap_base; LOG_VERBOSE("Reset __heap_base global to %u", aux_heap_base); } else { /* Insert app heap before new page */ - inc_page_count = (heap_size + num_bytes_per_page - 1) - / num_bytes_per_page; + inc_page_count = + (heap_size + num_bytes_per_page - 1) / num_bytes_per_page; heap_offset = num_bytes_per_page * init_page_count; heap_size = num_bytes_per_page * inc_page_count; if (heap_size > 0) @@ -498,8 +487,8 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, * so the range of ea is 0 to 8G */ if (total_size >= UINT32_MAX - || !(p = mapped_mem = os_mmap(NULL, map_size, - MMAP_PROT_NONE, MMAP_MAP_NONE))) { + || !(p = mapped_mem = + os_mmap(NULL, map_size, MMAP_PROT_NONE, MMAP_MAP_NONE))) { set_error_buf(error_buf, error_buf_size, "mmap memory failed"); return NULL; } @@ -539,46 +528,46 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, if (heap_size > 0) { uint32 heap_struct_size = mem_allocator_get_heap_struct_size(); - if (!(heap_handle = runtime_malloc((uint64)heap_struct_size, - error_buf, error_buf_size))) { + if (!(heap_handle = runtime_malloc((uint64)heap_struct_size, error_buf, + error_buf_size))) { goto fail1; } memory_inst->heap_handle.ptr = heap_handle; - if (!mem_allocator_create_with_struct_and_pool - (heap_handle, heap_struct_size, - memory_inst->heap_data.ptr, heap_size)) { - set_error_buf(error_buf, error_buf_size, - "init app heap failed"); + if (!mem_allocator_create_with_struct_and_pool( + heap_handle, heap_struct_size, memory_inst->heap_data.ptr, + heap_size)) { + set_error_buf(error_buf, error_buf_size, "init app heap failed"); goto fail2; } } if (total_size > 0) { - if (sizeof(uintptr_t) == sizeof(uint64)) { - memory_inst->mem_bound_check_1byte.u64 = total_size - 1; - memory_inst->mem_bound_check_2bytes.u64 = total_size - 2; - memory_inst->mem_bound_check_4bytes.u64 = total_size - 4; - memory_inst->mem_bound_check_8bytes.u64 = total_size - 8; - memory_inst->mem_bound_check_16bytes.u64 = total_size - 16; - } - else { - memory_inst->mem_bound_check_1byte.u32[0] = (uint32)total_size - 1; - memory_inst->mem_bound_check_2bytes.u32[0] = (uint32)total_size - 2; - memory_inst->mem_bound_check_4bytes.u32[0] = (uint32)total_size - 4; - memory_inst->mem_bound_check_8bytes.u32[0] = (uint32)total_size - 8; - memory_inst->mem_bound_check_16bytes.u32[0] = (uint32)total_size - 16; - } + if (sizeof(uintptr_t) == sizeof(uint64)) { + memory_inst->mem_bound_check_1byte.u64 = total_size - 1; + memory_inst->mem_bound_check_2bytes.u64 = total_size - 2; + memory_inst->mem_bound_check_4bytes.u64 = total_size - 4; + memory_inst->mem_bound_check_8bytes.u64 = total_size - 8; + memory_inst->mem_bound_check_16bytes.u64 = total_size - 16; + } + else { + memory_inst->mem_bound_check_1byte.u32[0] = (uint32)total_size - 1; + memory_inst->mem_bound_check_2bytes.u32[0] = (uint32)total_size - 2; + memory_inst->mem_bound_check_4bytes.u32[0] = (uint32)total_size - 4; + memory_inst->mem_bound_check_8bytes.u32[0] = (uint32)total_size - 8; + memory_inst->mem_bound_check_16bytes.u32[0] = + (uint32)total_size - 16; + } } #if WASM_ENABLE_SHARED_MEMORY != 0 if (is_shared_memory) { memory_inst->is_shared = true; - if (!shared_memory_set_memory_inst((WASMModuleCommon *)module, - (WASMMemoryInstanceCommon *)memory_inst)) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + if (!shared_memory_set_memory_inst( + (WASMModuleCommon *)module, + (WASMMemoryInstanceCommon *)memory_inst)) { + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); goto fail3; } } @@ -609,7 +598,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, return NULL; } -static AOTMemoryInstance* +static AOTMemoryInstance * aot_get_default_memory(AOTModuleInstance *module_inst) { if (module_inst->memories.ptr) @@ -631,16 +620,15 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module, module_inst->memory_count = memory_count; total_size = sizeof(AOTPointer) * (uint64)memory_count; if (!(module_inst->memories.ptr = - runtime_malloc(total_size, error_buf, error_buf_size))) { + runtime_malloc(total_size, error_buf, error_buf_size))) { return false; } memories = module_inst->global_table_data.memory_instances; for (i = 0; i < memory_count; i++, memories++) { - memory_inst = - memory_instantiate(module_inst, module, - memories, &module->memories[i], - heap_size, error_buf, error_buf_size); + memory_inst = memory_instantiate(module_inst, module, memories, + &module->memories[i], heap_size, + error_buf, error_buf_size); if (!memory_inst) { return false; } @@ -658,17 +646,16 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module, continue; #endif - bh_assert(data_seg->offset.init_expr_type == - INIT_EXPR_TYPE_I32_CONST - || data_seg->offset.init_expr_type == - INIT_EXPR_TYPE_GET_GLOBAL); + bh_assert(data_seg->offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST + || data_seg->offset.init_expr_type + == INIT_EXPR_TYPE_GET_GLOBAL); /* Resolve memory data base offset */ if (data_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { global_index = data_seg->offset.u.global_index; - if (!check_global_init_expr(module, global_index, - error_buf, error_buf_size)) { + if (!check_global_init_expr(module, global_index, error_buf, + error_buf_size)) { return false; } @@ -678,10 +665,10 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module, else global_data_offset = module->globals[global_index - module->import_global_count] - .data_offset; + .data_offset; - base_offset = *(uint32*) - ((uint8*)module_inst->global_data.ptr + global_data_offset); + base_offset = *(uint32 *)((uint8 *)module_inst->global_data.ptr + + global_data_offset); } else { base_offset = (uint32)data_seg->offset.u.i32; @@ -722,7 +709,7 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module, } if (memory_inst->memory_data.ptr) { - bh_memcpy_s((uint8*)memory_inst->memory_data.ptr + base_offset, + bh_memcpy_s((uint8 *)memory_inst->memory_data.ptr + base_offset, memory_inst->memory_data_size - base_offset, data_seg->bytes, length); } @@ -737,22 +724,22 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module, { uint32 i; void **func_ptrs; - uint64 total_size = - ((uint64)module->import_func_count + module->func_count) * sizeof(void*); + uint64 total_size = ((uint64)module->import_func_count + module->func_count) + * sizeof(void *); if (module->import_func_count + module->func_count == 0) return true; /* Allocate memory */ - if (!(module_inst->func_ptrs.ptr = runtime_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module_inst->func_ptrs.ptr = + runtime_malloc(total_size, error_buf, error_buf_size))) { return false; } /* Set import function pointers */ - func_ptrs = (void**)module_inst->func_ptrs.ptr; + func_ptrs = (void **)module_inst->func_ptrs.ptr; for (i = 0; i < module->import_func_count; i++, func_ptrs++) { - *func_ptrs = (void*)module->import_funcs[i].func_ptr_linked; + *func_ptrs = (void *)module->import_funcs[i].func_ptr_linked; if (!*func_ptrs) { const char *module_name = module->import_funcs[i].module_name; const char *field_name = module->import_funcs[i].func_name; @@ -762,8 +749,8 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module, } /* Set defined function pointers */ - bh_memcpy_s(func_ptrs, sizeof(void*) * module->func_count, - module->func_ptrs, sizeof(void*) * module->func_count); + bh_memcpy_s(func_ptrs, sizeof(void *) * module->func_count, + module->func_ptrs, sizeof(void *) * module->func_count); return true; } @@ -773,20 +760,20 @@ init_func_type_indexes(AOTModuleInstance *module_inst, AOTModule *module, { uint32 i; uint32 *func_type_index; - uint64 total_size = - ((uint64)module->import_func_count + module->func_count) * sizeof(uint32); + uint64 total_size = ((uint64)module->import_func_count + module->func_count) + * sizeof(uint32); if (module->import_func_count + module->func_count == 0) return true; /* Allocate memory */ if (!(module_inst->func_type_indexes.ptr = - runtime_malloc(total_size, error_buf, error_buf_size))) { + runtime_malloc(total_size, error_buf, error_buf_size))) { return false; } /* Set import function type indexes */ - func_type_index = (uint32*)module_inst->func_type_indexes.ptr; + func_type_index = (uint32 *)module_inst->func_type_indexes.ptr; for (i = 0; i < module->import_func_count; i++, func_type_index++) *func_type_index = module->import_funcs[i].func_type_index; @@ -809,7 +796,7 @@ create_export_funcs(AOTModuleInstance *module_inst, AOTModule *module, size = sizeof(AOTFunctionInstance) * (uint64)module_inst->export_func_count; if (!(module_inst->export_funcs.ptr = export_func = - runtime_malloc(size, error_buf, error_buf_size))) { + runtime_malloc(size, error_buf, error_buf_size))) { return false; } @@ -824,13 +811,13 @@ create_export_funcs(AOTModuleInstance *module_inst, AOTModule *module, } else { export_func->is_import_func = false; - func_index = export_func->func_index - - module->import_func_count; + func_index = + export_func->func_index - module->import_func_count; ftype_index = module->func_type_indexes[func_index]; export_func->u.func.func_type = - module->func_types[ftype_index]; + module->func_types[ftype_index]; export_func->u.func.func_ptr = - module->func_ptrs[func_index]; + module->func_ptrs[func_index]; } export_func++; } @@ -866,8 +853,7 @@ create_exports(AOTModuleInstance *module_inst, AOTModule *module, } } - return create_export_funcs(module_inst, module, - error_buf, error_buf_size); + return create_export_funcs(module_inst, module, error_buf, error_buf_size); } static bool @@ -898,22 +884,27 @@ execute_post_inst_function(AOTModuleInstance *module_inst) /* Not found */ return true; - return aot_create_exec_env_and_call_function(module_inst, post_inst_func, 0, NULL); + return aot_create_exec_env_and_call_function(module_inst, post_inst_func, 0, + NULL); } static bool execute_start_function(AOTModuleInstance *module_inst) { - AOTModule *module = (AOTModule*)module_inst->aot_module.ptr; + AOTModule *module = (AOTModule *)module_inst->aot_module.ptr; WASMExecEnv *exec_env; - typedef void (*F)(WASMExecEnv*); - union { F f; void *v; } u; + typedef void (*F)(WASMExecEnv *); + union { + F f; + void *v; + } u; if (!module->start_function) return true; - if (!(exec_env = wasm_exec_env_create((WASMModuleInstanceCommon*)module_inst, - module_inst->default_wasm_stack_size))) { + if (!(exec_env = + wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst, + module_inst->default_wasm_stack_size))) { aot_set_exception(module_inst, "allocate memory failed"); return false; } @@ -942,10 +933,9 @@ execute_memory_init_function(AOTModuleInstance *module_inst) } #endif -AOTModuleInstance* -aot_instantiate(AOTModule *module, bool is_sub_inst, - uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size) +AOTModuleInstance * +aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size, + uint32 heap_size, char *error_buf, uint32 error_buf_size) { AOTModuleInstance *module_inst; const uint32 module_inst_struct_size = @@ -970,8 +960,8 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, for (i = 0; i != module->import_table_count; ++i) { table_size += offsetof(AOTTableInstance, data); table_size += - (uint64)sizeof(uint32) - * (uint64)aot_get_imp_tbl_data_slots(module->import_tables + i); + (uint64)sizeof(uint32) + * (uint64)aot_get_imp_tbl_data_slots(module->import_tables + i); } for (i = 0; i != module->table_count; ++i) { @@ -982,8 +972,8 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, total_size += table_size; /* Allocate module instance, global data, table data and heap data */ - if (!(module_inst = runtime_malloc(total_size, - error_buf, error_buf_size))) { + if (!(module_inst = + runtime_malloc(total_size, error_buf, error_buf_size))) { return NULL; } @@ -991,8 +981,8 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, module_inst->aot_module.ptr = module; /* Initialize global info */ - p = (uint8*)module_inst + module_inst_struct_size + - module_inst_mem_inst_size; + p = (uint8 *)module_inst + module_inst_struct_size + + module_inst_mem_inst_size; module_inst->global_data.ptr = p; module_inst->global_data_size = module->global_data_size; if (!global_instantiate(module_inst, module, error_buf, error_buf_size)) @@ -1001,16 +991,15 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, /* Initialize table info */ p += module->global_data_size; module_inst->tables.ptr = p; - module_inst->table_count = - module->table_count + module->import_table_count; + module_inst->table_count = module->table_count + module->import_table_count; /* Set all elements to -1 to mark them as uninitialized elements */ memset(module_inst->tables.ptr, 0xff, (uint32)table_size); if (!table_instantiate(module_inst, module, error_buf, error_buf_size)) goto fail; /* Initialize memory space */ - if (!memories_instantiate(module_inst, module, heap_size, - error_buf, error_buf_size)) + if (!memories_instantiate(module_inst, module, heap_size, error_buf, + error_buf_size)) goto fail; /* Initialize function pointers */ @@ -1026,19 +1015,14 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, #if WASM_ENABLE_LIBC_WASI != 0 if (!is_sub_inst) { - if (!wasm_runtime_init_wasi((WASMModuleInstanceCommon*)module_inst, - module->wasi_args.dir_list, - module->wasi_args.dir_count, - module->wasi_args.map_dir_list, - module->wasi_args.map_dir_count, - module->wasi_args.env, - module->wasi_args.env_count, - module->wasi_args.argv, - module->wasi_args.argc, - module->wasi_args.stdio[0], - module->wasi_args.stdio[1], - module->wasi_args.stdio[2], - error_buf, error_buf_size)) + if (!wasm_runtime_init_wasi( + (WASMModuleInstanceCommon *)module_inst, + module->wasi_args.dir_list, module->wasi_args.dir_count, + module->wasi_args.map_dir_list, module->wasi_args.map_dir_count, + module->wasi_args.env, module->wasi_args.env_count, + module->wasi_args.argv, module->wasi_args.argc, + module->wasi_args.stdio[0], module->wasi_args.stdio[1], + module->wasi_args.stdio[2], error_buf, error_buf_size)) goto fail; } #endif @@ -1047,16 +1031,23 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, if (stack_size == 0) stack_size = DEFAULT_WASM_STACK_SIZE; #if WASM_ENABLE_SPEC_TEST != 0 - if (stack_size < 48 *1024) + if (stack_size < 48 * 1024) stack_size = 48 * 1024; #endif module_inst->default_wasm_stack_size = stack_size; #if WASM_ENABLE_PERF_PROFILING != 0 - total_size = (uint64)sizeof(AOTFuncPerfProfInfo) * - (module->import_func_count + module->func_count); + total_size = (uint64)sizeof(AOTFuncPerfProfInfo) + * (module->import_func_count + module->func_count); if (!(module_inst->func_perf_profilings.ptr = - runtime_malloc(total_size, error_buf, error_buf_size))) { + runtime_malloc(total_size, error_buf, error_buf_size))) { + goto fail; + } +#endif + +#if WASM_ENABLE_DUMP_CALL_STACK != 0 + if (!(module_inst->frames.ptr = + runtime_malloc(sizeof(Vector), error_buf, error_buf_size))) { goto fail; } #endif @@ -1064,8 +1055,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, /* Execute __post_instantiate function and start function*/ if (!execute_post_inst_function(module_inst) || !execute_start_function(module_inst)) { - set_error_buf(error_buf, error_buf_size, - module_inst->cur_exception); + set_error_buf(error_buf, error_buf_size, module_inst->cur_exception); goto fail; } @@ -1089,8 +1079,8 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, #endif #if WASM_ENABLE_MEMORY_TRACING != 0 - wasm_runtime_dump_module_inst_mem_consumption - ((WASMModuleInstanceCommon *)module_inst); + wasm_runtime_dump_module_inst_mem_consumption( + (WASMModuleInstanceCommon *)module_inst); #endif return module_inst; @@ -1122,7 +1112,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) which may allocated from global heap. */ /* Only destroy wasi ctx in the main module instance */ if (!is_sub_inst) - wasm_runtime_destroy_wasi((WASMModuleInstanceCommon*)module_inst); + wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst); #endif #if WASM_ENABLE_PERF_PROFILING != 0 @@ -1130,6 +1120,14 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) wasm_runtime_free(module_inst->func_perf_profilings.ptr); #endif +#if WASM_ENABLE_DUMP_CALL_STACK != 0 + if (module_inst->frames.ptr) { + bh_vector_destroy(module_inst->frames.ptr); + wasm_runtime_free(module_inst->frames.ptr); + module_inst->frames.ptr = NULL; + } +#endif + if (module_inst->memories.ptr) memories_deinstantiate(module_inst); @@ -1143,19 +1141,19 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) wasm_runtime_free(module_inst->func_type_indexes.ptr); if (module_inst->exec_env_singleton.ptr) - wasm_exec_env_destroy((WASMExecEnv *) - module_inst->exec_env_singleton.ptr); + wasm_exec_env_destroy( + (WASMExecEnv *)module_inst->exec_env_singleton.ptr); wasm_runtime_free(module_inst); } -AOTFunctionInstance* -aot_lookup_function(const AOTModuleInstance *module_inst, - const char *name, const char *signature) +AOTFunctionInstance * +aot_lookup_function(const AOTModuleInstance *module_inst, const char *name, + const char *signature) { uint32 i; - AOTFunctionInstance *export_funcs = (AOTFunctionInstance *) - module_inst->export_funcs.ptr; + AOTFunctionInstance *export_funcs = + (AOTFunctionInstance *)module_inst->export_funcs.ptr; for (i = 0; i < module_inst->export_func_count; i++) if (!strcmp(export_funcs[i].func_name, name)) @@ -1182,17 +1180,16 @@ aot_signal_handler(void *sig_addr) uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT; /* Check whether current thread is running aot function */ - if (aot_exec_env - && aot_exec_env->handle == os_self_thread() + if (aot_exec_env && aot_exec_env->handle == os_self_thread() && (jmpbuf_node = aot_exec_env->jmpbuf_stack_top)) { /* Get mapped mem info of current instance */ module_inst = (AOTModuleInstance *)aot_exec_env->module_inst; /* Get the default memory instance */ memory_inst = aot_get_default_memory(module_inst); if (memory_inst) { - mapped_mem_start_addr = (uint8*)memory_inst->memory_data.ptr; - mapped_mem_end_addr = (uint8*)memory_inst->memory_data.ptr - + 8 * (uint64)BH_GB; + mapped_mem_start_addr = (uint8 *)memory_inst->memory_data.ptr; + mapped_mem_end_addr = + (uint8 *)memory_inst->memory_data.ptr + 8 * (uint64)BH_GB; } /* Get stack info of current thread */ @@ -1200,16 +1197,17 @@ aot_signal_handler(void *sig_addr) stack_min_addr = os_thread_get_stack_boundary(); if (memory_inst - && (mapped_mem_start_addr <= (uint8*)sig_addr - && (uint8*)sig_addr < mapped_mem_end_addr)) { + && (mapped_mem_start_addr <= (uint8 *)sig_addr + && (uint8 *)sig_addr < mapped_mem_end_addr)) { /* The address which causes segmentation fault is inside aot instance's guard regions */ - aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS); + aot_set_exception_with_id(module_inst, + EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS); os_longjmp(jmpbuf_node->jmpbuf, 1); } - else if (stack_min_addr - page_size <= (uint8*)sig_addr - && (uint8*)sig_addr < stack_min_addr - + page_size * guard_page_count) { + else if (stack_min_addr - page_size <= (uint8 *)sig_addr + && (uint8 *)sig_addr + < stack_min_addr + page_size * guard_page_count) { /* The address which causes segmentation fault is inside native thread's guard page */ aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); @@ -1217,12 +1215,12 @@ aot_signal_handler(void *sig_addr) } } } -#else /* else of BH_PLATFORM_WINDOWS */ +#else /* else of BH_PLATFORM_WINDOWS */ static LONG aot_exception_handler(EXCEPTION_POINTERS *exce_info) { PEXCEPTION_RECORD ExceptionRecord = exce_info->ExceptionRecord; - uint8 *sig_addr = (uint8*)ExceptionRecord->ExceptionInformation[1]; + uint8 *sig_addr = (uint8 *)ExceptionRecord->ExceptionInformation[1]; AOTModuleInstance *module_inst; AOTMemoryInstance *memory_inst; WASMJmpBuf *jmpbuf_node; @@ -1230,19 +1228,18 @@ aot_exception_handler(EXCEPTION_POINTERS *exce_info) uint8 *mapped_mem_end_addr = NULL; uint32 page_size = os_getpagesize(); - if (aot_exec_env - && aot_exec_env->handle == os_self_thread() + if (aot_exec_env && aot_exec_env->handle == os_self_thread() && (jmpbuf_node = aot_exec_env->jmpbuf_stack_top)) { - module_inst = (AOTModuleInstance*)aot_exec_env->module_inst; + module_inst = (AOTModuleInstance *)aot_exec_env->module_inst; if (ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { /* Get the default memory instance */ memory_inst = aot_get_default_memory(module_inst); if (memory_inst) { - mapped_mem_start_addr = (uint8*)memory_inst->memory_data.ptr; - mapped_mem_end_addr = (uint8*)memory_inst->memory_data.ptr - + 8 * (uint64)BH_GB; - if (mapped_mem_start_addr <= (uint8*)sig_addr - && (uint8*)sig_addr < mapped_mem_end_addr) { + mapped_mem_start_addr = (uint8 *)memory_inst->memory_data.ptr; + mapped_mem_end_addr = + (uint8 *)memory_inst->memory_data.ptr + 8 * (uint64)BH_GB; + if (mapped_mem_start_addr <= (uint8 *)sig_addr + && (uint8 *)sig_addr < mapped_mem_end_addr) { /* The address which causes segmentation fault is inside aot instance's guard regions. Set exception and let the aot func continue to run, when @@ -1297,11 +1294,11 @@ aot_signal_destroy() static bool invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, - const WASMType *func_type, const char *signature, - void *attachment, - uint32 *argv, uint32 argc, uint32 *argv_ret) + const WASMType *func_type, + const char *signature, void *attachment, + uint32 *argv, uint32 argc, uint32 *argv_ret) { - AOTModuleInstance *module_inst = (AOTModuleInstance*)exec_env->module_inst; + AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; WASMExecEnv **p_aot_exec_env = &aot_exec_env; WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop; uint32 page_size = os_getpagesize(); @@ -1309,7 +1306,7 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, uint16 param_count = func_type->param_count; uint16 result_count = func_type->result_count; const uint8 *types = func_type->types; -#if BH_PLATFORM_WINDOWS +#ifdef BH_PLATFORM_WINDOWS const char *exce; int result; #endif @@ -1318,8 +1315,8 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, /* Check native stack overflow firstly to ensure we have enough native stack to run the following codes before actually calling the aot function in invokeNative function. */ - if ((uint8*)&module_inst < exec_env->native_stack_boundary - + page_size * (guard_page_count + 1)) { + if ((uint8 *)&module_inst < exec_env->native_stack_boundary + + page_size * (guard_page_count + 1)) { aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); return false; } @@ -1341,27 +1338,28 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, /* Quick call with func_ptr if the function signature is simple */ if (!signature && param_count == 1 && types[0] == VALUE_TYPE_I32) { if (result_count == 0) { - void (*NativeFunc)(WASMExecEnv*, uint32) = - (void (*)(WASMExecEnv*, uint32))func_ptr; + void (*NativeFunc)(WASMExecEnv *, uint32) = + (void (*)(WASMExecEnv *, uint32))func_ptr; NativeFunc(exec_env, argv[0]); ret = aot_get_exception(module_inst) ? false : true; } - else if (result_count == 1 && types[param_count] == VALUE_TYPE_I32) { - uint32 (*NativeFunc)(WASMExecEnv*, uint32) = - (uint32 (*)(WASMExecEnv*, uint32))func_ptr; + else if (result_count == 1 + && types[param_count] == VALUE_TYPE_I32) { + uint32 (*NativeFunc)(WASMExecEnv *, uint32) = + (uint32(*)(WASMExecEnv *, uint32))func_ptr; argv_ret[0] = NativeFunc(exec_env, argv[0]); ret = aot_get_exception(module_inst) ? false : true; } else { ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type, - signature, attachment, - argv, argc, argv_ret); + signature, attachment, argv, + argc, argv_ret); } } else { ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type, - signature, attachment, - argv, argc, argv_ret); + signature, attachment, argv, argc, + argv_ret); } #ifdef BH_PLATFORM_WINDOWS if ((exce = aot_get_exception(module_inst)) @@ -1397,11 +1395,10 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, #endif /* end of OS_ENABLE_HW_BOUND_CHECK */ bool -aot_call_function(WASMExecEnv *exec_env, - AOTFunctionInstance *function, +aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, unsigned argc, uint32 argv[]) { - AOTModuleInstance *module_inst = (AOTModuleInstance*)exec_env->module_inst; + AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; AOTFuncType *func_type = function->u.func.func_type; uint32 result_count = func_type->result_count; uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0; @@ -1419,9 +1416,11 @@ aot_call_function(WASMExecEnv *exec_env, uint64 size; /* Allocate memory all arguments */ - size = sizeof(uint32) * (uint64)argc /* original arguments */ - + sizeof(void*) * (uint64)ext_ret_count /* extra result values' addr */ - + sizeof(uint32) * (uint64)ext_ret_cell; /* extra result values */ + size = + sizeof(uint32) * (uint64)argc /* original arguments */ + + sizeof(void *) + * (uint64)ext_ret_count /* extra result values' addr */ + + sizeof(uint32) * (uint64)ext_ret_cell; /* extra result values */ if (size > sizeof(argv1_buf) && !(argv1 = runtime_malloc(size, module_inst->cur_exception, sizeof(module_inst->cur_exception)))) { @@ -1433,11 +1432,12 @@ aot_call_function(WASMExecEnv *exec_env, bh_memcpy_s(argv1, (uint32)size, argv, sizeof(uint32) * argc); /* Get the extra result value's address */ - ext_rets = argv1 + argc + sizeof(void*)/sizeof(uint32) * ext_ret_count; + ext_rets = + argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count; /* Append each extra result value's address to original arguments */ for (i = 0; i < ext_ret_count; i++) { - *(uintptr_t*)(argv1 + argc + sizeof(void*) / sizeof(uint32) * i) = + *(uintptr_t *)(argv1 + argc + sizeof(void *) / sizeof(uint32) * i) = (uintptr_t)(ext_rets + cell_num); cell_num += wasm_value_type_cell_num(ext_ret_types[i]); } @@ -1497,9 +1497,10 @@ aot_call_function(WASMExecEnv *exec_env, bh_assert(0); break; } - ext_rets = argv1 + argc + sizeof(void*)/sizeof(uint32) * ext_ret_count; - bh_memcpy_s(argv_ret, sizeof(uint32) * cell_num, - ext_rets, sizeof(uint32) * cell_num); + ext_rets = + argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count; + bh_memcpy_s(argv_ret, sizeof(uint32) * cell_num, ext_rets, + sizeof(uint32) * cell_num); if (argv1 != argv1_buf) wasm_runtime_free(argv1); @@ -1534,8 +1535,8 @@ aot_call_function(WASMExecEnv *exec_env, bool aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst, - AOTFunctionInstance *func, - unsigned argc, uint32 argv[]) + AOTFunctionInstance *func, unsigned argc, + uint32 argv[]) { WASMExecEnv *exec_env = NULL, *existing_exec_env = NULL; bool ret; @@ -1543,14 +1544,14 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst, #if defined(OS_ENABLE_HW_BOUND_CHECK) existing_exec_env = exec_env = aot_exec_env; #elif WASM_ENABLE_THREAD_MGR != 0 - existing_exec_env = exec_env = wasm_clusters_search_exec_env( - (WASMModuleInstanceCommon*)module_inst); + existing_exec_env = exec_env = + wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst); #endif if (!existing_exec_env) { if (!(exec_env = - wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst, - module_inst->default_wasm_stack_size))) { + wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst, + module_inst->default_wasm_stack_size))) { aot_set_exception(module_inst, "allocate memory failed"); return false; } @@ -1574,20 +1575,17 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst, } void -aot_set_exception(AOTModuleInstance *module_inst, - const char *exception) +aot_set_exception(AOTModuleInstance *module_inst, const char *exception) { if (exception) - snprintf(module_inst->cur_exception, - sizeof(module_inst->cur_exception), + snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), "Exception: %s", exception); else module_inst->cur_exception[0] = '\0'; } void -aot_set_exception_with_id(AOTModuleInstance *module_inst, - uint32 id) +aot_set_exception_with_id(AOTModuleInstance *module_inst, uint32 id) { switch (id) { case EXCE_UNREACHABLE: @@ -1621,7 +1619,8 @@ aot_set_exception_with_id(AOTModuleInstance *module_inst, aot_set_exception(module_inst, "uninitialized element"); break; case EXCE_CALL_UNLINKED_IMPORT_FUNC: - aot_set_exception(module_inst, "failed to call unlinked import function"); + aot_set_exception(module_inst, + "failed to call unlinked import function"); break; case EXCE_NATIVE_STACK_OVERFLOW: aot_set_exception(module_inst, "native stack overflow"); @@ -1643,7 +1642,7 @@ aot_set_exception_with_id(AOTModuleInstance *module_inst, } } -const char* +const char * aot_get_exception(AOTModuleInstance *module_inst) { if (module_inst->cur_exception[0] == '\0') @@ -1661,8 +1660,8 @@ aot_clear_exception(AOTModuleInstance *module_inst) static bool execute_malloc_function(AOTModuleInstance *module_inst, AOTFunctionInstance *malloc_func, - AOTFunctionInstance *retain_func, - uint32 size, uint32 *p_result) + AOTFunctionInstance *retain_func, uint32 size, + uint32 *p_result) { uint32 argv[2], argc; bool ret; @@ -1687,12 +1686,12 @@ execute_malloc_function(AOTModuleInstance *module_inst, else #endif { - ret = aot_create_exec_env_and_call_function - (module_inst, malloc_func, argc, argv); + ret = aot_create_exec_env_and_call_function(module_inst, malloc_func, + argc, argv); if (retain_func && ret) { - ret = aot_create_exec_env_and_call_function - (module_inst, retain_func, 1, argv); + ret = aot_create_exec_env_and_call_function(module_inst, + retain_func, 1, argv); } } @@ -1703,8 +1702,7 @@ execute_malloc_function(AOTModuleInstance *module_inst, static bool execute_free_function(AOTModuleInstance *module_inst, - AOTFunctionInstance *free_func, - uint32 offset) + AOTFunctionInstance *free_func, uint32 offset) { uint32 argv[2]; @@ -1718,8 +1716,8 @@ execute_free_function(AOTModuleInstance *module_inst, else #endif { - return aot_create_exec_env_and_call_function - (module_inst, free_func, 1, argv); + return aot_create_exec_env_and_call_function(module_inst, free_func, 1, + argv); } } @@ -1749,8 +1747,7 @@ aot_module_malloc(AOTModuleInstance *module_inst, uint32 size, if (module->retain_func_index != (uint32)-1) { malloc_func_name = "__new"; malloc_func_sig = "(ii)i"; - retain_func = - aot_lookup_function(module_inst, "__retain", "(i)i"); + retain_func = aot_lookup_function(module_inst, "__retain", "(i)i"); if (!retain_func) retain_func = aot_lookup_function(module_inst, "__pin", "(i)i"); bh_assert(retain_func); @@ -1760,17 +1757,14 @@ aot_module_malloc(AOTModuleInstance *module_inst, uint32 size, malloc_func_sig = "(i)i"; } malloc_func = - aot_lookup_function(module_inst, - malloc_func_name, malloc_func_sig); + aot_lookup_function(module_inst, malloc_func_name, malloc_func_sig); bh_assert(malloc_func); if (!execute_malloc_function(module_inst, malloc_func, retain_func, size, &offset)) { return 0; } - addr = offset - ? (uint8*)memory_inst->memory_data.ptr + offset - : NULL; + addr = offset ? (uint8 *)memory_inst->memory_data.ptr + offset : NULL; } if (!addr) { @@ -1789,12 +1783,12 @@ aot_module_malloc(AOTModuleInstance *module_inst, uint32 size, } if (p_native_addr) *p_native_addr = addr; - return (uint32)(addr - (uint8*)memory_inst->memory_data.ptr); + return (uint32)(addr - (uint8 *)memory_inst->memory_data.ptr); } uint32 -aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, - uint32 size, void **p_native_addr) +aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, uint32 size, + void **p_native_addr) { AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst); uint8 *addr = NULL; @@ -1805,10 +1799,9 @@ aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, } if (memory_inst->heap_handle.ptr) { - addr = - mem_allocator_realloc(memory_inst->heap_handle.ptr, - (uint8*)memory_inst->memory_data.ptr + ptr, - size); + addr = mem_allocator_realloc( + memory_inst->heap_handle.ptr, + (uint8 *)memory_inst->memory_data.ptr + ptr, size); } /* Only support realloc in WAMR's app heap */ @@ -1826,7 +1819,7 @@ aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, if (p_native_addr) *p_native_addr = addr; - return (uint32)(addr - (uint8*)memory_inst->memory_data.ptr); + return (uint32)(addr - (uint8 *)memory_inst->memory_data.ptr); } void @@ -1842,7 +1835,7 @@ aot_module_free(AOTModuleInstance *module_inst, uint32 ptr) if (ptr) { uint8 *addr = (uint8 *)memory_inst->memory_data.ptr + ptr; if (memory_inst->heap_handle.ptr - &&(uint8 *)memory_inst->heap_data.ptr < addr + && (uint8 *)memory_inst->heap_data.ptr < addr && addr < (uint8 *)memory_inst->heap_data_end.ptr) { mem_allocator_free(memory_inst->heap_handle.ptr, addr); } @@ -1871,12 +1864,12 @@ aot_module_free(AOTModuleInstance *module_inst, uint32 ptr) } uint32 -aot_module_dup_data(AOTModuleInstance *module_inst, - const char *src, uint32 size) +aot_module_dup_data(AOTModuleInstance *module_inst, const char *src, + uint32 size) { char *buffer; - uint32 buffer_offset = aot_module_malloc(module_inst, size, - (void**)&buffer); + uint32 buffer_offset = + aot_module_malloc(module_inst, size, (void **)&buffer); if (buffer_offset != 0) { buffer = aot_addr_app_to_native(module_inst, buffer_offset); @@ -1886,8 +1879,8 @@ aot_module_dup_data(AOTModuleInstance *module_inst, } bool -aot_validate_app_addr(AOTModuleInstance *module_inst, - uint32 app_offset, uint32 size) +aot_validate_app_addr(AOTModuleInstance *module_inst, uint32 app_offset, + uint32 size) { AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst); @@ -1896,7 +1889,7 @@ aot_validate_app_addr(AOTModuleInstance *module_inst, } /* integer overflow check */ - if(app_offset + size < app_offset) { + if (app_offset > UINT32_MAX - size) { goto fail; } @@ -1909,8 +1902,8 @@ aot_validate_app_addr(AOTModuleInstance *module_inst, } bool -aot_validate_native_addr(AOTModuleInstance *module_inst, - void *native_ptr, uint32 size) +aot_validate_native_addr(AOTModuleInstance *module_inst, void *native_ptr, + uint32 size) { AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst); uint8 *addr = (uint8 *)native_ptr; @@ -1920,7 +1913,7 @@ aot_validate_native_addr(AOTModuleInstance *module_inst, } /* integer overflow check */ - if (addr + size < addr) { + if ((uintptr_t)addr > UINTPTR_MAX - size) { goto fail; } @@ -1967,10 +1960,8 @@ aot_addr_native_to_app(AOTModuleInstance *module_inst, void *native_ptr) } bool -aot_get_app_addr_range(AOTModuleInstance *module_inst, - uint32 app_offset, - uint32 *p_app_start_offset, - uint32 *p_app_end_offset) +aot_get_app_addr_range(AOTModuleInstance *module_inst, uint32 app_offset, + uint32 *p_app_start_offset, uint32 *p_app_end_offset) { AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst); uint32 memory_data_size; @@ -1992,8 +1983,7 @@ aot_get_app_addr_range(AOTModuleInstance *module_inst, } bool -aot_get_native_addr_range(AOTModuleInstance *module_inst, - uint8 *native_ptr, +aot_get_native_addr_range(AOTModuleInstance *module_inst, uint8 *native_ptr, uint8 **p_native_start_addr, uint8 **p_native_end_addr) { @@ -2061,20 +2051,20 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) } #endif - if (!(memory_data = wasm_runtime_realloc(memory_data_old, - (uint32)total_size))) { + if (!(memory_data = + wasm_runtime_realloc(memory_data_old, (uint32)total_size))) { if (!(memory_data = wasm_runtime_malloc((uint32)total_size))) { return false; } if (memory_data_old) { - bh_memcpy_s(memory_data, (uint32)total_size, - memory_data_old, total_size_old); + bh_memcpy_s(memory_data, (uint32)total_size, memory_data_old, + total_size_old); wasm_runtime_free(memory_data_old); } } - memset(memory_data + total_size_old, - 0, (uint32)total_size - total_size_old); + memset(memory_data + total_size_old, 0, + (uint32)total_size - total_size_old); memory_inst->cur_page_count = total_page_count; memory_inst->memory_data_size = (uint32)total_size; @@ -2083,8 +2073,8 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) if (heap_size > 0) { if (mem_allocator_migrate(memory_inst->heap_handle.ptr, - (char*)heap_data_old - + (memory_data - memory_data_old), + (char *)heap_data_old + + (memory_data - memory_data_old), heap_size)) { return false; } @@ -2147,7 +2137,8 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) if (os_mprotect(memory_inst->memory_data_end.ptr, num_bytes_per_page * inc_page_count, - MMAP_PROT_READ | MMAP_PROT_WRITE) != 0) { + MMAP_PROT_READ | MMAP_PROT_WRITE) + != 0) { #ifdef BH_PLATFORM_WINDOWS os_mem_decommit(memory_inst->memory_data_end.ptr, num_bytes_per_page * inc_page_count); @@ -2160,8 +2151,8 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) memory_inst->cur_page_count = total_page_count; memory_inst->memory_data_size = (uint32)total_size; - memory_inst->memory_data_end.ptr = (uint8 *)memory_inst->memory_data.ptr - + (uint32)total_size; + memory_inst->memory_data_end.ptr = + (uint8 *)memory_inst->memory_data.ptr + (uint32)total_size; if (sizeof(uintptr_t) == sizeof(uint64)) { memory_inst->mem_bound_check_1byte.u64 = total_size - 1; @@ -2182,11 +2173,11 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) #endif /* end of OS_ENABLE_HW_BOUND_CHECK */ bool -aot_is_wasm_type_equal(AOTModuleInstance *module_inst, - uint32 type1_idx, uint32 type2_idx) +aot_is_wasm_type_equal(AOTModuleInstance *module_inst, uint32 type1_idx, + uint32 type2_idx) { WASMType *type1, *type2; - AOTModule *module = (AOTModule*)module_inst->aot_module.ptr; + AOTModule *module = (AOTModule *)module_inst->aot_module.ptr; if (type1_idx >= module->func_type_count || type2_idx >= module->func_type_count) { @@ -2204,21 +2195,21 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst, } bool -aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, - uint32 argc, uint32 *argv) +aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, + uint32 *argv) { - AOTModuleInstance *module_inst = (AOTModuleInstance*) - wasm_runtime_get_module_inst(exec_env); - AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr; - uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr; + AOTModuleInstance *module_inst = + (AOTModuleInstance *)wasm_runtime_get_module_inst(exec_env); + AOTModule *aot_module = (AOTModule *)module_inst->aot_module.ptr; + uint32 *func_type_indexes = (uint32 *)module_inst->func_type_indexes.ptr; uint32 func_type_idx = func_type_indexes[func_idx]; AOTFuncType *func_type = aot_module->func_types[func_type_idx]; - void **func_ptrs = (void**)module_inst->func_ptrs.ptr; + void **func_ptrs = (void **)module_inst->func_ptrs.ptr; void *func_ptr = func_ptrs[func_idx]; AOTImportFunc *import_func; const char *signature; void *attachment; - char buf[128]; + char buf[96]; bh_assert(func_idx < aot_module->import_func_count); @@ -2234,47 +2225,46 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, attachment = import_func->attachment; if (import_func->call_conv_wasm_c_api) { return wasm_runtime_invoke_c_api_native( - (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc, - argv, import_func->wasm_c_api_with_env, attachment); + (WASMModuleInstanceCommon *)module_inst, func_ptr, func_type, argc, + argv, import_func->wasm_c_api_with_env, attachment); } else if (!import_func->call_conv_raw) { signature = import_func->signature; - return wasm_runtime_invoke_native(exec_env, func_ptr, - func_type, signature, attachment, - argv, argc, argv); + return wasm_runtime_invoke_native(exec_env, func_ptr, func_type, + signature, attachment, argv, argc, + argv); } else { signature = import_func->signature; - return wasm_runtime_invoke_native_raw(exec_env, func_ptr, - func_type, signature, attachment, - argv, argc, argv); + return wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, + signature, attachment, argv, argc, + argv); } } bool -aot_call_indirect(WASMExecEnv *exec_env, - uint32 tbl_idx, uint32 table_elem_idx, +aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, uint32 argc, uint32 *argv) { - AOTModuleInstance *module_inst = (AOTModuleInstance*) - wasm_runtime_get_module_inst(exec_env); - AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr; - uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr; + AOTModuleInstance *module_inst = + (AOTModuleInstance *)wasm_runtime_get_module_inst(exec_env); + AOTModule *aot_module = (AOTModule *)module_inst->aot_module.ptr; + uint32 *func_type_indexes = (uint32 *)module_inst->func_type_indexes.ptr; AOTTableInstance *tbl_inst; AOTFuncType *func_type; - void **func_ptrs = (void**)module_inst->func_ptrs.ptr, *func_ptr; + void **func_ptrs = (void **)module_inst->func_ptrs.ptr, *func_ptr; uint32 func_type_idx, func_idx, ext_ret_count; AOTImportFunc *import_func; const char *signature = NULL; void *attachment = NULL; - char buf[128]; + char buf[96]; bool ret; /* this function is called from native code, so exec_env->handle and exec_env->native_stack_boundary must have been set, we don't set it again */ - if ((uint8*)&module_inst < exec_env->native_stack_boundary) { + if ((uint8 *)&module_inst < exec_env->native_stack_boundary) { aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); return false; } @@ -2287,7 +2277,7 @@ aot_call_indirect(WASMExecEnv *exec_env, return false; } - func_idx = ((uint32*)tbl_inst->data)[table_elem_idx]; + func_idx = ((uint32 *)tbl_inst->data)[table_elem_idx]; if (func_idx == (uint32)-1) { aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT); return false; @@ -2312,15 +2302,14 @@ aot_call_indirect(WASMExecEnv *exec_env, signature = import_func->signature; if (import_func->call_conv_raw) { attachment = import_func->attachment; - return wasm_runtime_invoke_native_raw(exec_env, func_ptr, - func_type, signature, - attachment, - argv, argc, argv); + return wasm_runtime_invoke_native_raw(exec_env, func_ptr, func_type, + signature, attachment, argv, + argc, argv); } } - ext_ret_count = func_type->result_count > 1 - ? func_type->result_count - 1 : 0; + ext_ret_count = + func_type->result_count > 1 ? func_type->result_count - 1 : 0; if (ext_ret_count > 0) { uint32 argv1_buf[32], *argv1 = argv1_buf; uint32 *ext_rets = NULL, *argv_ret = argv; @@ -2330,9 +2319,11 @@ aot_call_indirect(WASMExecEnv *exec_env, uint64 size; /* Allocate memory all arguments */ - size = sizeof(uint32) * (uint64)argc /* original arguments */ - + sizeof(void*) * (uint64)ext_ret_count /* extra result values' addr */ - + sizeof(uint32) * (uint64)ext_ret_cell; /* extra result values */ + size = + sizeof(uint32) * (uint64)argc /* original arguments */ + + sizeof(void *) + * (uint64)ext_ret_count /* extra result values' addr */ + + sizeof(uint32) * (uint64)ext_ret_cell; /* extra result values */ if (size > sizeof(argv1_buf) && !(argv1 = runtime_malloc(size, module_inst->cur_exception, sizeof(module_inst->cur_exception)))) { @@ -2344,18 +2335,18 @@ aot_call_indirect(WASMExecEnv *exec_env, bh_memcpy_s(argv1, (uint32)size, argv, sizeof(uint32) * argc); /* Get the extra result value's address */ - ext_rets = argv1 + argc + sizeof(void*)/sizeof(uint32) * ext_ret_count; + ext_rets = + argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count; /* Append each extra result value's address to original arguments */ for (i = 0; i < ext_ret_count; i++) { - *(uintptr_t*)(argv1 + argc + sizeof(void*) / sizeof(uint32) * i) = + *(uintptr_t *)(argv1 + argc + sizeof(void *) / sizeof(uint32) * i) = (uintptr_t)(ext_rets + cell_num); cell_num += wasm_value_type_cell_num(ext_ret_types[i]); } - ret = invoke_native_internal(exec_env, func_ptr, - func_type, signature, attachment, - argv1, argc, argv); + ret = invoke_native_internal(exec_env, func_ptr, func_type, signature, + attachment, argv1, argc, argv); if (!ret || aot_get_exception(module_inst)) { if (argv1 != argv1_buf) wasm_runtime_free(argv1); @@ -2387,9 +2378,10 @@ aot_call_indirect(WASMExecEnv *exec_env, bh_assert(0); break; } - ext_rets = argv1 + argc + sizeof(void*)/sizeof(uint32) * ext_ret_count; - bh_memcpy_s(argv_ret, sizeof(uint32) * cell_num, - ext_rets, sizeof(uint32) * cell_num); + ext_rets = + argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count; + bh_memcpy_s(argv_ret, sizeof(uint32) * cell_num, ext_rets, + sizeof(uint32) * cell_num); if (argv1 != argv1_buf) wasm_runtime_free(argv1); @@ -2397,9 +2389,8 @@ aot_call_indirect(WASMExecEnv *exec_env, return true; } else { - ret = invoke_native_internal(exec_env, func_ptr, - func_type, signature, attachment, - argv, argc, argv); + ret = invoke_native_internal(exec_env, func_ptr, func_type, signature, + attachment, argv, argc, argv); if (clear_wasi_proc_exit_exception(module_inst)) return true; return ret; @@ -2420,8 +2411,8 @@ aot_memset(void *s, int c, size_t n) #if WASM_ENABLE_BULK_MEMORY != 0 bool -aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, - uint32 offset, uint32 len, uint32 dst) +aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset, + uint32 len, uint32 dst) { AOTMemoryInstance *memory_inst = aot_get_default_memory(module_inst); AOTModule *aot_module; @@ -2432,7 +2423,8 @@ aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, aot_module = (AOTModule *)module_inst->aot_module.ptr; if (aot_module->is_jit_mode) { #if WASM_ENABLE_JIT != 0 - seg_len = aot_module->wasm_module->data_segments[seg_index]->data_length; + seg_len = + aot_module->wasm_module->data_segments[seg_index]->data_length; data = aot_module->wasm_module->data_segments[seg_index]->data; #endif } @@ -2451,8 +2443,7 @@ aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, maddr = aot_addr_app_to_native(module_inst, dst); - bh_memcpy_s(maddr, memory_inst->memory_data_size - dst, - data + offset, len); + bh_memcpy_s(maddr, memory_inst->memory_data_size - dst, data + offset, len); return true; } @@ -2479,11 +2470,9 @@ aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index) #if WASM_ENABLE_THREAD_MGR != 0 bool -aot_set_aux_stack(WASMExecEnv *exec_env, - uint32 start_offset, uint32 size) +aot_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size) { - AOTModuleInstance *module_inst = - (AOTModuleInstance*)exec_env->module_inst; + AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; AOTModule *module = (AOTModule *)module_inst->aot_module.ptr; uint32 stack_top_idx = module->aux_stack_top_global_index; @@ -2499,10 +2488,10 @@ aot_set_aux_stack(WASMExecEnv *exec_env, if (stack_top_idx != (uint32)-1) { /* The aux stack top is a wasm global, set the initial value for the global */ - uint32 global_offset = - module->globals[stack_top_idx].data_offset; - uint8 *global_addr = (uint8 *)module_inst->global_data.ptr + global_offset; - *(int32*)global_addr = start_offset; + uint32 global_offset = module->globals[stack_top_idx].data_offset; + uint8 *global_addr = + (uint8 *)module_inst->global_data.ptr + global_offset; + *(int32 *)global_addr = start_offset; /* The aux stack boundary is a constant value, set the value to exec_env */ @@ -2515,11 +2504,9 @@ aot_set_aux_stack(WASMExecEnv *exec_env, } bool -aot_get_aux_stack(WASMExecEnv *exec_env, - uint32 *start_offset, uint32 *size) +aot_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size) { - AOTModuleInstance *module_inst = - (AOTModuleInstance*)exec_env->module_inst; + AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; AOTModule *module = (AOTModule *)module_inst->aot_module.ptr; /* The aux stack information is resolved in loader @@ -2540,13 +2527,12 @@ aot_get_aux_stack(WASMExecEnv *exec_env, #if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_MEMORY_TRACING != 0) static void -const_string_node_size_cb(void *key, void *value, - void *p_const_string_size) +const_string_node_size_cb(void *key, void *value, void *p_const_string_size) { - uint32 const_string_size = *(uint32*)p_const_string_size; + uint32 const_string_size = *(uint32 *)p_const_string_size; const_string_size += bh_hash_map_get_elem_struct_size(); const_string_size += strlen((const char *)value) + 1; - *(uint32*)p_const_string_size += const_string_size; + *(uint32 *)p_const_string_size += const_string_size; } void @@ -2562,8 +2548,8 @@ aot_get_module_mem_consumption(const AOTModule *module, mem_conspn->types_size = sizeof(AOTFuncType *) * module->func_type_count; for (i = 0; i < module->func_type_count; i++) { AOTFuncType *type = module->func_types[i]; - size = offsetof(AOTFuncType, types) + - sizeof(uint8) * (type->param_count + type->result_count); + size = offsetof(AOTFuncType, types) + + sizeof(uint8) * (type->param_count + type->result_count); mem_conspn->types_size += size; } @@ -2592,8 +2578,8 @@ aot_get_module_mem_consumption(const AOTModule *module, mem_conspn->table_segs_size += size; } - mem_conspn->data_segs_size = sizeof(AOTMemInitData *) - * module->mem_init_data_count; + mem_conspn->data_segs_size = + sizeof(AOTMemInitData *) * module->mem_init_data_count; for (i = 0; i < module->mem_init_data_count; i++) { mem_conspn->data_segs_size += sizeof(AOTMemInitData); } @@ -2604,14 +2590,14 @@ aot_get_module_mem_consumption(const AOTModule *module, mem_conspn->const_strs_size = bh_hash_map_get_struct_size(module->const_str_set); - bh_hash_map_traverse(module->const_str_set, - const_string_node_size_cb, - (void*)&const_string_size); + bh_hash_map_traverse(module->const_str_set, const_string_node_size_cb, + (void *)&const_string_size); mem_conspn->const_strs_size += const_string_size; } /* code size + literal size + object data section size */ - mem_conspn->aot_code_size = module->code_size + module->literal_size + mem_conspn->aot_code_size = + module->code_size + module->literal_size + sizeof(AOTObjectDataSection) * module->data_section_count; for (i = 0; i < module->data_section_count; i++) { AOTObjectDataSection *obj_data = module->data_sections + i; @@ -2651,11 +2637,10 @@ aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst, ((AOTMemoryInstance **)module_inst->memories.ptr)[i]; mem_conspn->memories_size += mem_inst->num_bytes_per_page * mem_inst->cur_page_count; - mem_conspn->app_heap_size = - (uint8 *) mem_inst->heap_data_end.ptr - (uint8 *) mem_inst->heap_data.ptr; + mem_conspn->app_heap_size = (uint8 *)mem_inst->heap_data_end.ptr + - (uint8 *)mem_inst->heap_data.ptr; /* size of app heap structure */ - mem_conspn->memories_size += - mem_allocator_get_heap_struct_size(); + mem_conspn->memories_size += mem_allocator_get_heap_struct_size(); } tbl_inst = module_inst->tables.ptr; @@ -2666,9 +2651,10 @@ aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst, } /* func_ptrs and func_type_indexes */ - mem_conspn->functions_size = (sizeof(void *) + sizeof(uint32)) * - (((AOTModule *)module_inst->aot_module.ptr)->import_func_count - + ((AOTModule *)module_inst->aot_module.ptr)->func_count); + mem_conspn->functions_size = + (sizeof(void *) + sizeof(uint32)) + * (((AOTModule *)module_inst->aot_module.ptr)->import_func_count + + ((AOTModule *)module_inst->aot_module.ptr)->func_count); mem_conspn->globals_size = module_inst->global_data_size; @@ -2682,7 +2668,7 @@ aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst, mem_conspn->total_size += mem_conspn->globals_size; mem_conspn->total_size += mem_conspn->exports_size; } -#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) +#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \ || (WASM_ENABLE_MEMORY_TRACING != 0) */ #if WASM_ENABLE_REF_TYPES != 0 @@ -2695,9 +2681,9 @@ aot_drop_table_seg(AOTModuleInstance *module_inst, uint32 tbl_seg_idx) } void -aot_table_init(AOTModuleInstance *module_inst, - uint32 tbl_idx, uint32 tbl_seg_idx, - uint32 length, uint32 src_offset, uint32 dst_offset) +aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, + uint32 tbl_seg_idx, uint32 length, uint32 src_offset, + uint32 dst_offset) { AOTTableInstance *tbl_inst; AOTTableInitData *tbl_seg; @@ -2715,33 +2701,30 @@ aot_table_init(AOTModuleInstance *module_inst, if (length + src_offset > tbl_seg->func_index_count || dst_offset + length > tbl_inst->cur_size) { - aot_set_exception_with_id(module_inst, - EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); + aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } if (tbl_seg->is_dropped) { - aot_set_exception_with_id(module_inst, - EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); + aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } if (!wasm_elem_is_passive(tbl_seg->mode)) { - aot_set_exception_with_id(module_inst, - EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); + aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } bh_memcpy_s((uint8 *)tbl_inst + offsetof(AOTTableInstance, data) - + dst_offset * sizeof(uint32), + + dst_offset * sizeof(uint32), (tbl_inst->cur_size - dst_offset) * sizeof(uint32), tbl_seg->func_indexes + src_offset, length * sizeof(uint32)); } void -aot_table_copy(AOTModuleInstance *module_inst, - uint32 src_tbl_idx, uint32 dst_tbl_idx, - uint32 length, uint32 src_offset, uint32 dst_offset) +aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx, + uint32 dst_tbl_idx, uint32 length, uint32 src_offset, + uint32 dst_offset) { AOTTableInstance *src_tbl_inst, *dst_tbl_inst; @@ -2753,25 +2736,24 @@ aot_table_copy(AOTModuleInstance *module_inst, if ((uint64)src_offset + length > dst_tbl_inst->cur_size || (uint64)dst_offset + length > src_tbl_inst->cur_size) { - aot_set_exception_with_id(module_inst, - EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); + aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } /* if src_offset >= dst_offset, copy from front to back */ /* if src_offset < dst_offset, copy from back to front */ /* merge all together */ - bh_memcpy_s((uint8 *)(dst_tbl_inst) + offsetof(AOTTableInstance, data) - + dst_offset * sizeof(uint32), - (dst_tbl_inst->cur_size - dst_offset) * sizeof(uint32), - (uint8 *)(src_tbl_inst) + offsetof(AOTTableInstance, data) - + src_offset * sizeof(uint32), - length * sizeof(uint32)); + bh_memmove_s((uint8 *)(dst_tbl_inst) + offsetof(AOTTableInstance, data) + + dst_offset * sizeof(uint32), + (dst_tbl_inst->cur_size - dst_offset) * sizeof(uint32), + (uint8 *)(src_tbl_inst) + offsetof(AOTTableInstance, data) + + src_offset * sizeof(uint32), + length * sizeof(uint32)); } void -aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, - uint32 length, uint32 val, uint32 data_offset) +aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length, + uint32 val, uint32 data_offset) { AOTTableInstance *tbl_inst; @@ -2779,8 +2761,7 @@ aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, bh_assert(tbl_inst); if (data_offset + length > tbl_inst->cur_size) { - aot_set_exception_with_id(module_inst, - EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); + aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; } @@ -2807,9 +2788,12 @@ aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx, return orig_tbl_sz; } + if (tbl_inst->cur_size > UINT32_MAX - inc_entries) { + return (uint32)-1; + } + entry_count = tbl_inst->cur_size + inc_entries; - /* prevent from integer overflow */ - if (entry_count < tbl_inst->cur_size || entry_count > tbl_inst->max_size) { + if (entry_count > tbl_inst->max_size) { return (uint32)-1; } @@ -2839,8 +2823,7 @@ get_func_name_from_index(const AOTModuleInstance *module_inst, for (i = 0; i < module->export_count; i++) { AOTExport export = module->exports[i]; - if (export.index == func_index - && export.kind == EXPORT_KIND_FUNC) { + if (export.index == func_index && export.kind == EXPORT_KIND_FUNC) { func_name = export.name; break; } @@ -2856,14 +2839,14 @@ aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index) AOTFrame *frame = wasm_exec_env_alloc_wasm_frame(exec_env, sizeof(AOTFrame)); #if WASM_ENABLE_PERF_PROFILING != 0 - AOTModuleInstance *module_inst = - (AOTModuleInstance*)exec_env->module_inst; + AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; AOTFuncPerfProfInfo *func_perf_prof = - (AOTFuncPerfProfInfo*)module_inst->func_perf_profilings.ptr + func_index; + (AOTFuncPerfProfInfo *)module_inst->func_perf_profilings.ptr + + func_index; #endif if (!frame) { - aot_set_exception((AOTModuleInstance*)exec_env->module_inst, + aot_set_exception((AOTModuleInstance *)exec_env->module_inst, "auxiliary call stack overflow"); return false; } @@ -2888,23 +2871,23 @@ aot_free_frame(WASMExecEnv *exec_env) #if WASM_ENABLE_PERF_PROFILING != 0 cur_frame->func_perf_prof_info->total_exec_time += - os_time_get_boot_microsecond() - cur_frame->time_started; + os_time_get_boot_microsecond() - cur_frame->time_started; cur_frame->func_perf_prof_info->total_exec_cnt++; #endif wasm_exec_env_free_wasm_frame(exec_env, cur_frame); exec_env->cur_frame = (struct WASMInterpFrame *)prev_frame; } -#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) +#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \ || (WASM_ENABLE_PERF_PROFILING != 0) */ #if WASM_ENABLE_DUMP_CALL_STACK != 0 void aot_dump_call_stack(WASMExecEnv *exec_env) { - AOTFrame *cur_frame = (AOTFrame *)exec_env->cur_frame; - AOTModuleInstance *module_inst = - (AOTModuleInstance *)exec_env->module_inst; + AOTFrame *cur_frame = (AOTFrame *)exec_env->cur_frame, + *first_frame = cur_frame; + AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; const char *func_name; uint32 n = 0; @@ -2925,6 +2908,28 @@ aot_dump_call_stack(WASMExecEnv *exec_env) n++; } os_printf("\n"); + + /* release previous stack frames and create new ones */ + if (!bh_vector_destroy(module_inst->frames.ptr) + || !bh_vector_init(module_inst->frames.ptr, n, sizeof(WASMCApiFrame))) { + return; + } + + cur_frame = first_frame; + while (cur_frame) { + WASMCApiFrame frame = { 0 }; + frame.instance = module_inst; + frame.module_offset = 0; + frame.func_index = cur_frame->func_index; + frame.func_offset = 0; + + if (!bh_vector_append(module_inst->frames.ptr, &frame)) { + bh_vector_destroy(module_inst->frames.ptr); + return; + } + + cur_frame = cur_frame->prev_frame; + } } #endif /* end of WASM_ENABLE_DUMP_CALL_STACK */ @@ -2932,8 +2937,8 @@ aot_dump_call_stack(WASMExecEnv *exec_env) void aot_dump_perf_profiling(const AOTModuleInstance *module_inst) { - AOTFuncPerfProfInfo *perf_prof = (AOTFuncPerfProfInfo *) - module_inst->func_perf_profilings.ptr; + AOTFuncPerfProfInfo *perf_prof = + (AOTFuncPerfProfInfo *)module_inst->func_perf_profilings.ptr; AOTModule *module = (AOTModule *)module_inst->aot_module.ptr; uint32 total_func_count = module->import_func_count + module->func_count, i; const char *func_name; @@ -2943,14 +2948,15 @@ aot_dump_perf_profiling(const AOTModuleInstance *module_inst) func_name = get_func_name_from_index(module_inst, i); if (func_name) - os_printf(" func %s, execution time: %.3f ms, execution count: %d times\n", + os_printf(" func %s, execution time: %.3f ms, execution count: %d " + "times\n", func_name, perf_prof->total_exec_time / 1000.0f, perf_prof->total_exec_cnt); else - os_printf(" func %d, execution time: %.3f ms, execution count: %d times\n", + os_printf(" func %d, execution time: %.3f ms, execution count: %d " + "times\n", i, perf_prof->total_exec_time / 1000.0f, perf_prof->total_exec_cnt); } } #endif /* end of WASM_ENABLE_PERF_PROFILING */ - diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 237764b59e..4fe9889eeb 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -40,14 +40,20 @@ typedef enum AOTExceptionID { typedef enum AOTSectionType { AOT_SECTION_TYPE_TARGET_INFO = 0, - AOT_SECTION_TYPE_INIT_DATA, - AOT_SECTION_TYPE_TEXT, - AOT_SECTION_TYPE_FUNCTION, - AOT_SECTION_TYPE_EXPORT, - AOT_SECTION_TYPE_RELOCATION, - AOT_SECTION_TYPE_SIGANATURE + AOT_SECTION_TYPE_INIT_DATA = 1, + AOT_SECTION_TYPE_TEXT = 2, + AOT_SECTION_TYPE_FUNCTION = 3, + AOT_SECTION_TYPE_EXPORT = 4, + AOT_SECTION_TYPE_RELOCATION = 5, + AOT_SECTION_TYPE_SIGANATURE = 6, + AOT_SECTION_TYPE_CUSTOM = 100, } AOTSectionType; +typedef enum AOTCustomSectionType { + AOT_CUSTOM_SECTION_NATIVE_SYMBOL = 1, + AOT_CUSTOM_SECTION_ACCESS_CONTROL = 2, +} AOTCustomSectionType; + typedef struct AOTObjectDataSection { char *name; uint8 *data; @@ -89,6 +95,7 @@ typedef struct AOTFunctionInstance { } AOTFunctionInstance; #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) +/* clang-format off */ typedef struct AOTUnwindInfo { uint8 Version : 3; uint8 Flags : 5; @@ -105,6 +112,7 @@ typedef struct AOTUnwindInfo { uint16 FrameOffset; } UnwindCode[1]; } AOTUnwindInfo; +/* clang-format on */ /* size of mov instruction and jmp instruction */ #define PLT_ITEM_SIZE 12 @@ -125,6 +133,10 @@ typedef struct AOTModule { uint32 mem_init_data_count; AOTMemInitData **mem_init_data_list; + /* native symobl */ + uint32 native_symbol_count; + void **native_symbol_list; + /* import tables */ uint32 import_table_count; AOTImportTable *import_tables; @@ -244,6 +256,10 @@ typedef struct AOTModule { WASIArguments wasi_args; bool is_wasi_module; #endif +#if WASM_ENABLE_DEBUG_AOT != 0 + void *elf_hdr; + uint32 elf_size; +#endif } AOTModule; typedef union { @@ -314,7 +330,7 @@ typedef struct AOTModuleInstance { * TODO: for now we treate imported table like a local table */ uint32 table_count; - /* points to global_data */ + /* points to global_data */ AOTPointer global_data; /* points to AOTTableInstance[] */ AOTPointer tables; @@ -353,18 +369,21 @@ typedef struct AOTModuleInstance { uint32 llvm_stack; uint32 default_wasm_stack_size; + uint32 _padding; + /* store stacktrace information */ + AOTPointer frames; /* reserved */ - uint32 reserved[9]; - - /* - * +------------------------------+ <-- memories.ptr - * | #0 AOTMemoryInstance - * +------------------------------+ <-- global_data.ptr - * | global data - * +------------------------------+ <-- tables.ptr - * | AOTTableInstance[table_count] - * +------------------------------+ - */ + uint32 reserved[6]; + + /* + * +------------------------------+ <-- memories.ptr + * | #0 AOTMemoryInstance + * +------------------------------+ <-- global_data.ptr + * | global data + * +------------------------------+ <-- tables.ptr + * | AOTTableInstance[table_count] + * +------------------------------+ + */ union { uint64 _make_it_8_byte_aligned_; AOTMemoryInstance memory_instances[1]; @@ -392,8 +411,7 @@ typedef struct AOTTargetInfo { char arch[16]; } AOTTargetInfo; -typedef struct AOTFuncPerfProfInfo -{ +typedef struct AOTFuncPerfProfInfo { /* total execution time */ uint64 total_exec_time; /* total execution count */ @@ -419,9 +437,9 @@ typedef struct AOTFrame { * * @return return AOT module loaded, NULL if failed */ -AOTModule* -aot_load_from_aot_file(const uint8 *buf, uint32 size, - char *error_buf, uint32 error_buf_size); +AOTModule * +aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf, + uint32 error_buf_size); /** * Load a AOT module from a specified AOT section list. @@ -432,9 +450,9 @@ aot_load_from_aot_file(const uint8 *buf, uint32 size, * * @return return AOT module loaded, NULL if failed */ -AOTModule* -aot_load_from_sections(AOTSection *section_list, - char *error_buf, uint32 error_buf_size); +AOTModule * +aot_load_from_sections(AOTSection *section_list, char *error_buf, + uint32 error_buf_size); #if WASM_ENABLE_JIT != 0 /** @@ -446,9 +464,9 @@ aot_load_from_sections(AOTSection *section_list, * * @return return AOT module loaded, NULL if failed */ -AOTModule* -aot_convert_wasm_module(WASMModule *wasm_module, - char *error_buf, uint32 error_buf_size); +AOTModule * +aot_convert_wasm_module(WASMModule *wasm_module, char *error_buf, + uint32 error_buf_size); #endif /** @@ -473,10 +491,9 @@ aot_unload(AOTModule *module); * * @return return the instantiated AOT module instance, NULL if failed */ -AOTModuleInstance* -aot_instantiate(AOTModule *module, bool is_sub_inst, - uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size); +AOTModuleInstance * +aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size, + uint32 heap_size, char *error_buf, uint32 error_buf_size); /** * Deinstantiate a AOT module instance, destroy the resources. @@ -497,9 +514,9 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst); * * @return the function instance found */ -AOTFunctionInstance* -aot_lookup_function(const AOTModuleInstance *module_inst, - const char *name, const char *signature); +AOTFunctionInstance * +aot_lookup_function(const AOTModuleInstance *module_inst, const char *name, + const char *signature); /** * Call the given AOT function of a AOT module instance with * arguments. @@ -516,8 +533,7 @@ aot_lookup_function(const AOTModuleInstance *module_inst, * the caller can call aot_get_exception to get exception info. */ bool -aot_call_function(WASMExecEnv *exec_env, - AOTFunctionInstance *function, +aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, unsigned argc, uint32 argv[]); bool @@ -536,12 +552,10 @@ aot_create_exec_env_singleton(AOTModuleInstance *module_inst); * @param exception current exception string */ void -aot_set_exception(AOTModuleInstance *module_inst, - const char *exception); +aot_set_exception(AOTModuleInstance *module_inst, const char *exception); void -aot_set_exception_with_id(AOTModuleInstance *module_inst, - uint32 id); +aot_set_exception_with_id(AOTModuleInstance *module_inst, uint32 id); /** * Get exception info of the AOT module instance. @@ -550,7 +564,7 @@ aot_set_exception_with_id(AOTModuleInstance *module_inst, * * @return the exception string */ -const char* +const char * aot_get_exception(AOTModuleInstance *module_inst); /** @@ -566,24 +580,23 @@ aot_module_malloc(AOTModuleInstance *module_inst, uint32 size, void **p_native_addr); uint32 -aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, - uint32 size, void **p_native_addr); +aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, uint32 size, + void **p_native_addr); void aot_module_free(AOTModuleInstance *module_inst, uint32 ptr); uint32 -aot_module_dup_data(AOTModuleInstance *module_inst, - const char *src, uint32 size); +aot_module_dup_data(AOTModuleInstance *module_inst, const char *src, + uint32 size); bool -aot_validate_app_addr(AOTModuleInstance *module_inst, - uint32 app_offset, uint32 size); - +aot_validate_app_addr(AOTModuleInstance *module_inst, uint32 app_offset, + uint32 size); bool -aot_validate_native_addr(AOTModuleInstance *module_inst, - void *native_ptr, uint32 size); +aot_validate_native_addr(AOTModuleInstance *module_inst, void *native_ptr, + uint32 size); void * aot_addr_app_to_native(AOTModuleInstance *module_inst, uint32 app_offset); @@ -592,14 +605,11 @@ uint32 aot_addr_native_to_app(AOTModuleInstance *module_inst, void *native_ptr); bool -aot_get_app_addr_range(AOTModuleInstance *module_inst, - uint32 app_offset, - uint32 *p_app_start_offset, - uint32 *p_app_end_offset); +aot_get_app_addr_range(AOTModuleInstance *module_inst, uint32 app_offset, + uint32 *p_app_start_offset, uint32 *p_app_end_offset); bool -aot_get_native_addr_range(AOTModuleInstance *module_inst, - uint8 *native_ptr, +aot_get_native_addr_range(AOTModuleInstance *module_inst, uint8 *native_ptr, uint8 **p_native_start_addr, uint8 **p_native_end_addr); @@ -616,19 +626,18 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count); * @return true if equal, false otherwise */ bool -aot_is_wasm_type_equal(AOTModuleInstance *module_inst, - uint32 type1_idx, uint32 type2_idx); +aot_is_wasm_type_equal(AOTModuleInstance *module_inst, uint32 type1_idx, + uint32 type2_idx); /** * Invoke native function from aot code */ bool -aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, - uint32 argc, uint32 *argv); +aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc, + uint32 *argv); bool -aot_call_indirect(WASMExecEnv *exec_env, - uint32 tbl_idx, uint32 table_elem_idx, +aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, uint32 argc, uint32 *argv); uint32 @@ -642,8 +651,8 @@ aot_memset(void *s, int c, size_t n); #if WASM_ENABLE_BULK_MEMORY != 0 bool -aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, - uint32 offset, uint32 len, uint32 dst); +aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset, + uint32 len, uint32 dst); bool aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index); @@ -651,12 +660,10 @@ aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index); #if WASM_ENABLE_THREAD_MGR != 0 bool -aot_set_aux_stack(WASMExecEnv *exec_env, - uint32 start_offset, uint32 size); +aot_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size); bool -aot_get_aux_stack(WASMExecEnv *exec_env, - uint32 *start_offset, uint32 *size); +aot_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size); #endif #ifdef OS_ENABLE_HW_BOUND_CHECK @@ -680,18 +687,18 @@ void aot_drop_table_seg(AOTModuleInstance *module_inst, uint32 tbl_seg_idx); void -aot_table_init(AOTModuleInstance *module_inst, - uint32 tbl_idx, uint32 tbl_seg_idx, - uint32 length, uint32 src_offset, uint32 dst_offset); +aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, + uint32 tbl_seg_idx, uint32 length, uint32 src_offset, + uint32 dst_offset); void -aot_table_copy(AOTModuleInstance *module_inst, - uint32 src_tbl_idx, uint32 dst_tbl_idx, - uint32 length, uint32 src_offset, uint32 dst_offset); +aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx, + uint32 dst_tbl_idx, uint32 length, uint32 src_offset, + uint32 dst_offset); void -aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, - uint32 length, uint32 val, uint32 data_offset); +aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length, + uint32 val, uint32 data_offset); uint32 aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx, @@ -718,4 +725,3 @@ aot_dump_perf_profiling(const AOTModuleInstance *module_inst); #endif #endif /* end of _AOT_RUNTIME_H_ */ - diff --git a/core/iwasm/aot/arch/aot_reloc_aarch64.c b/core/iwasm/aot/arch/aot_reloc_aarch64.c index 91848086a1..0ca22b84b3 100644 --- a/core/iwasm/aot/arch/aot_reloc_aarch64.c +++ b/core/iwasm/aot/arch/aot_reloc_aarch64.c @@ -5,37 +5,39 @@ #include "aot_reloc.h" -#define R_AARCH64_MOVW_UABS_G0 263 -#define R_AARCH64_MOVW_UABS_G0_NC 264 -#define R_AARCH64_MOVW_UABS_G1 265 -#define R_AARCH64_MOVW_UABS_G1_NC 266 -#define R_AARCH64_MOVW_UABS_G2 267 -#define R_AARCH64_MOVW_UABS_G2_NC 268 -#define R_AARCH64_MOVW_UABS_G3 269 - -#define R_AARCH64_MOVW_SABS_G0 270 -#define R_AARCH64_MOVW_SABS_G1 271 -#define R_AARCH64_MOVW_SABS_G2 272 - -#define R_AARCH64_ADR_PREL_LO19 273 -#define R_AARCH64_ADR_PREL_LO21 274 -#define R_AARCH64_ADR_PREL_PG_HI21 275 -#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 - -#define R_AARCH64_ADD_ABS_LO12_NC 277 - -#define R_AARCH64_LDST8_ABS_LO12_NC 278 -#define R_AARCH64_LDST16_ABS_LO12_NC 284 -#define R_AARCH64_LDST32_ABS_LO12_NC 285 -#define R_AARCH64_LDST64_ABS_LO12_NC 286 -#define R_AARCH64_LDST128_ABS_LO12_NC 299 - -#define R_AARCH64_JUMP26 282 -#define R_AARCH64_CALL26 283 - +#define R_AARCH64_MOVW_UABS_G0 263 +#define R_AARCH64_MOVW_UABS_G0_NC 264 +#define R_AARCH64_MOVW_UABS_G1 265 +#define R_AARCH64_MOVW_UABS_G1_NC 266 +#define R_AARCH64_MOVW_UABS_G2 267 +#define R_AARCH64_MOVW_UABS_G2_NC 268 +#define R_AARCH64_MOVW_UABS_G3 269 + +#define R_AARCH64_MOVW_SABS_G0 270 +#define R_AARCH64_MOVW_SABS_G1 271 +#define R_AARCH64_MOVW_SABS_G2 272 + +#define R_AARCH64_ADR_PREL_LO19 273 +#define R_AARCH64_ADR_PREL_LO21 274 +#define R_AARCH64_ADR_PREL_PG_HI21 275 +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 + +#define R_AARCH64_ADD_ABS_LO12_NC 277 + +#define R_AARCH64_LDST8_ABS_LO12_NC 278 +#define R_AARCH64_LDST16_ABS_LO12_NC 284 +#define R_AARCH64_LDST32_ABS_LO12_NC 285 +#define R_AARCH64_LDST64_ABS_LO12_NC 286 +#define R_AARCH64_LDST128_ABS_LO12_NC 299 + +#define R_AARCH64_JUMP26 282 +#define R_AARCH64_CALL26 283 + +/* clang-format off */ static SymbolMap target_sym_map[] = { REG_COMMON_SYMBOLS }; +/* clang-format on */ static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) @@ -55,7 +57,7 @@ get_target_symbol_map(uint32 *sym_num) void get_current_target(char *target_buf, uint32 target_buf_size) { - const char * s = BUILD_TARGET; + const char *s = BUILD_TARGET; size_t s_size = sizeof(BUILD_TARGET); char *d = target_buf; @@ -64,14 +66,14 @@ get_current_target(char *target_buf, uint32 target_buf_size) s = BUILD_TARGET_AARCH64_DEFAULT; s_size = sizeof(BUILD_TARGET_AARCH64_DEFAULT); } - if(target_buf_size < s_size){ + if (target_buf_size < s_size) { s_size = target_buf_size; } while (--s_size) { if (*s >= 'A' && *s <= 'Z') *d++ = *s++ + 'a' - 'A'; else - *d++ = *s++ ; + *d++ = *s++; } /* Ensure the string is null byte ('\0') terminated */ *d = '\0'; @@ -90,15 +92,16 @@ init_plt_table(uint8 *plt) { uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap); for (i = 0; i < num; i++) { - uint32 *p = (uint32*)plt; + uint32 *p = (uint32 *)plt; *p++ = 0xf81f0ffe; /* str x30, [sp, #-16]! */ - *p++ = 0x100000be; /* adr x30, #20 ;symbol addr is PC + 5 instructions below */ + *p++ = 0x100000be; /* adr x30, #20; symbol addr is PC + 5 instructions + below */ *p++ = 0xf94003de; /* ldr x30, [x30] */ *p++ = 0xd63f03c0; /* blr x30 */ *p++ = 0xf84107fe; /* ldr x30, [sp], #16 */ *p++ = 0xd61f03c0; /* br x30 */ /* symbol addr */ - *(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr; + *(uint64 *)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr; p += 2; plt += get_plt_item_size(); } @@ -110,17 +113,18 @@ get_plt_table_size() return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap)); } -#define SIGN_EXTEND_TO_INT64(val, bits, val_ext) do { \ - int64 m = ((int64)1 << (bits - 1)); \ - val_ext = ((int64)val ^ m) - m; \ -} while (0) +#define SIGN_EXTEND_TO_INT64(val, bits, val_ext) \ + do { \ + int64 m = (int64)((uint64)1 << (bits - 1)); \ + val_ext = ((int64)val ^ m) - m; \ + } while (0) #define Page(expr) ((expr) & ~0xFFF) static bool -check_reloc_offset(uint32 target_section_size, - uint64 reloc_offset, uint32 reloc_data_size, - char *error_buf, uint32 error_buf_size) +check_reloc_offset(uint32 target_section_size, uint64 reloc_offset, + uint32 reloc_data_size, char *error_buf, + uint32 error_buf_size) { if (!(reloc_offset < (uint64)target_section_size && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { @@ -132,22 +136,21 @@ check_reloc_offset(uint32 target_section_size, } bool -apply_relocation(AOTModule *module, - uint8 *target_section_addr, uint32 target_section_size, - uint64 reloc_offset, uint64 reloc_addend, - uint32 reloc_type, void *symbol_addr, int32 symbol_index, - char *error_buf, uint32 error_buf_size) +apply_relocation(AOTModule *module, uint8 *target_section_addr, + uint32 target_section_size, uint64 reloc_offset, + uint64 reloc_addend, uint32 reloc_type, void *symbol_addr, + int32 symbol_index, char *error_buf, uint32 error_buf_size) { switch (reloc_type) { case R_AARCH64_CALL26: { - void *S, *P = (void*)(target_section_addr + reloc_offset); + void *S, *P = (void *)(target_section_addr + reloc_offset); int64 X, A, initial_addend; int32 insn, imm26; CHECK_RELOC_OFFSET(sizeof(int32)); - insn = *(int32*)P; + insn = *(int32 *)P; imm26 = insn & 0x3FFFFFF; SIGN_EXTEND_TO_INT64(imm26 << 2, 28, initial_addend); A = initial_addend; @@ -164,17 +167,18 @@ apply_relocation(AOTModule *module, else { uint8 *plt; if (reloc_addend > 0) { - set_error_buf(error_buf, error_buf_size, - "AOT module load failed: relocate to plt table " - "with reloc addend larger than 0 is unsupported."); - return false; + set_error_buf( + error_buf, error_buf_size, + "AOT module load failed: relocate to plt table " + "with reloc addend larger than 0 is unsupported."); + return false; } /* Symbol address is not an AOT function, * but a function of runtime or native. Its address is * beyond of the +-128MB space. Apply relocation with * the PLT which branch to the target symbol address. */ - S = plt = (uint8*)module->code + module->code_size + S = plt = (uint8 *)module->code + module->code_size - get_plt_table_size() + get_plt_item_size() * symbol_index; } @@ -191,7 +195,7 @@ apply_relocation(AOTModule *module, } /* write the imm26 back to instruction */ - *(int32*)P = (insn & 0xFC000000) | ((int32)((X >> 2) & 0x3FFFFFF)); + *(int32 *)P = (insn & 0xFC000000) | ((int32)((X >> 2) & 0x3FFFFFF)); break; } @@ -203,13 +207,14 @@ apply_relocation(AOTModule *module, case R_AARCH64_MOVW_UABS_G2_NC: case R_AARCH64_MOVW_UABS_G3: { - void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset); + void *S = symbol_addr, + *P = (void *)(target_section_addr + reloc_offset); int64 X, A, initial_addend; int32 insn, imm16; CHECK_RELOC_OFFSET(sizeof(int32)); - insn = *(int32*)P; + insn = *(int32 *)P; imm16 = (insn >> 5) & 0xFFFF; SIGN_EXTEND_TO_INT64(imm16, 16, initial_addend); @@ -241,18 +246,22 @@ apply_relocation(AOTModule *module, switch (reloc_type) { case R_AARCH64_MOVW_UABS_G0: case R_AARCH64_MOVW_UABS_G0_NC: - *(int32*)P = (insn & 0xFFE0001F) | ((int32)((X & 0xFFFF) << 5)); + *(int32 *)P = + (insn & 0xFFE0001F) | ((int32)((X & 0xFFFF) << 5)); break; case R_AARCH64_MOVW_UABS_G1: case R_AARCH64_MOVW_UABS_G1_NC: - *(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 16) & 0xFFFF) << 5)); + *(int32 *)P = (insn & 0xFFE0001F) + | ((int32)(((X >> 16) & 0xFFFF) << 5)); break; case R_AARCH64_MOVW_UABS_G2: case R_AARCH64_MOVW_UABS_G2_NC: - *(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 32) & 0xFFFF) << 5)); + *(int32 *)P = (insn & 0xFFE0001F) + | ((int32)(((X >> 32) & 0xFFFF) << 5)); break; case R_AARCH64_MOVW_UABS_G3: - *(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 48) & 0xFFFF) << 5)); + *(int32 *)P = (insn & 0xFFE0001F) + | ((int32)(((X >> 48) & 0xFFFF) << 5)); break; default: bh_assert(0); @@ -264,13 +273,14 @@ apply_relocation(AOTModule *module, case R_AARCH64_ADR_PREL_PG_HI21: case R_AARCH64_ADR_PREL_PG_HI21_NC: { - void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset); + void *S = symbol_addr, + *P = (void *)(target_section_addr + reloc_offset); int64 X, A, initial_addend; int32 insn, immhi19, immlo2, imm21; CHECK_RELOC_OFFSET(sizeof(int32)); - insn = *(int32*)P; + insn = *(int32 *)P; immhi19 = (insn >> 5) & 0x7FFFF; immlo2 = (insn >> 29) & 0x3; imm21 = (immhi19 << 2) | immlo2; @@ -290,20 +300,21 @@ apply_relocation(AOTModule *module, /* write the imm21 back to instruction */ immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF); immlo2 = (int32)((X >> 12) & 0x3); - *(int32*)P = (insn & 0x9F00001F) | (immlo2 << 29) | (immhi19 << 5); + *(int32 *)P = (insn & 0x9F00001F) | (immlo2 << 29) | (immhi19 << 5); break; } case R_AARCH64_ADD_ABS_LO12_NC: { - void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset); + void *S = symbol_addr, + *P = (void *)(target_section_addr + reloc_offset); int64 X, A, initial_addend; int32 insn, imm12; CHECK_RELOC_OFFSET(sizeof(int32)); - insn = *(int32*)P; + insn = *(int32 *)P; imm12 = (insn >> 10) & 0xFFF; SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend); @@ -316,7 +327,7 @@ apply_relocation(AOTModule *module, /* No need to check overflow for this reloction type */ /* write the imm12 back to instruction */ - *(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10)); + *(int32 *)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10)); break; } @@ -326,13 +337,14 @@ apply_relocation(AOTModule *module, case R_AARCH64_LDST64_ABS_LO12_NC: case R_AARCH64_LDST128_ABS_LO12_NC: { - void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset); + void *S = symbol_addr, + *P = (void *)(target_section_addr + reloc_offset); int64 X, A, initial_addend; int32 insn, imm12; CHECK_RELOC_OFFSET(sizeof(int32)); - insn = *(int32*)P; + insn = *(int32 *)P; imm12 = (insn >> 10) & 0xFFF; SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend); @@ -347,19 +359,24 @@ apply_relocation(AOTModule *module, /* write the imm12 back to instruction */ switch (reloc_type) { case R_AARCH64_LDST8_ABS_LO12_NC: - *(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10)); + *(int32 *)P = + (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10)); break; case R_AARCH64_LDST16_ABS_LO12_NC: - *(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 1) << 10)); + *(int32 *)P = (insn & 0xFFC003FF) + | ((int32)(((X & 0xFFF) >> 1) << 10)); break; case R_AARCH64_LDST32_ABS_LO12_NC: - *(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 2) << 10)); + *(int32 *)P = (insn & 0xFFC003FF) + | ((int32)(((X & 0xFFF) >> 2) << 10)); break; case R_AARCH64_LDST64_ABS_LO12_NC: - *(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 3) << 10)); + *(int32 *)P = (insn & 0xFFC003FF) + | ((int32)(((X & 0xFFF) >> 3) << 10)); break; case R_AARCH64_LDST128_ABS_LO12_NC: - *(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 4) << 10)); + *(int32 *)P = (insn & 0xFFC003FF) + | ((int32)(((X & 0xFFF) >> 4) << 10)); break; default: bh_assert(0); diff --git a/core/iwasm/aot/arch/aot_reloc_arc.c b/core/iwasm/aot/arch/aot_reloc_arc.c new file mode 100644 index 0000000000..6c23ac679e --- /dev/null +++ b/core/iwasm/aot/arch/aot_reloc_arc.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_reloc.h" + +#define R_ARC_S21H_PCREL 14 +#define R_ARC_S21W_PCREL 15 +#define R_ARC_S25H_PCREL 16 +#define R_ARC_S25W_PCREL 17 +#define R_ARC_32 4 +#define R_ARC_32_ME 27 + +/* clang-format off */ +void __st_r13_to_r15(); +void __st_r13_to_r16(); +void __st_r13_to_r17(); +void __st_r13_to_r18(); +void __st_r13_to_r19(); +void __st_r13_to_r20(); +void __st_r13_to_r21(); +void __st_r13_to_r22(); +void __st_r13_to_r23(); +void __st_r13_to_r24(); +void __st_r13_to_r25(); +void __ld_r13_to_r15(); +void __ld_r13_to_r16(); +void __ld_r13_to_r17(); +void __ld_r13_to_r18(); +void __ld_r13_to_r19(); +void __ld_r13_to_r20(); +void __ld_r13_to_r21(); +void __ld_r13_to_r22(); +void __ld_r13_to_r23(); +void __ld_r13_to_r24(); +void __ld_r13_to_r25(); +void __adddf3(); +void __addsf3(); +void __divdf3(); +void __divdi3(); +void __divsf3(); +void __divsi3(); +void __eqsf2(); +void __extendsfdf2(); +void __fixdfsi(); +void __floatsidf(); +void __floatsisf(); +void __gedf2(); +void __gtdf2(); +void __ledf2(); +void __lesf2(); +void __ltdf2(); +void __muldf3(); +void __mulsf3(); +void __subdf3(); +void __subsf3(); +void __truncdfsf2(); +void __unorddf2(); +/* clang-format on */ + +static SymbolMap target_sym_map[] = { + /* clang-format off */ + REG_COMMON_SYMBOLS + REG_SYM(__st_r13_to_r15), + /* clang-format on */ + REG_SYM(__st_r13_to_r16), + REG_SYM(__st_r13_to_r17), + REG_SYM(__st_r13_to_r18), + REG_SYM(__st_r13_to_r19), + REG_SYM(__st_r13_to_r20), + REG_SYM(__st_r13_to_r21), + REG_SYM(__st_r13_to_r22), + REG_SYM(__st_r13_to_r23), + REG_SYM(__st_r13_to_r24), + REG_SYM(__st_r13_to_r25), + REG_SYM(__ld_r13_to_r15), + REG_SYM(__ld_r13_to_r16), + REG_SYM(__ld_r13_to_r17), + REG_SYM(__ld_r13_to_r18), + REG_SYM(__ld_r13_to_r19), + REG_SYM(__ld_r13_to_r20), + REG_SYM(__ld_r13_to_r21), + REG_SYM(__ld_r13_to_r22), + REG_SYM(__ld_r13_to_r23), + REG_SYM(__ld_r13_to_r24), + REG_SYM(__ld_r13_to_r25), + REG_SYM(__adddf3), + REG_SYM(__addsf3), + REG_SYM(__divdf3), + REG_SYM(__divdi3), + REG_SYM(__divsf3), + REG_SYM(__divsi3), + REG_SYM(__eqsf2), + REG_SYM(__extendsfdf2), + REG_SYM(__fixdfsi), + REG_SYM(__floatsidf), + REG_SYM(__floatsisf), + REG_SYM(__gedf2), + REG_SYM(__gtdf2), + REG_SYM(__ledf2), + REG_SYM(__lesf2), + REG_SYM(__ltdf2), + REG_SYM(__muldf3), + REG_SYM(__mulsf3), + REG_SYM(__subdf3), + REG_SYM(__subsf3), + REG_SYM(__truncdfsf2), + REG_SYM(__unorddf2), +}; + +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, "%s", string); +} + +SymbolMap * +get_target_symbol_map(uint32 *sym_num) +{ + *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap); + return target_sym_map; +} + +void +get_current_target(char *target_buf, uint32 target_buf_size) +{ + snprintf(target_buf, target_buf_size, "arc"); +} + +uint32 +get_plt_table_size() +{ + return 0; +} + +void +init_plt_table(uint8 *plt) +{ + (void)plt; +} + +static bool +check_reloc_offset(uint32 target_section_size, uint64 reloc_offset, + uint32 reloc_data_size, char *error_buf, + uint32 error_buf_size) +{ + if (!(reloc_offset < (uint64)target_section_size + && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid relocation offset."); + return false; + } + return true; +} + +static uint32 +middle_endian_convert(uint32 insn) +{ + return ((insn & 0xFFFF0000) >> 16) | ((insn & 0x0000FFFF) << 16); +} + +bool +apply_relocation(AOTModule *module, uint8 *target_section_addr, + uint32 target_section_size, uint64 reloc_offset, + uint64 reloc_addend, uint32 reloc_type, void *symbol_addr, + int32 symbol_index, char *error_buf, uint32 error_buf_size) +{ + switch (reloc_type) { + case R_ARC_S25W_PCREL: + { + uint32 insn = LOAD_I32(target_section_addr + reloc_offset); + int32 addend, value; + uintptr_t S, A, P; + + CHECK_RELOC_OFFSET(sizeof(void *)); + + /* Convert from middle endian */ + insn = middle_endian_convert(insn); + + addend = ((insn << 28) >> 28) << 10; + /* Extract the next 10 bits from Position 6 to 15 in insn */ + addend |= ((insn << 16) >> 22); + addend = addend << 9; + /* Extract the remaining 9 bits from Position 18 to 26 in insn */ + addend |= ((insn << 5) >> 23); + /* Fill in 2 bits to get the 25 bit Offset Value */ + addend = addend << 2; + + /* (S + A) - P */ + S = (uintptr_t)(uint8 *)symbol_addr; + A = (uintptr_t)reloc_addend; + P = (uintptr_t)(target_section_addr + reloc_offset); + P &= (uintptr_t)~3; + value = (int32)(S + A + addend - P); + + insn = insn & 0xf8030030; + insn |= ((((value >> 2) & 0x1ff) << 18) + | (((value >> 2) & 0x7fe00) >> 3) + | (((value >> 2) & 0x780000) >> 19)); + + /* Convert to middle endian */ + insn = middle_endian_convert(insn); + + STORE_U32(target_section_addr + reloc_offset, insn); + break; + } + case R_ARC_32: + case R_ARC_32_ME: + { + uint32 insn; + + CHECK_RELOC_OFFSET(sizeof(void *)); + + /* (S + A) */ + insn = (uint32)(uintptr_t)((uint8 *)symbol_addr + reloc_addend); + + if (reloc_type == R_ARC_32_ME) + /* Convert to middle endian */ + insn = middle_endian_convert(insn); + + STORE_U32(target_section_addr + reloc_offset, insn); + break; + } + default: + { + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, + "Load relocation section failed: " + "invalid relocation type %d.", + reloc_type); + return false; + } + } + return true; +} diff --git a/core/iwasm/aot/arch/aot_reloc_arm.c b/core/iwasm/aot/arch/aot_reloc_arm.c index e3e2d1a7fa..5d5091c639 100644 --- a/core/iwasm/aot/arch/aot_reloc_arm.c +++ b/core/iwasm/aot/arch/aot_reloc_arm.c @@ -5,10 +5,11 @@ #include "aot_reloc.h" -#define R_ARM_CALL 28 /* PC relative 24 bit (BL, BLX). */ -#define R_ARM_JMP24 29 /* PC relative 24 bit (B/BL). */ -#define R_ARM_ABS32 2 /* Direct 32 bit */ +#define R_ARM_CALL 28 /* PC relative 24 bit (BL, BLX). */ +#define R_ARM_JMP24 29 /* PC relative 24 bit (B/BL). */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ +/* clang-format off */ void __divdi3(); void __udivdi3(); void __moddi3(); @@ -54,11 +55,14 @@ void __aeabi_fcmple(); void __aeabi_fcmpge(); void __aeabi_f2iz(); void __aeabi_f2d(); +/* clang-format on */ static SymbolMap target_sym_map[] = { + /* clang-format off */ REG_COMMON_SYMBOLS /* compiler-rt symbols that come from compiler(e.g. gcc) */ REG_SYM(__divdi3), + /* clang-format on */ REG_SYM(__udivdi3), REG_SYM(__umoddi3), REG_SYM(__divsi3), @@ -122,7 +126,7 @@ get_target_symbol_map(uint32 *sym_num) void get_current_target(char *target_buf, uint32 target_buf_size) { - const char * s = BUILD_TARGET; + const char *s = BUILD_TARGET; size_t s_size = sizeof(BUILD_TARGET); char *d = target_buf; @@ -131,14 +135,14 @@ get_current_target(char *target_buf, uint32 target_buf_size) s = BUILD_TARGET_ARM_DEFAULT; s_size = sizeof(BUILD_TARGET_ARM_DEFAULT); } - if(target_buf_size < s_size){ + if (target_buf_size < s_size) { s_size = target_buf_size; } while (--s_size) { if (*s >= 'A' && *s <= 'Z') *d++ = *s++ + 'a' - 'A'; else - *d++ = *s++ ; + *d++ = *s++; } /* Ensure the string is null byte ('\0') terminated */ *d = '\0'; @@ -163,7 +167,7 @@ init_plt_table(uint8 *plt) { uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap); for (i = 0; i < num; i++) { - uint32 *p = (uint32*)plt; + uint32 *p = (uint32 *)plt; /* ldr pc, [pc] */ *p++ = 0xe59ff000; /* nop */ @@ -175,9 +179,9 @@ init_plt_table(uint8 *plt) } static bool -check_reloc_offset(uint32 target_section_size, - uint64 reloc_offset, uint32 reloc_data_size, - char *error_buf, uint32 error_buf_size) +check_reloc_offset(uint32 target_section_size, uint64 reloc_offset, + uint32 reloc_data_size, char *error_buf, + uint32 error_buf_size) { if (!(reloc_offset < (uint64)target_section_size && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { @@ -189,11 +193,10 @@ check_reloc_offset(uint32 target_section_size, } bool -apply_relocation(AOTModule *module, - uint8 *target_section_addr, uint32 target_section_size, - uint64 reloc_offset, uint64 reloc_addend, - uint32 reloc_type, void *symbol_addr, int32 symbol_index, - char *error_buf, uint32 error_buf_size) +apply_relocation(AOTModule *module, uint8 *target_section_addr, + uint32 target_section_size, uint64 reloc_offset, + uint64 reloc_addend, uint32 reloc_type, void *symbol_addr, + int32 symbol_index, char *error_buf, uint32 error_buf_size) { switch (reloc_type) { case R_ARM_CALL: @@ -201,10 +204,10 @@ apply_relocation(AOTModule *module, { intptr_t result; int32 RESULT_MASK = 0x03FFFFFE; - int32 insn = *(int32*)(target_section_addr + reloc_offset); + int32 insn = *(int32 *)(target_section_addr + reloc_offset); /* Initial addend: sign_extend(insn[23:0] << 2) */ - int32 initial_addend = ((insn & 0xFFFFFF) << 2) - | ((insn & 0x800000) ? 0xFC000000 : 0); + int32 initial_addend = + ((insn & 0xFFFFFF) << 2) | ((insn & 0x800000) ? 0xFC000000 : 0); CHECK_RELOC_OFFSET(sizeof(int32)); @@ -214,17 +217,18 @@ apply_relocation(AOTModule *module, * Suppose the symbol address is in +-32MB relative * to the relocation address. */ - /* operation: ((S + A) | T) - P where S is symbol address and T is 0 */ - result = (intptr_t) - ((uint8*)symbol_addr + reloc_addend - - (target_section_addr + reloc_offset)); + /* operation: ((S + A) | T) - P where S is symbol address and T + * is 0 */ + result = (intptr_t)((uint8 *)symbol_addr + reloc_addend + - (target_section_addr + reloc_offset)); } else { if (reloc_addend > 0) { - set_error_buf(error_buf, error_buf_size, - "AOT module load failed: relocate to plt table " - "with reloc addend larger than 0 is unsupported."); - return false; + set_error_buf( + error_buf, error_buf_size, + "AOT module load failed: relocate to plt table " + "with reloc addend larger than 0 is unsupported."); + return false; } /* Symbol address is not an AOT function, @@ -232,12 +236,13 @@ apply_relocation(AOTModule *module, * beyond of the +-32MB space. Apply relocation with * the PLT which branch to the target symbol address. */ - /* operation: ((S + A) | T) - P where S is PLT address and T is 0 */ - uint8 *plt = (uint8*)module->code + module->code_size - get_plt_table_size() + /* operation: ((S + A) | T) - P where S is PLT address and T is + * 0 */ + uint8 *plt = (uint8 *)module->code + module->code_size + - get_plt_table_size() + get_plt_item_size() * symbol_index; - result = (intptr_t) - (plt + reloc_addend - - (target_section_addr + reloc_offset)); + result = (intptr_t)(plt + reloc_addend + - (target_section_addr + reloc_offset)); } result += initial_addend; @@ -250,20 +255,20 @@ apply_relocation(AOTModule *module, return false; } - *(int32*)(target_section_addr + reloc_offset) = - (int32) - ((insn & 0xff000000) - | (((int32)result & RESULT_MASK) >> 2)); + *(int32 *)(target_section_addr + reloc_offset) = + (int32)((insn & 0xff000000) + | (((int32)result & RESULT_MASK) >> 2)); break; } case R_ARM_ABS32: { intptr_t initial_addend; /* (S + A) | T where T is 0 */ - CHECK_RELOC_OFFSET(sizeof(void*)); - initial_addend = *(intptr_t*)(target_section_addr + (uint32)reloc_offset); - *(uint8**)(target_section_addr + reloc_offset) - = (uint8*)symbol_addr + initial_addend + reloc_addend; + CHECK_RELOC_OFFSET(sizeof(void *)); + initial_addend = + *(intptr_t *)(target_section_addr + (uint32)reloc_offset); + *(uint8 **)(target_section_addr + reloc_offset) = + (uint8 *)symbol_addr + initial_addend + reloc_addend; break; } @@ -278,4 +283,3 @@ apply_relocation(AOTModule *module, return true; } - diff --git a/core/iwasm/aot/arch/aot_reloc_mips.c b/core/iwasm/aot/arch/aot_reloc_mips.c index c1b3fa54c0..8e43cc031c 100644 --- a/core/iwasm/aot/arch/aot_reloc_mips.c +++ b/core/iwasm/aot/arch/aot_reloc_mips.c @@ -5,12 +5,14 @@ #include "aot_reloc.h" -#define R_MIPS_32 2 /* Direct 32 bit */ -#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +/* clang-format off */ static SymbolMap target_sym_map[] = { REG_COMMON_SYMBOLS }; +/* clang-format on */ SymbolMap * get_target_symbol_map(uint32 *sym_num) @@ -44,11 +46,10 @@ get_plt_table_size() } bool -apply_relocation(AOTModule *module, - uint8 *target_section_addr, uint32 target_section_size, - uint64 reloc_offset, uint64 reloc_addend, - uint32 reloc_type, void *symbol_addr, int32 symbol_index, - char *error_buf, uint32 error_buf_size) +apply_relocation(AOTModule *module, uint8 *target_section_addr, + uint32 target_section_size, uint64 reloc_offset, + uint64 reloc_addend, uint32 reloc_type, void *symbol_addr, + int32 symbol_index, char *error_buf, uint32 error_buf_size) { switch (reloc_type) { /* TODO: implement relocation for mips */ @@ -66,4 +67,3 @@ apply_relocation(AOTModule *module, return true; } - diff --git a/core/iwasm/aot/arch/aot_reloc_riscv.c b/core/iwasm/aot/arch/aot_reloc_riscv.c new file mode 100644 index 0000000000..05b8d734db --- /dev/null +++ b/core/iwasm/aot/arch/aot_reloc_riscv.c @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2021 XiaoMi Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_reloc.h" + +#define R_RISCV_32 1 +#define R_RISCV_64 2 +#define R_RISCV_CALL 18 +#define R_RISCV_CALL_PLT 19 +#define R_RISCV_HI20 26 +#define R_RISCV_LO12_I 27 +#define R_RISCV_LO12_S 28 + +#define RV_OPCODE_SW 0x23 + +/* clang-format off */ +void __divdi3(); +void __moddi3(); +void __muldi3(); +void __udivdi3(); +void __umoddi3(); +/* clang-format on */ + +static SymbolMap target_sym_map[] = { + /* clang-format off */ + REG_COMMON_SYMBOLS + REG_SYM(__divdi3), + /* clang-format on */ + REG_SYM(__moddi3), + REG_SYM(__muldi3), + REG_SYM(__udivdi3), + REG_SYM(__umoddi3), +}; + +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, "%s", string); +} + +void +get_current_target(char *target_buf, uint32 target_buf_size) +{ + snprintf(target_buf, target_buf_size, "riscv"); +} + +uint32 +get_plt_item_size() +{ +#if __riscv_xlen == 64 + /* auipc + ld + jalr + nop + addr */ + return 20; +#else + return 0; +#endif +} + +SymbolMap * +get_target_symbol_map(uint32 *sym_num) +{ + *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap); + return target_sym_map; +} + +/* Get a val from given address */ +static uint32 +rv_get_val(uint16 *addr) +{ + uint32 ret; + ret = *addr | (*(addr + 1)) << 16; + return ret; +} + +/* Set a val to given address */ +static void +rv_set_val(uint16 *addr, uint32 val) +{ + *addr = (val & 0xffff); + *(addr + 1) = (val >> 16); + + __asm__ volatile("fence.i"); +} + +/* Add a val to given address */ +static void +rv_add_val(uint16 *addr, uint32 val) +{ + uint32 cur = rv_get_val(addr); + rv_set_val(addr, cur + val); +} + +/** + * Get imm_hi and imm_lo from given integer + * + * @param imm given integer, signed 32bit + * @param imm_hi signed 20bit + * @param imm_lo signed 12bit + * + */ +static void +rv_calc_imm(int32 imm, int32 *imm_hi, int32 *imm_lo) +{ + int32 lo; + int32 hi = imm / 4096; + int32 r = imm % 4096; + + if (2047 < r) { + hi++; + } + else if (r < -2048) { + hi--; + } + + lo = imm - (hi * 4096); + + *imm_lo = lo; + *imm_hi = hi; +} + +uint32 +get_plt_table_size() +{ + return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap)); +} + +void +init_plt_table(uint8 *plt) +{ +#if __riscv_xlen == 64 + uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap); + uint8 *p; + + for (i = 0; i < num; i++) { + p = plt; + /* auipc t1, 0 */ + *(uint16 *)p = 0x0317; + p += 2; + *(uint16 *)p = 0x0000; + p += 2; + /* ld t1, 8(t1) */ + *(uint16 *)p = 0x3303; + p += 2; + *(uint16 *)p = 0x00C3; + p += 2; + /* jr t1 */ + *(uint16 *)p = 0x8302; + p += 2; + /* nop */ + *(uint16 *)p = 0x0001; + p += 2; + bh_memcpy_s(p, 8, &target_sym_map[i].symbol_addr, 8); + p += 8; + plt += get_plt_item_size(); + } +#endif +} + +typedef struct RelocTypeStrMap { + uint32 reloc_type; + char *reloc_str; +} RelocTypeStrMap; + +#define RELOC_TYPE_MAP(reloc_type) \ + { \ + reloc_type, #reloc_type \ + } + +static RelocTypeStrMap reloc_type_str_maps[] = { + RELOC_TYPE_MAP(R_RISCV_32), RELOC_TYPE_MAP(R_RISCV_CALL), + RELOC_TYPE_MAP(R_RISCV_CALL_PLT), RELOC_TYPE_MAP(R_RISCV_HI20), + RELOC_TYPE_MAP(R_RISCV_LO12_I), RELOC_TYPE_MAP(R_RISCV_LO12_S), +}; + +static const char * +reloc_type_to_str(uint32 reloc_type) +{ + uint32 i; + + for (i = 0; i < sizeof(reloc_type_str_maps) / sizeof(RelocTypeStrMap); + i++) { + if (reloc_type_str_maps[i].reloc_type == reloc_type) + return reloc_type_str_maps[i].reloc_str; + } + + return "Unknown_Reloc_Type"; +} + +static bool +check_reloc_offset(uint32 target_section_size, uint64 reloc_offset, + uint32 reloc_data_size, char *error_buf, + uint32 error_buf_size) +{ + if (!(reloc_offset < (uint64)target_section_size + && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid relocation offset."); + return false; + } + return true; +} + +bool +apply_relocation(AOTModule *module, uint8 *target_section_addr, + uint32 target_section_size, uint64 reloc_offset, + uint64 reloc_addend, uint32 reloc_type, void *symbol_addr, + int32 symbol_index, char *error_buf, uint32 error_buf_size) +{ + int32 val, imm_hi, imm_lo, insn; + uint8 *addr = target_section_addr + reloc_offset; + char buf[128]; + + switch (reloc_type) { + case R_RISCV_32: + { + uint32 val_32 = + (uint32)(uintptr_t)((uint8 *)symbol_addr + reloc_addend); + + CHECK_RELOC_OFFSET(sizeof(uint32)); + if (val_32 != (uintptr_t)((uint8 *)symbol_addr + reloc_addend)) { + goto fail_addr_out_of_range; + } + + rv_set_val((uint16 *)addr, val_32); + break; + } + case R_RISCV_64: + { + uint64 val_64 = + (uint64)(uintptr_t)((uint8 *)symbol_addr + reloc_addend); + CHECK_RELOC_OFFSET(sizeof(uint64)); + bh_memcpy_s(addr, 8, &val_64, 8); + break; + } + case R_RISCV_CALL: + case R_RISCV_CALL_PLT: + { + val = (int32)(intptr_t)((uint8 *)symbol_addr - addr); + + CHECK_RELOC_OFFSET(sizeof(uint32)); + if (val != (intptr_t)((uint8 *)symbol_addr - addr)) { + if (symbol_index >= 0) { + /* Call runtime function by plt code */ + symbol_addr = (uint8 *)module->code + module->code_size + - get_plt_table_size() + + get_plt_item_size() * symbol_index; + val = (int32)(intptr_t)((uint8 *)symbol_addr - addr); + } + } + + if (val != (intptr_t)((uint8 *)symbol_addr - addr)) { + goto fail_addr_out_of_range; + } + + rv_calc_imm(val, &imm_hi, &imm_lo); + + rv_add_val((uint16 *)addr, (imm_hi << 12)); + if ((rv_get_val((uint16 *)(addr + 4)) & 0x7f) == RV_OPCODE_SW) { + /* Adjust imm for SW : S-type */ + val = (((int32)imm_lo >> 5) << 25) + + (((int32)imm_lo & 0x1f) << 7); + + rv_add_val((uint16 *)(addr + 4), val); + } + else { + /* Adjust imm for MV(ADDI)/JALR : I-type */ + rv_add_val((uint16 *)(addr + 4), ((int32)imm_lo << 20)); + } + break; + } + + case R_RISCV_HI20: + { + val = (int32)(intptr_t)((uint8 *)symbol_addr + reloc_addend); + + CHECK_RELOC_OFFSET(sizeof(uint32)); + if (val != (intptr_t)((uint8 *)symbol_addr + reloc_addend)) { + goto fail_addr_out_of_range; + } + + addr = target_section_addr + reloc_offset; + insn = rv_get_val((uint16 *)addr); + rv_calc_imm(val, &imm_hi, &imm_lo); + insn = (insn & 0x00000fff) | (imm_hi << 12); + rv_set_val((uint16 *)addr, insn); + break; + } + + case R_RISCV_LO12_I: + { + val = (int32)(intptr_t)((uint8 *)symbol_addr + reloc_addend); + + CHECK_RELOC_OFFSET(sizeof(uint32)); + if (val != (intptr_t)((uint8 *)symbol_addr + reloc_addend)) { + goto fail_addr_out_of_range; + } + + addr = target_section_addr + reloc_offset; + insn = rv_get_val((uint16 *)addr); + rv_calc_imm(val, &imm_hi, &imm_lo); + insn = (insn & 0x000fffff) | (imm_lo << 20); + rv_set_val((uint16 *)addr, insn); + break; + } + + case R_RISCV_LO12_S: + { + val = (int32)(intptr_t)((uint8 *)symbol_addr + reloc_addend); + + CHECK_RELOC_OFFSET(sizeof(uint32)); + if (val != (intptr_t)((uint8 *)symbol_addr + reloc_addend)) { + goto fail_addr_out_of_range; + } + + addr = target_section_addr + reloc_offset; + rv_calc_imm(val, &imm_hi, &imm_lo); + val = (((int32)imm_lo >> 5) << 25) + (((int32)imm_lo & 0x1f) << 7); + rv_add_val((uint16 *)addr, val); + break; + } + + default: + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, + "Load relocation section failed: " + "invalid relocation type %d.", + reloc_type); + return false; + } + + return true; + +fail_addr_out_of_range: + snprintf(buf, sizeof(buf), + "AOT module load failed: " + "relocation truncated to fit %s failed.", + reloc_type_to_str(reloc_type)); + set_error_buf(error_buf, error_buf_size, buf); + return false; +} diff --git a/core/iwasm/aot/arch/aot_reloc_thumb.c b/core/iwasm/aot/arch/aot_reloc_thumb.c index 8b7bc748b2..1da8c86d31 100644 --- a/core/iwasm/aot/arch/aot_reloc_thumb.c +++ b/core/iwasm/aot/arch/aot_reloc_thumb.c @@ -5,9 +5,10 @@ #include "aot_reloc.h" -#define R_ARM_THM_CALL 10 /* PC relative (Thumb BL and ARMv5 Thumb BLX). */ -#define R_ARM_THM_JMP24 30 /* B.W */ +#define R_ARM_THM_CALL 10 /* PC relative (Thumb BL and ARMv5 Thumb BLX). */ +#define R_ARM_THM_JMP24 30 /* B.W */ +/* clang-format off */ void __ltdf2(); void __adddf3(); void __eqdf2(); @@ -45,6 +46,7 @@ void __aeabi_d2lz(); void __aeabi_l2d(); void __aeabi_f2ulz(); void __aeabi_ul2d(); +void __aeabi_ui2d(); void __aeabi_d2ulz(); void __aeabi_idiv(); void __aeabi_uidiv(); @@ -59,18 +61,23 @@ void __aeabi_dcmplt(); void __aeabi_dcmpun(); void __aeabi_dcmple(); void __aeabi_dcmpge(); +void __aeabi_dcmpgt(); void __aeabi_d2iz(); +void __aeabi_d2uiz(); void __aeabi_fcmplt(); void __aeabi_fcmpun(); void __aeabi_fcmple(); void __aeabi_fcmpge(); void __aeabi_f2iz(); void __aeabi_f2d(); +/* clang-format on */ static SymbolMap target_sym_map[] = { + /* clang-format off */ REG_COMMON_SYMBOLS /* compiler-rt symbols that come from compiler(e.g. gcc) */ REG_SYM(__ltdf2), + /* clang-format on */ REG_SYM(__adddf3), REG_SYM(__eqdf2), REG_SYM(__unorddf2), @@ -106,6 +113,7 @@ static SymbolMap target_sym_map[] = { REG_SYM(__aeabi_l2d), REG_SYM(__aeabi_f2ulz), REG_SYM(__aeabi_ul2d), + REG_SYM(__aeabi_ui2d), REG_SYM(__aeabi_d2ulz), REG_SYM(__aeabi_idiv), REG_SYM(__aeabi_uidiv), @@ -120,7 +128,9 @@ static SymbolMap target_sym_map[] = { REG_SYM(__aeabi_dcmpun), REG_SYM(__aeabi_dcmple), REG_SYM(__aeabi_dcmpge), + REG_SYM(__aeabi_dcmpgt), REG_SYM(__aeabi_d2iz), + REG_SYM(__aeabi_d2uiz), REG_SYM(__aeabi_fcmplt), REG_SYM(__aeabi_fcmpun), REG_SYM(__aeabi_fcmple), @@ -147,7 +157,7 @@ get_target_symbol_map(uint32 *sym_num) void get_current_target(char *target_buf, uint32 target_buf_size) { - const char * s = BUILD_TARGET; + const char *s = BUILD_TARGET; size_t s_size = sizeof(BUILD_TARGET); char *d = target_buf; @@ -156,14 +166,14 @@ get_current_target(char *target_buf, uint32 target_buf_size) s = BUILD_TARGET_THUMB_V4T; s_size = sizeof(BUILD_TARGET_THUMB_V4T); } - if(target_buf_size < s_size){ + if (target_buf_size < s_size) { s_size = target_buf_size; } while (--s_size) { if (*s >= 'A' && *s <= 'Z') *d++ = *s++ + 'a' - 'A'; else - *d++ = *s++ ; + *d++ = *s++; } /* Ensure the string is null byte ('\0') terminated */ *d = '\0'; @@ -188,7 +198,7 @@ init_plt_table(uint8 *plt) { uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap); for (i = 0; i < num; i++) { - uint16 *p = (uint16*)plt; + uint16 *p = (uint16 *)plt; /* nop */ *p++ = 0xbf00; /* push {r4} */ @@ -206,15 +216,15 @@ init_plt_table(uint8 *plt) /* nop */ *p++ = 0xbf00; /* symbol addr */ - *(uint32*)p = (uint32)(uintptr_t)target_sym_map[i].symbol_addr; + *(uint32 *)p = (uint32)(uintptr_t)target_sym_map[i].symbol_addr; plt += get_plt_item_size(); } } static bool -check_reloc_offset(uint32 target_section_size, - uint64 reloc_offset, uint32 reloc_data_size, - char *error_buf, uint32 error_buf_size) +check_reloc_offset(uint32 target_section_size, uint64 reloc_offset, + uint32 reloc_data_size, char *error_buf, + uint32 error_buf_size) { if (!(reloc_offset < (uint64)target_section_size && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { @@ -226,11 +236,10 @@ check_reloc_offset(uint32 target_section_size, } bool -apply_relocation(AOTModule *module, - uint8 *target_section_addr, uint32 target_section_size, - uint64 reloc_offset, uint64 reloc_addend, - uint32 reloc_type, void *symbol_addr, int32 symbol_index, - char *error_buf, uint32 error_buf_size) +apply_relocation(AOTModule *module, uint8 *target_section_addr, + uint32 target_section_size, uint64 reloc_offset, + uint64 reloc_addend, uint32 reloc_type, void *symbol_addr, + int32 symbol_index, char *error_buf, uint32 error_buf_size) { switch (reloc_type) { case R_ARM_THM_CALL: @@ -244,7 +253,7 @@ apply_relocation(AOTModule *module, CHECK_RELOC_OFFSET(sizeof(int32)); - reloc_addr = (int16*)(target_section_addr + reloc_offset); + reloc_addr = (int16 *)(target_section_addr + reloc_offset); initial_addend_0 = (*reloc_addr) & 0x7FF; initial_addend_1 = (*(reloc_addr + 1)) & 0x7FF; sign = (initial_addend_0 & 0x400) ? true : false; @@ -257,16 +266,20 @@ apply_relocation(AOTModule *module, * Suppose the symbol address is in +-4MB relative * to the relocation address. */ - /* operation: ((S + A) | T) - P where S is symbol address and T is 1 */ - result = (int32)(((intptr_t)((uint8*)symbol_addr + reloc_addend) | 1) - - (intptr_t)(target_section_addr + reloc_offset)); + /* operation: ((S + A) | T) - P where S is symbol address + and T is 1 */ + result = + (int32)(((intptr_t)((uint8 *)symbol_addr + reloc_addend) + | 1) + - (intptr_t)(target_section_addr + reloc_offset)); } else { if (reloc_addend > 0) { - set_error_buf(error_buf, error_buf_size, - "AOT module load failed: relocate to plt table " - "with reloc addend larger than 0 is unsupported."); - return false; + set_error_buf( + error_buf, error_buf_size, + "AOT module load failed: relocate to plt table " + "with reloc addend larger than 0 is unsupported."); + return false; } /* Symbol address is not an AOT function, @@ -274,11 +287,14 @@ apply_relocation(AOTModule *module, * beyond of the +-4MB space. Apply relocation with * the PLT which branch to the target symbol address. */ - /* operation: ((S + A) | T) - P where S is PLT address and T is 1 */ - uint8 *plt = (uint8*)module->code + module->code_size - get_plt_table_size() + /* operation: ((S + A) | T) - P where S is PLT address + and T is 1 */ + uint8 *plt = (uint8 *)module->code + module->code_size + - get_plt_table_size() + get_plt_item_size() * symbol_index + 1; - result = (int32)(((intptr_t)plt | 1) - - (intptr_t)(target_section_addr + reloc_offset)); + result = + (int32)(((intptr_t)plt | 1) + - (intptr_t)(target_section_addr + reloc_offset)); } result += initial_addend; @@ -310,4 +326,3 @@ apply_relocation(AOTModule *module, } return true; } - diff --git a/core/iwasm/aot/arch/aot_reloc_x86_32.c b/core/iwasm/aot/arch/aot_reloc_x86_32.c index 2b13b1dab3..784468231d 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_32.c +++ b/core/iwasm/aot/arch/aot_reloc_x86_32.c @@ -5,17 +5,19 @@ #include "aot_reloc.h" -#define R_386_32 1 /* Direct 32 bit */ -#define R_386_PC32 2 /* PC relative 32 bit */ +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ #if !defined(_WIN32) && !defined(_WIN32_) +/* clang-format off */ void __divdi3(); void __udivdi3(); void __moddi3(); void __umoddi3(); +/* clang-format on */ #else -#pragma function (floor) -#pragma function (ceil) +#pragma function(floor) +#pragma function(ceil) static int64 __divdi3(int64 a, int64 b) @@ -42,6 +44,7 @@ __umoddi3(uint64 a, uint64 b) } #endif +/* clang-format off */ static SymbolMap target_sym_map[] = { REG_COMMON_SYMBOLS /* compiler-rt symbols that come from compiler(e.g. gcc) */ @@ -50,6 +53,7 @@ static SymbolMap target_sym_map[] = { REG_SYM(__moddi3), REG_SYM(__umoddi3) }; +/* clang-format on */ static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) @@ -84,9 +88,9 @@ init_plt_table(uint8 *plt) } static bool -check_reloc_offset(uint32 target_section_size, - uint64 reloc_offset, uint32 reloc_data_size, - char *error_buf, uint32 error_buf_size) +check_reloc_offset(uint32 target_section_size, uint64 reloc_offset, + uint32 reloc_data_size, char *error_buf, + uint32 error_buf_size) { if (!(reloc_offset < (uint64)target_section_size && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { @@ -98,21 +102,20 @@ check_reloc_offset(uint32 target_section_size, } bool -apply_relocation(AOTModule *module, - uint8 *target_section_addr, uint32 target_section_size, - uint64 reloc_offset, uint64 reloc_addend, - uint32 reloc_type, void *symbol_addr, int32 symbol_index, - char *error_buf, uint32 error_buf_size) +apply_relocation(AOTModule *module, uint8 *target_section_addr, + uint32 target_section_size, uint64 reloc_offset, + uint64 reloc_addend, uint32 reloc_type, void *symbol_addr, + int32 symbol_index, char *error_buf, uint32 error_buf_size) { switch (reloc_type) { case R_386_32: { intptr_t value; - CHECK_RELOC_OFFSET(sizeof(void*)); - value = *(intptr_t*)(target_section_addr + (uint32)reloc_offset); - *(uint8**)(target_section_addr + reloc_offset) - = (uint8*)symbol_addr + reloc_addend + value; /* S + A */ + CHECK_RELOC_OFFSET(sizeof(void *)); + value = *(intptr_t *)(target_section_addr + (uint32)reloc_offset); + *(uint8 **)(target_section_addr + reloc_offset) = + (uint8 *)symbol_addr + reloc_addend + value; /* S + A */ break; } @@ -120,12 +123,12 @@ apply_relocation(AOTModule *module, { int32 value; - CHECK_RELOC_OFFSET(sizeof(void*)); - value = *(int32*)(target_section_addr + (uint32)reloc_offset); - *(uint32*)(target_section_addr + (uint32)reloc_offset) = (uint32) - ((uint8*)symbol_addr + (uint32)reloc_addend - - (uint8*)(target_section_addr + (uint32)reloc_offset) - + value); /* S + A - P */ + CHECK_RELOC_OFFSET(sizeof(void *)); + value = *(int32 *)(target_section_addr + (uint32)reloc_offset); + *(uint32 *)(target_section_addr + (uint32)reloc_offset) = + (uint32)((uint8 *)symbol_addr + (uint32)reloc_addend + - (uint8 *)(target_section_addr + (uint32)reloc_offset) + + value); /* S + A - P */ break; } @@ -139,4 +142,3 @@ apply_relocation(AOTModule *module, } return true; } - diff --git a/core/iwasm/aot/arch/aot_reloc_x86_64.c b/core/iwasm/aot/arch/aot_reloc_x86_64.c index a04b6a6eee..be5d09f8bc 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_64.c +++ b/core/iwasm/aot/arch/aot_reloc_x86_64.c @@ -6,30 +6,34 @@ #include "aot_reloc.h" #if !defined(BH_PLATFORM_WINDOWS) -#define R_X86_64_64 1 /* Direct 64 bit */ -#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ -#define R_X86_64_PLT32 4 /* 32 bit PLT address */ -#define R_X86_64_32 10 /* Direct 32 bit zero extended */ -#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ #else #ifndef IMAGE_REL_AMD64_ADDR64 #define IMAGE_REL_AMD64_ADDR64 1 /* The 64-bit VA of the relocation target */ #define IMAGE_REL_AMD64_ADDR32 2 /* The 32-bit VA of the relocation target */ +/* clang-format off */ #define IMAGE_REL_AMD64_REL32 4 /* The 32-bit relative address from the byte following the relocation*/ +/* clang-format on */ #endif #endif #if defined(BH_PLATFORM_WINDOWS) -#pragma function (floor) -#pragma function (ceil) -#pragma function (floorf) -#pragma function (ceilf) +#pragma function(floor) +#pragma function(ceil) +#pragma function(floorf) +#pragma function(ceilf) #endif +/* clang-format off */ static SymbolMap target_sym_map[] = { REG_COMMON_SYMBOLS }; +/* clang-format on */ static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) @@ -61,8 +65,8 @@ get_plt_item_size() uint32 get_plt_table_size() { - uint32 size = get_plt_item_size() - * (sizeof(target_sym_map) / sizeof(SymbolMap)); + uint32 size = + get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap)); #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) size += get_plt_item_size() + sizeof(AOTUnwindInfo); #endif @@ -80,7 +84,7 @@ init_plt_table(uint8 *plt) /* mov symbol_addr, rax */ *p++ = 0x48; *p++ = 0xB8; - *(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr; + *(uint64 *)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr; p += sizeof(uint64); /* jmp rax */ *p++ = 0xFF; @@ -92,19 +96,19 @@ init_plt_table(uint8 *plt) p = plt; /* mov exception_handler, rax */ *p++ = 0x48; - *p++ = 0xB8; - *(uint64*)p = 0;/*(uint64)(uintptr_t)aot_exception_handler;*/ + *p++ = 0xB8; + *(uint64 *)p = 0; /*(uint64)(uintptr_t)aot_exception_handler;*/ p += sizeof(uint64); /* jmp rax */ - *p++ = 0xFF; - *p++ = 0xE0; + *p++ = 0xFF; + *p++ = 0xE0; #endif } static bool -check_reloc_offset(uint32 target_section_size, - uint64 reloc_offset, uint32 reloc_data_size, - char *error_buf, uint32 error_buf_size) +check_reloc_offset(uint32 target_section_size, uint64 reloc_offset, + uint32 reloc_data_size, char *error_buf, + uint32 error_buf_size) { if (!(reloc_offset < (uint64)target_section_size && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { @@ -116,11 +120,10 @@ check_reloc_offset(uint32 target_section_size, } bool -apply_relocation(AOTModule *module, - uint8 *target_section_addr, uint32 target_section_size, - uint64 reloc_offset, uint64 reloc_addend, - uint32 reloc_type, void *symbol_addr, int32 symbol_index, - char *error_buf, uint32 error_buf_size) +apply_relocation(AOTModule *module, uint8 *target_section_addr, + uint32 target_section_size, uint64 reloc_offset, + uint64 reloc_addend, uint32 reloc_type, void *symbol_addr, + int32 symbol_index, char *error_buf, uint32 error_buf_size) { switch (reloc_type) { #if !defined(BH_PLATFORM_WINDOWS) @@ -131,10 +134,10 @@ apply_relocation(AOTModule *module, { intptr_t value; - CHECK_RELOC_OFFSET(sizeof(void*)); - value = *(intptr_t*)(target_section_addr + (uint32)reloc_offset); - *(uint8**)(target_section_addr + reloc_offset) - = (uint8*)symbol_addr + reloc_addend + value; /* S + A */ + CHECK_RELOC_OFFSET(sizeof(void *)); + value = *(intptr_t *)(target_section_addr + (uint32)reloc_offset); + *(uint8 **)(target_section_addr + reloc_offset) = + (uint8 *)symbol_addr + reloc_addend + value; /* S + A */ break; } #if defined(BH_PLATFORM_WINDOWS) @@ -144,14 +147,14 @@ apply_relocation(AOTModule *module, uintptr_t target_addr; CHECK_RELOC_OFFSET(sizeof(void *)); - value = *(int32*)(target_section_addr + (uint32)reloc_offset); + value = *(int32 *)(target_section_addr + (uint32)reloc_offset); target_addr = (uintptr_t)symbol_addr + reloc_addend + value; if ((int32)target_addr != target_addr) { - set_error_buf( - error_buf, error_buf_size, - "AOT module load failed: " - "relocation truncated to fit IMAGE_REL_AMD64_ADDR32 failed. " - "Try using wamrc with --size-level=1 option."); + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "relocation truncated to fit " + "IMAGE_REL_AMD64_ADDR32 failed. " + "Try using wamrc with --size-level=1 option."); return false; } @@ -162,20 +165,21 @@ apply_relocation(AOTModule *module, #if !defined(BH_PLATFORM_WINDOWS) case R_X86_64_PC32: { - intptr_t target_addr = (intptr_t) /* S + A - P */ - ((uint8*)symbol_addr + reloc_addend - - (target_section_addr + reloc_offset)); + intptr_t target_addr = (intptr_t) /* S + A - P */ + ((uint8 *)symbol_addr + reloc_addend + - (target_section_addr + reloc_offset)); CHECK_RELOC_OFFSET(sizeof(int32)); if ((int32)target_addr != target_addr) { - set_error_buf(error_buf, error_buf_size, - "AOT module load failed: " - "relocation truncated to fit R_X86_64_PC32 failed. " - "Try using wamrc with --size-level=1 option."); + set_error_buf( + error_buf, error_buf_size, + "AOT module load failed: " + "relocation truncated to fit R_X86_64_PC32 failed. " + "Try using wamrc with --size-level=1 option."); return false; } - *(int32*)(target_section_addr + reloc_offset) = (int32)target_addr; + *(int32 *)(target_section_addr + reloc_offset) = (int32)target_addr; break; } case R_X86_64_32: @@ -183,7 +187,7 @@ apply_relocation(AOTModule *module, { char buf[128]; uintptr_t target_addr = (uintptr_t) /* S + A */ - ((uint8*)symbol_addr + reloc_addend); + ((uint8 *)symbol_addr + reloc_addend); CHECK_RELOC_OFFSET(sizeof(int32)); @@ -192,16 +196,16 @@ apply_relocation(AOTModule *module, || (reloc_type == R_X86_64_32S && (int32)target_addr != (int64)target_addr)) { snprintf(buf, sizeof(buf), - "AOT module load failed: " - "relocation truncated to fit %s failed. " - "Try using wamrc with --size-level=1 option.", - reloc_type == R_X86_64_32 - ? "R_X86_64_32" : "R_X86_64_32S"); + "AOT module load failed: " + "relocation truncated to fit %s failed. " + "Try using wamrc with --size-level=1 option.", + reloc_type == R_X86_64_32 ? "R_X86_64_32" + : "R_X86_64_32S"); set_error_buf(error_buf, error_buf_size, buf); return false; } - *(int32*)(target_section_addr + reloc_offset) = (int32)target_addr; + *(int32 *)(target_section_addr + reloc_offset) = (int32)target_addr; break; } #endif @@ -217,16 +221,16 @@ apply_relocation(AOTModule *module, CHECK_RELOC_OFFSET(sizeof(int32)); if (symbol_index >= 0) { - plt = (uint8*)module->code + module->code_size - get_plt_table_size() + plt = (uint8 *)module->code + module->code_size + - get_plt_table_size() + get_plt_item_size() * symbol_index; - target_addr = (intptr_t) /* L + A - P */ - (plt + reloc_addend - - (target_section_addr + reloc_offset)); + target_addr = (intptr_t) /* L + A - P */ + (plt + reloc_addend - (target_section_addr + reloc_offset)); } else { - target_addr = (intptr_t) /* L + A - P */ - ((uint8*)symbol_addr + reloc_addend - - (target_section_addr + reloc_offset)); + target_addr = (intptr_t) /* L + A - P */ + ((uint8 *)symbol_addr + reloc_addend + - (target_section_addr + reloc_offset)); } #if defined(BH_PLATFORM_WINDOWS) @@ -244,7 +248,7 @@ apply_relocation(AOTModule *module, "Try using wamrc with --size-level=1 option."); return false; } - *(int32*)(target_section_addr + reloc_offset) = (int32)target_addr; + *(int32 *)(target_section_addr + reloc_offset) = (int32)target_addr; break; } @@ -259,4 +263,3 @@ apply_relocation(AOTModule *module, return true; } - diff --git a/core/iwasm/aot/arch/aot_reloc_xtensa.c b/core/iwasm/aot/arch/aot_reloc_xtensa.c index 91499a1736..d60231f8f5 100644 --- a/core/iwasm/aot/arch/aot_reloc_xtensa.c +++ b/core/iwasm/aot/arch/aot_reloc_xtensa.c @@ -5,9 +5,10 @@ #include "aot_reloc.h" -#define R_XTENSA_32 1 /* Direct 32 bit */ -#define R_XTENSA_SLOT0_OP 20 /* PC relative */ +#define R_XTENSA_32 1 /* Direct 32 bit */ +#define R_XTENSA_SLOT0_OP 20 /* PC relative */ +/* clang-format off */ /* for soft-float */ void __floatsidf(); void __divdf3(); @@ -38,9 +39,9 @@ static SymbolMap target_sym_map[] = { REG_SYM(__muldi3), REG_SYM(__modsi3), - REG_SYM(__divdi3), }; +/* clang-format on */ static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) @@ -81,9 +82,9 @@ get_plt_table_size() } static bool -check_reloc_offset(uint32 target_section_size, - uint64 reloc_offset, uint32 reloc_data_size, - char *error_buf, uint32 error_buf_size) +check_reloc_offset(uint32 target_section_size, uint64 reloc_offset, + uint32 reloc_data_size, char *error_buf, + uint32 error_buf_size) { if (!(reloc_offset < (uint64)target_section_size && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { @@ -106,18 +107,18 @@ put_imm16_to_addr(int16 imm16, int16 *addr) int8 bytes[8]; int32 *addr_aligned1, *addr_aligned2; - addr_aligned1 = (int32*)((intptr_t)addr & ~3); + addr_aligned1 = (int32 *)((intptr_t)addr & ~3); if ((intptr_t)addr % 4 != 3) { - *(int32*)bytes = *addr_aligned1; - *(int16*)(bytes + ((intptr_t)addr % 4)) = imm16; + *(int32 *)bytes = *addr_aligned1; + *(int16 *)(bytes + ((intptr_t)addr % 4)) = imm16; memcpy(addr_aligned1, bytes, 4); } else { - addr_aligned2 = (int32*)(((intptr_t)addr + 3) & ~3); - *(int32*)bytes = *addr_aligned1; - *(int32*)(bytes + 4) = *addr_aligned2; - *(int16*)(bytes + 3) = imm16; + addr_aligned2 = (int32 *)(((intptr_t)addr + 3) & ~3); + *(int32 *)bytes = *addr_aligned1; + *(int32 *)(bytes + 4) = *addr_aligned2; + *(int16 *)(bytes + 3) = imm16; memcpy(addr_aligned1, bytes, 8); } } @@ -142,11 +143,10 @@ typedef union { } l32r_insn_t; bool -apply_relocation(AOTModule *module, - uint8 *target_section_addr, uint32 target_section_size, - uint64 reloc_offset, uint64 reloc_addend, - uint32 reloc_type, void *symbol_addr, int32 symbol_index, - char *error_buf, uint32 error_buf_size) +apply_relocation(AOTModule *module, uint8 *target_section_addr, + uint32 target_section_size, uint64 reloc_offset, + uint64 reloc_addend, uint32 reloc_type, void *symbol_addr, + int32 symbol_index, char *error_buf, uint32 error_buf_size) { switch (reloc_type) { case R_XTENSA_32: @@ -161,19 +161,20 @@ apply_relocation(AOTModule *module, return false; } CHECK_RELOC_OFFSET(4); - initial_addend = *(int32*)insn_addr; - *(uint8**)insn_addr - = (uint8*)symbol_addr + initial_addend + reloc_addend; + initial_addend = *(int32 *)insn_addr; + *(uint8 **)insn_addr = + (uint8 *)symbol_addr + initial_addend + reloc_addend; break; } case R_XTENSA_SLOT0_OP: { uint8 *insn_addr = target_section_addr + reloc_offset; - /* Currently only l32r instruction generates R_XTENSA_SLOT0_OP relocation */ + /* Currently only l32r instruction generates R_XTENSA_SLOT0_OP + * relocation */ l32r_insn_t *l32r_insn = (l32r_insn_t *)insn_addr; uint8 *reloc_addr; - int32 relative_offset/*, initial_addend */; + int32 relative_offset /*, initial_addend */; int16 imm16; CHECK_RELOC_OFFSET(3); /* size of l32r instruction */ @@ -184,7 +185,7 @@ apply_relocation(AOTModule *module, initial_addend = (int32)imm16 << 2; */ - reloc_addr = (uint8*)symbol_addr + reloc_addend; + reloc_addr = (uint8 *)symbol_addr + reloc_addend; if ((intptr_t)reloc_addr & 3) { set_error_buf(error_buf, error_buf_size, @@ -193,9 +194,9 @@ apply_relocation(AOTModule *module, return false; } - relative_offset = (int32) - ((intptr_t)reloc_addr - - (((intptr_t)insn_addr + 3) & ~(intptr_t)3)); + relative_offset = + (int32)((intptr_t)reloc_addr + - (((intptr_t)insn_addr + 3) & ~(intptr_t)3)); /* relative_offset += initial_addend; */ /* check relative offset boundary */ @@ -228,4 +229,3 @@ apply_relocation(AOTModule *module, return true; } - diff --git a/core/iwasm/aot/debug/elf_parser.c b/core/iwasm/aot/debug/elf_parser.c new file mode 100644 index 0000000000..2fe3e11f2b --- /dev/null +++ b/core/iwasm/aot/debug/elf_parser.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "aot_runtime.h" +#include "bh_log.h" +#include "elf_parser.h" + +bool +is_ELF(void *buf) +{ + Elf32_Ehdr *eh = (Elf32_Ehdr *)buf; + if (!strncmp((char *)eh->e_ident, "\177ELF", 4)) { + LOG_VERBOSE("the buffer is ELF entry!"); + return true; + } + LOG_VERBOSE("the buffer is not ELF entry!"); + return false; +} + +static bool +is64Bit(Elf32_Ehdr *eh) +{ + if (eh->e_ident[EI_CLASS] == ELFCLASS64) + return true; + else + return false; +} + +static bool +is32Bit(Elf32_Ehdr *eh) +{ + if (eh->e_ident[EI_CLASS] == ELFCLASS32) + return true; + else + return false; +} + +bool +is_ELF64(void *buf) +{ + Elf64_Ehdr *eh = (Elf64_Ehdr *)buf; + if (!strncmp((char *)eh->e_ident, "\177ELF", 4)) { + LOG_VERBOSE("the buffer is ELF entry!"); + return true; + } + LOG_VERBOSE("the buffer is not ELF entry!"); + return false; +} + +static void +read_section_header_table(Elf32_Ehdr *eh, Elf32_Shdr *sh_table[]) +{ + uint32_t i; + char *buf = (char *)eh; + buf += eh->e_shoff; + LOG_VERBOSE("str index = %d count=%d", eh->e_shstrndx, eh->e_shnum); + for (i = 0; i < eh->e_shnum; i++) { + sh_table[i] = (Elf32_Shdr *)buf; + buf += eh->e_shentsize; + } +} + +static void +read_section_header_table64(Elf64_Ehdr *eh, Elf64_Shdr *sh_table[]) +{ + uint32_t i; + char *buf = (char *)eh; + buf += eh->e_shoff; + + for (i = 0; i < eh->e_shnum; i++) { + sh_table[i] = (Elf64_Shdr *)buf; + buf += eh->e_shentsize; + } +} + +static char * +get_section(Elf32_Ehdr *eh, Elf32_Shdr *section_header) +{ + char *buf = (char *)eh; + return buf + section_header->sh_offset; +} + +static char * +get_section64(Elf64_Ehdr *eh, Elf64_Shdr *section_header) +{ + char *buf = (char *)eh; + return buf + section_header->sh_offset; +} + +bool +get_text_section(void *buf, uint64_t *offset, uint64_t *size) +{ + bool ret = false; + uint32 i; + char *sh_str; + + if (is64Bit(buf)) { + Elf64_Ehdr *eh = (Elf64_Ehdr *)buf; + Elf64_Shdr **sh_table = + wasm_runtime_malloc(eh->e_shnum * sizeof(Elf64_Shdr *)); + if (sh_table) { + read_section_header_table64(eh, sh_table); + sh_str = get_section64(eh, sh_table[eh->e_shstrndx]); + for (i = 0; i < eh->e_shnum; i++) { + if (!strcmp(sh_str + sh_table[i]->sh_name, ".text")) { + *offset = sh_table[i]->sh_offset; + *size = sh_table[i]->sh_size; + sh_table[i]->sh_addr = + (Elf64_Addr)(uintptr_t)((char *)buf + + sh_table[i]->sh_offset); + ret = true; + break; + } + } + wasm_runtime_free(sh_table); + } + } + else if (is32Bit(buf)) { + Elf32_Ehdr *eh = (Elf32_Ehdr *)buf; + Elf32_Shdr **sh_table = + wasm_runtime_malloc(eh->e_shnum * sizeof(Elf32_Shdr *)); + if (sh_table) { + read_section_header_table(eh, sh_table); + sh_str = get_section(eh, sh_table[eh->e_shstrndx]); + for (i = 0; i < eh->e_shnum; i++) { + if (!strcmp(sh_str + sh_table[i]->sh_name, ".text")) { + *offset = sh_table[i]->sh_offset; + *size = sh_table[i]->sh_size; + sh_table[i]->sh_addr = + (Elf32_Addr)(uintptr_t)((char *)buf + + sh_table[i]->sh_offset); + ret = true; + break; + } + } + wasm_runtime_free(sh_table); + } + } + + return ret; +} diff --git a/core/iwasm/aot/debug/elf_parser.h b/core/iwasm/aot/debug/elf_parser.h new file mode 100644 index 0000000000..4e4b9b21b7 --- /dev/null +++ b/core/iwasm/aot/debug/elf_parser.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _ELF_PARSERE_H_ +#define _ELF_PARSER_H_ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool +is_ELF(void *buf); + +bool +is_ELF64(void *buf); + +bool +get_text_section(void *buf, uint64_t *offset, uint64_t *size); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/core/iwasm/aot/debug/jit_debug.c b/core/iwasm/aot/debug/jit_debug.c new file mode 100644 index 0000000000..310662f559 --- /dev/null +++ b/core/iwasm/aot/debug/jit_debug.c @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_log.h" +#include "bh_platform.h" +#include "../../interpreter/wasm_runtime.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/* This must be kept in sync with gdb/gdb/jit.h */ +#ifdef __cplusplus +extern "C" { +#endif + +/* clang-format off */ +typedef enum JITAction { + JIT_NOACTION = 0, + JIT_REGISTER_FN, + JIT_UNREGISTER_FN +} JITAction; +/* clang-format on */ + +typedef struct JITCodeEntry { + struct JITCodeEntry *next_; + struct JITCodeEntry *prev_; + const uint8 *symfile_addr_; + uint64 symfile_size_; +} JITCodeEntry; + +typedef struct JITDescriptor { + uint32 version_; + uint32 action_flag_; + JITCodeEntry *relevant_entry_; + JITCodeEntry *first_entry_; +} JITDescriptor; + +/* LLVM has already define this */ +#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) +/** + * GDB will place breakpoint into this function. + * To prevent GCC from inlining or removing it we place noinline attribute + * and inline assembler statement inside. + */ +void __attribute__((noinline)) __jit_debug_register_code(); + +void __attribute__((noinline)) __jit_debug_register_code() +{ + int x; + *(char *)&x = '\0'; +} + +/** + * GDB will inspect contents of this descriptor. + * Static initialization is necessary to prevent GDB from seeing + * uninitialized descriptor. + */ + +JITDescriptor __jit_debug_descriptor = { 1, JIT_NOACTION, NULL, NULL }; +#else +extern void +__jit_debug_register_code(); +extern JITDescriptor __jit_debug_descriptor; +#endif + +/** + * Call __jit_debug_register_code indirectly via global variable. + * This gives the debugger an easy way to inject custom code to + * handle the events. + */ +void (*__jit_debug_register_code_ptr)() = __jit_debug_register_code; + +#ifdef __cplusplus +} +#endif + +typedef struct WASMJITDebugEngine { + korp_mutex jit_entry_lock; + bh_list jit_entry_list; +} WASMJITDebugEngine; + +typedef struct WASMJITEntryNode { + struct WASMJITEntryNode *next; + JITCodeEntry *entry; +} WASMJITEntryNode; + +static WASMJITDebugEngine *jit_debug_engine; + +static JITCodeEntry * +CreateJITCodeEntryInternal(const uint8 *symfile_addr, uint64 symfile_size) +{ + JITCodeEntry *entry; + + os_mutex_lock(&jit_debug_engine->jit_entry_lock); + + if (!(entry = wasm_runtime_malloc(sizeof(JITCodeEntry)))) { + LOG_ERROR("WASM JIT Debug Engine error: failed to allocate memory"); + os_mutex_unlock(&jit_debug_engine->jit_entry_lock); + return NULL; + } + entry->symfile_addr_ = symfile_addr; + entry->symfile_size_ = symfile_size; + entry->prev_ = NULL; + + entry->next_ = __jit_debug_descriptor.first_entry_; + if (entry->next_ != NULL) { + entry->next_->prev_ = entry; + } + __jit_debug_descriptor.first_entry_ = entry; + __jit_debug_descriptor.relevant_entry_ = entry; + + __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN; + + (*__jit_debug_register_code_ptr)(); + + os_mutex_unlock(&jit_debug_engine->jit_entry_lock); + return entry; +} + +static void +DestroyJITCodeEntryInternal(JITCodeEntry *entry) +{ + os_mutex_lock(&jit_debug_engine->jit_entry_lock); + + if (entry->prev_ != NULL) { + entry->prev_->next_ = entry->next_; + } + else { + __jit_debug_descriptor.first_entry_ = entry->next_; + } + + if (entry->next_ != NULL) { + entry->next_->prev_ = entry->prev_; + } + + __jit_debug_descriptor.relevant_entry_ = entry; + __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN; + (*__jit_debug_register_code_ptr)(); + + wasm_runtime_free(entry); + + os_mutex_unlock(&jit_debug_engine->jit_entry_lock); +} + +bool +jit_debug_engine_init() +{ + if (jit_debug_engine) { + return true; + } + + if (!(jit_debug_engine = wasm_runtime_malloc(sizeof(WASMJITDebugEngine)))) { + LOG_ERROR("WASM JIT Debug Engine error: failed to allocate memory"); + return false; + } + memset(jit_debug_engine, 0, sizeof(WASMJITDebugEngine)); + + if (os_mutex_init(&jit_debug_engine->jit_entry_lock) != 0) { + wasm_runtime_free(jit_debug_engine); + jit_debug_engine = NULL; + return false; + } + + bh_list_init(&jit_debug_engine->jit_entry_list); + return true; +} + +void +jit_debug_engine_destroy() +{ + if (jit_debug_engine) { + WASMJITEntryNode *node, *node_next; + + /* Destroy all nodes */ + node = bh_list_first_elem(&jit_debug_engine->jit_entry_list); + while (node) { + node_next = bh_list_elem_next(node); + DestroyJITCodeEntryInternal(node->entry); + bh_list_remove(&jit_debug_engine->jit_entry_list, node); + wasm_runtime_free(node); + node = node_next; + } + + /* Destroy JIT Debug Engine */ + os_mutex_destroy(&jit_debug_engine->jit_entry_lock); + wasm_runtime_free(jit_debug_engine); + jit_debug_engine = NULL; + } +} + +bool +jit_code_entry_create(const uint8 *symfile_addr, uint64 symfile_size) +{ + JITCodeEntry *entry; + WASMJITEntryNode *node; + + if (!(node = wasm_runtime_malloc(sizeof(WASMJITEntryNode)))) { + LOG_ERROR("WASM JIT Debug Engine error: failed to allocate memory"); + return false; + } + + entry = CreateJITCodeEntryInternal(symfile_addr, symfile_size); + + if (!entry) { + wasm_runtime_free(node); + return false; + } + + node->entry = entry; + os_mutex_lock(&jit_debug_engine->jit_entry_lock); + bh_list_insert(&jit_debug_engine->jit_entry_list, node); + os_mutex_unlock(&jit_debug_engine->jit_entry_lock); + return true; +} + +void +jit_code_entry_destroy(const uint8 *symfile_addr) +{ + WASMJITEntryNode *node; + + node = bh_list_first_elem(&jit_debug_engine->jit_entry_list); + while (node) { + WASMJITEntryNode *next_node = bh_list_elem_next(node); + if (node->entry->symfile_addr_ == symfile_addr) { + DestroyJITCodeEntryInternal(node->entry); + os_mutex_lock(&jit_debug_engine->jit_entry_lock); + bh_list_remove(&jit_debug_engine->jit_entry_list, node); + os_mutex_unlock(&jit_debug_engine->jit_entry_lock); + wasm_runtime_free(node); + } + node = next_node; + } +} diff --git a/core/iwasm/aot/debug/jit_debug.h b/core/iwasm/aot/debug/jit_debug.h new file mode 100644 index 0000000000..5e3e365199 --- /dev/null +++ b/core/iwasm/aot/debug/jit_debug.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _JIT_DEBUG_H_ +#define _JIT_DEBUG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +bool +jit_debug_engine_init(); + +void +jit_debug_engine_destroy(); + +bool +jit_code_entry_create(const uint8 *symfile_addr, uint64 symfile_size); + +void +jit_code_entry_destroy(const uint8 *symfile_addr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/core/iwasm/aot/iwasm_aot.cmake b/core/iwasm/aot/iwasm_aot.cmake index e7d0549d9f..8014f23721 100644 --- a/core/iwasm/aot/iwasm_aot.cmake +++ b/core/iwasm/aot/iwasm_aot.cmake @@ -23,9 +23,18 @@ elseif (WAMR_BUILD_TARGET STREQUAL "MIPS") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_mips.c) elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_xtensa.c) +elseif (WAMR_BUILD_TARGET MATCHES "RISCV*") + set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_riscv.c) +elseif (WAMR_BUILD_TARGET STREQUAL "ARC") + set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arc.c) else () message (FATAL_ERROR "Build target isn't set") endif () -set (IWASM_AOT_SOURCE ${c_source_all} ${arch_source}) +if (WAMR_BUILD_DEBUG_AOT EQUAL 1) + add_definitions(-DWASM_ENABLE_DEBUG_AOT=1) + file(GLOB debug_source ${IWASM_AOT_DIR}/debug/*.c) +endif() + +set (IWASM_AOT_SOURCE ${c_source_all} ${arch_source} ${debug_source}) diff --git a/core/iwasm/common/SConscript b/core/iwasm/common/SConscript index 235b0e88b6..0a55f244b9 100644 --- a/core/iwasm/common/SConscript +++ b/core/iwasm/common/SConscript @@ -18,6 +18,8 @@ if rtconfig.ARCH == 'arm': src += ['arch/invokeNative_thumb.s'] elif re.match('^cortex-a.*', rtconfig.CPU): src += ['arch/invokeNative_arm.s'] +elif rtconfig.ARCH == 'ia32': + src += ['arch/invokeNative_ia32.s'] CPPPATH = [cwd, cwd + '/../include'] diff --git a/core/iwasm/common/arch/invokeNative_arc.s b/core/iwasm/common/arch/invokeNative_arc.s new file mode 100644 index 0000000000..e448eea650 --- /dev/null +++ b/core/iwasm/common/arch/invokeNative_arc.s @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + + .text + .align 2 +#ifndef BH_PLATFORM_DARWIN + .globl invokeNative + .type invokeNative, function +invokeNative: +#else + .globl _invokeNative +_invokeNative: +#endif /* end of BH_PLATFORM_DARWIN */ + +/* + * Arguments passed in: + * r0: function ptr + * r1: argv + * r2: nstacks + * ARC ABI: + * r0-r7: function arguments, caller-saved + * r8-r12: temp registers, caller-saved + */ + + push_s blink /* push return addr */ + st.aw fp, [sp, -4] /* push fp */ + mov fp, sp /* fp = sp */ + + mov r8, r0 /* r8 = func_ptr */ + mov r9, r1 /* r9 = argv */ + mov r10, r2 /* r10 = nstacks */ + + ld r0, [r9, 0] /* r0 = argv[0] */ + ld r1, [r9, 4] /* r1 = argv[1] */ + ld r2, [r9, 8] /* r2 = argv[2] */ + ld r3, [r9, 12] /* r3 = argv[3] */ + ld r4, [r9, 16] /* r4 = argv[4] */ + ld r5, [r9, 20] /* r5 = argv[5] */ + ld r6, [r9, 24] /* r6 = argv[6] */ + ld r7, [r9, 28] /* r7 = argv[7] */ + + add r9, r9, 32 /* r9 = stack_args */ + breq r10, 0, call_func /* if (r10 == 0) goto call_func */ + + asl r11, r10, 2 /* r11 = nstacks * 4 */ + sub sp, sp, r11 /* sp = sp - nstacks * 4 */ + and sp, sp, ~7 /* make sp 8-byte aligned */ + mov r11, sp /* r11 = sp */ + +loop_stack_args: + breq r10, 0, call_func /* if (r10 == 0) goto call_func */ + ld r12, [r9] /* r12 = stack_args[i] */ + st r12, [r11] /* stack[i] = r12 */ + add r9, r9, 4 /* r9 = r9 + 4 */ + add r11, r11, 4 /* r11 = r11 + 4 */ + sub r10, r10, 1 /* r10 = r10 + 1 */ + j loop_stack_args + +call_func: + jl [r8] /* call function */ + + mov sp, fp /* sp = fp */ + ld.ab fp, [sp, 4] /* pop fp */ + pop_s blink /* pop return addr */ + j_s [blink] /* ret */ + nop_s + diff --git a/core/iwasm/common/arch/invokeNative_arm_vfp.s b/core/iwasm/common/arch/invokeNative_arm_vfp.s index c7dbb980aa..78a4bab82d 100644 --- a/core/iwasm/common/arch/invokeNative_arm_vfp.s +++ b/core/iwasm/common/arch/invokeNative_arm_vfp.s @@ -22,6 +22,7 @@ _invokeNative: */ stmfd sp!, {r4, r5, r6, r7, lr} + sub sp, sp, #4 /* make sp 8 byte aligned */ mov ip, r0 /* ip = function ptr */ mov r4, r1 /* r4 = argv */ mov r5, r2 /* r5 = nstacks */ @@ -79,6 +80,7 @@ call_func: mov sp, r6 /* restore sp */ return: + add sp, sp, #4 /* make sp 8 byte aligned */ ldmfd sp!, {r4, r5, r6, r7, lr} bx lr diff --git a/core/iwasm/common/arch/invokeNative_general.c b/core/iwasm/common/arch/invokeNative_general.c index 8d6e70f4f4..4799c9fa82 100644 --- a/core/iwasm/common/arch/invokeNative_general.c +++ b/core/iwasm/common/arch/invokeNative_general.c @@ -6,11 +6,12 @@ #include "../wasm_runtime_common.h" #include "../wasm_exec_env.h" -void invokeNative(void (*native_code)(), uint32 argv[], uint32 argc) +void +invokeNative(void (*native_code)(), uint32 argv[], uint32 argc) { - bh_assert(argc >= sizeof(WASMExecEnv*)/sizeof(uint32)); + bh_assert(argc >= sizeof(WASMExecEnv *) / sizeof(uint32)); - switch(argc) { + switch (argc) { case 0: native_code(); break; @@ -33,53 +34,80 @@ void invokeNative(void (*native_code)(), uint32 argv[], uint32 argc) native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); break; case 7: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6]); break; case 8: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7]); break; case 9: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8]); break; case 10: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9]); break; case 11: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9], argv[10]); break; case 12: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]); break; case 13: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], + argv[12]); break; case 14: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], + argv[12], argv[13]); break; case 15: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], + argv[12], argv[13], argv[14]); break; case 16: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], + argv[12], argv[13], argv[14], argv[15]); break; case 17: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], + argv[12], argv[13], argv[14], argv[15], argv[16]); break; case 18: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], + argv[12], argv[13], argv[14], argv[15], argv[16], + argv[17]); break; case 19: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], + argv[12], argv[13], argv[14], argv[15], argv[16], + argv[17], argv[18]); break; case 20: - native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18], argv[19]); + native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], + argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], + argv[12], argv[13], argv[14], argv[15], argv[16], + argv[17], argv[18], argv[19]); break; default: { /* FIXME: If this happen, add more cases. */ - WASMExecEnv *exec_env = *(WASMExecEnv**)argv; + WASMExecEnv *exec_env = *(WASMExecEnv **)argv; WASMModuleInstanceCommon *module_inst = exec_env->module_inst; - wasm_runtime_set_exception(module_inst, "the argument number of native function exceeds maximum"); + wasm_runtime_set_exception( + module_inst, + "the argument number of native function exceeds maximum"); return; } } diff --git a/core/iwasm/common/arch/invokeNative_riscv.S b/core/iwasm/common/arch/invokeNative_riscv.S new file mode 100644 index 0000000000..0908f73cc2 --- /dev/null +++ b/core/iwasm/common/arch/invokeNative_riscv.S @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +/* + * The float abi macros used bellow are from risc-v c api: + * https://github.com/riscv/riscv-c-api-doc/blob/master/riscv-c-api.md + * + */ + +#if defined(__riscv_float_abi_soft) +#define RV_FPREG_SIZE 0 +#elif defined(__riscv_float_abi_single) +#define RV_OP_LOADFPREG flw +#define RV_OP_STROEFPREG fsw +#define RV_FPREG_SIZE 4 +#elif defined(__riscv_float_abi_double) +#define RV_OP_LOADFPREG fld +#define RV_OP_STROEFPREG fsd +#define RV_FPREG_SIZE 8 +#endif + +#if __riscv_xlen == 32 +#define RV_OP_LOADREG lw +#define RV_OP_STOREREG sw +#define RV_REG_SIZE 4 +#define RV_REG_SHIFT 2 +#define RV_FP_OFFSET (8 * RV_REG_SIZE) +#define RV_INT_OFFSET 0 +#else +#define RV_OP_LOADREG ld +#define RV_OP_STOREREG sd +#define RV_REG_SIZE 8 +#define RV_REG_SHIFT 3 +#define RV_FP_OFFSET 0 +#define RV_INT_OFFSET (8 * RV_FPREG_SIZE) +#endif + + .text + .align 2 +#ifndef BH_PLATFORM_DARWIN + .globl invokeNative + .type invokeNative, function +invokeNative: +#else + .globl _invokeNative +_invokeNative: +#endif /* end of BH_PLATFORM_DARWIN */ + +/* + * Arguments passed in: + * + * a0 function ptr + * a1 argv + * a2 nstacks + */ + +/* + * sp (stack pointer) + * |- sd/sw to store 64/32-bit values from register to memory + * |- ld/lw to load from stack to register + * fp/s0 (frame pointer) + * a0-a7 (8 integer arguments) + * |- sd/sw to store + * |- ld/lw to load + * fa0-a7 (8 float arguments) + * |- fsd/fsw to store + * |- fld/fsw to load + * t0-t6 (temporaries regisgers) + * |- caller saved + */ + + /* reserve space on stack to save return address and frame pointer */ + addi sp, sp, - 2 * RV_REG_SIZE + RV_OP_STOREREG fp, 0 * RV_REG_SIZE(sp) /* save frame pointer */ + RV_OP_STOREREG ra, 1 * RV_REG_SIZE(sp) /* save return address */ + + mv fp, sp /* set frame pointer to bottom of fixed frame */ + + /* save function ptr, argv & nstacks */ + mv t0, a0 /* t0 = function ptr */ + mv t1, a1 /* t1 = argv array address */ + mv t2, a2 /* t2 = nstack */ + +#ifndef __riscv_float_abi_soft + /* fill in fa0-7 float-registers*/ + RV_OP_LOADFPREG fa0, RV_FP_OFFSET + 0 * RV_FPREG_SIZE(t1) /* fa0 */ + RV_OP_LOADFPREG fa1, RV_FP_OFFSET + 1 * RV_FPREG_SIZE(t1) /* fa1 */ + RV_OP_LOADFPREG fa2, RV_FP_OFFSET + 2 * RV_FPREG_SIZE(t1) /* fa2 */ + RV_OP_LOADFPREG fa3, RV_FP_OFFSET + 3 * RV_FPREG_SIZE(t1) /* fa3 */ + RV_OP_LOADFPREG fa4, RV_FP_OFFSET + 4 * RV_FPREG_SIZE(t1) /* fa4 */ + RV_OP_LOADFPREG fa5, RV_FP_OFFSET + 5 * RV_FPREG_SIZE(t1) /* fa5 */ + RV_OP_LOADFPREG fa6, RV_FP_OFFSET + 6 * RV_FPREG_SIZE(t1) /* fa6 */ + RV_OP_LOADFPREG fa7, RV_FP_OFFSET + 7 * RV_FPREG_SIZE(t1) /* fa7 */ +#endif + + /* fill in a0-7 integer-registers*/ + RV_OP_LOADREG a0, RV_INT_OFFSET + 0 * RV_REG_SIZE(t1) /* a0 */ + RV_OP_LOADREG a1, RV_INT_OFFSET + 1 * RV_REG_SIZE(t1) /* a1 */ + RV_OP_LOADREG a2, RV_INT_OFFSET + 2 * RV_REG_SIZE(t1) /* a2 */ + RV_OP_LOADREG a3, RV_INT_OFFSET + 3 * RV_REG_SIZE(t1) /* a3 */ + RV_OP_LOADREG a4, RV_INT_OFFSET + 4 * RV_REG_SIZE(t1) /* a4 */ + RV_OP_LOADREG a5, RV_INT_OFFSET + 5 * RV_REG_SIZE(t1) /* a5 */ + RV_OP_LOADREG a6, RV_INT_OFFSET + 6 * RV_REG_SIZE(t1) /* a6 */ + RV_OP_LOADREG a7, RV_INT_OFFSET + 7 * RV_REG_SIZE(t1) /* a7 */ + + /* t1 points to stack args */ + + /* RV_FPREG_SIZE is zero when __riscv_float_abi_soft defined */ + addi t1, t1, RV_REG_SIZE * 8 + RV_FPREG_SIZE * 8 + + /* directly call the function if no args in stack, + x0 always holds 0 */ + beq t2, x0, call_func + + /* reserve enough stack space for function arguments */ + sll t3, t2, RV_REG_SHIFT /* shift left 3 bits. t3 = n_stacks * 8 */ + sub sp, sp, t3 + + /* make 16-byte aligned */ + li t3, 15 + not t3, t3 + and sp, sp, t3 + + /* save sp in t4 register */ + mv t4, sp + + /* copy left arguments from caller stack to own frame stack */ +loop_stack_args: + beq t2, x0, call_func + RV_OP_LOADREG t5, 0(t1) /* load stack argument, t5 = argv[i] */ + RV_OP_STOREREG t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */ + addi t1, t1, RV_REG_SIZE /* move to next stack argument */ + addi t4, t4, RV_REG_SIZE /* move to next stack pointer */ + addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */ + j loop_stack_args + +call_func: + jalr t0 + + /* restore registers pushed in stack or saved in another register */ +return: + mv sp, fp /* restore sp saved in fp before function call */ + RV_OP_LOADREG fp, 0 * RV_REG_SIZE(sp) /* load previous frame poniter to fp register */ + RV_OP_LOADREG ra, 1 * RV_REG_SIZE(sp) /* load previous return address to ra register */ + addi sp, sp, 2 * RV_REG_SIZE /* pop frame, restore sp */ + jr ra diff --git a/core/iwasm/common/arch/invokeNative_riscv32_ilp32.s b/core/iwasm/common/arch/invokeNative_riscv32_ilp32.s deleted file mode 100644 index b0b41aa069..0000000000 --- a/core/iwasm/common/arch/invokeNative_riscv32_ilp32.s +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - .text - .align 2 -#ifndef BH_PLATFORM_DARWIN - .globl invokeNative - .type invokeNative, function -invokeNative: -#else - .globl _invokeNative -_invokeNative: -#endif /* end of BH_PLATFORM_DARWIN */ - - -/* - * Arguments passed in: - * - * a0 function ptr - * a1 argv - * a2 nstacks - */ - -/* - * sp (stack pointer) - * |- sw to store 32-bit values from register to memory - * |- lw to load from stack to register - * fp/s0 (frame pointer) - * a0-a7 (8 integer arguments) - * |- sw to store - * |- lw to load - * t0-t6 (temporaries regisgers) - * |- caller saved - */ - - /* reserve space on stack to save return address and frame pointer */ - addi sp, sp, -8 - sw fp, 0(sp) /* save frame pointer */ - sw ra, 4(sp) /* save return address */ - - mv fp, sp /* set frame pointer to bottom of fixed frame */ - - /* save function ptr, argv & nstacks */ - mv t0, a0 /* t0 = function ptr */ - mv t1, a1 /* t1 = argv array address */ - mv t2, a2 /* t2 = nstack */ - - /* fill in a0-7 integer-registers */ - lw a0, 0(t1) /* a0 = argv[0] */ - lw a1, 4(t1) /* a1 = argv[1] */ - lw a2, 8(t1) /* a2 = argv[2] */ - lw a3, 12(t1) /* a3 = argv[3] */ - lw a4, 16(t1) /* a4 = argv[4] */ - lw a5, 20(t1) /* a5 = argv[5] */ - lw a6, 24(t1) /* a6 = argv[6] */ - lw a7, 28(t1) /* a7 = argv[7] */ - - addi t1, t1, 32 /* t1 points to stack args */ - - /* directly call the function if no args in stack, - x0 always holds 0 */ - beq t2, x0, call_func - - /* reserve enough stack space for function arguments */ - sll t3, t2, 2 /* shift left 2 bits. t3 = n_stacks * 4 */ - sub sp, sp, t3 - - /* make 16-byte aligned */ - and sp, sp, ~15 - - /* save sp in t4 register */ - mv t4, sp - - /* copy left arguments from caller stack to own frame stack */ -loop_stack_args: - beq t2, x0, call_func - lw t5, 0(t1) /* load stack argument, t5 = argv[i] */ - sw t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */ - addi t1, t1, 4 /* move to next stack argument */ - addi t4, t4, 4 /* move to next stack pointer */ - addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */ - j loop_stack_args - -call_func: - jalr t0 - - /* restore registers pushed in stack or saved in another register */ -return: - mv sp, fp /* restore sp saved in fp before function call */ - lw fp, 0(sp) /* load previous frame poniter to fp register */ - lw ra, 4(sp) /* load previous return address to ra register */ - addi sp, sp, 8 /* pop frame, restore sp */ - jr ra - diff --git a/core/iwasm/common/arch/invokeNative_riscv32_ilp32d.s b/core/iwasm/common/arch/invokeNative_riscv32_ilp32d.s deleted file mode 100644 index 49e8ec766b..0000000000 --- a/core/iwasm/common/arch/invokeNative_riscv32_ilp32d.s +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - .text - .align 2 -#ifndef BH_PLATFORM_DARWIN - .globl invokeNative - .type invokeNative, function -invokeNative: -#else - .globl _invokeNative -_invokeNative: -#endif /* end of BH_PLATFORM_DARWIN */ - - -/* - * Arguments passed in: - * - * a0 function ptr - * a1 argv - * a2 nstacks - */ - -/* - * sp (stack pointer) - * |- sw to store 32-bit values from register to memory - * |- lw to load from stack to register - * fp/s0 (frame pointer) - * a0-a7 (8 integer arguments) - * |- sw to store - * |- lw to load - * t0-t6 (temporaries regisgers) - * |- caller saved - */ - - /* reserve space on stack to save return address and frame pointer */ - addi sp, sp, -8 - sw fp, 0(sp) /* save frame pointer */ - sw ra, 4(sp) /* save return address */ - - mv fp, sp /* set frame pointer to bottom of fixed frame */ - - /* save function ptr, argv & nstacks */ - mv t0, a0 /* t0 = function ptr */ - mv t1, a1 /* t1 = argv array address */ - mv t2, a2 /* t2 = nstack */ - - /* fill in a0-7 integer-registers */ - lw a0, 0(t1) /* a0 = argv[0] */ - lw a1, 4(t1) /* a1 = argv[1] */ - lw a2, 8(t1) /* a2 = argv[2] */ - lw a3, 12(t1) /* a3 = argv[3] */ - lw a4, 16(t1) /* a4 = argv[4] */ - lw a5, 20(t1) /* a5 = argv[5] */ - lw a6, 24(t1) /* a6 = argv[6] */ - lw a7, 28(t1) /* a7 = argv[7] */ - - /* fill in fa0-7 float-registers*/ - fld fa0, 32(t1) /* fa0 = argv[8] */ - fld fa1, 40(t1) /* fa1 = argv[9] */ - fld fa2, 48(t1) /* fa2 = argv[10] */ - fld fa3, 56(t1) /* fa3 = argv[11] */ - fld fa4, 64(t1) /* fa4 = argv[12] */ - fld fa5, 72(t1) /* fa5 = argv[13] */ - fld fa6, 80(t1) /* fa6 = argv[14] */ - fld fa7, 88(t1) /* fa7 = argv[15] */ - - addi t1, t1, 96 /* t1 points to stack args */ - - /* directly call the function if no args in stack, - x0 always holds 0 */ - beq t2, x0, call_func - - /* reserve enough stack space for function arguments */ - sll t3, t2, 2 /* shift left 2 bits. t3 = n_stacks * 4 */ - sub sp, sp, t3 - - /* make 16-byte aligned */ - and sp, sp, ~15 - - /* save sp in t4 register */ - mv t4, sp - - /* copy left arguments from caller stack to own frame stack */ -loop_stack_args: - beq t2, x0, call_func - lw t5, 0(t1) /* load stack argument, t5 = argv[i] */ - sw t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */ - addi t1, t1, 4 /* move to next stack argument */ - addi t4, t4, 4 /* move to next stack pointer */ - addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */ - j loop_stack_args - -call_func: - jalr t0 - - /* restore registers pushed in stack or saved in another register */ -return: - mv sp, fp /* restore sp saved in fp before function call */ - lw fp, 0(sp) /* load previous frame poniter to fp register */ - lw ra, 4(sp) /* load previous return address to ra register */ - addi sp, sp, 8 /* pop frame, restore sp */ - jr ra diff --git a/core/iwasm/common/arch/invokeNative_riscv64_lp64.s b/core/iwasm/common/arch/invokeNative_riscv64_lp64.s deleted file mode 100644 index 86a3c9c826..0000000000 --- a/core/iwasm/common/arch/invokeNative_riscv64_lp64.s +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - .text - .align 2 -#ifndef BH_PLATFORM_DARWIN - .globl invokeNative - .type invokeNative, function -invokeNative: -#else - .globl _invokeNative -_invokeNative: -#endif /* end of BH_PLATFORM_DARWIN */ - - -/* - * Arguments passed in: - * - * a0 function ptr - * a1 argv - * a2 nstacks - */ - -/* - * sp (stack pointer) - * |- sd to store 64-bit values from register to memory - * |- ld to load from stack to register - * fp/s0 (frame pointer) - * a0-a7 (8 integer arguments) - * |- sd to store - * |- ld to load - * t0-t6 (temporaries regisgers) - * |- caller saved - */ - - /* reserve space on stack to save return address and frame pointer */ - addi sp, sp, -16 - sd fp, 0(sp) /* save frame pointer */ - sd ra, 8(sp) /* save return address */ - - mv fp, sp /* set frame pointer to bottom of fixed frame */ - - /* save function ptr, argv & nstacks */ - mv t0, a0 /* t0 = function ptr */ - mv t1, a1 /* t1 = argv array address */ - mv t2, a2 /* t2 = nstack */ - - /* fill in a0-7 integer-registers*/ - ld a0, 0(t1) /* a0 = argv[0] */ - ld a1, 8(t1) /* a1 = argv[1] */ - ld a2, 16(t1) /* a2 = argv[2] */ - ld a3, 24(t1) /* a3 = argv[3] */ - ld a4, 32(t1) /* a4 = argv[4] */ - ld a5, 40(t1) /* a5 = argv[5] */ - ld a6, 48(t1) /* a6 = argv[6] */ - ld a7, 56(t1) /* a7 = argv[7] */ - - addi t1, t1, 64 /* t1 points to stack args */ - - /* directly call the function if no args in stack, - x0 always holds 0 */ - beq t2, x0, call_func - - /* reserve enough stack space for function arguments */ - sll t3, t2, 3 /* shift left 3 bits. t3 = n_stacks * 8 */ - sub sp, sp, t3 - - /* make 16-byte aligned */ - and sp, sp, ~(15LL) - - /* save sp in t4 register */ - mv t4, sp - - /* copy left arguments from caller stack to own frame stack */ -loop_stack_args: - beq t2, x0, call_func - ld t5, 0(t1) /* load stack argument, t5 = argv[i] */ - sd t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */ - addi t1, t1, 8 /* move to next stack argument */ - addi t4, t4, 8 /* move to next stack pointer */ - addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */ - j loop_stack_args - -call_func: - jalr t0 - - /* restore registers pushed in stack or saved in another register */ -return: - mv sp, fp /* restore sp saved in fp before function call */ - ld fp, 0(sp) /* load previous frame poniter to fp register */ - ld ra, 8(sp) /* load previous return address to ra register */ - addi sp, sp, 16 /* pop frame, restore sp */ - jr ra - diff --git a/core/iwasm/common/arch/invokeNative_riscv64_lp64d.s b/core/iwasm/common/arch/invokeNative_riscv64_lp64d.s deleted file mode 100644 index a82df0264e..0000000000 --- a/core/iwasm/common/arch/invokeNative_riscv64_lp64d.s +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - .text - .align 2 -#ifndef BH_PLATFORM_DARWIN - .globl invokeNative - .type invokeNative, function -invokeNative: -#else - .globl _invokeNative -_invokeNative: -#endif /* end of BH_PLATFORM_DARWIN */ - -/* - * Arguments passed in: - * - * a0 function ptr - * a1 argv - * a2 nstacks - */ - -/* - * sp (stack pointer) - * |- sd to store 64-bit values from register to memory - * |- ld to load from stack to register - * fp/s0 (frame pointer) - * a0-a7 (8 integer arguments) - * |- sd to store - * |- ld to load - * fa0-a7 (8 float arguments) - * |- fsd to store - * |- fld to load - * t0-t6 (temporaries regisgers) - * |- caller saved - */ - - /* reserve space on stack to save return address and frame pointer */ - addi sp, sp, -16 - sd fp, 0(sp) /* save frame pointer */ - sd ra, 8(sp) /* save return address */ - - mv fp, sp /* set frame pointer to bottom of fixed frame */ - - /* save function ptr, argv & nstacks */ - mv t0, a0 /* t0 = function ptr */ - mv t1, a1 /* t1 = argv array address */ - mv t2, a2 /* t2 = nstack */ - - /* fill in fa0-7 float-registers*/ - fld fa0, 0(t1) /* fa0 = argv[0] */ - fld fa1, 8(t1) /* fa1 = argv[1] */ - fld fa2, 16(t1) /* fa2 = argv[2] */ - fld fa3, 24(t1) /* fa3 = argv[3] */ - fld fa4, 32(t1) /* fa4 = argv[4] */ - fld fa5, 40(t1) /* fa5 = argv[5] */ - fld fa6, 48(t1) /* fa6 = argv[6] */ - fld fa7, 56(t1) /* fa7 = argv[7] */ - - /* fill in a0-7 integer-registers*/ - ld a0, 64(t1) /* a0 = argv[8] */ - ld a1, 72(t1) /* a1 = argv[9] */ - ld a2, 80(t1) /* a2 = argv[10] */ - ld a3, 88(t1) /* a3 = argv[11] */ - ld a4, 96(t1) /* a4 = argv[12] */ - ld a5, 104(t1) /* a5 = argv[13] */ - ld a6, 112(t1) /* a6 = argv[14] */ - ld a7, 120(t1) /* a7 = argv[15] */ - - addi t1, t1, 128 /* t1 points to stack args */ - - /* directly call the function if no args in stack, - x0 always holds 0 */ - beq t2, x0, call_func - - /* reserve enough stack space for function arguments */ - sll t3, t2, 3 /* shift left 3 bits. t3 = n_stacks * 8 */ - sub sp, sp, t3 - - /* make 16-byte aligned */ - and sp, sp, ~(15LL) - - /* save sp in t4 register */ - mv t4, sp - - /* copy left arguments from caller stack to own frame stack */ -loop_stack_args: - beq t2, x0, call_func - ld t5, 0(t1) /* load stack argument, t5 = argv[i] */ - sd t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */ - addi t1, t1, 8 /* move to next stack argument */ - addi t4, t4, 8 /* move to next stack pointer */ - addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */ - j loop_stack_args - -call_func: - jalr t0 - - /* restore registers pushed in stack or saved in another register */ -return: - mv sp, fp /* restore sp saved in fp before function call */ - ld fp, 0(sp) /* load previous frame poniter to fp register */ - ld ra, 8(sp) /* load previous return address to ra register */ - addi sp, sp, 16 /* pop frame, restore sp */ - jr ra - - diff --git a/core/iwasm/common/arch/invokeNative_thumb.s b/core/iwasm/common/arch/invokeNative_thumb.s index 30c64e1d4c..3669fe77ed 100644 --- a/core/iwasm/common/arch/invokeNative_thumb.s +++ b/core/iwasm/common/arch/invokeNative_thumb.s @@ -23,6 +23,7 @@ _invokeNative: push {r4, r5, r6, r7} push {lr} + sub sp, sp, #4 /* make sp 8 byte aligned */ mov ip, r0 /* ip = function ptr */ mov r4, r1 /* r4 = argv */ mov r5, r2 /* r5 = argc */ @@ -83,6 +84,7 @@ call_func: add sp, sp, r6 /* restore sp */ return: + add sp, sp, #4 /* make sp 8 byte aligned */ pop {r3} pop {r4, r5, r6, r7} mov lr, r3 diff --git a/core/iwasm/common/arch/invokeNative_thumb_vfp.s b/core/iwasm/common/arch/invokeNative_thumb_vfp.s index 2d836fb827..218cd91e01 100644 --- a/core/iwasm/common/arch/invokeNative_thumb_vfp.s +++ b/core/iwasm/common/arch/invokeNative_thumb_vfp.s @@ -23,6 +23,7 @@ _invokeNative: push {r4, r5, r6, r7} push {lr} + sub sp, sp, #4 /* make sp 8 byte aligned */ mov ip, r0 /* ip = function ptr */ mov r4, r1 /* r4 = argv */ mov r5, r2 /* r5 = nstacks */ @@ -91,6 +92,7 @@ call_func: mov sp, r7 /* restore sp */ return: + add sp, sp, #4 /* make sp 8 byte aligned */ pop {r3} pop {r4, r5, r6, r7} mov lr, r3 diff --git a/core/iwasm/common/iwasm_common.cmake b/core/iwasm/common/iwasm_common.cmake index 7e9944fc07..de0826e2ca 100644 --- a/core/iwasm/common/iwasm_common.cmake +++ b/core/iwasm/common/iwasm_common.cmake @@ -66,14 +66,10 @@ elseif (WAMR_BUILD_TARGET STREQUAL "MIPS") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s) elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_xtensa.s) -elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64" OR WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64D") - set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv64_lp64d.s) -elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64") - set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv64_lp64.s) -elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32D") - set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv32_ilp32d.s) -elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32") - set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv32_ilp32.s) +elseif (WAMR_BUILD_TARGET MATCHES "RISCV*") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv.S) +elseif (WAMR_BUILD_TARGET STREQUAL "ARC") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arc.s) else () message (FATAL_ERROR "Build target isn't set") endif () diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index b3e979fc9b..03771b17e9 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -24,15 +24,12 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst, { void *mem; - if (size >= UINT32_MAX - || !(mem = wasm_runtime_malloc((uint32)size))) { + if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) { if (module_inst != NULL) { - wasm_runtime_set_exception(module_inst, - "allocate memory failed"); + wasm_runtime_set_exception(module_inst, "allocate memory failed"); } else if (error_buf != NULL) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); } return NULL; } @@ -52,29 +49,31 @@ static union { * Implementation of wasm_application_execute_main() */ -static WASMFunctionInstanceCommon* -resolve_function(const WASMModuleInstanceCommon *module_inst, - const char *name); +static WASMFunctionInstanceCommon * +resolve_function(const WASMModuleInstanceCommon *module_inst, const char *name); static bool check_main_func_type(const WASMType *type) { if (!(type->param_count == 0 || type->param_count == 2) - ||type->result_count > 1) { - LOG_ERROR("WASM execute application failed: invalid main function type.\n"); + || type->result_count > 1) { + LOG_ERROR( + "WASM execute application failed: invalid main function type.\n"); return false; } if (type->param_count == 2 && !(type->types[0] == VALUE_TYPE_I32 - && type->types[1] == VALUE_TYPE_I32)) { - LOG_ERROR("WASM execute application failed: invalid main function type.\n"); + && type->types[1] == VALUE_TYPE_I32)) { + LOG_ERROR( + "WASM execute application failed: invalid main function type.\n"); return false; } if (type->result_count && type->types[type->param_count] != VALUE_TYPE_I32) { - LOG_ERROR("WASM execute application failed: invalid main function type.\n"); + LOG_ERROR( + "WASM execute application failed: invalid main function type.\n"); return false; } @@ -82,8 +81,8 @@ check_main_func_type(const WASMType *type) } bool -wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, - int32 argc, char *argv[]) +wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, + char *argv[]) { WASMFunctionInstanceCommon *func; WASMType *func_type = NULL; @@ -103,9 +102,9 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, the actual main function. Directly call main function may cause exception thrown. */ if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) - return wasm_runtime_create_exec_env_and_call_wasm( - module_inst, func, 0, NULL); - /* if no start function is found, we execute + return wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, + 0, NULL); + /* If no start function was found, we execute the main function as normal */ } #endif /* end of WASM_ENABLE_LIBC_WASI */ @@ -113,25 +112,23 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, if (!(func = resolve_function(module_inst, "main")) && !(func = resolve_function(module_inst, "__main_argc_argv")) && !(func = resolve_function(module_inst, "_main"))) { - wasm_runtime_set_exception(module_inst, - "lookup main function failed"); + wasm_runtime_set_exception(module_inst, "lookup main function failed"); return false; } #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - is_import_func = ((WASMFunctionInstance*)func)->is_import_func; + is_import_func = ((WASMFunctionInstance *)func)->is_import_func; } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - is_import_func = ((AOTFunctionInstance*)func)->is_import_func; + is_import_func = ((AOTFunctionInstance *)func)->is_import_func; } #endif if (is_import_func) { - wasm_runtime_set_exception(module_inst, - "lookup main function failed"); + wasm_runtime_set_exception(module_inst, "lookup main function failed"); return false; } @@ -157,34 +154,34 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, total_size = (uint64)total_argv_size + sizeof(int32) * (uint64)argc; if (total_size >= UINT32_MAX - || !(argv_buf_offset = - wasm_runtime_module_malloc(module_inst, (uint32)total_size, - (void**)&argv_buf))) { - wasm_runtime_set_exception(module_inst, - "allocate memory failed"); + || !(argv_buf_offset = wasm_runtime_module_malloc( + module_inst, (uint32)total_size, (void **)&argv_buf))) { + wasm_runtime_set_exception(module_inst, "allocate memory failed"); return false; } p = argv_buf; - argv_offsets = (uint32*)(p + total_argv_size); + argv_offsets = (uint32 *)(p + total_argv_size); p_end = p + total_size; for (i = 0; i < argc; i++) { - bh_memcpy_s(p, (uint32)(p_end - p), argv[i], (uint32)(strlen(argv[i]) + 1)); + bh_memcpy_s(p, (uint32)(p_end - p), argv[i], + (uint32)(strlen(argv[i]) + 1)); argv_offsets[i] = argv_buf_offset + (uint32)(p - argv_buf); p += strlen(argv[i]) + 1; } argc1 = 2; argv1[0] = (uint32)argc; - argv1[1] = (uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets); + argv1[1] = + (uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets); } - ret = wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, - argc1, argv1); + ret = wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, argc1, + argv1); if (ret && func_type->result_count > 0 && argc > 0 && argv) /* copy the return value */ - *(int*)argv = (int)argv1[0]; + *(int *)argv = (int)argv1[0]; if (argv_buf_offset) wasm_runtime_module_free(module_inst, argv_buf_offset); @@ -197,7 +194,7 @@ get_sub_module_inst(const WASMModuleInstance *parent_module_inst, const char *sub_module_name) { WASMSubModInstNode *node = - bh_list_first_elem(parent_module_inst->sub_module_inst_list); + bh_list_first_elem(parent_module_inst->sub_module_inst_list); while (node && strcmp(node->module_name, sub_module_name)) { node = bh_list_elem_next(node); @@ -241,9 +238,8 @@ parse_function_name(char *orig_function_name, char **p_module_name, * Implementation of wasm_application_execute_func() */ -static WASMFunctionInstanceCommon* -resolve_function(const WASMModuleInstanceCommon *module_inst, - const char *name) +static WASMFunctionInstanceCommon * +resolve_function(const WASMModuleInstanceCommon *module_inst, const char *name) { uint32 i = 0; WASMFunctionInstanceCommon *ret = NULL; @@ -268,8 +264,8 @@ resolve_function(const WASMModuleInstanceCommon *module_inst, LOG_DEBUG("%s -> %s and %s", name, sub_module_name, function_name); if (sub_module_name) { - sub_module_inst = get_sub_module_inst( - (WASMModuleInstance *)module_inst, sub_module_name); + sub_module_inst = get_sub_module_inst((WASMModuleInstance *)module_inst, + sub_module_name); if (!sub_module_inst) { LOG_DEBUG("can not find a sub module named %s", sub_module_name); goto LEAVE; @@ -281,26 +277,26 @@ resolve_function(const WASMModuleInstanceCommon *module_inst, #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - WASMModuleInstance *wasm_inst = (WASMModuleInstance*)module_inst; + WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst; #if WASM_ENABLE_MULTI_MODULE != 0 wasm_inst = sub_module_inst ? sub_module_inst : wasm_inst; #endif /* WASM_ENABLE_MULTI_MODULE */ for (i = 0; i < wasm_inst->export_func_count; i++) { - if (!strcmp(wasm_inst->export_functions[i].name, function_name)) { + if (!strcmp(wasm_inst->export_functions[i].name, function_name)) { ret = wasm_inst->export_functions[i].function; break; - } + } } } #endif /* WASM_ENABLE_INTERP */ #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - AOTModuleInstance *aot_inst = (AOTModuleInstance*)module_inst; - AOTFunctionInstance *export_funcs = (AOTFunctionInstance *) - aot_inst->export_funcs.ptr; + AOTModuleInstance *aot_inst = (AOTModuleInstance *)module_inst; + AOTFunctionInstance *export_funcs = + (AOTFunctionInstance *)aot_inst->export_funcs.ptr; for (i = 0; i < aot_inst->export_func_count; i++) { if (!strcmp(export_funcs[i].func_name, function_name)) { ret = &export_funcs[i]; @@ -323,14 +319,14 @@ union ieee754_float { /* This is the IEEE 754 single-precision format. */ union { struct { - unsigned int negative:1; - unsigned int exponent:8; - unsigned int mantissa:23; + unsigned int negative : 1; + unsigned int exponent : 8; + unsigned int mantissa : 23; } ieee_big_endian; struct { - unsigned int mantissa:23; - unsigned int exponent:8; - unsigned int negative:1; + unsigned int mantissa : 23; + unsigned int exponent : 8; + unsigned int negative : 1; } ieee_little_endian; } ieee; }; @@ -341,19 +337,19 @@ union ieee754_double { /* This is the IEEE 754 double-precision format. */ union { struct { - unsigned int negative:1; - unsigned int exponent:11; + unsigned int negative : 1; + unsigned int exponent : 11; /* Together these comprise the mantissa. */ - unsigned int mantissa0:20; - unsigned int mantissa1:32; + unsigned int mantissa0 : 20; + unsigned int mantissa1 : 32; } ieee_big_endian; struct { /* Together these comprise the mantissa. */ - unsigned int mantissa1:32; - unsigned int mantissa0:20; - unsigned int exponent:11; - unsigned int negative:1; + unsigned int mantissa1 : 32; + unsigned int mantissa0 : 20; + unsigned int exponent : 11; + unsigned int negative : 1; } ieee_little_endian; } ieee; }; @@ -382,7 +378,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - WASMFunctionInstance *wasm_func = (WASMFunctionInstance*)func; + WASMFunctionInstance *wasm_func = (WASMFunctionInstance *)func; if (wasm_func->is_import_func #if WASM_ENABLE_MULTI_MODULE != 0 && !wasm_func->import_func_inst @@ -404,8 +400,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, } if (type->param_count != (uint32)argc) { - wasm_runtime_set_exception(module_inst, - "invalid input argument count"); + wasm_runtime_set_exception(module_inst, "invalid input argument count"); goto fail; } @@ -413,8 +408,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, cell_num = (argc1 > type->ret_cell_num) ? argc1 : type->ret_cell_num; total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2); - if ((!(argv1 = runtime_malloc((uint32)total_size, module_inst, - NULL, 0)))) { + if ((!(argv1 = runtime_malloc((uint32)total_size, module_inst, NULL, 0)))) { goto fail; } @@ -433,7 +427,10 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, break; case VALUE_TYPE_I64: { - union { uint64 val; uint32 parts[2]; } u; + union { + uint64 val; + uint32 parts[2]; + } u; u.val = strtoull(argv[i], &endptr, 0); argv1[p++] = u.parts[0]; argv1[p++] = u.parts[1]; @@ -469,7 +466,10 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, } case VALUE_TYPE_F64: { - union { float64 val; uint32 parts[2]; } u; + union { + float64 val; + uint32 parts[2]; + } u; u.val = strtod(argv[i], &endptr); if (isnan(u.val)) { if (argv[i][0] == '-') { @@ -506,11 +506,11 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, { /* it likes 0x123\0x234 or 123\234 */ /* retrive first i64 */ - *(uint64*)(argv1 + p) = strtoull(argv[i], &endptr, 0); + *(uint64 *)(argv1 + p) = strtoull(argv[i], &endptr, 0); /* skip \ */ endptr++; /* retrive second i64 */ - *(uint64*)(argv1 + p + 2) = strtoull(endptr, &endptr, 0); + *(uint64 *)(argv1 + p + 2) = strtoull(endptr, &endptr, 0); p += 4; break; } @@ -541,7 +541,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, if (!wasm_externref_obj2ref(module_inst, extern_obj, &externref_idx)) { wasm_runtime_set_exception( - module_inst, "map extern object to ref failed"); + module_inst, "map extern object to ref failed"); goto fail; } argv1[p++] = externref_idx; @@ -554,8 +554,8 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, break; } if (endptr && *endptr != '\0' && *endptr != '_') { - snprintf(buf, sizeof(buf), "invalid input argument %d: %s", - i, argv[i]); + snprintf(buf, sizeof(buf), "invalid input argument %d: %s", i, + argv[i]); wasm_runtime_set_exception(module_inst, buf); goto fail; } @@ -563,8 +563,8 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, bh_assert(p == (int32)argc1); wasm_runtime_set_exception(module_inst, NULL); - if (!wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, - argc1, argv1)) { + if (!wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, argc1, + argv1)) { goto fail; } @@ -579,12 +579,15 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, } case VALUE_TYPE_I64: { - union { uint64 val; uint32 parts[2]; } u; + union { + uint64 val; + uint32 parts[2]; + } u; u.parts[0] = argv1[k]; u.parts[1] = argv1[k + 1]; k += 2; #ifdef PRIx64 - os_printf("0x%"PRIx64":i64", u.val); + os_printf("0x%" PRIx64 ":i64", u.val); #else char buf[16]; if (sizeof(long) == 4) @@ -597,13 +600,16 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, } case VALUE_TYPE_F32: { - os_printf("%.7g:f32", *(float32*)(argv1 + k)); + os_printf("%.7g:f32", *(float32 *)(argv1 + k)); k++; break; } case VALUE_TYPE_F64: { - union { float64 val; uint32 parts[2]; } u; + union { + float64 val; + uint32 parts[2]; + } u; u.parts[0] = argv1[k]; u.parts[1] = argv1[k + 1]; k += 2; @@ -638,9 +644,10 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, #if WASM_ENABLE_SIMD != 0 case VALUE_TYPE_V128: { - uint64 *v = (uint64*)(argv1 + k); + uint64 *v = (uint64 *)(argv1 + k); #if defined(PRIx64) - os_printf("<0x%016"PRIx64" 0x%016"PRIx64">:v128", *v, *(v + 1)); + os_printf("<0x%016" PRIx64 " 0x%016" PRIx64 ">:v128", *v, + *(v + 1)); #else if (4 == sizeof(long)) { os_printf("<0x%016llx 0x%016llx>:v128", *v, *(v + 1)); diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 90d059e75d..9bffeb6620 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -5,6 +5,7 @@ #include "wasm_c_api_internal.h" #include "wasm_memory.h" +#include "wasm_runtime_common.h" #if WASM_ENABLE_INTERP != 0 #include "wasm_runtime.h" #endif @@ -13,6 +14,7 @@ #endif #define ASSERT_NOT_IMPLEMENTED() bh_assert(!"not implemented") +#define UNREACHABLE() bh_assert(!"unreachable") typedef struct wasm_module_ex_t wasm_module_ex_t; @@ -47,7 +49,8 @@ wasm_instance_copy(const wasm_instance_t *src) return NULL; } -static void * +/* ---------------------------------------------------------------------- */ +static inline void * malloc_internal(uint64 size) { void *mem = NULL; @@ -59,203 +62,202 @@ malloc_internal(uint64 size) return mem; } -#define FREEIF(p) \ - if (p) { \ - wasm_runtime_free(p); \ - } - /* clang-format off */ -#define RETURN_OBJ(obj, obj_del_func) \ - return obj; \ -failed: \ - obj_del_func(obj); \ +#define RETURN_OBJ(obj, obj_del_func) \ + return obj; \ +failed: \ + obj_del_func(obj); \ return NULL; -#define RETURN_VOID(obj, obj_del_func) \ - return; \ -failed: \ - obj_del_func(obj); \ +#define RETURN_VOID(obj, obj_del_func) \ + return; \ +failed: \ + obj_del_func(obj); \ return; /* clang-format on */ /* Vectors */ -#define INIT_VEC(vector_p, init_func, ...) \ - do { \ - if (!(vector_p = malloc_internal(sizeof(*(vector_p))))) { \ - goto failed; \ - } \ - \ - init_func(vector_p, ##__VA_ARGS__); \ - if (vector_p->size && !vector_p->data) { \ - LOG_DEBUG("%s failed", #init_func); \ - goto failed; \ - } \ +#define INIT_VEC(vector_p, init_func, ...) \ + do { \ + if (!(vector_p = malloc_internal(sizeof(*(vector_p))))) { \ + goto failed; \ + } \ + \ + init_func(vector_p, ##__VA_ARGS__); \ + if (vector_p->size && !vector_p->data) { \ + LOG_DEBUG("%s failed", #init_func); \ + goto failed; \ + } \ } while (false) -#define DEINIT_VEC(vector_p, deinit_func) \ - if ((vector_p)) { \ - deinit_func(vector_p); \ - wasm_runtime_free(vector_p); \ - vector_p = NULL; \ +#define DEINIT_VEC(vector_p, deinit_func) \ + if ((vector_p)) { \ + deinit_func(vector_p); \ + wasm_runtime_free(vector_p); \ + vector_p = NULL; \ } -#define WASM_DEFINE_VEC(name) \ - void wasm_##name##_vec_new_empty(own wasm_##name##_vec_t *out) \ - { \ - wasm_##name##_vec_new_uninitialized(out, 0); \ - } \ - void wasm_##name##_vec_new_uninitialized(own wasm_##name##_vec_t *out, \ - size_t size) \ - { \ - wasm_##name##_vec_new(out, size, NULL); \ +#define WASM_DEFINE_VEC(name) \ + void wasm_##name##_vec_new_empty(own wasm_##name##_vec_t *out) \ + { \ + wasm_##name##_vec_new_uninitialized(out, 0); \ + } \ + void wasm_##name##_vec_new_uninitialized(own wasm_##name##_vec_t *out, \ + size_t size) \ + { \ + wasm_##name##_vec_new(out, size, NULL); \ } /* vectors with no ownership management of elements */ -#define WASM_DEFINE_VEC_PLAIN(name) \ - WASM_DEFINE_VEC(name) \ - void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size, \ - own wasm_##name##_t const data[]) \ - { \ - if (!out) { \ - return; \ - } \ - \ - memset(out, 0, sizeof(wasm_##name##_vec_t)); \ - \ - if (!size) { \ - return; \ - } \ - \ - if (!bh_vector_init((Vector *)out, size, sizeof(wasm_##name##_t))) { \ - LOG_DEBUG("bh_vector_init failed"); \ - goto failed; \ - } \ - \ - if (data) { \ - unsigned int size_in_bytes = 0; \ - size_in_bytes = size * sizeof(wasm_##name##_t); \ - bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes); \ - out->num_elems = size; \ - } \ - \ - RETURN_VOID(out, wasm_##name##_vec_delete) \ - } \ - void wasm_##name##_vec_copy(wasm_##name##_vec_t *out, \ - const wasm_##name##_vec_t *src) \ - { \ - wasm_##name##_vec_new(out, src->size, src->data); \ - } \ - void wasm_##name##_vec_delete(wasm_##name##_vec_t *v) \ - { \ - if (v) { \ - bh_vector_destroy((Vector *)v); \ - } \ +#define WASM_DEFINE_VEC_PLAIN(name) \ + WASM_DEFINE_VEC(name) \ + void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size, \ + own wasm_##name##_t const data[]) \ + { \ + if (!out) { \ + return; \ + } \ + \ + memset(out, 0, sizeof(wasm_##name##_vec_t)); \ + \ + if (!size) { \ + return; \ + } \ + \ + if (!bh_vector_init((Vector *)out, size, sizeof(wasm_##name##_t))) { \ + LOG_DEBUG("bh_vector_init failed"); \ + goto failed; \ + } \ + \ + if (data) { \ + uint32 size_in_bytes = 0; \ + size_in_bytes = (uint32)(size * sizeof(wasm_##name##_t)); \ + bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes); \ + out->num_elems = size; \ + } \ + \ + RETURN_VOID(out, wasm_##name##_vec_delete) \ + } \ + void wasm_##name##_vec_copy(wasm_##name##_vec_t *out, \ + const wasm_##name##_vec_t *src) \ + { \ + wasm_##name##_vec_new(out, src->size, src->data); \ + } \ + void wasm_##name##_vec_delete(wasm_##name##_vec_t *v) \ + { \ + if (v) { \ + bh_vector_destroy((Vector *)v); \ + } \ } /* vectors that own their elements */ -#define WASM_DEFINE_VEC_OWN(name, elem_destroy_func) \ - WASM_DEFINE_VEC(name) \ - void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size, \ - own wasm_##name##_t *const data[]) \ - { \ - if (!out) { \ - return; \ - } \ - \ - memset(out, 0, sizeof(wasm_##name##_vec_t)); \ - \ - if (!size) { \ - return; \ - } \ - \ - if (!bh_vector_init((Vector *)out, size, \ - sizeof(wasm_##name##_t *))) { \ - LOG_DEBUG("bh_vector_init failed"); \ - goto failed; \ - } \ - \ - if (data) { \ - unsigned int size_in_bytes = 0; \ - size_in_bytes = size * sizeof(wasm_##name##_t *); \ - bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes); \ - out->num_elems = size; \ - } \ - \ - RETURN_VOID(out, wasm_##name##_vec_delete) \ - } \ - void wasm_##name##_vec_copy(own wasm_##name##_vec_t *out, \ - const wasm_##name##_vec_t *src) \ - { \ - size_t i = 0; \ - memset(out, 0, sizeof(Vector)); \ - \ - if (!src->size) { \ - return; \ - } \ - \ - if (!bh_vector_init((Vector *)out, src->size, \ - sizeof(wasm_##name##_t *))) { \ - LOG_DEBUG("bh_vector_init failed"); \ - goto failed; \ - } \ - \ - for (i = 0; i != src->num_elems; ++i) { \ - if (!(out->data[i] = wasm_##name##_copy(src->data[i]))) { \ - LOG_DEBUG("wasm_%s_copy failed", #name); \ - goto failed; \ - } \ - } \ - out->num_elems = src->num_elems; \ - \ - RETURN_VOID(out, wasm_##name##_vec_delete) \ - } \ - void wasm_##name##_vec_delete(wasm_##name##_vec_t *v) \ - { \ - size_t i = 0; \ - if (!v) { \ - return; \ - } \ - for (i = 0; i != v->num_elems; ++i) { \ - elem_destroy_func(*(v->data + i)); \ - } \ - bh_vector_destroy((Vector *)v); \ +#define WASM_DEFINE_VEC_OWN(name, elem_destroy_func) \ + WASM_DEFINE_VEC(name) \ + void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size, \ + own wasm_##name##_t *const data[]) \ + { \ + if (!out) { \ + return; \ + } \ + \ + memset(out, 0, sizeof(wasm_##name##_vec_t)); \ + \ + if (!size) { \ + return; \ + } \ + \ + if (!bh_vector_init((Vector *)out, size, sizeof(wasm_##name##_t *))) { \ + LOG_DEBUG("bh_vector_init failed"); \ + goto failed; \ + } \ + \ + if (data) { \ + uint32 size_in_bytes = 0; \ + size_in_bytes = (uint32)(size * sizeof(wasm_##name##_t *)); \ + bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes); \ + out->num_elems = size; \ + } \ + \ + RETURN_VOID(out, wasm_##name##_vec_delete) \ + } \ + void wasm_##name##_vec_copy(own wasm_##name##_vec_t *out, \ + const wasm_##name##_vec_t *src) \ + { \ + size_t i = 0; \ + memset(out, 0, sizeof(Vector)); \ + \ + if (!src || !src->size) { \ + return; \ + } \ + \ + if (!bh_vector_init((Vector *)out, src->size, \ + sizeof(wasm_##name##_t *))) { \ + LOG_DEBUG("bh_vector_init failed"); \ + goto failed; \ + } \ + \ + for (i = 0; i != src->num_elems; ++i) { \ + if (!(out->data[i] = wasm_##name##_copy(src->data[i]))) { \ + LOG_DEBUG("wasm_%s_copy failed", #name); \ + goto failed; \ + } \ + } \ + out->num_elems = src->num_elems; \ + \ + RETURN_VOID(out, wasm_##name##_vec_delete) \ + } \ + void wasm_##name##_vec_delete(wasm_##name##_vec_t *v) \ + { \ + size_t i = 0; \ + if (!v) { \ + return; \ + } \ + for (i = 0; i != v->num_elems; ++i) { \ + elem_destroy_func(*(v->data + i)); \ + } \ + bh_vector_destroy((Vector *)v); \ } WASM_DEFINE_VEC_PLAIN(byte) WASM_DEFINE_VEC_PLAIN(val) -WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete) -WASM_DEFINE_VEC_OWN(functype, wasm_functype_delete) WASM_DEFINE_VEC_OWN(exporttype, wasm_exporttype_delete) +WASM_DEFINE_VEC_OWN(extern, wasm_extern_delete) +WASM_DEFINE_VEC_OWN(frame, wasm_frame_delete) +WASM_DEFINE_VEC_OWN(functype, wasm_functype_delete) WASM_DEFINE_VEC_OWN(importtype, wasm_importtype_delete) -WASM_DEFINE_VEC_OWN(store, wasm_store_delete) -WASM_DEFINE_VEC_OWN(module, wasm_module_delete_internal) WASM_DEFINE_VEC_OWN(instance, wasm_instance_delete_internal) -WASM_DEFINE_VEC_OWN(extern, wasm_extern_delete) +WASM_DEFINE_VEC_OWN(module, wasm_module_delete_internal) +WASM_DEFINE_VEC_OWN(store, wasm_store_delete) +WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete) -static inline bool -valid_module_type(uint32 module_type) -{ - bool result = false; +/* conflicting declaration between aot_export.h and aot.h */ +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 +bool +aot_compile_wasm_file_init(); -#if WASM_ENABLE_INTERP != 0 - result = result || (module_type == Wasm_Module_Bytecode); -#endif +void +aot_compile_wasm_file_destroy(); -#if WASM_ENABLE_AOT != 0 - result = result || (module_type == Wasm_Module_AoT); +uint8 * +aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size, + uint32 opt_level, uint32 size_level, char *error_buf, + uint32 error_buf_size, uint32 *p_aot_file_size); #endif - if (!result) { - LOG_VERBOSE( - "current building isn't compatiable with the module, may need " - "recompile"); - } +/* Runtime Environment */ +own wasm_config_t * +wasm_config_new(void) +{ + return NULL; +} - return result; +void +wasm_config_delete(own wasm_config_t *config) +{ + (void)config; } -/* Runtime Environment */ static void wasm_engine_delete_internal(wasm_engine_t *engine) { @@ -264,6 +266,10 @@ wasm_engine_delete_internal(wasm_engine_t *engine) wasm_runtime_free(engine); } +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 + aot_compile_wasm_file_destroy(); +#endif + wasm_runtime_destroy(); } @@ -289,11 +295,11 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts) } init_args.mem_alloc_option.allocator.malloc_func = - opts->allocator.malloc_func; + opts->allocator.malloc_func; init_args.mem_alloc_option.allocator.free_func = - opts->allocator.free_func; + opts->allocator.free_func; init_args.mem_alloc_option.allocator.realloc_func = - opts->allocator.realloc_func; + opts->allocator.realloc_func; } else { init_args.mem_alloc_option.pool.heap_buf = NULL; @@ -311,6 +317,12 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts) bh_log_set_verbose_level(3); #endif +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 + if (!aot_compile_wasm_file_init()) { + goto failed; + } +#endif + /* create wasm_engine_t */ if (!(engine = malloc_internal(sizeof(wasm_engine_t)))) { goto failed; @@ -325,17 +337,24 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts) /* global engine instance */ static wasm_engine_t *singleton_engine = NULL; -wasm_engine_t * +own wasm_engine_t * wasm_engine_new() { if (!singleton_engine) { singleton_engine = - wasm_engine_new_internal(Alloc_With_System_Allocator, NULL); + wasm_engine_new_internal(Alloc_With_System_Allocator, NULL); } return singleton_engine; } -wasm_engine_t * +own wasm_engine_t * +wasm_engine_new_with_config(own wasm_config_t *config) +{ + (void)config; + return wasm_engine_new(); +} + +own wasm_engine_t * wasm_engine_new_with_args(mem_alloc_type_t type, const MemAllocOption *opts) { if (!singleton_engine) { @@ -379,6 +398,11 @@ wasm_store_new(wasm_engine_t *engine) INIT_VEC(store->instances, wasm_instance_vec_new_uninitialized, DEFAULT_VECTOR_INIT_LENGTH); + if (!(store->foreigns = malloc_internal(sizeof(Vector))) + || !(bh_vector_init(store->foreigns, 24, sizeof(Vector *)))) { + goto failed; + } + /* append to a store list of engine */ if (!bh_vector_append((Vector *)singleton_engine->stores, &store)) { LOG_DEBUG("bh_vector_append failed"); @@ -405,43 +429,47 @@ wasm_store_delete(wasm_store_t *store) for (i = 0; i != store_count; ++i) { wasm_store_t *tmp; - if (!bh_vector_get((Vector *)singleton_engine->stores, i, &tmp)) { + if (!bh_vector_get((Vector *)singleton_engine->stores, (uint32)i, + &tmp)) { break; } if (tmp == store) { - bh_vector_remove((Vector *)singleton_engine->stores, i, NULL); + bh_vector_remove((Vector *)singleton_engine->stores, (uint32)i, + NULL); break; } } DEINIT_VEC(store->modules, wasm_module_vec_delete); DEINIT_VEC(store->instances, wasm_instance_vec_delete); + if (store->foreigns) { + bh_vector_destroy(store->foreigns); + wasm_runtime_free(store->foreigns); + } + wasm_runtime_free(store); wasm_runtime_destroy_thread_env(); } /* Type Representations */ -static wasm_valkind_t +static inline wasm_valkind_t val_type_rt_2_valkind(uint8 val_type_rt) { switch (val_type_rt) { - case VALUE_TYPE_I32: - return WASM_I32; - case VALUE_TYPE_I64: - return WASM_I64; - case VALUE_TYPE_F32: - return WASM_F32; - case VALUE_TYPE_F64: - return WASM_F64; - case VALUE_TYPE_ANY: - return WASM_ANYREF; - case VALUE_TYPE_FUNCREF: - return WASM_FUNCREF; +#define WAMR_VAL_TYPE_2_WASM_VAL_KIND(name) \ + case VALUE_TYPE_##name: \ + return WASM_##name; + + WAMR_VAL_TYPE_2_WASM_VAL_KIND(I32) + WAMR_VAL_TYPE_2_WASM_VAL_KIND(I64) + WAMR_VAL_TYPE_2_WASM_VAL_KIND(F32) + WAMR_VAL_TYPE_2_WASM_VAL_KIND(F64) + WAMR_VAL_TYPE_2_WASM_VAL_KIND(FUNCREF) +#undef WAMR_VAL_TYPE_2_WASM_VAL_KIND + default: - LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__, - val_type_rt); return WASM_ANYREF; } } @@ -469,41 +497,21 @@ wasm_valtype_new(wasm_valkind_t kind) void wasm_valtype_delete(wasm_valtype_t *val_type) { - FREEIF(val_type); + if (val_type) { + wasm_runtime_free(val_type); + } } wasm_valtype_t * wasm_valtype_copy(const wasm_valtype_t *src) { - if (!src) { - return NULL; - } - - return wasm_valtype_new(src->kind); + return src ? wasm_valtype_new(src->kind) : NULL; } wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t *val_type) { - if (!val_type) { - return WASM_ANYREF; - } - - return val_type->kind; -} - -bool -wasm_valtype_same(const wasm_valtype_t *vt1, const wasm_valtype_t *vt2) -{ - if (!vt1 && !vt2) { - return true; - } - - if (!vt1 || !vt2) { - return false; - } - - return vt1->kind == vt2->kind; + return val_type ? val_type->kind : WASM_ANYREF; } static wasm_functype_t * @@ -537,12 +545,13 @@ wasm_functype_new_internal(WASMType *type_rt) } } - /* WASMType->types[type_rt->param_count : type_rt->result_count) -> type->results */ + /* WASMType->types[type_rt->param_count : type_rt->result_count) -> + * type->results */ INIT_VEC(type->results, wasm_valtype_vec_new_uninitialized, type_rt->result_count); for (i = 0; i < type_rt->result_count; ++i) { if (!(result_type = wasm_valtype_new_internal( - *(type_rt->types + type_rt->param_count + i)))) { + *(type_rt->types + type_rt->param_count + i)))) { goto failed; } @@ -697,7 +706,7 @@ wasm_globaltype_new_internal(uint8 val_type_rt, bool is_mutable) } if (!(globaltype = wasm_globaltype_new( - val_type, is_mutable ? WASM_VAR : WASM_CONST))) { + val_type, is_mutable ? WASM_VAR : WASM_CONST))) { wasm_valtype_delete(val_type); } @@ -760,25 +769,8 @@ wasm_globaltype_mutability(const wasm_globaltype_t *global_type) return global_type->mutability; } -bool -wasm_globaltype_same(const wasm_globaltype_t *gt1, - const wasm_globaltype_t *gt2) -{ - if (!gt1 && !gt2) { - return true; - } - - if (!gt1 || !gt2) { - return false; - } - - return wasm_valtype_same(gt1->val_type, gt2->val_type) - || gt1->mutability == gt2->mutability; -} - static wasm_tabletype_t * -wasm_tabletype_new_internal(uint8 val_type_rt, - uint32 init_size, +wasm_tabletype_new_internal(uint8 val_type_rt, uint32 init_size, uint32 max_size) { wasm_tabletype_t *table_type; @@ -913,7 +905,9 @@ wasm_memorytype_copy(const wasm_memorytype_t *src) void wasm_memorytype_delete(wasm_memorytype_t *memory_type) { - FREEIF(memory_type); + if (memory_type) { + wasm_runtime_free(memory_type); + } } const wasm_limits_t * @@ -936,46 +930,45 @@ wasm_externtype_kind(const wasm_externtype_t *extern_type) return extern_type->extern_kind; } -#define BASIC_FOUR_TYPE_LIST(V) \ - V(functype) \ - V(globaltype) \ - V(memorytype) \ +#define BASIC_FOUR_TYPE_LIST(V) \ + V(functype) \ + V(globaltype) \ + V(memorytype) \ V(tabletype) -#define WASM_EXTERNTYPE_AS_OTHERTYPE(name) \ - wasm_##name##_t *wasm_externtype_as_##name( \ - wasm_externtype_t *extern_type) \ - { \ - return (wasm_##name##_t *)extern_type; \ +#define WASM_EXTERNTYPE_AS_OTHERTYPE(name) \ + wasm_##name##_t *wasm_externtype_as_##name(wasm_externtype_t *extern_type) \ + { \ + return (wasm_##name##_t *)extern_type; \ } BASIC_FOUR_TYPE_LIST(WASM_EXTERNTYPE_AS_OTHERTYPE) #undef WASM_EXTERNTYPE_AS_OTHERTYPE -#define WASM_OTHERTYPE_AS_EXTERNTYPE(name) \ - wasm_externtype_t *wasm_##name##_as_externtype(wasm_##name##_t *other) \ - { \ - return (wasm_externtype_t *)other; \ +#define WASM_OTHERTYPE_AS_EXTERNTYPE(name) \ + wasm_externtype_t *wasm_##name##_as_externtype(wasm_##name##_t *other) \ + { \ + return (wasm_externtype_t *)other; \ } BASIC_FOUR_TYPE_LIST(WASM_OTHERTYPE_AS_EXTERNTYPE) #undef WASM_OTHERTYPE_AS_EXTERNTYPE -#define WASM_EXTERNTYPE_AS_OTHERTYPE_CONST(name) \ - const wasm_##name##_t *wasm_externtype_as_##name##_const( \ - const wasm_externtype_t *extern_type) \ - { \ - return (const wasm_##name##_t *)extern_type; \ +#define WASM_EXTERNTYPE_AS_OTHERTYPE_CONST(name) \ + const wasm_##name##_t *wasm_externtype_as_##name##_const( \ + const wasm_externtype_t *extern_type) \ + { \ + return (const wasm_##name##_t *)extern_type; \ } BASIC_FOUR_TYPE_LIST(WASM_EXTERNTYPE_AS_OTHERTYPE_CONST) #undef WASM_EXTERNTYPE_AS_OTHERTYPE_CONST -#define WASM_OTHERTYPE_AS_EXTERNTYPE_CONST(name) \ - const wasm_externtype_t *wasm_##name##_as_externtype_const( \ - const wasm_##name##_t *other) \ - { \ - return (const wasm_externtype_t *)other; \ +#define WASM_OTHERTYPE_AS_EXTERNTYPE_CONST(name) \ + const wasm_externtype_t *wasm_##name##_as_externtype_const( \ + const wasm_##name##_t *other) \ + { \ + return (const wasm_externtype_t *)other; \ } BASIC_FOUR_TYPE_LIST(WASM_OTHERTYPE_AS_EXTERNTYPE_CONST) @@ -991,12 +984,12 @@ wasm_externtype_copy(const wasm_externtype_t *src) } switch (src->extern_kind) { -#define COPY_EXTERNTYPE(NAME, name) \ - case WASM_EXTERN_##NAME: \ - { \ - extern_type = wasm_##name##_as_externtype( \ - wasm_##name##_copy(wasm_externtype_as_##name##_const(src))); \ - break; \ +#define COPY_EXTERNTYPE(NAME, name) \ + case WASM_EXTERN_##NAME: \ + { \ + extern_type = wasm_##name##_as_externtype( \ + wasm_##name##_copy(wasm_externtype_as_##name##_const(src))); \ + break; \ } COPY_EXTERNTYPE(FUNC, functype) COPY_EXTERNTYPE(GLOBAL, globaltype) @@ -1032,8 +1025,7 @@ wasm_externtype_delete(wasm_externtype_t *extern_type) wasm_tabletype_delete(wasm_externtype_as_tabletype(extern_type)); break; default: - LOG_WARNING("%s meets unsupported type", __FUNCTION__, - extern_type); + LOG_WARNING("%s meets unsupported type", __FUNCTION__, extern_type); break; } } @@ -1051,7 +1043,7 @@ wasm_importtype_new(own wasm_byte_vec_t *module_name, /* take ownership */ if (!(import_type->module_name = - malloc_internal(sizeof(wasm_byte_vec_t)))) { + malloc_internal(sizeof(wasm_byte_vec_t)))) { goto failed; } bh_memcpy_s(import_type->module_name, sizeof(wasm_byte_vec_t), module_name, @@ -1110,7 +1102,7 @@ wasm_importtype_copy(const wasm_importtype_t *src) } if (!(import_type = - wasm_importtype_new(&module_name, &name, extern_type))) { + wasm_importtype_new(&module_name, &name, extern_type))) { goto failed; } @@ -1240,11 +1232,12 @@ wasm_exporttype_type(const wasm_exporttype_t *export_type) } /* Runtime Objects */ - void wasm_val_delete(wasm_val_t *v) { - FREEIF(v); + if (v) { + wasm_runtime_free(v); + } } void @@ -1258,41 +1251,340 @@ wasm_val_copy(wasm_val_t *out, const wasm_val_t *src) } bool -wasm_val_same(const wasm_val_t *v1, const wasm_val_t *v2) +rt_val_to_wasm_val(const uint8 *data, uint8 val_type_rt, wasm_val_t *out) { - if (!v1 && !v2) { - return true; + bool ret = true; + switch (val_type_rt) { + case VALUE_TYPE_I32: + out->kind = WASM_I32; + out->of.i32 = *((int32 *)data); + break; + case VALUE_TYPE_F32: + out->kind = WASM_F32; + out->of.f32 = *((float32 *)data); + break; + case VALUE_TYPE_I64: + out->kind = WASM_I64; + out->of.i64 = *((int64 *)data); + break; + case VALUE_TYPE_F64: + out->kind = WASM_F64; + out->of.f64 = *((float64 *)data); + break; +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_EXTERNREF: + out->kind = WASM_ANYREF; + if (NULL_REF == *(uint32 *)data) { + out->of.ref = NULL; + } + else { + ret = wasm_externref_ref2obj(*(uint32 *)data, + (void **)&out->of.ref); + } + break; +#endif + default: + LOG_WARNING("unexpected value type %d", val_type_rt); + ret = false; } + return ret; +} - if (!v1 || !v2) { - return false; +bool +wasm_val_to_rt_val(WASMModuleInstanceCommon *inst_comm_rt, uint8 val_type_rt, + const wasm_val_t *v, uint8 *data) +{ + bool ret = true; + switch (val_type_rt) { + case VALUE_TYPE_I32: + bh_assert(WASM_I32 == v->kind); + *((int32 *)data) = v->of.i32; + break; + case VALUE_TYPE_F32: + bh_assert(WASM_F32 == v->kind); + *((float32 *)data) = v->of.f32; + break; + case VALUE_TYPE_I64: + bh_assert(WASM_I64 == v->kind); + *((int64 *)data) = v->of.i64; + break; + case VALUE_TYPE_F64: + bh_assert(WASM_F64 == v->kind); + *((float64 *)data) = v->of.f64; + break; +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_EXTERNREF: + bh_assert(WASM_ANYREF == v->kind); + ret = + wasm_externref_obj2ref(inst_comm_rt, v->of.ref, (uint32 *)data); + break; +#endif + default: + LOG_WARNING("unexpected value type %d", val_type_rt); + ret = false; + break; } - if (v1->kind != v2->kind) { - return false; + return ret; +} + +wasm_ref_t * +wasm_ref_new_internal(wasm_store_t *store, enum wasm_reference_kind kind, + uint32 ref_idx_rt, WASMModuleInstanceCommon *inst_comm_rt) +{ + wasm_ref_t *ref; + + if (!store) { + return NULL; } - switch (v1->kind) { - case WASM_I32: - return v1->of.i32 == v2->of.i32; - case WASM_I64: - return v1->of.i64 == v2->of.i64; - case WASM_F32: - return v1->of.f32 == v2->of.f32; - case WASM_F64: - return v1->of.f64 == v2->of.f64; - case WASM_FUNCREF: - return v1->of.ref == v2->of.ref; - default: - break; + if (!(ref = malloc_internal(sizeof(wasm_ref_t)))) { + return NULL; } - return false; + + ref->store = store; + ref->kind = kind; + ref->ref_idx_rt = ref_idx_rt; + ref->inst_comm_rt = inst_comm_rt; + + /* workaround */ + if (WASM_REF_foreign == kind) { + wasm_foreign_t *foreign; + + if (!(bh_vector_get(ref->store->foreigns, ref->ref_idx_rt, &foreign)) + || !foreign) { + wasm_runtime_free(ref); + return NULL; + } + + foreign->ref_cnt++; + } + /* others doesn't include ref counters */ + + return ref; +} + +own wasm_ref_t * +wasm_ref_copy(const wasm_ref_t *src) +{ + if (!src) + return NULL; + + /* host_info are different in wasm_ref_t(s) */ + return wasm_ref_new_internal(src->store, src->kind, src->ref_idx_rt, + src->inst_comm_rt); +} + +#define DELETE_HOST_INFO(obj) \ + if (obj->host_info.info) { \ + if (obj->host_info.finalizer) { \ + obj->host_info.finalizer(obj->host_info.info); \ + } \ + } + +void +wasm_ref_delete(own wasm_ref_t *ref) +{ + if (!ref) + return; + + DELETE_HOST_INFO(ref); + + if (WASM_REF_foreign == ref->kind) { + wasm_foreign_t *foreign = NULL; + + if (bh_vector_get(ref->store->foreigns, ref->ref_idx_rt, &foreign) + && foreign) { + wasm_foreign_delete(foreign); + } + } + + wasm_runtime_free(ref); +} + +#define WASM_DEFINE_REF_BASE(name) \ + bool wasm_##name##_same(const wasm_##name##_t *o1, \ + const wasm_##name##_t *o2) \ + { \ + return (!o1 && !o2) ? true \ + : (!o1 || !o2) ? false \ + : (o1->kind != o2->kind) \ + ? false \ + : o1->name##_idx_rt == o2->name##_idx_rt; \ + } \ + \ + void *wasm_##name##_get_host_info(const wasm_##name##_t *obj) \ + { \ + return obj ? obj->host_info.info : NULL; \ + } \ + \ + void wasm_##name##_set_host_info(wasm_##name##_t *obj, void *host_info) \ + { \ + if (obj) { \ + obj->host_info.info = host_info; \ + obj->host_info.finalizer = NULL; \ + } \ + } \ + \ + void wasm_##name##_set_host_info_with_finalizer( \ + wasm_##name##_t *obj, void *host_info, void (*finalizer)(void *)) \ + { \ + if (obj) { \ + obj->host_info.info = host_info; \ + obj->host_info.finalizer = finalizer; \ + } \ + } + +#define WASM_DEFINE_REF(name) \ + WASM_DEFINE_REF_BASE(name) \ + \ + wasm_ref_t *wasm_##name##_as_ref(wasm_##name##_t *name) \ + { \ + if (!name) { \ + return NULL; \ + } \ + \ + return wasm_ref_new_internal(name->store, WASM_REF_##name, \ + name->name##_idx_rt, name->inst_comm_rt); \ + } \ + \ + const wasm_ref_t *wasm_##name##_as_ref_const(const wasm_##name##_t *name) \ + { \ + if (!name) { \ + return NULL; \ + } \ + \ + return wasm_ref_new_internal(name->store, WASM_REF_##name, \ + name->name##_idx_rt, name->inst_comm_rt); \ + } \ + \ + wasm_##name##_t *wasm_ref_as_##name(wasm_ref_t *ref) \ + { \ + if (!ref || WASM_REF_##name != ref->kind) { \ + return NULL; \ + } \ + \ + return wasm_##name##_new_internal(ref->store, ref->ref_idx_rt, \ + ref->inst_comm_rt); \ + } \ + \ + const wasm_##name##_t *wasm_ref_as_##name##_const(const wasm_ref_t *ref) \ + { \ + if (!ref || WASM_REF_##name != ref->kind) { \ + return NULL; \ + } \ + \ + return wasm_##name##_new_internal(ref->store, ref->ref_idx_rt, \ + ref->inst_comm_rt); \ + } + +WASM_DEFINE_REF_BASE(ref) +WASM_DEFINE_REF(foreign) +WASM_DEFINE_REF(func) +WASM_DEFINE_REF(global) +WASM_DEFINE_REF(memory) +WASM_DEFINE_REF(table) + +static wasm_frame_t * +wasm_frame_new(wasm_instance_t *instance, size_t module_offset, + uint32 func_index, size_t func_offset) +{ + wasm_frame_t *frame; + + if (!(frame = malloc_internal(sizeof(wasm_frame_t)))) { + return NULL; + } + + frame->instance = instance; + frame->module_offset = (uint32)module_offset; + frame->func_index = func_index; + frame->func_offset = (uint32)func_offset; + return frame; +} + +own wasm_frame_t * +wasm_frame_copy(const wasm_frame_t *src) +{ + if (!src) { + return NULL; + } + + return wasm_frame_new(src->instance, src->module_offset, src->func_index, + src->func_offset); +} + +void +wasm_frame_delete(own wasm_frame_t *frame) +{ + if (frame) { + wasm_runtime_free(frame); + } +} + +struct wasm_instance_t * +wasm_frame_instance(const wasm_frame_t *frame) +{ + return frame ? frame->instance : NULL; +} + +size_t +wasm_frame_module_offset(const wasm_frame_t *frame) +{ + return frame ? frame->module_offset : 0; +} + +uint32_t +wasm_frame_func_index(const wasm_frame_t *frame) +{ + return frame ? frame->func_index : 0; +} + +size_t +wasm_frame_func_offset(const wasm_frame_t *frame) +{ + return frame ? frame->func_offset : 0; } static wasm_trap_t * -wasm_trap_new_internal(const char *string) +wasm_trap_new_internal(WASMModuleInstanceCommon *inst_comm_rt, + const char *default_error_info) { wasm_trap_t *trap; + const char *error_info = NULL; + wasm_instance_vec_t *instances; + wasm_instance_t *frame_instance = NULL; + uint32 i; + + if (!singleton_engine || !singleton_engine->stores + || !singleton_engine->stores->num_elems) { + return NULL; + } + +#if WASM_ENABLE_INTERP != 0 + if (inst_comm_rt->module_type == Wasm_Module_Bytecode) { + if (!(error_info = + wasm_get_exception((WASMModuleInstance *)inst_comm_rt))) { + return NULL; + } + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (inst_comm_rt->module_type == Wasm_Module_AoT) { + if (!(error_info = + aot_get_exception((AOTModuleInstance *)inst_comm_rt))) { + return NULL; + } + } +#endif + + /* + * a wrong combination of module filetype and compilation flags + * also leads to below branch + */ + if (!error_info && !(error_info = default_error_info)) { + return NULL; + } if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) { return NULL; @@ -1302,11 +1594,45 @@ wasm_trap_new_internal(const char *string) goto failed; } - wasm_name_new_from_string(trap->message, string); - if (strlen(string) && !trap->message->data) { + wasm_name_new_from_string_nt(trap->message, error_info); + if (strlen(error_info) && !trap->message->data) { + goto failed; + } + +#if WASM_ENABLE_DUMP_CALL_STACK != 0 +#if WASM_ENABLE_INTERP != 0 + if (inst_comm_rt->module_type == Wasm_Module_Bytecode) { + trap->frames = ((WASMModuleInstance *)inst_comm_rt)->frames; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (inst_comm_rt->module_type == Wasm_Module_AoT) { + trap->frames = ((AOTModuleInstance *)inst_comm_rt)->frames.ptr; + } +#endif +#endif /* WASM_ENABLE_DUMP_CALL_STACK != 0 */ + + /* allow a NULL frames list */ + if (!trap->frames) { + return trap; + } + + if (!(instances = singleton_engine->stores->data[0]->instances)) { goto failed; } + for (i = 0; i < instances->num_elems; i++) { + if (instances->data[i]->inst_comm_rt == inst_comm_rt) { + frame_instance = instances->data[i]; + break; + } + } + + for (i = 0; i < trap->frames->num_elems; i++) { + (((wasm_frame_t *)trap->frames->data) + i)->instance = frame_instance; + } + return trap; failed: wasm_trap_delete(trap); @@ -1342,6 +1668,7 @@ wasm_trap_delete(wasm_trap_t *trap) } DEINIT_VEC(trap->message, wasm_byte_vec_delete); + /* reuse frames of WASMModuleInstance, do not free it here */ wasm_runtime_free(trap); } @@ -1356,10 +1683,123 @@ wasm_trap_message(const wasm_trap_t *trap, own wasm_message_t *out) wasm_byte_vec_copy(out, trap->message); } -struct wasm_module_ex_t { - struct WASMModuleCommon *module_comm_rt; - wasm_byte_vec_t *binary; -}; +own wasm_frame_t * +wasm_trap_origin(const wasm_trap_t *trap) +{ + wasm_frame_t *latest_frame; + + if (!trap || !trap->frames || !trap->frames->num_elems) { + return NULL; + } + + /* first frame is the latest frame */ + latest_frame = (wasm_frame_t *)trap->frames->data; + return wasm_frame_copy(latest_frame); +} + +void +wasm_trap_trace(const wasm_trap_t *trap, own wasm_frame_vec_t *out) +{ + uint32 i; + + if (!trap || !out) { + return; + } + + if (!trap->frames || !trap->frames->num_elems) { + wasm_frame_vec_new_empty(out); + return; + } + + wasm_frame_vec_new_uninitialized(out, trap->frames->num_elems); + if (out->size == 0 || !out->data) { + return; + } + + for (i = 0; i < trap->frames->num_elems; i++) { + wasm_frame_t *frame; + + frame = ((wasm_frame_t *)trap->frames->data) + i; + + if (!(out->data[i] = + wasm_frame_new(frame->instance, frame->module_offset, + frame->func_index, frame->func_offset))) { + goto failed; + } + out->num_elems++; + } + + return; +failed: + for (i = 0; i < out->num_elems; i++) { + if (out->data[i]) { + wasm_runtime_free(out->data[i]); + } + } + + wasm_runtime_free(out->data); +} + +wasm_foreign_t * +wasm_foreign_new_internal(wasm_store_t *store, uint32 foreign_idx_rt, + WASMModuleInstanceCommon *inst_comm_rt) +{ + wasm_foreign_t *foreign = NULL; + + if (!store || !store->foreigns) + return NULL; + + if (!(bh_vector_get(store->foreigns, foreign_idx_rt, &foreign)) + || !foreign) { + return NULL; + } + + foreign->ref_cnt++; + return foreign; +} + +own wasm_foreign_t * +wasm_foreign_new(wasm_store_t *store) +{ + wasm_foreign_t *foreign; + + if (!store) + return NULL; + + if (!(foreign = malloc_internal(sizeof(wasm_foreign_t)))) + return NULL; + + foreign->store = store; + foreign->kind = WASM_REF_foreign; + foreign->foreign_idx_rt = (uint32)bh_vector_size(store->foreigns); + if (!(bh_vector_append(store->foreigns, &foreign))) { + wasm_runtime_free(foreign); + return NULL; + } + + return foreign; +} + +void +wasm_foreign_delete(wasm_foreign_t *foreign) +{ + if (!foreign) + return; + + if (foreign->ref_cnt < 1) { + return; + } + + foreign->ref_cnt--; + if (!foreign->ref_cnt) { + wasm_runtime_free(foreign); + } +} + +struct wasm_module_ex_t { + struct WASMModuleCommon *module_comm_rt; + wasm_byte_vec_t *binary; +}; static inline wasm_module_t * module_ext_to_module(wasm_module_ex_t *module_ex) @@ -1374,11 +1814,11 @@ module_to_module_ext(wasm_module_t *module) } #if WASM_ENABLE_INTERP != 0 -#define MODULE_INTERP(module) ((WASMModule *)(*module)) +#define MODULE_INTERP(module_comm) ((WASMModule *)(*module_comm)) #endif #if WASM_ENABLE_AOT != 0 -#define MODULE_AOT(module) ((AOTModule *)(*module)) +#define MODULE_AOT(module_comm) ((AOTModule *)(*module_comm)) #endif wasm_module_t * @@ -1386,6 +1826,11 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) { char error_buf[128] = { 0 }; wasm_module_ex_t *module_ex = NULL; + PackageType pkg_type; +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 + uint8 *aot_file_buf = NULL; + uint32 aot_file_size; +#endif bh_assert(singleton_engine); @@ -1394,6 +1839,25 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) return NULL; } + pkg_type = get_package_type((uint8 *)binary->data, (uint32)binary->size); + + /* whether the combination of compilation flags are compatable with the + * package type */ + { + bool result = false; +#if WASM_ENABLE_INTERP != 0 + result = (pkg_type == Wasm_Module_Bytecode); +#endif + +#if WASM_ENABLE_AOT != 0 + result = result || (pkg_type == Wasm_Module_AoT); +#endif + if (!result) { + LOG_VERBOSE("current building isn't compatiable with the module," + "may need recompile"); + } + } + module_ex = malloc_internal(sizeof(wasm_module_ex_t)); if (!module_ex) { goto failed; @@ -1401,12 +1865,33 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) INIT_VEC(module_ex->binary, wasm_byte_vec_new, binary->size, binary->data); - module_ex->module_comm_rt = wasm_runtime_load( - (uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, - error_buf, (uint32)sizeof(error_buf)); - if (!(module_ex->module_comm_rt)) { - LOG_ERROR(error_buf); - goto failed; +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 + if (Wasm_Module_Bytecode == pkg_type) { + if (!(aot_file_buf = aot_compile_wasm_file( + (uint8 *)module_ex->binary->data, + (uint32)module_ex->binary->size, 3, 3, error_buf, + (uint32)sizeof(error_buf), &aot_file_size))) { + LOG_ERROR(error_buf); + goto failed; + } + + if (!(module_ex->module_comm_rt = + wasm_runtime_load(aot_file_buf, aot_file_size, error_buf, + (uint32)sizeof(error_buf)))) { + LOG_ERROR(error_buf); + goto failed; + } + } + else +#endif + { + module_ex->module_comm_rt = wasm_runtime_load( + (uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, + error_buf, (uint32)sizeof(error_buf)); + if (!(module_ex->module_comm_rt)) { + LOG_ERROR(error_buf); + goto failed; + } } /* add it to a watching list in store */ @@ -1422,6 +1907,30 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) return NULL; } +bool +wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary) +{ + struct WASMModuleCommon *module_rt; + char error_buf[128] = { 0 }; + + bh_assert(singleton_engine); + + if (!store || !binary || binary->size > UINT32_MAX) { + LOG_ERROR("%s failed", __FUNCTION__); + return false; + } + + if ((module_rt = wasm_runtime_load((uint8 *)binary->data, + (uint32)binary->size, error_buf, 128))) { + wasm_runtime_unload(module_rt); + return true; + } + else { + LOG_VERBOSE(error_buf); + return false; + } +} + static void wasm_module_delete_internal(wasm_module_t *module) { @@ -1449,17 +1958,15 @@ wasm_module_delete(wasm_module_t *module) } void -wasm_module_imports(const wasm_module_t *module, - own wasm_importtype_vec_t *out) +wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out) { uint32 i, import_func_count = 0, import_memory_count = 0, - import_global_count = 0, import_table_count = 0, - import_count = 0; + import_global_count = 0, import_table_count = 0, import_count = 0; wasm_byte_vec_t module_name = { 0 }, name = { 0 }; wasm_externtype_t *extern_type = NULL; wasm_importtype_t *import_type = NULL; - if (!module || !out || !valid_module_type((*module)->module_type)) { + if (!module || !out) { return; } @@ -1483,8 +1990,13 @@ wasm_module_imports(const wasm_module_t *module, import_count = import_func_count + import_global_count + import_table_count + import_memory_count; + wasm_importtype_vec_new_uninitialized(out, import_count); - if (import_count && !out->data) { + /* + * a wrong combination of module filetype and compilation flags + * also leads to below branch + */ + if (!out->data) { return; } @@ -1498,7 +2010,7 @@ wasm_module_imports(const wasm_module_t *module, #if WASM_ENABLE_INTERP != 0 if ((*module)->module_type == Wasm_Module_Bytecode) { WASMImport *import = - MODULE_INTERP(module)->import_functions + i; + MODULE_INTERP(module)->import_functions + i; module_name_rt = import->u.names.module_name; field_name_rt = import->u.names.field_name; type_rt = import->u.function.func_type; @@ -1552,8 +2064,8 @@ wasm_module_imports(const wasm_module_t *module, #if WASM_ENABLE_AOT != 0 if ((*module)->module_type == Wasm_Module_AoT) { - AOTImportGlobal *import = - MODULE_AOT(module)->import_globals + (i - import_func_count); + AOTImportGlobal *import = MODULE_AOT(module)->import_globals + + (i - import_func_count); module_name_rt = import->module_name; field_name_rt = import->global_name; val_type_rt = import->type; @@ -1573,15 +2085,15 @@ wasm_module_imports(const wasm_module_t *module, extern_type = wasm_globaltype_as_externtype(type); } else if (i < import_func_count + import_global_count - + import_memory_count) { + + import_memory_count) { wasm_memorytype_t *type = NULL; uint32 min_page = 0, max_page = 0; #if WASM_ENABLE_INTERP != 0 if ((*module)->module_type == Wasm_Module_Bytecode) { WASMImport *import = - MODULE_INTERP(module)->import_memories - + (i - import_func_count - import_global_count); + MODULE_INTERP(module)->import_memories + + (i - import_func_count - import_global_count); module_name_rt = import->u.names.module_name; field_name_rt = import->u.names.field_name; min_page = import->u.memory.init_page_count; @@ -1592,8 +2104,8 @@ wasm_module_imports(const wasm_module_t *module, #if WASM_ENABLE_AOT != 0 if ((*module)->module_type == Wasm_Module_AoT) { AOTImportMemory *import = - MODULE_AOT(module)->import_memories - + (i - import_func_count - import_global_count); + MODULE_AOT(module)->import_memories + + (i - import_func_count - import_global_count); module_name_rt = import->module_name; field_name_rt = import->memory_name; min_page = import->mem_init_page_count; @@ -1629,9 +2141,9 @@ wasm_module_imports(const wasm_module_t *module, #if WASM_ENABLE_INTERP != 0 if ((*module)->module_type == Wasm_Module_Bytecode) { WASMImport *import = - MODULE_INTERP(module)->import_tables - + (i - import_func_count - import_global_count - - import_memory_count); + MODULE_INTERP(module)->import_tables + + (i - import_func_count - import_global_count + - import_memory_count); module_name_rt = import->u.names.module_name; field_name_rt = import->u.names.field_name; elem_type_rt = import->u.table.elem_type; @@ -1643,9 +2155,9 @@ wasm_module_imports(const wasm_module_t *module, #if WASM_ENABLE_AOT != 0 if ((*module)->module_type == Wasm_Module_AoT) { AOTImportTable *import = - MODULE_AOT(module)->import_tables - + (i - import_func_count - import_global_count - - import_memory_count); + MODULE_AOT(module)->import_tables + + (i - import_func_count - import_global_count + - import_memory_count); module_name_rt = import->module_name; field_name_rt = import->table_name; elem_type_rt = VALUE_TYPE_FUNCREF; @@ -1671,7 +2183,7 @@ wasm_module_imports(const wasm_module_t *module, } if (!(import_type = - wasm_importtype_new(&module_name, &name, extern_type))) { + wasm_importtype_new(&module_name, &name, extern_type))) { goto failed; } @@ -1699,7 +2211,7 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out) wasm_externtype_t *extern_type = NULL; wasm_exporttype_t *export_type = NULL; - if (!module || !out || !valid_module_type((*module)->module_type)) { + if (!module || !out) { return; } @@ -1716,7 +2228,11 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out) #endif wasm_exporttype_vec_new_uninitialized(out, export_count); - if (export_count && !out->data) { + /* + * a wrong combination of module filetype and compilation flags + * also leads to below branch + */ + if (!out->data) { return; } @@ -1727,6 +2243,7 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out) export = MODULE_INTERP(module)->exports + i; } #endif + #if WASM_ENABLE_AOT != 0 if ((*module)->module_type == Wasm_Module_AoT) { export = MODULE_AOT(module)->exports + i; @@ -1743,7 +2260,8 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out) goto failed; } - /* WASMExport -> (WASMType, (uint8, bool)) -> (wasm_functype_t, wasm_globaltype_t) -> wasm_externtype_t*/ + /* WASMExport -> (WASMType, (uint8, bool)) -> (wasm_functype_t, + * wasm_globaltype_t) -> wasm_externtype_t*/ switch (export->kind) { case EXPORT_KIND_FUNC: { @@ -1769,7 +2287,7 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out) bool mutability_rt = 0; if (!wasm_runtime_get_export_global_type( - *module, export, &val_type_rt, &mutability_rt)) { + *module, export, &val_type_rt, &mutability_rt)) { goto failed; } @@ -1787,12 +2305,12 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out) uint32 min_page = 0, max_page = 0; if (!wasm_runtime_get_export_memory_type( - *module, export, &min_page, &max_page)) { + *module, export, &min_page, &max_page)) { goto failed; } if (!(type = - wasm_memorytype_new_internal(min_page, max_page))) { + wasm_memorytype_new_internal(min_page, max_page))) { goto failed; } @@ -1806,12 +2324,12 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out) uint32 min_size = 0, max_size = 0; if (!wasm_runtime_get_export_table_type( - *module, export, &elem_type_rt, &min_size, &max_size)) { + *module, export, &elem_type_rt, &min_size, &max_size)) { goto failed; } - if (!(type = wasm_tabletype_new_internal( - elem_type_rt, min_size, max_size))) { + if (!(type = wasm_tabletype_new_internal(elem_type_rt, min_size, + max_size))) { goto failed; } @@ -1846,7 +2364,7 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out) } static wasm_func_t * -wasm_func_new_basic(const wasm_functype_t *type, +wasm_func_new_basic(wasm_store_t *store, const wasm_functype_t *type, wasm_func_callback_t func_callback) { wasm_func_t *func = NULL; @@ -1855,7 +2373,9 @@ wasm_func_new_basic(const wasm_functype_t *type, goto failed; } + func->store = store; func->kind = WASM_EXTERN_FUNC; + func->func_idx_rt = (uint16)-1; func->with_env = false; func->u.cb = func_callback; @@ -1867,9 +2387,8 @@ wasm_func_new_basic(const wasm_functype_t *type, } static wasm_func_t * -wasm_func_new_with_env_basic(const wasm_functype_t *type, - wasm_func_callback_with_env_t callback, - void *env, +wasm_func_new_with_env_basic(wasm_store_t *store, const wasm_functype_t *type, + wasm_func_callback_with_env_t callback, void *env, void (*finalizer)(void *)) { wasm_func_t *func = NULL; @@ -1878,7 +2397,9 @@ wasm_func_new_with_env_basic(const wasm_functype_t *type, goto failed; } + func->store = store; func->kind = WASM_EXTERN_FUNC; + func->func_idx_rt = (uint16)-1; func->with_env = true; func->u.cb_env.cb = callback; func->u.cb_env.env = env; @@ -1892,28 +2413,24 @@ wasm_func_new_with_env_basic(const wasm_functype_t *type, } wasm_func_t * -wasm_func_new(wasm_store_t *store, - const wasm_functype_t *type, +wasm_func_new(wasm_store_t *store, const wasm_functype_t *type, wasm_func_callback_t callback) { bh_assert(singleton_engine); - return wasm_func_new_basic(type, callback); + return wasm_func_new_basic(store, type, callback); } wasm_func_t * -wasm_func_new_with_env(wasm_store_t *store, - const wasm_functype_t *type, - wasm_func_callback_with_env_t callback, - void *env, +wasm_func_new_with_env(wasm_store_t *store, const wasm_functype_t *type, + wasm_func_callback_with_env_t callback, void *env, void (*finalizer)(void *)) { bh_assert(singleton_engine); - return wasm_func_new_with_env_basic(type, callback, env, finalizer); + return wasm_func_new_with_env_basic(store, type, callback, env, finalizer); } -static wasm_func_t * -wasm_func_new_internal(wasm_store_t *store, - uint16 func_idx_rt, +wasm_func_t * +wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt, WASMModuleInstanceCommon *inst_comm_rt) { wasm_func_t *func = NULL; @@ -1921,7 +2438,7 @@ wasm_func_new_internal(wasm_store_t *store, bh_assert(singleton_engine); - if (!inst_comm_rt || !valid_module_type(inst_comm_rt->module_type)) { + if (!inst_comm_rt) { return NULL; } @@ -1937,30 +2454,35 @@ wasm_func_new_internal(wasm_store_t *store, bh_assert(func_idx_rt < ((WASMModuleInstance *)inst_comm_rt)->function_count); WASMFunctionInstance *func_interp = - ((WASMModuleInstance *)inst_comm_rt)->functions + func_idx_rt; + ((WASMModuleInstance *)inst_comm_rt)->functions + func_idx_rt; type_rt = func_interp->is_import_func - ? func_interp->u.func_import->func_type - : func_interp->u.func->func_type; + ? func_interp->u.func_import->func_type + : func_interp->u.func->func_type; } #endif #if WASM_ENABLE_AOT != 0 if (inst_comm_rt->module_type == Wasm_Module_AoT) { - /* use same index to trace the function type in AOTFuncType **func_types */ + /* use same index to trace the function type in AOTFuncType **func_types + */ AOTModule *module_aot = - ((AOTModuleInstance *)inst_comm_rt)->aot_module.ptr; + ((AOTModuleInstance *)inst_comm_rt)->aot_module.ptr; if (func_idx_rt < module_aot->import_func_count) { type_rt = (module_aot->import_funcs + func_idx_rt)->func_type; } else { type_rt = - module_aot - ->func_types[module_aot->func_type_indexes - [func_idx_rt - module_aot->import_func_count]]; + module_aot->func_types[module_aot->func_type_indexes + [func_idx_rt + - module_aot->import_func_count]]; } } #endif + /* + * a wrong combination of module filetype and compilation flags + * also leads to below branch + */ if (!type_rt) { goto failed; } @@ -1971,6 +2493,7 @@ wasm_func_new_internal(wasm_store_t *store, } /* will add name information when processing "exports" */ + func->store = store; func->module_name = NULL; func->name = NULL; func->func_idx_rt = func_idx_rt; @@ -2003,6 +2526,8 @@ wasm_func_delete(wasm_func_t *func) } } + DELETE_HOST_INFO(func) + wasm_runtime_free(func); } @@ -2015,11 +2540,11 @@ wasm_func_copy(const wasm_func_t *func) return NULL; } - if (!(cloned = func->with_env - ? wasm_func_new_with_env_basic( - func->type, func->u.cb_env.cb, func->u.cb_env.env, - func->u.cb_env.finalizer) - : wasm_func_new_basic(func->type, func->u.cb))) { + if (!(cloned = func->with_env ? wasm_func_new_with_env_basic( + func->store, func->type, func->u.cb_env.cb, + func->u.cb_env.env, func->u.cb_env.finalizer) + : wasm_func_new_basic(func->store, func->type, + func->u.cb))) { goto failed; } @@ -2039,9 +2564,8 @@ wasm_func_type(const wasm_func_t *func) } static uint32 -params_to_argv(const wasm_val_t *params, - const wasm_valtype_vec_t *param_defs, - size_t param_arity, +params_to_argv(WASMModuleInstanceCommon *inst_comm_rt, const wasm_val_t *params, + const wasm_valtype_vec_t *param_defs, size_t param_arity, uint32 *out) { size_t i = 0; @@ -2080,8 +2604,18 @@ params_to_argv(const wasm_val_t *params, out += 2; argc += 2; break; +#if WASM_ENABLE_REF_TYPES != 0 + case WASM_ANYREF: + if (!wasm_externref_obj2ref(inst_comm_rt, param->of.ref, out)) { + goto failed; + } + + out += 1; + argc += 1; + break; +#endif default: - LOG_DEBUG("unexpected parameter val type %d", param->kind); + LOG_WARNING("unexpected parameter val type %d", param->kind); goto failed; } } @@ -2094,10 +2628,8 @@ params_to_argv(const wasm_val_t *params, } static uint32 -argv_to_results(const uint32 *results, - const wasm_valtype_vec_t *result_defs, - size_t result_arity, - wasm_val_t *out) +argv_to_results(const uint32 *results, const wasm_valtype_vec_t *result_defs, + size_t result_arity, wasm_val_t *out) { size_t i = 0; uint32 argc = 0; @@ -2143,6 +2675,25 @@ argv_to_results(const uint32 *results, result += 2; break; } +#if WASM_ENABLE_REF_TYPES != 0 + case WASM_ANYREF: + { + out->kind = WASM_ANYREF; + + if (NULL_REF == *(uint32 *)result) { + out->of.ref = NULL; + } + else { + if (!wasm_externref_ref2obj(*(uint32 *)result, + (void **)&out->of.ref)) { + goto failed; + } + } + + result += 1; + break; + } +#endif default: LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__, def->kind); @@ -2160,9 +2711,8 @@ argv_to_results(const uint32 *results, } wasm_trap_t * -wasm_func_call(const wasm_func_t *func, - const wasm_val_t params[], - wasm_val_t results[]) +wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params, + wasm_val_vec_t *results) { /* parameters count as if all are uint32 */ /* a int64 or float64 parameter means 2 */ @@ -2186,7 +2736,7 @@ wasm_func_call(const wasm_func_t *func, if (func->inst_comm_rt->module_type == Wasm_Module_AoT) { if (!(func_comm_rt = func->func_comm_rt)) { AOTModuleInstance *inst_aot = - (AOTModuleInstance *)func->inst_comm_rt; + (AOTModuleInstance *)func->inst_comm_rt; AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr; uint32 export_i = 0, export_func_j = 0; @@ -2195,8 +2745,8 @@ wasm_func_call(const wasm_func_t *func, if (export->kind == EXPORT_KIND_FUNC) { if (export->index == func->func_idx_rt) { func_comm_rt = - (AOTFunctionInstance *)inst_aot->export_funcs.ptr - + export_func_j; + (AOTFunctionInstance *)inst_aot->export_funcs.ptr + + export_func_j; ((wasm_func_t *)func)->func_comm_rt = func_comm_rt; break; } @@ -2207,6 +2757,10 @@ wasm_func_call(const wasm_func_t *func, } #endif + /* + * a wrong combination of module filetype and compilation flags + * also leads to below branch + */ if (!func_comm_rt) { goto failed; } @@ -2214,7 +2768,7 @@ wasm_func_call(const wasm_func_t *func, param_count = wasm_func_param_arity(func); result_count = wasm_func_result_arity(func); alloc_count = (param_count > result_count) ? param_count : result_count; - if (alloc_count > sizeof(argv_buf) / sizeof(uint64)) { + if (alloc_count > (size_t)sizeof(argv_buf) / sizeof(uint64)) { if (!(argv = malloc_internal(sizeof(uint64) * alloc_count))) { goto failed; } @@ -2222,8 +2776,10 @@ wasm_func_call(const wasm_func_t *func, /* copy parametes */ if (param_count - && !(argc = params_to_argv(params, wasm_functype_params(func->type), - param_count, argv))) { + && (!params + || !(argc = params_to_argv(func->inst_comm_rt, params->data, + wasm_functype_params(func->type), + param_count, argv)))) { goto failed; } @@ -2232,6 +2788,7 @@ wasm_func_call(const wasm_func_t *func, goto failed; } + wasm_runtime_set_exception(func->inst_comm_rt, NULL); if (!wasm_runtime_call_wasm(exec_env, func_comm_rt, argc, argv)) { if (wasm_runtime_get_exception(func->inst_comm_rt)) { LOG_DEBUG(wasm_runtime_get_exception(func->inst_comm_rt)); @@ -2241,10 +2798,13 @@ wasm_func_call(const wasm_func_t *func, /* copy results */ if (result_count) { - if (!(argc = argv_to_results(argv, wasm_functype_results(func->type), - result_count, results))) { + if (!results + || !(argc = argv_to_results(argv, wasm_functype_results(func->type), + result_count, results->data))) { goto failed; } + results->num_elems = result_count; + results->size = result_count; } if (argv != argv_buf) @@ -2255,12 +2815,13 @@ wasm_func_call(const wasm_func_t *func, if (argv != argv_buf) wasm_runtime_free(argv); + /* trap -> exception -> trap */ if (wasm_runtime_get_exception(func->inst_comm_rt)) { - return wasm_trap_new_internal( - wasm_runtime_get_exception(func->inst_comm_rt)); + return wasm_trap_new_internal(func->inst_comm_rt, NULL); } else { - return wasm_trap_new_internal("wasm_func_call failed"); + return wasm_trap_new_internal(func->inst_comm_rt, + "wasm_func_call failed"); } } @@ -2283,8 +2844,7 @@ wasm_func_result_arity(const wasm_func_t *func) } wasm_global_t * -wasm_global_new(wasm_store_t *store, - const wasm_globaltype_t *global_type, +wasm_global_new(wasm_store_t *store, const wasm_globaltype_t *global_type, const wasm_val_t *init) { wasm_global_t *global = NULL; @@ -2296,6 +2856,7 @@ wasm_global_new(wasm_store_t *store, goto failed; } + global->store = store; global->kind = WASM_EXTERN_GLOBAL; global->type = wasm_globaltype_copy(global_type); if (!global->type) { @@ -2374,122 +2935,60 @@ wasm_global_delete(wasm_global_t *global) global->type = NULL; } - wasm_runtime_free(global); -} - -bool -wasm_global_same(const wasm_global_t *g1, const wasm_global_t *g2) -{ - if (!g1 && !g2) { - return true; - } - - if (!g1 || !g2) { - return false; - } + DELETE_HOST_INFO(global) - return g1->kind == g2->kind && wasm_globaltype_same(g1->type, g2->type) - && wasm_val_same(g1->init, g2->init); + wasm_runtime_free(global); } #if WASM_ENABLE_INTERP != 0 static bool -interp_global_set(const WASMModuleInstance *inst_interp, - uint16 global_idx_rt, +interp_global_set(const WASMModuleInstance *inst_interp, uint16 global_idx_rt, const wasm_val_t *v) { const WASMGlobalInstance *global_interp = - inst_interp->globals + global_idx_rt; + inst_interp->globals + global_idx_rt; uint8 val_type_rt = global_interp->type; #if WASM_ENABLE_MULTI_MODULE != 0 uint8 *data = global_interp->import_global_inst - ? global_interp->import_module_inst->global_data - + global_interp->import_global_inst->data_offset - : inst_interp->global_data + global_interp->data_offset; + ? global_interp->import_module_inst->global_data + + global_interp->import_global_inst->data_offset + : inst_interp->global_data + global_interp->data_offset; #else uint8 *data = inst_interp->global_data + global_interp->data_offset; #endif - bool ret = true; - switch (val_type_rt) { - case VALUE_TYPE_I32: - bh_assert(WASM_I32 == v->kind); - *((int32 *)data) = v->of.i32; - break; - case VALUE_TYPE_F32: - bh_assert(WASM_F32 == v->kind); - *((float32 *)data) = v->of.f32; - break; - case VALUE_TYPE_I64: - bh_assert(WASM_I64 == v->kind); - *((int64 *)data) = v->of.i64; - break; - case VALUE_TYPE_F64: - bh_assert(WASM_F64 == v->kind); - *((float64 *)data) = v->of.f64; - break; - default: - LOG_DEBUG("unexpected value type %d", val_type_rt); - ret = false; - break; - } - - return ret; + return wasm_val_to_rt_val((WASMModuleInstanceCommon *)inst_interp, + val_type_rt, v, data); } static bool -interp_global_get(const WASMModuleInstance *inst_interp, - uint16 global_idx_rt, +interp_global_get(const WASMModuleInstance *inst_interp, uint16 global_idx_rt, wasm_val_t *out) { WASMGlobalInstance *global_interp = inst_interp->globals + global_idx_rt; uint8 val_type_rt = global_interp->type; #if WASM_ENABLE_MULTI_MODULE != 0 uint8 *data = global_interp->import_global_inst - ? global_interp->import_module_inst->global_data - + global_interp->import_global_inst->data_offset - : inst_interp->global_data + global_interp->data_offset; + ? global_interp->import_module_inst->global_data + + global_interp->import_global_inst->data_offset + : inst_interp->global_data + global_interp->data_offset; #else uint8 *data = inst_interp->global_data + global_interp->data_offset; #endif - bool ret = true; - switch (val_type_rt) { - case VALUE_TYPE_I32: - out->kind = WASM_I32; - out->of.i32 = *((int32 *)data); - break; - case VALUE_TYPE_F32: - out->kind = WASM_F32; - out->of.f32 = *((float32 *)data); - break; - case VALUE_TYPE_I64: - out->kind = WASM_I64; - out->of.i64 = *((int64 *)data); - break; - case VALUE_TYPE_F64: - out->kind = WASM_F64; - out->of.f64 = *((float64 *)data); - break; - default: - LOG_DEBUG("unexpected value type %d", val_type_rt); - ret = false; - } - return ret; + return rt_val_to_wasm_val(data, val_type_rt, out); } #endif #if WASM_ENABLE_AOT != 0 static bool -aot_global_set(const AOTModuleInstance *inst_aot, - uint16 global_idx_rt, +aot_global_set(const AOTModuleInstance *inst_aot, uint16 global_idx_rt, const wasm_val_t *v) { AOTModule *module_aot = inst_aot->aot_module.ptr; uint8 val_type_rt = 0; uint32 data_offset = 0; void *data = NULL; - bool ret = true; if (global_idx_rt < module_aot->import_global_count) { data_offset = module_aot->import_globals[global_idx_rt].data_offset; @@ -2497,48 +2996,26 @@ aot_global_set(const AOTModuleInstance *inst_aot, } else { data_offset = - module_aot->globals[global_idx_rt - module_aot->import_global_count] - .data_offset; + module_aot->globals[global_idx_rt - module_aot->import_global_count] + .data_offset; val_type_rt = - module_aot->globals[global_idx_rt - module_aot->import_global_count] - .type; + module_aot->globals[global_idx_rt - module_aot->import_global_count] + .type; } data = (void *)((uint8 *)inst_aot->global_data.ptr + data_offset); - switch (val_type_rt) { - case VALUE_TYPE_I32: - bh_assert(WASM_I32 == v->kind); - *((int32 *)data) = v->of.i32; - break; - case VALUE_TYPE_F32: - bh_assert(WASM_F32 == v->kind); - *((float32 *)data) = v->of.f32; - break; - case VALUE_TYPE_I64: - bh_assert(WASM_I64 == v->kind); - *((int64 *)data) = v->of.i64; - break; - case VALUE_TYPE_F64: - bh_assert(WASM_F64 == v->kind); - *((float64 *)data) = v->of.f64; - break; - default: - LOG_DEBUG("unexpected value type %d", val_type_rt); - ret = false; - } - return ret; + return wasm_val_to_rt_val((WASMModuleInstanceCommon *)inst_aot, val_type_rt, + v, data); } static bool -aot_global_get(const AOTModuleInstance *inst_aot, - uint16 global_idx_rt, +aot_global_get(const AOTModuleInstance *inst_aot, uint16 global_idx_rt, wasm_val_t *out) { AOTModule *module_aot = inst_aot->aot_module.ptr; uint8 val_type_rt = 0; uint32 data_offset = 0; - void *data = NULL; - bool ret = true; + uint8 *data = NULL; if (global_idx_rt < module_aot->import_global_count) { data_offset = module_aot->import_globals[global_idx_rt].data_offset; @@ -2546,44 +3023,22 @@ aot_global_get(const AOTModuleInstance *inst_aot, } else { data_offset = - module_aot->globals[global_idx_rt - module_aot->import_global_count] - .data_offset; + module_aot->globals[global_idx_rt - module_aot->import_global_count] + .data_offset; val_type_rt = - module_aot->globals[global_idx_rt - module_aot->import_global_count] - .type; + module_aot->globals[global_idx_rt - module_aot->import_global_count] + .type; } - data = (void *)((uint8 *)inst_aot->global_data.ptr + data_offset); - switch (val_type_rt) { - case VALUE_TYPE_I32: - out->kind = WASM_I32; - out->of.i32 = *((int32 *)data); - break; - case VALUE_TYPE_F32: - out->kind = WASM_F32; - out->of.f32 = *((float32 *)data); - break; - case VALUE_TYPE_I64: - out->kind = WASM_I64; - out->of.i64 = *((int64 *)data); - break; - case VALUE_TYPE_F64: - out->kind = WASM_F64; - out->of.f64 = *((float64 *)data); - break; - default: - LOG_DEBUG("unexpected value type %d", val_type_rt); - ret = false; - } - return ret; + data = (uint8 *)inst_aot->global_data.ptr + data_offset; + return rt_val_to_wasm_val(data, val_type_rt, out); } #endif void wasm_global_set(wasm_global_t *global, const wasm_val_t *v) { - if (!global || !v - || !valid_module_type(global->inst_comm_rt->module_type)) { + if (!global || !v) { return; } @@ -2591,21 +3046,29 @@ wasm_global_set(wasm_global_t *global, const wasm_val_t *v) if (global->inst_comm_rt->module_type == Wasm_Module_Bytecode) { (void)interp_global_set((WASMModuleInstance *)global->inst_comm_rt, global->global_idx_rt, v); + return; } #endif + #if WASM_ENABLE_AOT != 0 if (global->inst_comm_rt->module_type == Wasm_Module_AoT) { (void)aot_global_set((AOTModuleInstance *)global->inst_comm_rt, global->global_idx_rt, v); + return; } #endif + + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + UNREACHABLE(); } void wasm_global_get(const wasm_global_t *global, wasm_val_t *out) { - if (!global || !out - || !valid_module_type(global->inst_comm_rt->module_type)) { + if (!global || !out) { return; } @@ -2615,30 +3078,37 @@ wasm_global_get(const wasm_global_t *global, wasm_val_t *out) if (global->inst_comm_rt->module_type == Wasm_Module_Bytecode) { (void)interp_global_get((WASMModuleInstance *)global->inst_comm_rt, global->global_idx_rt, out); + return; } #endif + #if WASM_ENABLE_AOT != 0 if (global->inst_comm_rt->module_type == Wasm_Module_AoT) { (void)aot_global_get((AOTModuleInstance *)global->inst_comm_rt, global->global_idx_rt, out); + return; } #endif - bh_assert(global->init->kind == out->kind); + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + UNREACHABLE(); } -static wasm_global_t * -wasm_global_new_internal(wasm_store_t *store, - uint16 global_idx_rt, +wasm_global_t * +wasm_global_new_internal(wasm_store_t *store, uint16 global_idx_rt, WASMModuleInstanceCommon *inst_comm_rt) { wasm_global_t *global = NULL; uint8 val_type_rt = 0; bool is_mutable = 0; + bool init = false; bh_assert(singleton_engine); - if (!inst_comm_rt || !valid_module_type(inst_comm_rt->module_type)) { + if (!inst_comm_rt) { return NULL; } @@ -2647,18 +3117,16 @@ wasm_global_new_internal(wasm_store_t *store, goto failed; } - /* - * global->module_name = NULL; - * global->name = NULL; - */ + global->store = store; global->kind = WASM_EXTERN_GLOBAL; #if WASM_ENABLE_INTERP != 0 if (inst_comm_rt->module_type == Wasm_Module_Bytecode) { WASMGlobalInstance *global_interp = - ((WASMModuleInstance *)inst_comm_rt)->globals + global_idx_rt; + ((WASMModuleInstance *)inst_comm_rt)->globals + global_idx_rt; val_type_rt = global_interp->type; is_mutable = global_interp->is_mutable; + init = true; } #endif @@ -2666,22 +3134,33 @@ wasm_global_new_internal(wasm_store_t *store, if (inst_comm_rt->module_type == Wasm_Module_AoT) { AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt; AOTModule *module_aot = inst_aot->aot_module.ptr; + + init = true; + if (global_idx_rt < module_aot->import_global_count) { AOTImportGlobal *global_import_aot = - module_aot->import_globals + global_idx_rt; + module_aot->import_globals + global_idx_rt; val_type_rt = global_import_aot->type; is_mutable = global_import_aot->is_mutable; } else { AOTGlobal *global_aot = - module_aot->globals - + (global_idx_rt - module_aot->import_global_count); + module_aot->globals + + (global_idx_rt - module_aot->import_global_count); val_type_rt = global_aot->type; is_mutable = global_aot->is_mutable; } } #endif + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + if (!init) { + goto failed; + } + global->type = wasm_globaltype_new_internal(val_type_rt, is_mutable); if (!global->type) { goto failed; @@ -2727,7 +3206,7 @@ wasm_global_type(const wasm_global_t *global) } static wasm_table_t * -wasm_table_new_basic(const wasm_tabletype_t *type) +wasm_table_new_basic(wasm_store_t *store, const wasm_tabletype_t *type) { wasm_table_t *table = NULL; @@ -2735,6 +3214,7 @@ wasm_table_new_basic(const wasm_tabletype_t *type) goto failed; } + table->store = store; table->kind = WASM_EXTERN_TABLE; if (!(table->type = wasm_tabletype_copy(type))) { @@ -2744,18 +3224,18 @@ wasm_table_new_basic(const wasm_tabletype_t *type) RETURN_OBJ(table, wasm_table_delete); } -static wasm_table_t * -wasm_table_new_internal(wasm_store_t *store, - uint16 table_idx_rt, +wasm_table_t * +wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt, WASMModuleInstanceCommon *inst_comm_rt) { wasm_table_t *table = NULL; uint8 val_type_rt = 0; uint32 init_size = 0, max_size = 0; + bool init_flag = false; bh_assert(singleton_engine); - if (!inst_comm_rt || !valid_module_type(inst_comm_rt->module_type)) { + if (!inst_comm_rt) { return NULL; } @@ -2763,15 +3243,17 @@ wasm_table_new_internal(wasm_store_t *store, goto failed; } + table->store = store; table->kind = WASM_EXTERN_TABLE; #if WASM_ENABLE_INTERP != 0 if (inst_comm_rt->module_type == Wasm_Module_Bytecode) { WASMTableInstance *table_interp = - ((WASMModuleInstance *)inst_comm_rt)->tables[table_idx_rt]; + ((WASMModuleInstance *)inst_comm_rt)->tables[table_idx_rt]; val_type_rt = table_interp->elem_type; init_size = table_interp->cur_size; max_size = table_interp->max_size; + init_flag = true; } #endif @@ -2782,24 +3264,33 @@ wasm_table_new_internal(wasm_store_t *store, if (table_idx_rt < module_aot->import_table_count) { AOTImportTable *table_aot = - module_aot->import_tables + table_idx_rt; + module_aot->import_tables + table_idx_rt; val_type_rt = VALUE_TYPE_FUNCREF; init_size = table_aot->table_init_size; max_size = table_aot->table_max_size; } else { AOTTable *table_aot = - module_aot->tables - + (table_idx_rt - module_aot->import_table_count); + module_aot->tables + + (table_idx_rt - module_aot->import_table_count); val_type_rt = VALUE_TYPE_FUNCREF; init_size = table_aot->table_init_size; max_size = table_aot->table_max_size; } + init_flag = true; } #endif + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + if (!init_flag) { + goto failed; + } + if (!(table->type = - wasm_tabletype_new_internal(val_type_rt, init_size, max_size))) { + wasm_tabletype_new_internal(val_type_rt, init_size, max_size))) { goto failed; } @@ -2809,20 +3300,35 @@ wasm_table_new_internal(wasm_store_t *store, RETURN_OBJ(table, wasm_table_delete); } +/* will not actually apply this new table into the runtime */ wasm_table_t * -wasm_table_new(wasm_store_t *store, - const wasm_tabletype_t *table_type, +wasm_table_new(wasm_store_t *store, const wasm_tabletype_t *table_type, wasm_ref_t *init) { + wasm_table_t *table; (void)init; + bh_assert(singleton_engine); - return wasm_table_new_basic(table_type); + + if ((table = wasm_table_new_basic(store, table_type))) { + table->store = store; + } + + return table; } wasm_table_t * wasm_table_copy(const wasm_table_t *src) { - return wasm_table_new_basic(src->type); + wasm_table_t *table; + + if (!(table = wasm_table_new_basic(src->store, src->type))) { + return NULL; + } + + table->table_idx_rt = src->table_idx_rt; + table->inst_comm_rt = src->inst_comm_rt; + return table; } void @@ -2837,6 +3343,8 @@ wasm_table_delete(wasm_table_t *table) table->type = NULL; } + DELETE_HOST_INFO(table) + wasm_runtime_free(table); } @@ -2849,8 +3357,179 @@ wasm_table_type(const wasm_table_t *table) return wasm_tabletype_copy(table->type); } +own wasm_ref_t * +wasm_table_get(const wasm_table_t *table, wasm_table_size_t index) +{ + uint32 func_idx_rt = NULL_REF; + + if (!table) { + return NULL; + } + + /* index -> func_idx_rt */ +#if WASM_ENABLE_INTERP != 0 + if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) { + WASMTableInstance *table_interp = + ((WASMModuleInstance *)table->inst_comm_rt) + ->tables[table->table_idx_rt]; + if (index >= table_interp->cur_size) { + return NULL; + } + func_idx_rt = ((uint32 *)table_interp->base_addr)[index]; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (table->inst_comm_rt->module_type == Wasm_Module_AoT) { + AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt; + AOTTableInstance *table_aot = + (AOTTableInstance *)inst_aot->tables.ptr + table->table_idx_rt; + if (index >= table_aot->cur_size) { + return NULL; + } + func_idx_rt = table_aot->data[index]; + } +#endif + + /* + * a wrong combination of module filetype and compilation flags + * also leads to below branch + */ + if (func_idx_rt == NULL_REF) { + return NULL; + } + + return wasm_ref_new_internal(table->store, WASM_REF_func, func_idx_rt, + table->inst_comm_rt); +} + +bool +wasm_table_set(wasm_table_t *table, wasm_table_size_t index, + own wasm_ref_t *func_ref) +{ + uint32 *p_func_idx_rt = NULL; + uint32 function_count = 0, ref_idx_rt = NULL_REF; + + if (!table) { + return false; + } + + if (func_ref && func_ref->kind != WASM_REF_func) { + return false; + } + + if (func_ref) { + ref_idx_rt = func_ref->ref_idx_rt; + wasm_ref_delete(func_ref); + } + + /* index -> *p_func_idx_rt */ +#if WASM_ENABLE_INTERP != 0 + if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) { + WASMTableInstance *table_interp = + ((WASMModuleInstance *)table->inst_comm_rt) + ->tables[table->table_idx_rt]; + + if (index >= table_interp->cur_size) { + return false; + } + + p_func_idx_rt = ((uint32 *)table_interp->base_addr) + index; + function_count = + ((WASMModuleInstance *)table->inst_comm_rt)->function_count; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (table->inst_comm_rt->module_type == Wasm_Module_AoT) { + AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt; + AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr; + AOTTableInstance *table_aot = + (AOTTableInstance *)inst_aot->tables.ptr + table->table_idx_rt; + + if (index >= table_aot->cur_size) { + return false; + } + + p_func_idx_rt = table_aot->data + index; + function_count = module_aot->func_count; + } +#endif + + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + if (!p_func_idx_rt) { + return false; + } + + if (NULL_REF != ref_idx_rt) { + if (ref_idx_rt >= function_count) { + return false; + } + } + + *p_func_idx_rt = ref_idx_rt; + return true; +} + +wasm_table_size_t +wasm_table_size(const wasm_table_t *table) +{ + if (!table) { + return 0; + } + +#if WASM_ENABLE_INTERP != 0 + if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) { + WASMTableInstance *table_interp = + ((WASMModuleInstance *)table->inst_comm_rt) + ->tables[table->table_idx_rt]; + return table_interp->cur_size; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (table->inst_comm_rt->module_type == Wasm_Module_AoT) { + AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt; + AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr; + + if (table->table_idx_rt < module_aot->import_table_count) { + AOTImportTable *table_aot = + module_aot->import_tables + table->table_idx_rt; + return table_aot->table_init_size; + } + else { + AOTTable *table_aot = + module_aot->tables + + (table->table_idx_rt - module_aot->import_table_count); + return table_aot->table_init_size; + } + } +#endif + + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + return 0; +} + +bool +wasm_table_grow(wasm_table_t *table, wasm_table_size_t delta, + own wasm_ref_t *init) +{ + (void)table; + (void)delta; + (void)init; + LOG_WARNING("Calling wasm_table_grow() by host is not supported." + "Only allow growing a table via the opcode table.grow"); + return false; +} + static wasm_memory_t * -wasm_memory_new_basic(const wasm_memorytype_t *type) +wasm_memory_new_basic(wasm_store_t *store, const wasm_memorytype_t *type) { wasm_memory_t *memory = NULL; @@ -2858,6 +3537,7 @@ wasm_memory_new_basic(const wasm_memorytype_t *type) goto failed; } + memory->store = store; memory->kind = WASM_EXTERN_MEMORY; memory->type = wasm_memorytype_copy(type); @@ -2868,7 +3548,7 @@ wasm_memory_t * wasm_memory_new(wasm_store_t *store, const wasm_memorytype_t *type) { bh_assert(singleton_engine); - return wasm_memory_new_basic(type); + return wasm_memory_new_basic(store, type); } wasm_memory_t * @@ -2880,7 +3560,7 @@ wasm_memory_copy(const wasm_memory_t *src) return NULL; } - if (!(dst = wasm_memory_new_basic(src->type))) { + if (!(dst = wasm_memory_new_basic(src->store, src->type))) { goto failed; } @@ -2890,17 +3570,17 @@ wasm_memory_copy(const wasm_memory_t *src) RETURN_OBJ(dst, wasm_memory_delete) } -static wasm_memory_t * -wasm_memory_new_internal(wasm_store_t *store, - uint16 memory_idx_rt, +wasm_memory_t * +wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt, WASMModuleInstanceCommon *inst_comm_rt) { wasm_memory_t *memory = NULL; uint32 min_pages = 0, max_pages = 0; + bool init_flag = false; bh_assert(singleton_engine); - if (!inst_comm_rt || !valid_module_type(inst_comm_rt->module_type)) { + if (!inst_comm_rt) { return NULL; } @@ -2908,14 +3588,16 @@ wasm_memory_new_internal(wasm_store_t *store, goto failed; } + memory->store = store; memory->kind = WASM_EXTERN_MEMORY; #if WASM_ENABLE_INTERP != 0 if (inst_comm_rt->module_type == Wasm_Module_Bytecode) { WASMMemoryInstance *memory_interp = - ((WASMModuleInstance *)inst_comm_rt)->memories[memory_idx_rt]; + ((WASMModuleInstance *)inst_comm_rt)->memories[memory_idx_rt]; min_pages = memory_interp->cur_page_count; max_pages = memory_interp->max_page_count; + init_flag = true; } #endif @@ -2932,9 +3614,18 @@ wasm_memory_new_internal(wasm_store_t *store, min_pages = module_aot->memories->mem_init_page_count; max_pages = module_aot->memories->mem_max_page_count; } + init_flag = true; } #endif + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + if (!init_flag) { + goto failed; + } + if (!(memory->type = wasm_memorytype_new_internal(min_pages, max_pages))) { goto failed; } @@ -2957,6 +3648,8 @@ wasm_memory_delete(wasm_memory_t *memory) memory->type = NULL; } + DELETE_HOST_INFO(memory) + wasm_runtime_free(memory); } @@ -2973,23 +3666,113 @@ wasm_memory_type(const wasm_memory_t *memory) byte_t * wasm_memory_data(wasm_memory_t *memory) { - return (byte_t *)wasm_runtime_get_memory_data(memory->inst_comm_rt, - memory->memory_idx_rt); + WASMModuleInstanceCommon *module_inst_comm = memory->inst_comm_rt; + +#if WASM_ENABLE_INTERP != 0 + if (module_inst_comm->module_type == Wasm_Module_Bytecode) { + WASMModuleInstance *module_inst = + (WASMModuleInstance *)module_inst_comm; + WASMMemoryInstance *memory_inst = + module_inst->memories[memory->memory_idx_rt]; + return (byte_t *)memory_inst->memory_data; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst_comm->module_type == Wasm_Module_AoT) { + AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm; + AOTMemoryInstance *memory_inst = + ((AOTMemoryInstance **) + module_inst->memories.ptr)[memory->memory_idx_rt]; + return (byte_t *)memory_inst->memory_data.ptr; + } +#endif + + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + return NULL; } size_t wasm_memory_data_size(const wasm_memory_t *memory) { - return wasm_runtime_get_memory_data_size(memory->inst_comm_rt, - memory->memory_idx_rt); + WASMModuleInstanceCommon *module_inst_comm = memory->inst_comm_rt; + +#if WASM_ENABLE_INTERP != 0 + if (module_inst_comm->module_type == Wasm_Module_Bytecode) { + WASMModuleInstance *module_inst = + (WASMModuleInstance *)module_inst_comm; + WASMMemoryInstance *memory_inst = + module_inst->memories[memory->memory_idx_rt]; + return memory_inst->cur_page_count * memory_inst->num_bytes_per_page; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst_comm->module_type == Wasm_Module_AoT) { + AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm; + AOTMemoryInstance *memory_inst = + ((AOTMemoryInstance **) + module_inst->memories.ptr)[memory->memory_idx_rt]; + return memory_inst->cur_page_count * memory_inst->num_bytes_per_page; + } +#endif + + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + return 0; +} + +wasm_memory_pages_t +wasm_memory_size(const wasm_memory_t *memory) +{ + WASMModuleInstanceCommon *module_inst_comm = memory->inst_comm_rt; + +#if WASM_ENABLE_INTERP != 0 + if (module_inst_comm->module_type == Wasm_Module_Bytecode) { + WASMModuleInstance *module_inst = + (WASMModuleInstance *)module_inst_comm; + WASMMemoryInstance *memory_inst = + module_inst->memories[memory->memory_idx_rt]; + return memory_inst->cur_page_count; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst_comm->module_type == Wasm_Module_AoT) { + AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm; + AOTMemoryInstance *memory_inst = + ((AOTMemoryInstance **) + module_inst->memories.ptr)[memory->memory_idx_rt]; + return memory_inst->cur_page_count; + } +#endif + + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + return 0; +} + +bool +wasm_memory_grow(wasm_memory_t *memory, wasm_memory_pages_t delta) +{ + (void)memory; + (void)delta; + LOG_WARNING("Calling wasm_memory_grow() by host is not supported." + "Only allow growing a memory via the opcode memory.grow"); + return false; } #if WASM_ENABLE_INTERP != 0 static bool -interp_link_func(const wasm_instance_t *inst, - const WASMModule *module_interp, - uint16 func_idx_rt, - wasm_func_t *import) +interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp, + uint16 func_idx_rt, wasm_func_t *import) { WASMImport *imported_func_interp = NULL; wasm_func_t *cloned = NULL; @@ -3026,8 +3809,7 @@ interp_link_func(const wasm_instance_t *inst, } static bool -interp_link_global(const WASMModule *module_interp, - uint16 global_idx_rt, +interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt, wasm_global_t *import) { WASMImport *imported_global_interp = NULL; @@ -3044,22 +3826,22 @@ interp_link_global(const WASMModule *module_interp, case WASM_I32: bh_assert(VALUE_TYPE_I32 == imported_global_interp->u.global.type); imported_global_interp->u.global.global_data_linked.i32 = - import->init->of.i32; + import->init->of.i32; break; case WASM_I64: bh_assert(VALUE_TYPE_I64 == imported_global_interp->u.global.type); imported_global_interp->u.global.global_data_linked.i64 = - import->init->of.i64; + import->init->of.i64; break; case WASM_F32: bh_assert(VALUE_TYPE_F32 == imported_global_interp->u.global.type); imported_global_interp->u.global.global_data_linked.f32 = - import->init->of.f32; + import->init->of.f32; break; case WASM_F64: bh_assert(VALUE_TYPE_F64 == imported_global_interp->u.global.type); imported_global_interp->u.global.global_data_linked.f64 = - import->init->of.f64; + import->init->of.f64; break; default: return false; @@ -3071,8 +3853,7 @@ interp_link_global(const WASMModule *module_interp, } static uint32 -interp_link(const wasm_instance_t *inst, - const WASMModule *module_interp, +interp_link(const wasm_instance_t *inst, const WASMModule *module_interp, wasm_extern_t *imports[]) { uint32 i = 0; @@ -3146,8 +3927,8 @@ interp_process_export(wasm_store_t *store, { wasm_func_t *func; if (!(func = wasm_func_new_internal( - store, export->index, - (WASMModuleInstanceCommon *)inst_interp))) { + store, export->index, + (WASMModuleInstanceCommon *)inst_interp))) { goto failed; } @@ -3158,8 +3939,8 @@ interp_process_export(wasm_store_t *store, { wasm_global_t *global; if (!(global = wasm_global_new_internal( - store, export->index, - (WASMModuleInstanceCommon *)inst_interp))) { + store, export->index, + (WASMModuleInstanceCommon *)inst_interp))) { goto failed; } @@ -3170,8 +3951,8 @@ interp_process_export(wasm_store_t *store, { wasm_table_t *table; if (!(table = wasm_table_new_internal( - store, export->index, - (WASMModuleInstanceCommon *)inst_interp))) { + store, export->index, + (WASMModuleInstanceCommon *)inst_interp))) { goto failed; } @@ -3182,8 +3963,8 @@ interp_process_export(wasm_store_t *store, { wasm_memory_t *memory; if (!(memory = wasm_memory_new_internal( - store, export->index, - (WASMModuleInstanceCommon *)inst_interp))) { + store, export->index, + (WASMModuleInstanceCommon *)inst_interp))) { goto failed; } @@ -3211,10 +3992,8 @@ interp_process_export(wasm_store_t *store, #if WASM_ENABLE_AOT != 0 static bool -aot_link_func(const wasm_instance_t *inst, - const AOTModule *module_aot, - uint32 import_func_idx_rt, - wasm_func_t *import) +aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot, + uint32 import_func_idx_rt, wasm_func_t *import) { AOTImportFunc *import_aot_func = NULL; wasm_func_t *cloned = NULL; @@ -3247,8 +4026,7 @@ aot_link_func(const wasm_instance_t *inst, } static bool -aot_link_global(const AOTModule *module_aot, - uint16 global_idx_rt, +aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt, wasm_global_t *import) { AOTImportGlobal *import_aot_global = NULL; @@ -3259,7 +4037,6 @@ aot_link_global(const AOTModule *module_aot, import_aot_global = module_aot->import_globals + global_idx_rt; bh_assert(import_aot_global); - //TODO: import->type ? val_type = wasm_globaltype_content(import->type); bh_assert(val_type); @@ -3293,8 +4070,7 @@ aot_link_global(const AOTModule *module_aot, } static uint32 -aot_link(const wasm_instance_t *inst, - const AOTModule *module_aot, +aot_link(const wasm_instance_t *inst, const AOTModule *module_aot, wasm_extern_t *imports[]) { uint32 i = 0; @@ -3346,8 +4122,7 @@ aot_link(const wasm_instance_t *inst, } static bool -aot_process_export(wasm_store_t *store, - const AOTModuleInstance *inst_aot, +aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot, wasm_extern_vec_t *externals) { uint32 i; @@ -3367,8 +4142,8 @@ aot_process_export(wasm_store_t *store, { wasm_func_t *func = NULL; if (!(func = wasm_func_new_internal( - store, export->index, - (WASMModuleInstanceCommon *)inst_aot))) { + store, export->index, + (WASMModuleInstanceCommon *)inst_aot))) { goto failed; } @@ -3379,8 +4154,8 @@ aot_process_export(wasm_store_t *store, { wasm_global_t *global = NULL; if (!(global = wasm_global_new_internal( - store, export->index, - (WASMModuleInstanceCommon *)inst_aot))) { + store, export->index, + (WASMModuleInstanceCommon *)inst_aot))) { goto failed; } @@ -3391,8 +4166,8 @@ aot_process_export(wasm_store_t *store, { wasm_table_t *table; if (!(table = wasm_table_new_internal( - store, export->index, - (WASMModuleInstanceCommon *)inst_aot))) { + store, export->index, + (WASMModuleInstanceCommon *)inst_aot))) { goto failed; } @@ -3403,8 +4178,8 @@ aot_process_export(wasm_store_t *store, { wasm_memory_t *memory; if (!(memory = wasm_memory_new_internal( - store, export->index, - (WASMModuleInstanceCommon *)inst_aot))) { + store, export->index, + (WASMModuleInstanceCommon *)inst_aot))) { goto failed; } @@ -3440,22 +4215,30 @@ aot_process_export(wasm_store_t *store, #endif /* WASM_ENABLE_AOT */ wasm_instance_t * -wasm_instance_new(wasm_store_t *store, - const wasm_module_t *module, - const wasm_extern_t *const imports[], - own wasm_trap_t **traps) +wasm_instance_new(wasm_store_t *store, const wasm_module_t *module, + const wasm_extern_vec_t *imports, own wasm_trap_t **traps) +{ + return wasm_instance_new_with_args(store, module, imports, traps, + KILOBYTE(32), KILOBYTE(32)); +} + +wasm_instance_t * +wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, + const wasm_extern_vec_t *imports, + own wasm_trap_t **traps, const uint32 stack_size, + const uint32 heap_size) { char error_buf[128] = { 0 }; - const uint32 stack_size = 16 * 1024; - const uint32 heap_size = 16 * 1024; uint32 import_count = 0; + bool import_count_verified = false; wasm_instance_t *instance = NULL; uint32 i = 0; + bool processed = false; (void)traps; bh_assert(singleton_engine); - if (!module || !valid_module_type((*module)->module_type)) { + if (!module) { return NULL; } @@ -3474,14 +4257,16 @@ wasm_instance_new(wasm_store_t *store, import_count); if (import_count) { - uint32 actual_link_import_count = interp_link( - instance, MODULE_INTERP(module), (wasm_extern_t **)imports); + uint32 actual_link_import_count = + interp_link(instance, MODULE_INTERP(module), + (wasm_extern_t **)imports->data); /* make sure a complete import list */ if ((int32)import_count < 0 || import_count != actual_link_import_count) { goto failed; } } + import_count_verified = true; } #endif @@ -3497,17 +4282,26 @@ wasm_instance_new(wasm_store_t *store, if (import_count) { import_count = aot_link(instance, MODULE_AOT(module), - (wasm_extern_t **)imports); + (wasm_extern_t **)imports->data); if ((int32)import_count < 0) { goto failed; } } + import_count_verified = true; } #endif + + /* + * a wrong combination of module filetype and compilation flags + * also leads to below branch + */ + if (!import_count_verified) { + goto failed; + } } instance->inst_comm_rt = wasm_runtime_instantiate( - *module, stack_size, heap_size, error_buf, sizeof(error_buf)); + *module, stack_size, heap_size, error_buf, sizeof(error_buf)); if (!instance->inst_comm_rt) { LOG_ERROR(error_buf); goto failed; @@ -3518,24 +4312,24 @@ wasm_instance_new(wasm_store_t *store, } /* fill with inst */ - for (i = 0; imports && i < (uint32)import_count; ++i) { - wasm_extern_t *import = (wasm_extern_t *)imports[i]; + for (i = 0; imports && imports->data && i < (uint32)import_count; ++i) { + wasm_extern_t *import = imports->data[i]; switch (import->kind) { case WASM_EXTERN_FUNC: wasm_extern_as_func(import)->inst_comm_rt = - instance->inst_comm_rt; + instance->inst_comm_rt; break; case WASM_EXTERN_GLOBAL: wasm_extern_as_global(import)->inst_comm_rt = - instance->inst_comm_rt; + instance->inst_comm_rt; break; case WASM_EXTERN_MEMORY: wasm_extern_as_memory(import)->inst_comm_rt = - instance->inst_comm_rt; + instance->inst_comm_rt; break; case WASM_EXTERN_TABLE: wasm_extern_as_table(import)->inst_comm_rt = - instance->inst_comm_rt; + instance->inst_comm_rt; break; default: goto failed; @@ -3545,27 +4339,29 @@ wasm_instance_new(wasm_store_t *store, /* build the exports list */ #if WASM_ENABLE_INTERP != 0 if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) { - uint32 export_cnt = - ((WASMModuleInstance *)instance->inst_comm_rt)->module->export_count; + uint32 export_cnt = ((WASMModuleInstance *)instance->inst_comm_rt) + ->module->export_count; INIT_VEC(instance->exports, wasm_extern_vec_new_uninitialized, export_cnt); - if (!interp_process_export( - store, (WASMModuleInstance *)instance->inst_comm_rt, - instance->exports)) { + if (!interp_process_export(store, + (WASMModuleInstance *)instance->inst_comm_rt, + instance->exports)) { goto failed; } + + processed = true; } #endif #if WASM_ENABLE_AOT != 0 if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) { uint32 export_cnt = - ((AOTModuleInstance *)instance->inst_comm_rt)->export_func_count - + ((AOTModuleInstance *)instance->inst_comm_rt)->export_global_count - + ((AOTModuleInstance *)instance->inst_comm_rt)->export_tab_count - + ((AOTModuleInstance *)instance->inst_comm_rt)->export_mem_count; + ((AOTModuleInstance *)instance->inst_comm_rt)->export_func_count + + ((AOTModuleInstance *)instance->inst_comm_rt)->export_global_count + + ((AOTModuleInstance *)instance->inst_comm_rt)->export_tab_count + + ((AOTModuleInstance *)instance->inst_comm_rt)->export_mem_count; INIT_VEC(instance->exports, wasm_extern_vec_new_uninitialized, export_cnt); @@ -3575,9 +4371,19 @@ wasm_instance_new(wasm_store_t *store, instance->exports)) { goto failed; } + + processed = true; } #endif + /* + * a wrong combination of module filetype and compilation flags + * leads to below branch + */ + if (!processed) { + goto failed; + } + /* add it to a watching list in store */ if (!bh_vector_append((Vector *)store->instances, &instance)) { goto failed; @@ -3609,8 +4415,9 @@ wasm_instance_delete_internal(wasm_instance_t *instance) } void -wasm_instance_delete(wasm_instance_t *module) +wasm_instance_delete(wasm_instance_t *inst) { + DELETE_HOST_INFO(inst) /* will release instance when releasing the store */ } @@ -3636,19 +4443,19 @@ wasm_extern_copy(const wasm_extern_t *src) switch (wasm_extern_kind(src)) { case WASM_EXTERN_FUNC: dst = wasm_func_as_extern( - wasm_func_copy(wasm_extern_as_func_const(src))); + wasm_func_copy(wasm_extern_as_func_const(src))); break; case WASM_EXTERN_GLOBAL: dst = wasm_global_as_extern( - wasm_global_copy(wasm_extern_as_global_const(src))); + wasm_global_copy(wasm_extern_as_global_const(src))); break; case WASM_EXTERN_MEMORY: dst = wasm_memory_as_extern( - wasm_memory_copy(wasm_extern_as_memory_const(src))); + wasm_memory_copy(wasm_extern_as_memory_const(src))); break; case WASM_EXTERN_TABLE: dst = wasm_table_as_extern( - wasm_table_copy(wasm_extern_as_table_const(src))); + wasm_table_copy(wasm_extern_as_table_const(src))); break; default: LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__, @@ -3721,16 +4528,16 @@ wasm_extern_type(const wasm_extern_t *external) switch (wasm_extern_kind(external)) { case WASM_EXTERN_FUNC: return wasm_functype_as_externtype( - wasm_func_type(wasm_extern_as_func_const(external))); + wasm_func_type(wasm_extern_as_func_const(external))); case WASM_EXTERN_GLOBAL: return wasm_globaltype_as_externtype( - wasm_global_type(wasm_extern_as_global_const(external))); + wasm_global_type(wasm_extern_as_global_const(external))); case WASM_EXTERN_MEMORY: return wasm_memorytype_as_externtype( - wasm_memory_type(wasm_extern_as_memory_const(external))); + wasm_memory_type(wasm_extern_as_memory_const(external))); case WASM_EXTERN_TABLE: return wasm_tabletype_as_externtype( - wasm_table_type(wasm_extern_as_table_const(external))); + wasm_table_type(wasm_extern_as_table_const(external))); default: LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__, external->kind); @@ -3739,45 +4546,45 @@ wasm_extern_type(const wasm_extern_t *external) return NULL; } -#define BASIC_FOUR_LIST(V) \ - V(func) \ - V(global) \ - V(memory) \ +#define BASIC_FOUR_LIST(V) \ + V(func) \ + V(global) \ + V(memory) \ V(table) -#define WASM_EXTERN_AS_OTHER(name) \ - wasm_##name##_t *wasm_extern_as_##name(wasm_extern_t *external) \ - { \ - return (wasm_##name##_t *)external; \ +#define WASM_EXTERN_AS_OTHER(name) \ + wasm_##name##_t *wasm_extern_as_##name(wasm_extern_t *external) \ + { \ + return (wasm_##name##_t *)external; \ } BASIC_FOUR_LIST(WASM_EXTERN_AS_OTHER) #undef WASM_EXTERN_AS_OTHER -#define WASM_OTHER_AS_EXTERN(name) \ - wasm_extern_t *wasm_##name##_as_extern(wasm_##name##_t *other) \ - { \ - return (wasm_extern_t *)other; \ +#define WASM_OTHER_AS_EXTERN(name) \ + wasm_extern_t *wasm_##name##_as_extern(wasm_##name##_t *other) \ + { \ + return (wasm_extern_t *)other; \ } BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN) #undef WASM_OTHER_AS_EXTERN -#define WASM_EXTERN_AS_OTHER_CONST(name) \ - const wasm_##name##_t *wasm_extern_as_##name##_const( \ - const wasm_extern_t *external) \ - { \ - return (const wasm_##name##_t *)external; \ +#define WASM_EXTERN_AS_OTHER_CONST(name) \ + const wasm_##name##_t *wasm_extern_as_##name##_const( \ + const wasm_extern_t *external) \ + { \ + return (const wasm_##name##_t *)external; \ } BASIC_FOUR_LIST(WASM_EXTERN_AS_OTHER_CONST) #undef WASM_EXTERN_AS_OTHER_CONST -#define WASM_OTHER_AS_EXTERN_CONST(name) \ - const wasm_extern_t *wasm_##name##_as_extern_const( \ - const wasm_##name##_t *other) \ - { \ - return (const wasm_extern_t *)other; \ +#define WASM_OTHER_AS_EXTERN_CONST(name) \ + const wasm_extern_t *wasm_##name##_as_extern_const( \ + const wasm_##name##_t *other) \ + { \ + return (const wasm_extern_t *)other; \ } BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN_CONST) diff --git a/core/iwasm/common/wasm_c_api_internal.h b/core/iwasm/common/wasm_c_api_internal.h index 073eead867..919d1524fc 100644 --- a/core/iwasm/common/wasm_c_api_internal.h +++ b/core/iwasm/common/wasm_c_api_internal.h @@ -6,7 +6,7 @@ #ifndef _WASM_C_API_INTERNAL_H #define _WASM_C_API_INTERNAL_H -#include "wasm_c_api.h" +#include "../include/wasm_c_api.h" #include "wasm_runtime_common.h" #ifndef own @@ -19,9 +19,9 @@ /* caller needs to take care resource for the vector itself */ #define DEFAULT_VECTOR_INIT_LENGTH (64) -WASM_DECLARE_VEC(store, *) -WASM_DECLARE_VEC(module, *) WASM_DECLARE_VEC(instance, *) +WASM_DECLARE_VEC(module, *) +WASM_DECLARE_VEC(store, *) /* Runtime Environment */ struct wasm_engine_t { @@ -32,6 +32,7 @@ struct wasm_engine_t { struct wasm_store_t { wasm_module_vec_t *modules; wasm_instance_vec_t *instances; + Vector *foreigns; }; /* Type Representations */ @@ -67,6 +68,7 @@ struct wasm_memorytype_t { struct wasm_externtype_t { uint32 extern_kind; + /* reservered space */ uint8 data[1]; }; @@ -82,19 +84,48 @@ struct wasm_exporttype_t { }; /* Runtime Objects */ +enum wasm_reference_kind { + WASM_REF_foreign, + WASM_REF_func, + WASM_REF_global, + WASM_REF_memory, + WASM_REF_table, +}; + +struct wasm_host_info { + void *info; + void (*finalizer)(void *); +}; + struct wasm_ref_t { - uint32 obj; + wasm_store_t *store; + enum wasm_reference_kind kind; + struct wasm_host_info host_info; + uint32 ref_idx_rt; + WASMModuleInstanceCommon *inst_comm_rt; }; struct wasm_trap_t { wasm_byte_vec_t *message; + Vector *frames; +}; + +struct wasm_foreign_t { + wasm_store_t *store; + enum wasm_reference_kind kind; + struct wasm_host_info host_info; + int32 ref_cnt; + uint32 foreign_idx_rt; + WASMModuleInstanceCommon *inst_comm_rt; }; struct wasm_func_t { + wasm_store_t *store; wasm_name_t *module_name; wasm_name_t *name; uint16 kind; + struct wasm_host_info host_info; wasm_functype_t *type; bool with_env; @@ -116,10 +147,12 @@ struct wasm_func_t { }; struct wasm_global_t { + wasm_store_t *store; wasm_name_t *module_name; wasm_name_t *name; uint16 kind; + struct wasm_host_info host_info; wasm_globaltype_t *type; wasm_val_t *init; /* @@ -131,10 +164,12 @@ struct wasm_global_t { }; struct wasm_memory_t { + wasm_store_t *store; wasm_name_t *module_name; wasm_name_t *name; uint16 kind; + struct wasm_host_info host_info; wasm_memorytype_t *type; /* * an index in both memory runtime instance lists @@ -145,10 +180,12 @@ struct wasm_memory_t { }; struct wasm_table_t { + wasm_store_t *store; wasm_name_t *module_name; wasm_name_t *name; uint16 kind; + struct wasm_host_info host_info; wasm_tabletype_t *type; /* * an index in both table runtime instance lists @@ -159,16 +196,44 @@ struct wasm_table_t { }; struct wasm_extern_t { + wasm_store_t *store; wasm_name_t *module_name; wasm_name_t *name; wasm_externkind_t kind; + /* reservered space */ uint8 data[1]; }; struct wasm_instance_t { + wasm_store_t *store; wasm_extern_vec_t *imports; wasm_extern_vec_t *exports; + struct wasm_host_info host_info; WASMModuleInstanceCommon *inst_comm_rt; }; +wasm_ref_t * +wasm_ref_new_internal(wasm_store_t *store, enum wasm_reference_kind kind, + uint32 obj_idx_rt, + WASMModuleInstanceCommon *inst_comm_rt); + +wasm_foreign_t * +wasm_foreign_new_internal(wasm_store_t *store, uint32 foreign_idx_rt, + WASMModuleInstanceCommon *inst_comm_rt); + +wasm_func_t * +wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt, + WASMModuleInstanceCommon *inst_comm_rt); + +wasm_global_t * +wasm_global_new_internal(wasm_store_t *store, uint16 global_idx_rt, + WASMModuleInstanceCommon *inst_comm_rt); + +wasm_memory_t * +wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt, + WASMModuleInstanceCommon *inst_comm_rt); + +wasm_table_t * +wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt, + WASMModuleInstanceCommon *inst_comm_rt); #endif /* _WASM_C_API_INTERNAL_H */ diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index d1c2cfe209..685542b793 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -12,16 +12,23 @@ #include "../aot/aot_runtime.h" #endif +#if WASM_ENABLE_AOT != 0 +#include "aot_runtime.h" +#endif + #if WASM_ENABLE_THREAD_MGR != 0 #include "../libraries/thread-mgr/thread_manager.h" +#if WASM_ENABLE_DEBUG_INTERP != 0 +#include "../libraries/debug-engine/debug_engine.h" +#endif #endif WASMExecEnv * wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst, uint32 stack_size) { - uint64 total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom) - + (uint64)stack_size; + uint64 total_size = + offsetof(WASMExecEnv, wasm_stack.s.bottom) + (uint64)stack_size; WASMExecEnv *exec_env; if (total_size >= UINT32_MAX @@ -42,6 +49,12 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst, if (os_cond_init(&exec_env->wait_cond) != 0) goto fail3; + +#if WASM_ENABLE_DEBUG_INTERP != 0 + if (!(exec_env->current_status = wasm_cluster_create_exenv_status())) + goto fail4; +#endif + #endif exec_env->module_inst = module_inst; @@ -50,12 +63,24 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst, exec_env->wasm_stack.s.bottom + stack_size; exec_env->wasm_stack.s.top = exec_env->wasm_stack.s.bottom; +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + AOTModuleInstance *i = (AOTModuleInstance *)module_inst; + AOTModule *m = (AOTModule *)i->aot_module.ptr; + exec_env->native_symbol = m->native_symbol_list; + } +#endif + #if WASM_ENABLE_MEMORY_TRACING != 0 wasm_runtime_dump_exec_env_mem_consumption(exec_env); #endif return exec_env; #if WASM_ENABLE_THREAD_MGR != 0 +#if WASM_ENABLE_DEBUG_INTERP != 0 +fail4: + os_cond_destroy(&exec_env->wait_cond); +#endif fail3: os_mutex_destroy(&exec_env->wait_lock); fail2: @@ -74,6 +99,9 @@ wasm_exec_env_destroy_internal(WASMExecEnv *exec_env) #if WASM_ENABLE_THREAD_MGR != 0 os_mutex_destroy(&exec_env->wait_lock); os_cond_destroy(&exec_env->wait_cond); +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_cluster_destroy_exenv_status(exec_env->current_status); +#endif #endif #if WASM_ENABLE_AOT != 0 wasm_runtime_free(exec_env->argv_buf); @@ -94,22 +122,23 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst, if (!exec_env) return NULL; - /* Set the aux_stack_boundary and aux_stack_bottom */ #if WASM_ENABLE_INTERP != 0 + /* Set the aux_stack_boundary and aux_stack_bottom */ if (module_inst->module_type == Wasm_Module_Bytecode) { WASMModule *module = ((WASMModuleInstance *)module_inst)->module; exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom; - exec_env->aux_stack_boundary.boundary = module->aux_stack_bottom - - module->aux_stack_size; + exec_env->aux_stack_boundary.boundary = + module->aux_stack_bottom - module->aux_stack_size; } #endif #if WASM_ENABLE_AOT != 0 + /* Set the aux_stack_boundary and aux_stack_bottom */ if (module_inst->module_type == Wasm_Module_AoT) { AOTModule *module = (AOTModule *)(((AOTModuleInstance *)module_inst)->aot_module.ptr); exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom; - exec_env->aux_stack_boundary.boundary = module->aux_stack_bottom - - module->aux_stack_size; + exec_env->aux_stack_boundary.boundary = + module->aux_stack_bottom - module->aux_stack_size; } #endif @@ -119,7 +148,11 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst, wasm_exec_env_destroy_internal(exec_env); return NULL; } +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_debug_instance_create(cluster); #endif +#endif /* end of WASM_ENABLE_THREAD_MGR */ + return exec_env; } @@ -130,10 +163,15 @@ wasm_exec_env_destroy(WASMExecEnv *exec_env) /* Terminate all sub-threads */ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); if (cluster) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_cluster_thread_exited(exec_env); + wasm_debug_instance_destroy(cluster); +#endif wasm_cluster_terminate_all_except_self(cluster, exec_env); wasm_cluster_del_exec_env(cluster, exec_env); } -#endif +#endif /* end of WASM_ENABLE_THREAD_MGR */ + wasm_exec_env_destroy_internal(exec_env); } @@ -186,4 +224,3 @@ wasm_exec_env_pop_jmpbuf(WASMExecEnv *exec_env) return NULL; } #endif - diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index f101504dd0..ea2fafd680 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -20,6 +20,9 @@ struct WASMInterpFrame; #if WASM_ENABLE_THREAD_MGR != 0 typedef struct WASMCluster WASMCluster; +#if WASM_ENABLE_DEBUG_INTERP != 0 +typedef struct WASMCurrentEnvStatus WASMCurrentEnvStatus; +#endif #endif #ifdef OS_ENABLE_HW_BOUND_CHECK @@ -86,7 +89,7 @@ typedef struct WASMExecEnv { void *thread_ret_value; /* Must be provided by thread library */ - void* (*thread_start_routine)(void *); + void *(*thread_start_routine)(void *); void *thread_arg; /* pointer to the cluster */ @@ -97,6 +100,10 @@ typedef struct WASMExecEnv { korp_cond wait_cond; #endif +#if WASM_ENABLE_DEBUG_INTERP != 0 + WASMCurrentEnvStatus *current_status; +#endif + /* attachment for native function */ void *attachment; @@ -185,8 +192,8 @@ wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size) #if WASM_ENABLE_MEMORY_PROFILING != 0 { - uint32 wasm_stack_used = exec_env->wasm_stack.s.top - - exec_env->wasm_stack.s.bottom; + uint32 wasm_stack_used = + exec_env->wasm_stack.s.top - exec_env->wasm_stack.s.bottom; if (wasm_stack_used > exec_env->max_wasm_stack_used) exec_env->max_wasm_stack_used = wasm_stack_used; } @@ -208,7 +215,7 @@ wasm_exec_env_free_wasm_frame(WASMExecEnv *exec_env, void *prev_top) * * @return the current WASM stack top pointer */ -static inline void* +static inline void * wasm_exec_env_wasm_stack_top(WASMExecEnv *exec_env) { return exec_env->wasm_stack.s.top; @@ -234,7 +241,7 @@ wasm_exec_env_set_cur_frame(WASMExecEnv *exec_env, * * @return the current frame pointer */ -static inline struct WASMInterpFrame* +static inline struct WASMInterpFrame * wasm_exec_env_get_cur_frame(WASMExecEnv *exec_env) { return exec_env->cur_frame; @@ -246,7 +253,6 @@ wasm_exec_env_get_module_inst(WASMExecEnv *exec_env); void wasm_exec_env_set_thread_info(WASMExecEnv *exec_env); - #if WASM_ENABLE_THREAD_MGR != 0 void * wasm_exec_env_get_thread_arg(WASMExecEnv *exec_env); diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 0b558cb51d..42f52cacfd 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -39,8 +39,7 @@ wasm_memory_init_with_pool(void *mem, unsigned int bytes) } static bool -wasm_memory_init_with_allocator(void *_malloc_func, - void *_realloc_func, +wasm_memory_init_with_allocator(void *_malloc_func, void *_realloc_func, void *_free_func) { if (_malloc_func && _free_func && _malloc_func != _free_func) { @@ -50,8 +49,8 @@ wasm_memory_init_with_allocator(void *_malloc_func, free_func = _free_func; return true; } - LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n", - _malloc_func, _realloc_func, _free_func); + LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n", _malloc_func, + _realloc_func, _free_func); return false; } @@ -63,9 +62,10 @@ wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type, return wasm_memory_init_with_pool(alloc_option->pool.heap_buf, alloc_option->pool.heap_size); else if (mem_alloc_type == Alloc_With_Allocator) - return wasm_memory_init_with_allocator(alloc_option->allocator.malloc_func, - alloc_option->allocator.realloc_func, - alloc_option->allocator.free_func); + return wasm_memory_init_with_allocator( + alloc_option->allocator.malloc_func, + alloc_option->allocator.realloc_func, + alloc_option->allocator.free_func); else if (mem_alloc_type == Alloc_With_System_Allocator) return wasm_memory_init_with_allocator(os_malloc, os_realloc, os_free); else @@ -93,7 +93,8 @@ static inline void * wasm_runtime_malloc_internal(unsigned int size) { if (memory_mode == MEMORY_MODE_UNKNOWN) { - LOG_WARNING("wasm_runtime_malloc failed: memory hasn't been initialize.\n"); + LOG_WARNING( + "wasm_runtime_malloc failed: memory hasn't been initialize.\n"); return NULL; } else if (memory_mode == MEMORY_MODE_POOL) { @@ -108,7 +109,8 @@ static inline void * wasm_runtime_realloc_internal(void *ptr, unsigned int size) { if (memory_mode == MEMORY_MODE_UNKNOWN) { - LOG_WARNING("wasm_runtime_realloc failed: memory hasn't been initialize.\n"); + LOG_WARNING( + "wasm_runtime_realloc failed: memory hasn't been initialize.\n"); return NULL; } else if (memory_mode == MEMORY_MODE_POOL) { diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h index 08157acfbe..8511ae647c 100644 --- a/core/iwasm/common/wasm_memory.h +++ b/core/iwasm/common/wasm_memory.h @@ -25,4 +25,3 @@ wasm_runtime_memory_destroy(); #endif #endif /* end of _WASM_MEMORY_H */ - diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index 1522b95e7c..15cb0e5c61 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -17,7 +17,7 @@ #define ENABLE_SORT_DEBUG 0 #if ENABLE_SORT_DEBUG != 0 -#include +#include #endif static NativeSymbolsList g_native_symbols_list = NULL; @@ -80,7 +80,7 @@ check_symbol_signature(const WASMType *type, const char *signature) #if WASM_ENABLE_REF_TYPES != 0 || (sig == 'i' && type->types[i] == VALUE_TYPE_EXTERNREF) #endif - ) + ) /* normal parameter */ continue; @@ -91,8 +91,7 @@ check_symbol_signature(const WASMType *type, const char *signature) if (sig == '*') { /* it is a pointer */ if (i + 1 < type->param_count - && type->types[i + 1] == VALUE_TYPE_I32 - && *p == '~') { + && type->types[i + 1] == VALUE_TYPE_I32 && *p == '~') { /* pointer length followed */ i++; p++; @@ -132,8 +131,8 @@ sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols) for (i = 0; i < n_native_symbols - 1; i++) { for (j = i + 1; j < n_native_symbols; j++) { - if (strcmp(native_symbols[i].symbol, - native_symbols[j].symbol) > 0) { + if (strcmp(native_symbols[i].symbol, native_symbols[j].symbol) + > 0) { temp = native_symbols[i]; native_symbols[i] = native_symbols[j]; native_symbols[j] = temp; @@ -143,7 +142,7 @@ sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols) } #else static void -swap_symbol(NativeSymbol* left, NativeSymbol* right) +swap_symbol(NativeSymbol *left, NativeSymbol *right) { NativeSymbol temp = *left; *left = *right; @@ -151,7 +150,7 @@ swap_symbol(NativeSymbol* left, NativeSymbol* right) } static void -quick_sort_symbols(NativeSymbol* native_symbols, int left, int right) +quick_sort_symbols(NativeSymbol *native_symbols, int left, int right) { NativeSymbol base_symbol; int pin_left = left; @@ -164,8 +163,8 @@ quick_sort_symbols(NativeSymbol* native_symbols, int left, int right) base_symbol = native_symbols[left]; while (left < right) { while (left < right - && strcmp(native_symbols[right].symbol, - base_symbol.symbol) > 0) { + && strcmp(native_symbols[right].symbol, base_symbol.symbol) + > 0) { right--; } @@ -175,8 +174,7 @@ quick_sort_symbols(NativeSymbol* native_symbols, int left, int right) } while (left < right - && strcmp(native_symbols[left].symbol, - base_symbol.symbol) < 0) { + && strcmp(native_symbols[left].symbol, base_symbol.symbol) < 0) { left++; } @@ -216,7 +214,7 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols, return NULL; } -void* +void * wasm_native_resolve_symbol(const char *module_name, const char *field_name, const WASMType *func_type, const char **p_signature, void **p_attachment, bool *p_call_conv_raw) @@ -229,15 +227,14 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name, while (node) { node_next = node->next; if (!strcmp(node->module_name, module_name)) { - if ((func_ptr = lookup_symbol(node->native_symbols, - node->n_native_symbols, - field_name, &signature, &attachment)) + if ((func_ptr = + lookup_symbol(node->native_symbols, node->n_native_symbols, + field_name, &signature, &attachment)) || (field_name[0] == '_' - && (func_ptr = lookup_symbol(node->native_symbols, - node->n_native_symbols, - field_name + 1, - &signature, &attachment)))) - break; + && (func_ptr = lookup_symbol( + node->native_symbols, node->n_native_symbols, + field_name + 1, &signature, &attachment)))) + break; } node = node_next; } @@ -246,7 +243,8 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name, if (signature && signature[0] != '\0') { /* signature is not empty, check its format */ if (!check_symbol_signature(func_type, signature)) { -#if WASM_ENABLE_WAMR_COMPILER == 0 /* Output warning except running aot compiler */ +#if WASM_ENABLE_WAMR_COMPILER == 0 + /* Output warning except running aot compiler */ LOG_WARNING("failed to check signature '%s' and resolve " "pointer params for import function (%s %s)\n", signature, module_name, field_name); @@ -270,10 +268,8 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name, } static bool -register_natives(const char *module_name, - NativeSymbol *native_symbols, - uint32 n_native_symbols, - bool call_conv_raw) +register_natives(const char *module_name, NativeSymbol *native_symbols, + uint32 n_native_symbols, bool call_conv_raw) { NativeSymbolsNode *node; #if ENABLE_SORT_DEBUG != 0 @@ -309,10 +305,10 @@ register_natives(const char *module_name, #if ENABLE_SORT_DEBUG != 0 gettimeofday(&end, NULL); - timer = 1000000 * (end.tv_sec - start.tv_sec) - + (end.tv_usec - start.tv_usec); - LOG_ERROR("module_name: %s, nums: %d, sorted used: %ld us", - module_name, n_native_symbols, timer); + timer = + 1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec); + LOG_ERROR("module_name: %s, nums: %d, sorted used: %ld us", module_name, + n_native_symbols, timer); #endif return true; } @@ -322,7 +318,8 @@ wasm_native_register_natives(const char *module_name, NativeSymbol *native_symbols, uint32 n_native_symbols) { - return register_natives(module_name, native_symbols, n_native_symbols, false); + return register_natives(module_name, native_symbols, n_native_symbols, + false); } bool @@ -330,7 +327,8 @@ wasm_native_register_natives_raw(const char *module_name, NativeSymbol *native_symbols, uint32 n_native_symbols) { - return register_natives(module_name, native_symbols, n_native_symbols, true); + return register_natives(module_name, native_symbols, n_native_symbols, + true); } bool @@ -341,41 +339,40 @@ wasm_native_init() #if WASM_ENABLE_LIBC_BUILTIN != 0 n_native_symbols = get_libc_builtin_export_apis(&native_symbols); - if (!wasm_native_register_natives("env", - native_symbols, n_native_symbols)) + if (!wasm_native_register_natives("env", native_symbols, n_native_symbols)) return false; #endif /* WASM_ENABLE_LIBC_BUILTIN */ #if WASM_ENABLE_SPEC_TEST n_native_symbols = get_spectest_export_apis(&native_symbols); - if (!wasm_native_register_natives("spectest", - native_symbols, n_native_symbols)) + if (!wasm_native_register_natives("spectest", native_symbols, + n_native_symbols)) return false; #endif /* WASM_ENABLE_SPEC_TEST */ #if WASM_ENABLE_LIBC_WASI != 0 n_native_symbols = get_libc_wasi_export_apis(&native_symbols); - if (!wasm_native_register_natives("wasi_unstable", - native_symbols, n_native_symbols)) + if (!wasm_native_register_natives("wasi_unstable", native_symbols, + n_native_symbols)) return false; - if (!wasm_native_register_natives("wasi_snapshot_preview1", - native_symbols, n_native_symbols)) + if (!wasm_native_register_natives("wasi_snapshot_preview1", native_symbols, + n_native_symbols)) return false; #endif #if WASM_ENABLE_BASE_LIB != 0 n_native_symbols = get_base_lib_export_apis(&native_symbols); if (n_native_symbols > 0 - && !wasm_native_register_natives("env", - native_symbols, n_native_symbols)) + && !wasm_native_register_natives("env", native_symbols, + n_native_symbols)) return false; #endif #if WASM_ENABLE_APP_FRAMEWORK != 0 n_native_symbols = get_ext_lib_export_apis(&native_symbols); if (n_native_symbols > 0 - && !wasm_native_register_natives("env", - native_symbols, n_native_symbols)) + && !wasm_native_register_natives("env", native_symbols, + n_native_symbols)) return false; #endif @@ -385,16 +382,16 @@ wasm_native_init() n_native_symbols = get_lib_pthread_export_apis(&native_symbols); if (n_native_symbols > 0 - && !wasm_native_register_natives("env", - native_symbols, n_native_symbols)) + && !wasm_native_register_natives("env", native_symbols, + n_native_symbols)) return false; #endif #if WASM_ENABLE_LIBC_EMCC != 0 n_native_symbols = get_libc_emcc_export_apis(&native_symbols); if (n_native_symbols > 0 - && !wasm_native_register_natives("env", - native_symbols, n_native_symbols)) + && !wasm_native_register_natives("env", native_symbols, + n_native_symbols)) return false; #endif /* WASM_ENABLE_LIBC_EMCC */ diff --git a/core/iwasm/common/wasm_native.h b/core/iwasm/common/wasm_native.h index d76d238a81..2777b38b2b 100644 --- a/core/iwasm/common/wasm_native.h +++ b/core/iwasm/common/wasm_native.h @@ -49,7 +49,7 @@ wasm_native_lookup_libc_builtin_global(const char *module_name, * * @return the native function pointer if success, NULL otherwise */ -void* +void * wasm_native_resolve_symbol(const char *module_name, const char *field_name, const WASMType *func_type, const char **p_signature, void **p_attachment, bool *p_call_conv_raw); @@ -75,4 +75,3 @@ wasm_native_destroy(); #endif #endif /* end of _WASM_NATIVE_H */ - diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 64ab7ac878..286c2200c0 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -14,9 +14,15 @@ #endif #if WASM_ENABLE_AOT != 0 #include "../aot/aot_runtime.h" +#if WASM_ENABLE_DEBUG_AOT != 0 +#include "../aot/debug/jit_debug.h" +#endif #endif #if WASM_ENABLE_THREAD_MGR != 0 #include "../libraries/thread-mgr/thread_manager.h" +#if WASM_ENABLE_DEBUG_INTERP != 0 +#include "../libraries/debug-engine/debug_engine.h" +#endif #endif #if WASM_ENABLE_SHARED_MEMORY != 0 #include "wasm_shared_memory.h" @@ -24,10 +30,10 @@ #include "../common/wasm_c_api_internal.h" #if WASM_ENABLE_MULTI_MODULE != 0 -/* - * a safety insurance to prevent - * circular depencies leading a stack overflow - * try break early +/** + * A safety insurance to prevent + * circular depencies which leads stack overflow + * try to break early */ typedef struct LoadingModule { bh_list_link l; @@ -39,9 +45,9 @@ static bh_list loading_module_list_head; static bh_list *const loading_module_list = &loading_module_list_head; static korp_mutex loading_module_list_lock; -/* - * a list about all exported functions, globals, memories, tables of every - * fully loaded module +/** + * A list to store all exported functions/globals/memories/tables + * of every fully loaded module */ static bh_list registered_module_list_head; static bh_list *const registered_module_list = ®istered_module_list_head; @@ -73,15 +79,12 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst, { void *mem; - if (size >= UINT32_MAX - || !(mem = wasm_runtime_malloc((uint32)size))) { + if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) { if (module_inst != NULL) { - wasm_runtime_set_exception(module_inst, - "allocate memory failed"); + wasm_runtime_set_exception(module_inst, "allocate memory failed"); } else if (error_buf != NULL) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); } return NULL; } @@ -128,20 +131,29 @@ wasm_runtime_env_init() goto fail6; } #endif +#if WASM_ENABLE_DEBUG_AOT != 0 + if (!jit_debug_engine_init()) { + goto fail7; + } +#endif #endif #if WASM_ENABLE_REF_TYPES != 0 if (!wasm_externref_map_init()) { - goto fail7; + goto fail8; } #endif return true; #if WASM_ENABLE_REF_TYPES != 0 -fail7: +fail8: #endif #if WASM_ENABLE_AOT != 0 +#if WASM_ENABLE_DEBUG_AOT != 0 + jit_debug_engine_destroy(); +fail7: +#endif #ifdef OS_ENABLE_HW_BOUND_CHECK aot_signal_destroy(); fail6: @@ -171,11 +183,9 @@ wasm_runtime_env_init() static bool wasm_runtime_exec_env_check(WASMExecEnv *exec_env) { - return exec_env - && exec_env->module_inst - && exec_env->wasm_stack_size > 0 - && exec_env->wasm_stack.s.top_boundary == - exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size + return exec_env && exec_env->module_inst && exec_env->wasm_stack_size > 0 + && exec_env->wasm_stack.s.top_boundary + == exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size && exec_env->wasm_stack.s.top <= exec_env->wasm_stack.s.top_boundary; } @@ -201,6 +211,9 @@ wasm_runtime_destroy() #endif #if WASM_ENABLE_AOT != 0 +#if WASM_ENABLE_DEBUG_AOT != 0 + jit_debug_engine_destroy(); +#endif #ifdef OS_ENABLE_HW_BOUND_CHECK aot_signal_destroy(); #endif @@ -220,6 +233,9 @@ wasm_runtime_destroy() #endif #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0) +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_debug_engine_destroy(); +#endif thread_manager_destroy(); #endif @@ -241,6 +257,16 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args) return false; } +#if WASM_ENABLE_DEBUG_INTERP != 0 + if (strlen(init_args->ip_addr)) + if (!wasm_debug_engine_init(init_args->ip_addr, + init_args->platform_port, + init_args->instance_port)) { + wasm_runtime_destroy(); + return false; + } +#endif + if (init_args->n_native_symbols > 0 && !wasm_runtime_register_natives(init_args->native_module_name, init_args->native_symbols, @@ -311,29 +337,29 @@ wasm_runtime_register_module_internal(const char *module_name, WASMModuleCommon *module, uint8 *orig_file_buf, uint32 orig_file_buf_size, - char *error_buf, - uint32_t error_buf_size) + char *error_buf, uint32_t error_buf_size) { WASMRegisteredModule *node = NULL; node = wasm_runtime_find_module_registered_by_reference(module); - if (node) { /* module has been registered */ + if (node) { /* module has been registered */ if (node->module_name) { /* module has name */ - if (!module_name || strcmp(node->module_name, module_name)) { - /* module has different name */ - LOG_DEBUG("module(%p) has been registered with name %s", - module, node->module_name); - set_error_buf(error_buf, error_buf_size, - "Register module failed: " - "failed to rename the module"); - return false; - } - else { - /* module has the same name */ - LOG_DEBUG("module(%p) has been registered with the same name %s", - module, node->module_name); - return true; - } + if (!module_name || strcmp(node->module_name, module_name)) { + /* module has different name */ + LOG_DEBUG("module(%p) has been registered with name %s", module, + node->module_name); + set_error_buf(error_buf, error_buf_size, + "Register module failed: " + "failed to rename the module"); + return false; + } + else { + /* module has the same name */ + LOG_DEBUG( + "module(%p) has been registered with the same name %s", + module, node->module_name); + return true; + } } else { /* module has empyt name, reset it */ @@ -389,9 +415,8 @@ wasm_runtime_register_module(const char *module_name, WASMModuleCommon *module, return false; } - return wasm_runtime_register_module_internal( - module_name, module, NULL, 0, - error_buf, error_buf_size); + return wasm_runtime_register_module_internal(module_name, module, NULL, 0, + error_buf, error_buf_size); } void @@ -422,8 +447,7 @@ wasm_runtime_find_module_registered(const char *module_name) module = bh_list_first_elem(registered_module_list); while (module) { module_next = bh_list_elem_next(module); - if (module->module_name - && !strcmp(module_name, module->module_name)) { + if (module->module_name && !strcmp(module_name, module->module_name)) { break; } module = module_next; @@ -481,13 +505,12 @@ wasm_runtime_destroy_registered_module_list() } bool -wasm_runtime_add_loading_module(const char *module_name, - char *error_buf, uint32 error_buf_size) +wasm_runtime_add_loading_module(const char *module_name, char *error_buf, + uint32 error_buf_size) { LOG_DEBUG("add %s into a loading list", module_name); LoadingModule *loadingModule = - runtime_malloc(sizeof(LoadingModule), NULL, - error_buf, error_buf_size); + runtime_malloc(sizeof(LoadingModule), NULL, error_buf, error_buf_size); if (!loadingModule) { return false; @@ -569,8 +592,7 @@ wasm_runtime_destroy_loading_module_list() bool wasm_runtime_is_built_in_module(const char *module_name) { - return (!strcmp("env", module_name) - || !strcmp("wasi_unstable", module_name) + return (!strcmp("env", module_name) || !strcmp("wasi_unstable", module_name) || !strcmp("wasi_snapshot_preview1", module_name) #if WASM_ENABLE_SPEC_TEST != 0 || !strcmp("spectest", module_name) @@ -580,11 +602,11 @@ wasm_runtime_is_built_in_module(const char *module_name) #if WASM_ENABLE_THREAD_MGR != 0 bool -wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, - uint32 start_offset, uint32 size) +wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, + uint32 size) { - WASMModuleInstanceCommon *module_inst - = wasm_exec_env_get_module_inst(exec_env); + WASMModuleInstanceCommon *module_inst = + wasm_exec_env_get_module_inst(exec_env); #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { return wasm_set_aux_stack(exec_env, start_offset, size); @@ -599,11 +621,11 @@ wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, } bool -wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env, - uint32 *start_offset, uint32 *size) +wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, + uint32 *size) { - WASMModuleInstanceCommon *module_inst - = wasm_exec_env_get_module_inst(exec_env); + WASMModuleInstanceCommon *module_inst = + wasm_exec_env_get_module_inst(exec_env); #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { return wasm_get_aux_stack(exec_env, start_offset, size); @@ -625,15 +647,13 @@ wasm_runtime_set_max_thread_num(uint32 num) #endif /* end of WASM_ENABLE_THREAD_MGR */ static WASMModuleCommon * -register_module_with_null_name(WASMModuleCommon *module_common, - char *error_buf, uint32 error_buf_size) +register_module_with_null_name(WASMModuleCommon *module_common, char *error_buf, + uint32 error_buf_size) { #if WASM_ENABLE_MULTI_MODULE != 0 if (module_common) { - if (!wasm_runtime_register_module_internal(NULL, module_common, - NULL, 0, - error_buf, - error_buf_size)) { + if (!wasm_runtime_register_module_internal(NULL, module_common, NULL, 0, + error_buf, error_buf_size)) { wasm_runtime_unload(module_common); return NULL; } @@ -647,8 +667,8 @@ register_module_with_null_name(WASMModuleCommon *module_common, } WASMModuleCommon * -wasm_runtime_load(const uint8 *buf, uint32 size, - char *error_buf, uint32 error_buf_size) +wasm_runtime_load(const uint8 *buf, uint32 size, char *error_buf, + uint32 error_buf_size) { WASMModuleCommon *module_common = NULL; @@ -659,28 +679,28 @@ wasm_runtime_load(const uint8 *buf, uint32 size, if (!module) return NULL; - if (!(aot_module = aot_convert_wasm_module(module, - error_buf, error_buf_size))) { + if (!(aot_module = + aot_convert_wasm_module(module, error_buf, error_buf_size))) { wasm_unload(module); return NULL; } - module_common = (WASMModuleCommon*)aot_module; - return register_module_with_null_name(module_common, - error_buf, error_buf_size); + module_common = (WASMModuleCommon *)aot_module; + return register_module_with_null_name(module_common, error_buf, + error_buf_size); #elif WASM_ENABLE_INTERP != 0 - module_common = (WASMModuleCommon*) - wasm_load(buf, size, error_buf, error_buf_size); - return register_module_with_null_name(module_common, - error_buf, error_buf_size); + module_common = + (WASMModuleCommon *)wasm_load(buf, size, error_buf, error_buf_size); + return register_module_with_null_name(module_common, error_buf, + error_buf_size); #endif } else if (get_package_type(buf, size) == Wasm_Module_AoT) { #if WASM_ENABLE_AOT != 0 - module_common = (WASMModuleCommon*) - aot_load_from_aot_file(buf, size, error_buf, error_buf_size); - return register_module_with_null_name(module_common, - error_buf, error_buf_size); + module_common = (WASMModuleCommon *)aot_load_from_aot_file( + buf, size, error_buf, error_buf_size); + return register_module_with_null_name(module_common, error_buf, + error_buf_size); #endif } @@ -688,8 +708,8 @@ wasm_runtime_load(const uint8 *buf, uint32 size, set_error_buf(error_buf, error_buf_size, "WASM module load failed: unexpected end"); else - set_error_buf(error_buf, error_buf_size, - "WASM module load failed: magic header not detected"); + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: magic header not detected"); return NULL; } @@ -701,20 +721,18 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, #if WASM_ENABLE_INTERP != 0 if (!is_aot) { - module_common = (WASMModuleCommon*) - wasm_load_from_sections(section_list, - error_buf, error_buf_size); - return register_module_with_null_name(module_common, - error_buf, error_buf_size); + module_common = (WASMModuleCommon *)wasm_load_from_sections( + section_list, error_buf, error_buf_size); + return register_module_with_null_name(module_common, error_buf, + error_buf_size); } #endif #if WASM_ENABLE_AOT != 0 if (is_aot) { - module_common = (WASMModuleCommon*) - aot_load_from_sections(section_list, - error_buf, error_buf_size); - return register_module_with_null_name(module_common, - error_buf, error_buf_size); + module_common = (WASMModuleCommon *)aot_load_from_sections( + section_list, error_buf, error_buf_size); + return register_module_with_null_name(module_common, error_buf, + error_buf_size); } #endif @@ -736,14 +754,14 @@ wasm_runtime_unload(WASMModuleCommon *module) #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) { - wasm_unload((WASMModule*)module); + wasm_unload((WASMModule *)module); return; } #endif #if WASM_ENABLE_AOT != 0 if (module->module_type == Wasm_Module_AoT) { - aot_unload((AOTModule*)module); + aot_unload((AOTModule *)module); return; } #endif @@ -756,17 +774,15 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst, { #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) - return (WASMModuleInstanceCommon*) - wasm_instantiate((WASMModule*)module, is_sub_inst, - stack_size, heap_size, - error_buf, error_buf_size); + return (WASMModuleInstanceCommon *)wasm_instantiate( + (WASMModule *)module, is_sub_inst, stack_size, heap_size, error_buf, + error_buf_size); #endif #if WASM_ENABLE_AOT != 0 if (module->module_type == Wasm_Module_AoT) - return (WASMModuleInstanceCommon*) - aot_instantiate((AOTModule*)module, is_sub_inst, - stack_size, heap_size, - error_buf, error_buf_size); + return (WASMModuleInstanceCommon *)aot_instantiate( + (AOTModule *)module, is_sub_inst, stack_size, heap_size, error_buf, + error_buf_size); #endif set_error_buf(error_buf, error_buf_size, "Instantiate module failed, invalid module type"); @@ -774,13 +790,12 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst, } WASMModuleInstanceCommon * -wasm_runtime_instantiate(WASMModuleCommon *module, - uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size) +wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size, + uint32 heap_size, char *error_buf, + uint32 error_buf_size) { - return wasm_runtime_instantiate_internal(module, false, - stack_size, heap_size, - error_buf, error_buf_size); + return wasm_runtime_instantiate_internal( + module, false, stack_size, heap_size, error_buf, error_buf_size); } void @@ -789,13 +804,13 @@ wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - wasm_deinstantiate((WASMModuleInstance*)module_inst, is_sub_inst); + wasm_deinstantiate((WASMModuleInstance *)module_inst, is_sub_inst); return; } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - aot_deinstantiate((AOTModuleInstance*)module_inst, is_sub_inst); + aot_deinstantiate((AOTModuleInstance *)module_inst, is_sub_inst); return; } #endif @@ -821,24 +836,38 @@ wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env) } bool -wasm_runtime_init_thread_env() +wasm_runtime_init_thread_env(void) { +#ifdef BH_PLATFORM_WINDOWS + if (os_thread_env_init() != 0) + return false; +#endif + #if WASM_ENABLE_AOT != 0 #ifdef OS_ENABLE_HW_BOUND_CHECK - return aot_signal_init(); + if (!aot_signal_init()) { +#ifdef BH_PLATFORM_WINDOWS + os_thread_env_destroy(); +#endif + return false; + } #endif #endif return true; } void -wasm_runtime_destroy_thread_env() +wasm_runtime_destroy_thread_env(void) { #if WASM_ENABLE_AOT != 0 #ifdef OS_ENABLE_HW_BOUND_CHECK aot_signal_destroy(); #endif #endif + +#ifdef BH_PLATFORM_WINDOWS + os_thread_env_destroy(); +#endif } #if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_MEMORY_TRACING != 0) @@ -849,12 +878,12 @@ wasm_runtime_dump_module_mem_consumption(const WASMModuleCommon *module) #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) { - wasm_get_module_mem_consumption((WASMModule*)module, &mem_conspn); + wasm_get_module_mem_consumption((WASMModule *)module, &mem_conspn); } #endif #if WASM_ENABLE_AOT != 0 if (module->module_type == Wasm_Module_AoT) { - aot_get_module_mem_consumption((AOTModule*)module, &mem_conspn); + aot_get_module_mem_consumption((AOTModule *)module, &mem_conspn); } #endif @@ -877,20 +906,20 @@ wasm_runtime_dump_module_mem_consumption(const WASMModuleCommon *module) } void -wasm_runtime_dump_module_inst_mem_consumption(const WASMModuleInstanceCommon - *module_inst) +wasm_runtime_dump_module_inst_mem_consumption( + const WASMModuleInstanceCommon *module_inst) { WASMModuleInstMemConsumption mem_conspn = { 0 }; #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - wasm_get_module_inst_mem_consumption((WASMModuleInstance*)module_inst, + wasm_get_module_inst_mem_consumption((WASMModuleInstance *)module_inst, &mem_conspn); } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - aot_get_module_inst_mem_consumption((AOTModuleInstance*)module_inst, + aot_get_module_inst_mem_consumption((AOTModuleInstance *)module_inst, &mem_conspn); } #endif @@ -910,8 +939,8 @@ wasm_runtime_dump_module_inst_mem_consumption(const WASMModuleInstanceCommon void wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env) { - uint32 total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom) - + exec_env->wasm_stack_size; + uint32 total_size = + offsetof(WASMExecEnv, wasm_stack.s.bottom) + exec_env->wasm_stack_size; os_printf("Exec env memory consumption, total size: %u\n", total_size); os_printf(" exec env struct size: %u\n", @@ -941,16 +970,15 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env) #if WASM_ENABLE_INTERP != 0 if (module_inst_common->module_type == Wasm_Module_Bytecode) { WASMModuleInstance *wasm_module_inst = - (WASMModuleInstance*)module_inst_common; + (WASMModuleInstance *)module_inst_common; WASMModule *wasm_module = wasm_module_inst->module; - module_common = (WASMModuleCommon*)wasm_module; + module_common = (WASMModuleCommon *)wasm_module; if (wasm_module_inst->memories) { heap_handle = wasm_module_inst->memories[0]->heap_handle; } - wasm_get_module_inst_mem_consumption - (wasm_module_inst, &module_inst_mem_consps); - wasm_get_module_mem_consumption - (wasm_module, &module_mem_consps); + wasm_get_module_inst_mem_consumption(wasm_module_inst, + &module_inst_mem_consps); + wasm_get_module_mem_consumption(wasm_module, &module_mem_consps); if (wasm_module_inst->module->aux_stack_top_global_index != (uint32)-1) max_aux_stack_used = wasm_module_inst->max_aux_stack_used; } @@ -958,19 +986,17 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env) #if WASM_ENABLE_AOT != 0 if (module_inst_common->module_type == Wasm_Module_AoT) { AOTModuleInstance *aot_module_inst = - (AOTModuleInstance*)module_inst_common; - AOTModule *aot_module = - (AOTModule*)aot_module_inst->aot_module.ptr; - module_common = (WASMModuleCommon*)aot_module; + (AOTModuleInstance *)module_inst_common; + AOTModule *aot_module = (AOTModule *)aot_module_inst->aot_module.ptr; + module_common = (WASMModuleCommon *)aot_module; if (aot_module_inst->memories.ptr) { AOTMemoryInstance **memories = - (AOTMemoryInstance **)aot_module_inst->memories.ptr; + (AOTMemoryInstance **)aot_module_inst->memories.ptr; heap_handle = memories[0]->heap_handle.ptr; } - aot_get_module_inst_mem_consumption - (aot_module_inst, &module_inst_mem_consps); - aot_get_module_mem_consumption - (aot_module, &module_mem_consps); + aot_get_module_inst_mem_consumption(aot_module_inst, + &module_inst_mem_consps); + aot_get_module_mem_consumption(aot_module, &module_mem_consps); } #endif @@ -981,8 +1007,7 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env) } total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom) - + exec_env->wasm_stack_size - + module_mem_consps.total_size + + exec_env->wasm_stack_size + module_mem_consps.total_size + module_inst_mem_consps.total_size; os_printf("\nMemory consumption summary (bytes):\n"); @@ -990,7 +1015,8 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env) wasm_runtime_dump_module_inst_mem_consumption(module_inst_common); wasm_runtime_dump_exec_env_mem_consumption(exec_env); os_printf("\nTotal memory consumption of module, module inst and " - "exec env: %u\n", total_size); + "exec env: %u\n", + total_size); os_printf("Total interpreter stack used: %u\n", exec_env->max_wasm_stack_used); @@ -1001,7 +1027,7 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env) os_printf("Total app heap used: %u\n", app_heap_peak_size); } -#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) +#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \ || (WASM_ENABLE_MEMORY_TRACING != 0) */ #if WASM_ENABLE_PERF_PROFILING != 0 @@ -1010,12 +1036,12 @@ wasm_runtime_dump_perf_profiling(WASMModuleInstanceCommon *module_inst) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - wasm_dump_perf_profiling((WASMModuleInstance*)module_inst); + wasm_dump_perf_profiling((WASMModuleInstance *)module_inst); } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - aot_dump_perf_profiling((AOTModuleInstance*)module_inst); + aot_dump_perf_profiling((AOTModuleInstance *)module_inst); } #endif } @@ -1054,17 +1080,15 @@ wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function, #if WASM_ENABLE_INTERP != 0 if (module_type == Wasm_Module_Bytecode) { WASMFunctionInstance *wasm_func = (WASMFunctionInstance *)function; - type = wasm_func->is_import_func - ? wasm_func->u.func_import->func_type - : wasm_func->u.func->func_type; + type = wasm_func->is_import_func ? wasm_func->u.func_import->func_type + : wasm_func->u.func->func_type; } #endif #if WASM_ENABLE_AOT != 0 if (module_type == Wasm_Module_AoT) { AOTFunctionInstance *aot_func = (AOTFunctionInstance *)function; - type = aot_func->is_import_func - ? aot_func->u.func_import->func_type - : aot_func->u.func.func_type; + type = aot_func->is_import_func ? aot_func->u.func_import->func_type + : aot_func->u.func.func_type; } #endif @@ -1072,20 +1096,18 @@ wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function, } WASMFunctionInstanceCommon * -wasm_runtime_lookup_function(WASMModuleInstanceCommon * const module_inst, +wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst, const char *name, const char *signature) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return (WASMFunctionInstanceCommon*) - wasm_lookup_function((const WASMModuleInstance*)module_inst, - name, signature); + return (WASMFunctionInstanceCommon *)wasm_lookup_function( + (const WASMModuleInstance *)module_inst, name, signature); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return (WASMFunctionInstanceCommon*) - aot_lookup_function((const AOTModuleInstance*)module_inst, - name, signature); + return (WASMFunctionInstanceCommon *)aot_lookup_function( + (const AOTModuleInstance *)module_inst, name, signature); #endif return NULL; } @@ -1098,7 +1120,7 @@ wasm_runtime_reclaim_externref(WASMExecEnv *exec_env, { uint32 i = 0, cell_num = 0; WASMType *func_type = wasm_runtime_get_function_type( - function, exec_env->module_inst->module_type); + function, exec_env->module_inst->module_type); bh_assert(func_type); while (i < func_type->result_count) { @@ -1136,8 +1158,8 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env, bool wasm_runtime_call_wasm(WASMExecEnv *exec_env, - WASMFunctionInstanceCommon *function, - uint32 argc, uint32 argv[]) + WASMFunctionInstanceCommon *function, uint32 argc, + uint32 argv[]) { bool ret = false; @@ -1152,15 +1174,13 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env, #if WASM_ENABLE_INTERP != 0 if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) - ret = wasm_call_function(exec_env, - (WASMFunctionInstance*)function, - argc, argv); + ret = wasm_call_function(exec_env, (WASMFunctionInstance *)function, + argc, argv); #endif #if WASM_ENABLE_AOT != 0 if (exec_env->module_inst->module_type == Wasm_Module_AoT) - ret = aot_call_function(exec_env, - (AOTFunctionInstance*)function, - argc, argv); + ret = aot_call_function(exec_env, (AOTFunctionInstance *)function, argc, + argv); #endif #if WASM_ENABLE_REF_TYPES != 0 @@ -1171,8 +1191,7 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env, } static uint32 -parse_args_to_uint32_array(WASMType *type, - uint32 num_args, wasm_val_t *args, +parse_args_to_uint32_array(WASMType *type, uint32 num_args, wasm_val_t *args, uint32 *out_argv) { uint32 i, p; @@ -1184,7 +1203,10 @@ parse_args_to_uint32_array(WASMType *type, break; case WASM_I64: { - union { uint64 val; uint32 parts[2]; } u; + union { + uint64 val; + uint32 parts[2]; + } u; u.val = args[i].of.i64; out_argv[p++] = u.parts[0]; out_argv[p++] = u.parts[1]; @@ -1192,14 +1214,20 @@ parse_args_to_uint32_array(WASMType *type, } case WASM_F32: { - union { float32 val; uint32 part; } u; + union { + float32 val; + uint32 part; + } u; u.val = args[i].of.f32; out_argv[p++] = u.part; break; } case WASM_F64: { - union { float64 val; uint32 parts[2]; } u; + union { + float64 val; + uint32 parts[2]; + } u; u.val = args[i].of.f64; out_argv[p++] = u.parts[0]; out_argv[p++] = u.parts[1]; @@ -1214,8 +1242,7 @@ parse_args_to_uint32_array(WASMType *type, } static uint32 -parse_uint32_array_to_results(WASMType *type, - uint32 argc, uint32 *argv, +parse_uint32_array_to_results(WASMType *type, uint32 argc, uint32 *argv, wasm_val_t *out_results) { uint32 i, p; @@ -1228,7 +1255,10 @@ parse_uint32_array_to_results(WASMType *type, break; case VALUE_TYPE_I64: { - union { uint64 val; uint32 parts[2]; } u; + union { + uint64 val; + uint32 parts[2]; + } u; u.parts[0] = argv[p++]; u.parts[1] = argv[p++]; out_results[i].kind = WASM_I64; @@ -1237,7 +1267,10 @@ parse_uint32_array_to_results(WASMType *type, } case VALUE_TYPE_F32: { - union { float32 val; uint32 part; } u; + union { + float32 val; + uint32 part; + } u; u.part = argv[p++]; out_results[i].kind = WASM_F32; out_results[i].of.f32 = u.val; @@ -1245,7 +1278,10 @@ parse_uint32_array_to_results(WASMType *type, } case VALUE_TYPE_F64: { - union { float64 val; uint32 parts[2]; } u; + union { + float64 val; + uint32 parts[2]; + } u; u.parts[0] = argv[p++]; u.parts[1] = argv[p++]; out_results[i].kind = WASM_F64; @@ -1275,7 +1311,8 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env, type = wasm_runtime_get_function_type(function, module_type); if (!type) { - LOG_ERROR("Function type get failed, WAMR Interpreter and AOT must be enabled at least one."); + LOG_ERROR("Function type get failed, WAMR Interpreter and AOT must be " + "enabled at least one."); goto fail1; } @@ -1283,18 +1320,22 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env, cell_num = (argc > type->ret_cell_num) ? argc : type->ret_cell_num; if (num_results != type->result_count) { - LOG_ERROR("The result value number does not match the function declaration."); + LOG_ERROR( + "The result value number does not match the function declaration."); goto fail1; } if (num_args != type->param_count) { - LOG_ERROR("The argument value number does not match the function declaration."); + LOG_ERROR("The argument value number does not match the function " + "declaration."); goto fail1; } total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2); - if (!(argv = runtime_malloc((uint32)total_size, exec_env->module_inst, NULL, 0))) { - wasm_runtime_set_exception(exec_env->module_inst, "allocate memory failed"); + if (!(argv = runtime_malloc((uint32)total_size, exec_env->module_inst, NULL, + 0))) { + wasm_runtime_set_exception(exec_env->module_inst, + "allocate memory failed"); goto fail1; } @@ -1302,7 +1343,8 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env, if (!(ret = wasm_runtime_call_wasm(exec_env, function, argc, argv))) goto fail2; - ret_num = parse_uint32_array_to_results(type, type->ret_cell_num, argv, results); + ret_num = + parse_uint32_array_to_results(type, type->ret_cell_num, argv, results); bh_assert(ret_num == num_results); (void)ret_num; @@ -1338,8 +1380,10 @@ wasm_runtime_call_wasm_v(WASMExecEnv *exec_env, "function declaration."); goto fail1; } - if (!(args = runtime_malloc(sizeof(wasm_val_t) * num_args, NULL, NULL, 0))) { - wasm_runtime_set_exception(exec_env->module_inst, "allocate memory failed"); + if (!(args = + runtime_malloc(sizeof(wasm_val_t) * num_args, NULL, NULL, 0))) { + wasm_runtime_set_exception(exec_env->module_inst, + "allocate memory failed"); goto fail1; } @@ -1360,7 +1404,7 @@ wasm_runtime_call_wasm_v(WASMExecEnv *exec_env, break; case VALUE_TYPE_F64: args[i].kind = WASM_F64; - args[i].of.f64 = va_arg(vargs, float64);; + args[i].of.f64 = va_arg(vargs, float64); break; default: bh_assert(0); @@ -1377,23 +1421,23 @@ wasm_runtime_call_wasm_v(WASMExecEnv *exec_env, } bool -wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst, - WASMFunctionInstanceCommon *function, - uint32 argc, uint32 argv[]) +wasm_runtime_create_exec_env_and_call_wasm( + WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function, + uint32 argc, uint32 argv[]) { bool ret = false; #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) ret = wasm_create_exec_env_and_call_function( - (WASMModuleInstance *)module_inst, (WASMFunctionInstance *)function, - argc, argv); + (WASMModuleInstance *)module_inst, (WASMFunctionInstance *)function, + argc, argv); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) ret = aot_create_exec_env_and_call_function( - (AOTModuleInstance *)module_inst, (AOTFunctionInstance *)function, - argc, argv); + (AOTModuleInstance *)module_inst, (AOTFunctionInstance *)function, + argc, argv); #endif return ret; } @@ -1403,7 +1447,8 @@ wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return wasm_create_exec_env_singleton((WASMModuleInstance *)module_inst); + return wasm_create_exec_env_singleton( + (WASMModuleInstance *)module_inst); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) @@ -1421,8 +1466,8 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst) #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return (WASMExecEnv *) - ((AOTModuleInstance *)module_inst)->exec_env_singleton.ptr; + return (WASMExecEnv *)((AOTModuleInstance *)module_inst) + ->exec_env_singleton.ptr; #endif return NULL; } @@ -1433,29 +1478,29 @@ wasm_runtime_set_exception(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - wasm_set_exception((WASMModuleInstance*)module_inst, exception); + wasm_set_exception((WASMModuleInstance *)module_inst, exception); return; } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - aot_set_exception((AOTModuleInstance*)module_inst, exception); + aot_set_exception((AOTModuleInstance *)module_inst, exception); return; } #endif } -const char* +const char * wasm_runtime_get_exception(WASMModuleInstanceCommon *module_inst) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - return wasm_get_exception((WASMModuleInstance*)module_inst); + return wasm_get_exception((WASMModuleInstance *)module_inst); } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - return aot_get_exception((AOTModuleInstance*)module_inst); + return aot_get_exception((AOTModuleInstance *)module_inst); } #endif return NULL; @@ -1473,13 +1518,13 @@ wasm_runtime_set_custom_data_internal(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - ((WASMModuleInstance*)module_inst)->custom_data = custom_data; + ((WASMModuleInstance *)module_inst)->custom_data = custom_data; return; } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - ((AOTModuleInstance*)module_inst)->custom_data.ptr = custom_data; + ((AOTModuleInstance *)module_inst)->custom_data.ptr = custom_data; return; } #endif @@ -1496,16 +1541,16 @@ wasm_runtime_set_custom_data(WASMModuleInstanceCommon *module_inst, #endif } -void* +void * wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return ((WASMModuleInstance*)module_inst)->custom_data; + return ((WASMModuleInstance *)module_inst)->custom_data; #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return ((AOTModuleInstance*)module_inst)->custom_data.ptr; + return ((AOTModuleInstance *)module_inst)->custom_data.ptr; #endif return NULL; } @@ -1516,12 +1561,12 @@ wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return wasm_module_malloc((WASMModuleInstance*)module_inst, size, + return wasm_module_malloc((WASMModuleInstance *)module_inst, size, p_native_addr); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return aot_module_malloc((AOTModuleInstance*)module_inst, size, + return aot_module_malloc((AOTModuleInstance *)module_inst, size, p_native_addr); #endif return 0; @@ -1533,13 +1578,13 @@ wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint32 ptr, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return wasm_module_realloc((WASMModuleInstance*)module_inst, ptr, - size, p_native_addr); + return wasm_module_realloc((WASMModuleInstance *)module_inst, ptr, size, + p_native_addr); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return aot_module_realloc((AOTModuleInstance*)module_inst, ptr, - size, p_native_addr); + return aot_module_realloc((AOTModuleInstance *)module_inst, ptr, size, + p_native_addr); #endif return 0; } @@ -1549,13 +1594,13 @@ wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, uint32 ptr) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - wasm_module_free((WASMModuleInstance*)module_inst, ptr); + wasm_module_free((WASMModuleInstance *)module_inst, ptr); return; } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - aot_module_free((AOTModuleInstance*)module_inst, ptr); + aot_module_free((AOTModuleInstance *)module_inst, ptr); return; } #endif @@ -1567,12 +1612,13 @@ wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - return wasm_module_dup_data((WASMModuleInstance*)module_inst, src, size); + return wasm_module_dup_data((WASMModuleInstance *)module_inst, src, + size); } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - return aot_module_dup_data((AOTModuleInstance*)module_inst, src, size); + return aot_module_dup_data((AOTModuleInstance *)module_inst, src, size); } #endif return 0; @@ -1584,12 +1630,12 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return wasm_validate_app_addr((WASMModuleInstance*)module_inst, + return wasm_validate_app_addr((WASMModuleInstance *)module_inst, app_offset, size); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return aot_validate_app_addr((AOTModuleInstance*)module_inst, + return aot_validate_app_addr((AOTModuleInstance *)module_inst, app_offset, size); #endif return false; @@ -1602,8 +1648,8 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst, uint32 app_end_offset; char *str, *str_end; - if (!wasm_runtime_get_app_addr_range(module_inst, app_str_offset, - NULL, &app_end_offset)) + if (!wasm_runtime_get_app_addr_range(module_inst, app_str_offset, NULL, + &app_end_offset)) goto fail; str = wasm_runtime_addr_app_to_native(module_inst, app_str_offset); @@ -1625,12 +1671,12 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return wasm_validate_native_addr((WASMModuleInstance*)module_inst, + return wasm_validate_native_addr((WASMModuleInstance *)module_inst, native_ptr, size); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return aot_validate_native_addr((AOTModuleInstance*)module_inst, + return aot_validate_native_addr((AOTModuleInstance *)module_inst, native_ptr, size); #endif return false; @@ -1642,12 +1688,12 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return wasm_addr_app_to_native((WASMModuleInstance*)module_inst, + return wasm_addr_app_to_native((WASMModuleInstance *)module_inst, app_offset); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return aot_addr_app_to_native((AOTModuleInstance*)module_inst, + return aot_addr_app_to_native((AOTModuleInstance *)module_inst, app_offset); #endif return NULL; @@ -1659,12 +1705,12 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return wasm_addr_native_to_app((WASMModuleInstance*)module_inst, + return wasm_addr_native_to_app((WASMModuleInstance *)module_inst, native_ptr); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return aot_addr_native_to_app((AOTModuleInstance*)module_inst, + return aot_addr_native_to_app((AOTModuleInstance *)module_inst, native_ptr); #endif return 0; @@ -1672,19 +1718,18 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst, bool wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst, - uint32 app_offset, - uint32 *p_app_start_offset, + uint32 app_offset, uint32 *p_app_start_offset, uint32 *p_app_end_offset) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return wasm_get_app_addr_range((WASMModuleInstance*)module_inst, - app_offset, p_app_start_offset, - p_app_end_offset); + return wasm_get_app_addr_range((WASMModuleInstance *)module_inst, + app_offset, p_app_start_offset, + p_app_end_offset); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return aot_get_app_addr_range((AOTModuleInstance*)module_inst, + return aot_get_app_addr_range((AOTModuleInstance *)module_inst, app_offset, p_app_start_offset, p_app_end_offset); #endif @@ -1699,13 +1744,13 @@ wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return wasm_get_native_addr_range((WASMModuleInstance*)module_inst, + return wasm_get_native_addr_range((WASMModuleInstance *)module_inst, native_ptr, p_native_start_addr, p_native_end_addr); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return aot_get_native_addr_range((AOTModuleInstance*)module_inst, + return aot_get_native_addr_range((AOTModuleInstance *)module_inst, native_ptr, p_native_start_addr, p_native_end_addr); #endif @@ -1717,11 +1762,11 @@ wasm_runtime_get_temp_ret(WASMModuleInstanceCommon *module_inst) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return ((WASMModuleInstance*)module_inst)->temp_ret; + return ((WASMModuleInstance *)module_inst)->temp_ret; #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return ((AOTModuleInstance*)module_inst)->temp_ret; + return ((AOTModuleInstance *)module_inst)->temp_ret; #endif return 0; } @@ -1732,14 +1777,14 @@ wasm_runtime_set_temp_ret(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - ((WASMModuleInstance*)module_inst)->temp_ret = temp_ret; + ((WASMModuleInstance *)module_inst)->temp_ret = temp_ret; return; } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - ((AOTModuleInstance*)module_inst)->temp_ret = temp_ret; - return; + ((AOTModuleInstance *)module_inst)->temp_ret = temp_ret; + return; } #endif } @@ -1749,11 +1794,11 @@ wasm_runtime_get_llvm_stack(WASMModuleInstanceCommon *module_inst) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return ((WASMModuleInstance*)module_inst)->llvm_stack; + return ((WASMModuleInstance *)module_inst)->llvm_stack; #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return ((AOTModuleInstance*)module_inst)->llvm_stack; + return ((AOTModuleInstance *)module_inst)->llvm_stack; #endif return 0; } @@ -1764,14 +1809,14 @@ wasm_runtime_set_llvm_stack(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - ((WASMModuleInstance*)module_inst)->llvm_stack = llvm_stack; + ((WASMModuleInstance *)module_inst)->llvm_stack = llvm_stack; return; } #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - ((AOTModuleInstance*)module_inst)->llvm_stack = llvm_stack; - return; + ((AOTModuleInstance *)module_inst)->llvm_stack = llvm_stack; + return; } #endif } @@ -1782,13 +1827,12 @@ wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, { #if WASM_ENABLE_INTERP != 0 if (module->module_type == Wasm_Module_Bytecode) - return wasm_enlarge_memory((WASMModuleInstance*)module, + return wasm_enlarge_memory((WASMModuleInstance *)module, inc_page_count); #endif #if WASM_ENABLE_AOT != 0 if (module->module_type == Wasm_Module_AoT) - return aot_enlarge_memory((AOTModuleInstance*)module, - inc_page_count); + return aot_enlarge_memory((AOTModuleInstance *)module, inc_page_count); #endif return false; } @@ -1796,22 +1840,21 @@ wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, #if WASM_ENABLE_LIBC_WASI != 0 void -wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module, - const char *dir_list[], uint32 dir_count, - const char *map_dir_list[], uint32 map_dir_count, - const char *env_list[], uint32 env_count, - char *argv[], int argc, - int stdinfd, int stdoutfd, int stderrfd) +wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module, const char *dir_list[], + uint32 dir_count, const char *map_dir_list[], + uint32 map_dir_count, const char *env_list[], + uint32 env_count, char *argv[], int argc, + int stdinfd, int stdoutfd, int stderrfd) { WASIArguments *wasi_args = NULL; #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 if (module->module_type == Wasm_Module_Bytecode) - wasi_args = &((WASMModule*)module)->wasi_args; + wasi_args = &((WASMModule *)module)->wasi_args; #endif #if WASM_ENABLE_AOT != 0 if (module->module_type == Wasm_Module_AoT) - wasi_args = &((AOTModule*)module)->wasi_args; + wasi_args = &((AOTModule *)module)->wasi_args; #endif if (wasi_args) { @@ -1830,18 +1873,14 @@ wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module, } void -wasm_runtime_set_wasi_args(WASMModuleCommon *module, - const char *dir_list[], uint32 dir_count, - const char *map_dir_list[], uint32 map_dir_count, - const char *env_list[], uint32 env_count, - char *argv[], int argc) +wasm_runtime_set_wasi_args(WASMModuleCommon *module, const char *dir_list[], + uint32 dir_count, const char *map_dir_list[], + uint32 map_dir_count, const char *env_list[], + uint32 env_count, char *argv[], int argc) { - wasm_runtime_set_wasi_args_ex(module, - dir_list, dir_count, - map_dir_list, map_dir_count, - env_list, env_count, - argv, argc, - -1, -1, -1); + wasm_runtime_set_wasi_args_ex(module, dir_list, dir_count, map_dir_list, + map_dir_count, env_list, env_count, argv, + argc, -1, -1, -1); } #if WASM_ENABLE_UVWASI == 0 @@ -1849,9 +1888,8 @@ bool wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, const char *dir_list[], uint32 dir_count, const char *map_dir_list[], uint32 map_dir_count, - const char *env[], uint32 env_count, - char *argv[], uint32 argc, - int stdinfd, int stdoutfd, int stderrfd, + const char *env[], uint32 env_count, char *argv[], + uint32 argc, int stdinfd, int stdoutfd, int stderrfd, char *error_buf, uint32 error_buf_size) { WASIContext *wasi_ctx; @@ -1871,8 +1909,8 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, char *path, resolved_path[PATH_MAX]; uint32 i; - if (!(wasi_ctx = runtime_malloc(sizeof(WASIContext), NULL, - error_buf, error_buf_size))) { + if (!(wasi_ctx = runtime_malloc(sizeof(WASIContext), NULL, error_buf, + error_buf_size))) { return false; } @@ -1880,13 +1918,14 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode - && !((WASMModuleInstance*)module_inst)->default_memory) + && !((WASMModuleInstance *)module_inst)->default_memory) return true; #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT - && !((AOTModuleInstance*)module_inst)-> - global_table_data.memory_instances[0].memory_data.ptr) + && !((AOTModuleInstance *)module_inst) + ->global_table_data.memory_instances[0] + .memory_data.ptr) return true; #endif @@ -1896,11 +1935,11 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, total_size = sizeof(char *) * (uint64)argc; if (total_size >= UINT32_MAX - || (total_size > 0 && - !(argv_list = wasm_runtime_malloc((uint32)total_size))) + || (total_size > 0 + && !(argv_list = wasm_runtime_malloc((uint32)total_size))) || argv_buf_size >= UINT32_MAX - || (argv_buf_size > 0 && - !(argv_buf = wasm_runtime_malloc((uint32)argv_buf_size)))) { + || (argv_buf_size > 0 + && !(argv_buf = wasm_runtime_malloc((uint32)argv_buf_size)))) { set_error_buf(error_buf, error_buf_size, "Init wasi environment failed: allocate memory failed"); goto fail; @@ -1938,7 +1977,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, if (!(curfds = wasm_runtime_malloc(sizeof(struct fd_table))) || !(prestats = wasm_runtime_malloc(sizeof(struct fd_prestats))) || !(argv_environ = - wasm_runtime_malloc(sizeof(struct argv_environ_values)))) { + wasm_runtime_malloc(sizeof(struct argv_environ_values)))) { set_error_buf(error_buf, error_buf_size, "Init wasi environment failed: allocate memory failed"); goto fail; @@ -1960,11 +1999,8 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, } fd_prestats_inited = true; - if (!argv_environ_init(argv_environ, - argv_buf, argv_buf_size, - argv_list, argc, - env_buf, env_buf_size, - env_list, env_count)) { + if (!argv_environ_init(argv_environ, argv_buf, argv_buf_size, argv_list, + argc, env_buf, env_buf_size, env_list, env_count)) { set_error_buf(error_buf, error_buf_size, "Init wasi environment failed: " "init argument environment failed"); @@ -1975,7 +2011,8 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, /* Prepopulate curfds with stdin, stdout, and stderr file descriptors. */ if (!fd_table_insert_existing(curfds, 0, (stdinfd != -1) ? stdinfd : 0) || !fd_table_insert_existing(curfds, 1, (stdoutfd != -1) ? stdoutfd : 1) - || !fd_table_insert_existing(curfds, 2, (stderrfd != -1) ? stderrfd : 2)) { + || !fd_table_insert_existing(curfds, 2, + (stderrfd != -1) ? stderrfd : 2)) { set_error_buf(error_buf, error_buf_size, "Init wasi environment failed: init fd table failed"); goto fail; @@ -2038,7 +2075,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, wasm_runtime_free(env_list); return false; } -#else /* else of WASM_ENABLE_UVWASI == 0 */ +#else /* else of WASM_ENABLE_UVWASI == 0 */ static void * wasm_uvwasi_malloc(size_t size, void *mem_user_data) { @@ -2055,8 +2092,7 @@ wasm_uvwasi_free(void *ptr, void *mem_user_data) } static void * -wasm_uvwasi_calloc(size_t nmemb, size_t size, - void *mem_user_data) +wasm_uvwasi_calloc(size_t nmemb, size_t size, void *mem_user_data) { uint64 total_size = (uint64)nmemb * size; return runtime_malloc(total_size, NULL, NULL, 0); @@ -2064,8 +2100,7 @@ wasm_uvwasi_calloc(size_t nmemb, size_t size, } static void * -wasm_uvwasi_realloc(void *ptr, size_t size, - void *mem_user_data) +wasm_uvwasi_realloc(void *ptr, size_t size, void *mem_user_data) { if (size >= UINT32_MAX) { return NULL; @@ -2073,6 +2108,7 @@ wasm_uvwasi_realloc(void *ptr, size_t size, return wasm_runtime_realloc(ptr, (uint32)size); } +/* clang-format off */ static uvwasi_mem_t uvwasi_allocator = { .mem_user_data = 0, .malloc = wasm_uvwasi_malloc, @@ -2080,14 +2116,14 @@ static uvwasi_mem_t uvwasi_allocator = { .calloc = wasm_uvwasi_calloc, .realloc = wasm_uvwasi_realloc }; +/* clang-format on */ bool wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, const char *dir_list[], uint32 dir_count, const char *map_dir_list[], uint32 map_dir_count, - const char *env[], uint32 env_count, - char *argv[], uint32 argc, - int stdinfd, int stdoutfd, int stderrfd, + const char *env[], uint32 env_count, char *argv[], + uint32 argc, int stdinfd, int stdoutfd, int stderrfd, char *error_buf, uint32 error_buf_size) { uvwasi_t *uvwasi = NULL; @@ -2097,8 +2133,8 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, uint32 i; bool ret = false; - uvwasi = runtime_malloc(sizeof(uvwasi_t), module_inst, - error_buf, error_buf_size); + uvwasi = runtime_malloc(sizeof(uvwasi_t), module_inst, error_buf, + error_buf_size); if (!uvwasi) return false; @@ -2108,30 +2144,31 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, init_options.argc = argc; init_options.argv = (const char **)argv; init_options.in = (stdinfd != -1) ? (uvwasi_fd_t)stdinfd : init_options.in; - init_options.out = (stdoutfd != -1) ? (uvwasi_fd_t)stdoutfd : init_options.out; - init_options.err = (stderrfd != -1) ? (uvwasi_fd_t)stderrfd : init_options.err; + init_options.out = + (stdoutfd != -1) ? (uvwasi_fd_t)stdoutfd : init_options.out; + init_options.err = + (stderrfd != -1) ? (uvwasi_fd_t)stderrfd : init_options.err; if (dir_count > 0) { init_options.preopenc = dir_count; total_size = sizeof(uvwasi_preopen_t) * (uint64)init_options.preopenc; - init_options.preopens = - (uvwasi_preopen_t *)runtime_malloc(total_size, module_inst, - error_buf, error_buf_size); + init_options.preopens = (uvwasi_preopen_t *)runtime_malloc( + total_size, module_inst, error_buf, error_buf_size); if (init_options.preopens == NULL) goto fail; for (i = 0; i < init_options.preopenc; i++) { init_options.preopens[i].real_path = dir_list[i]; init_options.preopens[i].mapped_path = - (i < map_dir_count) ? map_dir_list[i] : dir_list[i]; + (i < map_dir_count) ? map_dir_list[i] : dir_list[i]; } } if (env_count > 0) { total_size = sizeof(char *) * (uint64)(env_count + 1); - envp = runtime_malloc(total_size, module_inst, - error_buf, error_buf_size); + envp = + runtime_malloc(total_size, module_inst, error_buf, error_buf_size); if (envp == NULL) goto fail; @@ -2153,7 +2190,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, fail: if (envp) - wasm_runtime_free((void*)envp); + wasm_runtime_free((void *)envp); if (init_options.preopens) wasm_runtime_free(init_options.preopens); @@ -2170,13 +2207,13 @@ wasm_runtime_is_wasi_mode(WASMModuleInstanceCommon *module_inst) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode - && ((WASMModuleInstance*)module_inst)->module->is_wasi_module) + && ((WASMModuleInstance *)module_inst)->module->is_wasi_module) return true; #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT - && ((AOTModule*)((AOTModuleInstance*)module_inst)->aot_module.ptr) - ->is_wasi_module) + && ((AOTModule *)((AOTModuleInstance *)module_inst)->aot_module.ptr) + ->is_wasi_module) return true; #endif return false; @@ -2189,7 +2226,7 @@ wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst) #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { - WASMModuleInstance *wasm_inst = (WASMModuleInstance*)module_inst; + WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst; WASMFunctionInstance *func; for (i = 0; i < wasm_inst->export_func_count; i++) { if (!strcmp(wasm_inst->export_functions[i].name, "_start")) { @@ -2200,7 +2237,7 @@ wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst) "invalid function type.\n"); return NULL; } - return (WASMFunctionInstanceCommon*)func; + return (WASMFunctionInstanceCommon *)func; } } return NULL; @@ -2209,9 +2246,9 @@ wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst) #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) { - AOTModuleInstance *aot_inst = (AOTModuleInstance*)module_inst; - AOTFunctionInstance *export_funcs = (AOTFunctionInstance *) - aot_inst->export_funcs.ptr; + AOTModuleInstance *aot_inst = (AOTModuleInstance *)module_inst; + AOTFunctionInstance *export_funcs = + (AOTFunctionInstance *)aot_inst->export_funcs.ptr; for (i = 0; i < aot_inst->export_func_count; i++) { if (!strcmp(export_funcs[i].func_name, "_start")) { AOTFuncType *func_type = export_funcs[i].u.func.func_type; @@ -2221,7 +2258,7 @@ wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst) "invalid function type.\n"); return NULL; } - return (WASMFunctionInstanceCommon*)&export_funcs[i]; + return (WASMFunctionInstanceCommon *)&export_funcs[i]; } } return NULL; @@ -2279,11 +2316,11 @@ wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst) { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return ((WASMModuleInstance*)module_inst)->wasi_ctx; + return ((WASMModuleInstance *)module_inst)->wasi_ctx; #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return ((AOTModuleInstance*)module_inst)->wasi_ctx.ptr; + return ((AOTModuleInstance *)module_inst)->wasi_ctx.ptr; #endif return NULL; } @@ -2294,29 +2331,28 @@ wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst, { #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - ((WASMModuleInstance*)module_inst)->wasi_ctx = wasi_ctx; + ((WASMModuleInstance *)module_inst)->wasi_ctx = wasi_ctx; #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - ((AOTModuleInstance*)module_inst)->wasi_ctx.ptr = wasi_ctx; + ((AOTModuleInstance *)module_inst)->wasi_ctx.ptr = wasi_ctx; #endif } #endif /* end of WASM_ENABLE_LIBC_WASI */ -WASMModuleCommon* +WASMModuleCommon * wasm_exec_env_get_module(WASMExecEnv *exec_env) { WASMModuleInstanceCommon *module_inst = wasm_runtime_get_module_inst(exec_env); #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - return (WASMModuleCommon*) - ((WASMModuleInstance*)module_inst)->module; + return (WASMModuleCommon *)((WASMModuleInstance *)module_inst)->module; #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - return (WASMModuleCommon*) - ((AOTModuleInstance*)module_inst)->aot_module.ptr; + return (WASMModuleCommon *)((AOTModuleInstance *)module_inst) + ->aot_module.ptr; #endif return NULL; } @@ -2333,8 +2369,8 @@ wasm_runtime_register_natives(const char *module_name, NativeSymbol *native_symbols, uint32 n_native_symbols) { - return wasm_native_register_natives(module_name, - native_symbols, n_native_symbols); + return wasm_native_register_natives(module_name, native_symbols, + n_native_symbols); } bool @@ -2342,18 +2378,18 @@ wasm_runtime_register_natives_raw(const char *module_name, NativeSymbol *native_symbols, uint32 n_native_symbols) { - return wasm_native_register_natives_raw(module_name, - native_symbols, n_native_symbols); + return wasm_native_register_natives_raw(module_name, native_symbols, + n_native_symbols); } bool wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, - void *attachment, - uint32 *argv, uint32 argc, uint32 *argv_ret) + void *attachment, uint32 *argv, uint32 argc, + uint32 *argv_ret) { WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); - typedef void (*NativeRawFuncPtr)(WASMExecEnv*, uint64*); + typedef void (*NativeRawFuncPtr)(WASMExecEnv *, uint64 *); NativeRawFuncPtr invokeNativeRaw = (NativeRawFuncPtr)func_ptr; uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size; uint32 *argv_src = argv, i, argc1, ptr_len; @@ -2363,8 +2399,8 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, argc1 = func_type->param_count; if (argc1 > sizeof(argv_buf) / sizeof(uint64)) { size = sizeof(uint64) * (uint64)argc1; - if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, - NULL, 0))) { + if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, NULL, + 0))) { return false; } } @@ -2376,7 +2412,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, switch (func_type->types[i]) { case VALUE_TYPE_I32: { - *(uint32*)argv_dst = arg_i32 = *argv_src++; + *(uint32 *)argv_dst = arg_i32 = *argv_src++; if (signature) { if (signature[i + 1] == '*') { /* param is a pointer */ @@ -2387,35 +2423,40 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, /* pointer without length followed */ ptr_len = 1; - if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len)) + if (!wasm_runtime_validate_app_addr(module, arg_i32, + ptr_len)) goto fail; - *(uintptr_t*)argv_dst = (uintptr_t) - wasm_runtime_addr_app_to_native(module, arg_i32); + *(uintptr_t *)argv_dst = + (uintptr_t)wasm_runtime_addr_app_to_native(module, + arg_i32); } else if (signature[i + 1] == '$') { /* param is a string */ - if (!wasm_runtime_validate_app_str_addr(module, arg_i32)) + if (!wasm_runtime_validate_app_str_addr(module, + arg_i32)) goto fail; - *(uintptr_t*)argv_dst = (uintptr_t) - wasm_runtime_addr_app_to_native(module, arg_i32); + *(uintptr_t *)argv_dst = + (uintptr_t)wasm_runtime_addr_app_to_native(module, + arg_i32); } } break; } case VALUE_TYPE_I64: case VALUE_TYPE_F64: - bh_memcpy_s(argv_dst, sizeof(uint64), argv_src, sizeof(uint32) * 2); + bh_memcpy_s(argv_dst, sizeof(uint64), argv_src, + sizeof(uint32) * 2); argv_src += 2; break; case VALUE_TYPE_F32: - *(float32*)argv_dst = *(float32*)argv_src++; + *(float32 *)argv_dst = *(float32 *)argv_src++; break; #if WASM_ENABLE_REF_TYPES != 0 case VALUE_TYPE_FUNCREF: case VALUE_TYPE_EXTERNREF: - *(uint32*)argv_dst = *argv_src++; + *(uint32 *)argv_dst = *argv_src++; break; #endif default: @@ -2435,14 +2476,15 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, case VALUE_TYPE_FUNCREF: case VALUE_TYPE_EXTERNREF: #endif - argv_ret[0] = *(uint32*)argv1; + argv_ret[0] = *(uint32 *)argv1; break; case VALUE_TYPE_F32: - *(float32*)argv_ret = *(float32*)argv1; + *(float32 *)argv_ret = *(float32 *)argv1; break; case VALUE_TYPE_I64: case VALUE_TYPE_F64: - bh_memcpy_s(argv_ret, sizeof(uint32) * 2, argv1, sizeof(uint64)); + bh_memcpy_s(argv_ret, sizeof(uint32) * 2, argv1, + sizeof(uint64)); break; default: bh_assert(0); @@ -2455,7 +2497,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, fail: if (argv1 != argv_buf) wasm_runtime_free(argv1); - return ret; + return ret; } /** @@ -2463,39 +2505,40 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, */ /* The invoke native implementation on ARM platform with VFP co-processor */ -#if defined(BUILD_TARGET_ARM_VFP) \ - || defined(BUILD_TARGET_THUMB_VFP) \ - || defined(BUILD_TARGET_RISCV32_ILP32D) \ - || defined(BUILD_TARGET_RISCV32_ILP32) +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) \ + || defined(BUILD_TARGET_RISCV32_ILP32D) \ + || defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC) typedef void (*GenericFunctionPointer)(); -int64 invokeNative(GenericFunctionPointer f, uint32 *args, uint32 n_stacks); - -typedef float64 (*Float64FuncPtr)(GenericFunctionPointer, uint32*, uint32); -typedef float32 (*Float32FuncPtr)(GenericFunctionPointer, uint32*, uint32); -typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint32*,uint32); -typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint32*, uint32); -typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint32*, uint32); - -static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)(uintptr_t)invokeNative; -static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)(uintptr_t)invokeNative; +int64 +invokeNative(GenericFunctionPointer f, uint32 *args, uint32 n_stacks); + +typedef float64 (*Float64FuncPtr)(GenericFunctionPointer, uint32 *, uint32); +typedef float32 (*Float32FuncPtr)(GenericFunctionPointer, uint32 *, uint32); +typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint32 *, uint32); +typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint32 *, uint32); +typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint32 *, uint32); + +static Float64FuncPtr invokeNative_Float64 = + (Float64FuncPtr)(uintptr_t)invokeNative; +static Float32FuncPtr invokeNative_Float32 = + (Float32FuncPtr)(uintptr_t)invokeNative; static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)(uintptr_t)invokeNative; static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)(uintptr_t)invokeNative; static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)(uintptr_t)invokeNative; -#if !defined(BUILD_TARGET_RISCV32_ILP32D) \ - && !defined(BUILD_TARGET_RISCV32_ILP32) -#define MAX_REG_INTS 4 +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) +#define MAX_REG_INTS 4 #define MAX_REG_FLOATS 16 #else -#define MAX_REG_INTS 8 +#define MAX_REG_INTS 8 #define MAX_REG_FLOATS 8 #endif bool wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, - void *attachment, - uint32 *argv, uint32 argc, uint32 *argv_ret) + void *attachment, uint32 *argv, uint32 argc, + uint32 *argv_ret) { WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); /* argv buf layout: int args(fix cnt) + float args(fix cnt) + stack args */ @@ -2505,7 +2548,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, uint32 result_count = func_type->result_count; uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0; bool ret = false; -#if !defined(BUILD_TARGET_RISCV32_ILP32) +#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC) uint32 *fps; int n_fps = 0; #else @@ -2530,14 +2573,15 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, break; case VALUE_TYPE_I64: if (n_ints < MAX_REG_INTS - 1) { -#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_RISCV32_ILP32D) +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) /* 64-bit data must be 8 bytes aligned in arm */ if (n_ints & 1) n_ints++; #endif n_ints += 2; } -#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_RISCV32_ILP32D) +#if defined(BUILD_TARGET_RISCV32_ILP32) \ + || defined(BUILD_TARGET_RISCV32_ILP32D) || defined(BUILD_TARGET_ARC) /* part in register, part in stack */ else if (n_ints == MAX_REG_INTS - 1) { n_ints++; @@ -2547,8 +2591,10 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, else { /* 64-bit data in stack must be 8 bytes aligned in arm and riscv32 */ +#if !defined(BUILD_TARGET_ARC) if (n_stacks & 1) n_stacks++; +#endif n_stacks += 2; } break; @@ -2561,27 +2607,30 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, break; case VALUE_TYPE_F64: if (n_fps < MAX_REG_FLOATS - 1) { -#if !defined(BUILD_TARGET_RISCV32_ILP32) +#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC) /* 64-bit data must be 8 bytes aligned in arm */ if (n_fps & 1) n_fps++; #endif n_fps += 2; } -#if defined(BUILD_TARGET_RISCV32_ILP32) +#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC) else if (n_fps == MAX_REG_FLOATS - 1) { n_fps++; n_stacks++; } #endif else { - /* 64-bit data must be 8 bytes aligned in arm */ + /* 64-bit data in stack must be 8 bytes aligned + in arm and riscv32 */ +#if !defined(BUILD_TARGET_ARC) if (n_stacks & 1) n_stacks++; +#endif n_stacks += 2; } break; -#else /* BUILD_TARGET_RISCV32_ILP32D */ +#else /* BUILD_TARGET_RISCV32_ILP32D */ case VALUE_TYPE_F32: case VALUE_TYPE_F64: if (n_fps < MAX_REG_FLOATS) { @@ -2600,7 +2649,8 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, ints += 2; } else { - /* 64-bit data in stack must be 8 bytes aligned in riscv32 */ + /* 64-bit data in stack must be 8 bytes aligned in riscv32 + */ if (n_stacks & 1) n_stacks++; n_stacks += 2; @@ -2620,29 +2670,29 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, n_stacks++; } -#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_RISCV32_ILP32D) +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) argc1 = MAX_REG_INTS + MAX_REG_FLOATS + n_stacks; -#elif defined(BUILD_TARGET_RISCV32_ILP32) +#elif defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC) argc1 = MAX_REG_INTS + n_stacks; -#else +#else /* for BUILD_TARGET_RISCV32_ILP32D */ argc1 = MAX_REG_INTS + MAX_REG_FLOATS * 2 + n_stacks; #endif if (argc1 > sizeof(argv_buf) / sizeof(uint32)) { size = sizeof(uint32) * (uint32)argc1; - if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, - NULL, 0))) { + if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, NULL, + 0))) { return false; } } ints = argv1; -#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_RISCV32_ILP32D) +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) fps = ints + MAX_REG_INTS; stacks = fps + MAX_REG_FLOATS; -#elif defined(BUILD_TARGET_RISCV32_ILP32) +#elif defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC) stacks = ints + MAX_REG_INTS; -#else +#else /* for BUILD_TARGET_RISCV32_ILP32D */ fps = ints + MAX_REG_INTS; stacks = fps + MAX_REG_FLOATS * 2; #endif @@ -2669,19 +2719,21 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, /* pointer without length followed */ ptr_len = 1; - if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len)) + if (!wasm_runtime_validate_app_addr(module, arg_i32, + ptr_len)) goto fail; - arg_i32 = (uintptr_t) - wasm_runtime_addr_app_to_native(module, arg_i32); + arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native( + module, arg_i32); } else if (signature[i + 1] == '$') { /* param is a string */ - if (!wasm_runtime_validate_app_str_addr(module, arg_i32)) + if (!wasm_runtime_validate_app_str_addr(module, + arg_i32)) goto fail; - arg_i32 = (uintptr_t) - wasm_runtime_addr_app_to_native(module, arg_i32); + arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native( + module, arg_i32); } } @@ -2705,16 +2757,16 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, case VALUE_TYPE_I64: { if (n_ints < MAX_REG_INTS - 1) { -#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_RISCV32_ILP32D) +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) /* 64-bit data must be 8 bytes aligned in arm */ if (n_ints & 1) n_ints++; #endif - *(uint64*)&ints[n_ints] = *(uint64*)argv_src; - n_ints += 2; - argv_src += 2; + ints[n_ints++] = *argv_src++; + ints[n_ints++] = *argv_src++; } -#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_RISCV32_ILP32D) +#if defined(BUILD_TARGET_RISCV32_ILP32) \ + || defined(BUILD_TARGET_RISCV32_ILP32D) || defined(BUILD_TARGET_ARC) else if (n_ints == MAX_REG_INTS - 1) { ints[n_ints++] = *argv_src++; stacks[n_stacks++] = *argv_src++; @@ -2723,11 +2775,12 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, else { /* 64-bit data in stack must be 8 bytes aligned in arm and riscv32 */ +#if !defined(BUILD_TARGET_ARC) if (n_stacks & 1) n_stacks++; - *(uint64*)&stacks[n_stacks] = *(uint64*)argv_src; - n_stacks += 2; - argv_src += 2; +#endif + stacks[n_stacks++] = *argv_src++; + stacks[n_stacks++] = *argv_src++; } break; } @@ -2735,52 +2788,53 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, case VALUE_TYPE_F32: { if (n_fps < MAX_REG_FLOATS) - *(float32*)&fps[n_fps++] = *(float32*)argv_src++; + *(float32 *)&fps[n_fps++] = *(float32 *)argv_src++; else - *(float32*)&stacks[n_stacks++] = *(float32*)argv_src++; + *(float32 *)&stacks[n_stacks++] = *(float32 *)argv_src++; break; } case VALUE_TYPE_F64: { if (n_fps < MAX_REG_FLOATS - 1) { -#if !defined(BUILD_TARGET_RISCV32_ILP32) +#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC) /* 64-bit data must be 8 bytes aligned in arm */ if (n_fps & 1) n_fps++; #endif - *(float64*)&fps[n_fps] = *(float64*)argv_src; - n_fps += 2; - argv_src += 2; + fps[n_fps++] = *argv_src++; + fps[n_fps++] = *argv_src++; } -#if defined(BUILD_TARGET_RISCV32_ILP32) +#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC) else if (n_fps == MAX_REG_FLOATS - 1) { fps[n_fps++] = *argv_src++; stacks[n_stacks++] = *argv_src++; } #endif else { - /* 64-bit data must be 8 bytes aligned in arm */ + /* 64-bit data in stack must be 8 bytes aligned + in arm and riscv32 */ +#if !defined(BUILD_TARGET_ARC) if (n_stacks & 1) n_stacks++; - *(float64*)&stacks[n_stacks] = *(float64*)argv_src; - n_stacks += 2; - argv_src += 2; +#endif + stacks[n_stacks++] = *argv_src++; + stacks[n_stacks++] = *argv_src++; } break; } -#else /* BUILD_TARGET_RISCV32_ILP32D */ +#else /* BUILD_TARGET_RISCV32_ILP32D */ case VALUE_TYPE_F32: case VALUE_TYPE_F64: { if (n_fps < MAX_REG_FLOATS) { if (func_type->types[i] == VALUE_TYPE_F32) { - *(float32*)&fps[n_fps * 2] = *(float32*)argv_src++; + *(float32 *)&fps[n_fps * 2] = *(float32 *)argv_src++; /* NaN boxing, the upper bits of a valid NaN-boxed value must be all 1s. */ fps[n_fps * 2 + 1] = 0xFFFFFFFF; } else { - *(float64*)&fps[n_fps * 2] = *(float64*)argv_src; + *(float64 *)&fps[n_fps * 2] = *(float64 *)argv_src; argv_src += 2; } n_fps++; @@ -2788,29 +2842,30 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, else if (func_type->types[i] == VALUE_TYPE_F32 && n_ints < MAX_REG_INTS) { /* use int reg firstly if available */ - *(float32*)&ints[n_ints++] = *(float32*)argv_src++; + *(float32 *)&ints[n_ints++] = *(float32 *)argv_src++; } else if (func_type->types[i] == VALUE_TYPE_F64 && n_ints < MAX_REG_INTS - 1) { /* use int regs firstly if available */ if (n_ints & 1) n_ints++; - *(float64*)&ints[n_ints] = *(float64*)argv_src; + *(float64 *)&ints[n_ints] = *(float64 *)argv_src; n_ints += 2; argv_src += 2; } else { - /* 64-bit data in stack must be 8 bytes aligned in riscv32 */ + /* 64-bit data in stack must be 8 bytes aligned in riscv32 + */ if (n_stacks & 1) n_stacks++; if (func_type->types[i] == VALUE_TYPE_F32) { - *(float32*)&stacks[n_stacks] = *(float32*)argv_src++; + *(float32 *)&stacks[n_stacks] = *(float32 *)argv_src++; /* NaN boxing, the upper bits of a valid NaN-boxed value must be all 1s. */ stacks[n_stacks + 1] = 0xFFFFFFFF; } else { - *(float64*)&stacks[n_stacks] = *(float64*)argv_src; + *(float64 *)&stacks[n_stacks] = *(float64 *)argv_src; argv_src += 2; } n_stacks += 2; @@ -2827,9 +2882,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, /* Save extra result values' address to argv1 */ for (i = 0; i < ext_ret_count; i++) { if (n_ints < MAX_REG_INTS) - ints[n_ints++] = *(uint32*)argv_src++; + ints[n_ints++] = *(uint32 *)argv_src++; else - stacks[n_stacks++] = *(uint32*)argv_src++; + stacks[n_stacks++] = *(uint32 *)argv_src++; } exec_env->attachment = attachment; @@ -2843,16 +2898,20 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, case VALUE_TYPE_FUNCREF: case VALUE_TYPE_EXTERNREF: #endif - argv_ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); + argv_ret[0] = + (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); break; case VALUE_TYPE_I64: - PUT_I64_TO_ADDR(argv_ret, invokeNative_Int64(func_ptr, argv1, n_stacks)); + PUT_I64_TO_ADDR(argv_ret, + invokeNative_Int64(func_ptr, argv1, n_stacks)); break; case VALUE_TYPE_F32: - *(float32*)argv_ret = invokeNative_Float32(func_ptr, argv1, n_stacks); + *(float32 *)argv_ret = + invokeNative_Float32(func_ptr, argv1, n_stacks); break; case VALUE_TYPE_F64: - PUT_F64_TO_ADDR(argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); + PUT_F64_TO_ADDR( + argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); break; default: bh_assert(0); @@ -2868,24 +2927,24 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, wasm_runtime_free(argv1); return ret; } -#endif /* end of defined(BUILD_TARGET_ARM_VFP) - || defined(BUILD_TARGET_THUMB_VFP) \ - || defined(BUILD_TARGET_RISCV32_ILP32D) - || defined(BUILD_TARGET_RISCV32_ILP32) */ +#endif /* end of defined(BUILD_TARGET_ARM_VFP) \ + || defined(BUILD_TARGET_THUMB_VFP) \ + || defined(BUILD_TARGET_RISCV32_ILP32D) \ + || defined(BUILD_TARGET_RISCV32_ILP32) \ + || defined(BUILD_TARGET_ARC) */ -#if defined(BUILD_TARGET_X86_32) \ - || defined(BUILD_TARGET_ARM) \ - || defined(BUILD_TARGET_THUMB) \ - || defined(BUILD_TARGET_MIPS) \ +#if defined(BUILD_TARGET_X86_32) || defined(BUILD_TARGET_ARM) \ + || defined(BUILD_TARGET_THUMB) || defined(BUILD_TARGET_MIPS) \ || defined(BUILD_TARGET_XTENSA) typedef void (*GenericFunctionPointer)(); -int64 invokeNative(GenericFunctionPointer f, uint32 *args, uint32 sz); +int64 +invokeNative(GenericFunctionPointer f, uint32 *args, uint32 sz); -typedef float64 (*Float64FuncPtr)(GenericFunctionPointer f, uint32*, uint32); -typedef float32 (*Float32FuncPtr)(GenericFunctionPointer f, uint32*, uint32); -typedef int64 (*Int64FuncPtr)(GenericFunctionPointer f, uint32*, uint32); -typedef int32 (*Int32FuncPtr)(GenericFunctionPointer f, uint32*, uint32); -typedef void (*VoidFuncPtr)(GenericFunctionPointer f, uint32*, uint32); +typedef float64 (*Float64FuncPtr)(GenericFunctionPointer f, uint32 *, uint32); +typedef float32 (*Float32FuncPtr)(GenericFunctionPointer f, uint32 *, uint32); +typedef int64 (*Int64FuncPtr)(GenericFunctionPointer f, uint32 *, uint32); +typedef int32 (*Int32FuncPtr)(GenericFunctionPointer f, uint32 *, uint32); +typedef void (*VoidFuncPtr)(GenericFunctionPointer f, uint32 *, uint32); static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative; static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative; @@ -2903,8 +2962,8 @@ word_copy(uint32 *dest, uint32 *src, unsigned num) bool wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, - void *attachment, - uint32 *argv, uint32 argc, uint32 *argv_ret) + void *attachment, uint32 *argv, uint32 argc, + uint32 *argv_ret) { WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); uint32 argv_buf[32], *argv1 = argv_buf, argc1, i, j = 0; @@ -2924,14 +2983,14 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, if (argc1 > sizeof(argv_buf) / sizeof(uint32)) { size = sizeof(uint32) * (uint64)argc1; - if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, - NULL, 0))) { + if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, NULL, + 0))) { return false; } } - for (i = 0; i < sizeof(WASMExecEnv*) / sizeof(uint32); i++) - argv1[j++] = ((uint32*)&exec_env)[i]; + for (i = 0; i < sizeof(WASMExecEnv *) / sizeof(uint32); i++) + argv1[j++] = ((uint32 *)&exec_env)[i]; for (i = 0; i < func_type->param_count; i++) { switch (func_type->types[i]) { @@ -2949,19 +3008,21 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, /* pointer without length followed */ ptr_len = 1; - if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len)) + if (!wasm_runtime_validate_app_addr(module, arg_i32, + ptr_len)) goto fail; - arg_i32 = (uintptr_t) - wasm_runtime_addr_app_to_native(module, arg_i32); + arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native( + module, arg_i32); } else if (signature[i + 1] == '$') { /* param is a string */ - if (!wasm_runtime_validate_app_str_addr(module, arg_i32)) + if (!wasm_runtime_validate_app_str_addr(module, + arg_i32)) goto fail; - arg_i32 = (uintptr_t) - wasm_runtime_addr_app_to_native(module, arg_i32); + arg_i32 = (uintptr_t)wasm_runtime_addr_app_to_native( + module, arg_i32); } } @@ -3007,16 +3068,20 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, case VALUE_TYPE_FUNCREF: case VALUE_TYPE_EXTERNREF: #endif - argv_ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, argc1); + argv_ret[0] = + (uint32)invokeNative_Int32(func_ptr, argv1, argc1); break; case VALUE_TYPE_I64: - PUT_I64_TO_ADDR(argv_ret, invokeNative_Int64(func_ptr, argv1, argc1)); + PUT_I64_TO_ADDR(argv_ret, + invokeNative_Int64(func_ptr, argv1, argc1)); break; case VALUE_TYPE_F32: - *(float32*)argv_ret = invokeNative_Float32(func_ptr, argv1, argc1); + *(float32 *)argv_ret = + invokeNative_Float32(func_ptr, argv1, argc1); break; case VALUE_TYPE_F64: - PUT_F64_TO_ADDR(argv_ret, invokeNative_Float64(func_ptr, argv1, argc1)); + PUT_F64_TO_ADDR(argv_ret, + invokeNative_Float64(func_ptr, argv1, argc1)); break; default: bh_assert(0); @@ -3033,17 +3098,15 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, return ret; } -#endif /* end of defined(BUILD_TARGET_X86_32) \ - || defined(BUILD_TARGET_ARM) \ +#endif /* end of defined(BUILD_TARGET_X86_32) \ + || defined(BUILD_TARGET_ARM) \ || defined(BUILD_TARGET_THUMB) \ - || defined(BUILD_TARGET_MIPS) \ + || defined(BUILD_TARGET_MIPS) \ || defined(BUILD_TARGET_XTENSA) */ -#if defined(BUILD_TARGET_X86_64) \ - || defined(BUILD_TARGET_AMD_64) \ - || defined(BUILD_TARGET_AARCH64) \ - || defined(BUILD_TARGET_RISCV64_LP64D) \ - || defined(BUILD_TARGET_RISCV64_LP64) +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ + || defined(BUILD_TARGET_RISCV64_LP64) #if WASM_ENABLE_SIMD != 0 #ifdef v128 @@ -3061,9 +3124,11 @@ typedef union __declspec(intrin_type) __declspec(align(8)) v128 { unsigned __int32 m128i_u32[4]; unsigned __int64 m128i_u64[2]; } v128; -#elif defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) -typedef long long v128 __attribute__ ((__vector_size__ (16), - __may_alias__, __aligned__ (1))); +#elif defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_RISCV64_LP64D) \ + || defined(BUILD_TARGET_RISCV64_LP64) +typedef long long v128 + __attribute__((__vector_size__(16), __may_alias__, __aligned__(1))); #elif defined(BUILD_TARGET_AARCH64) #include typedef uint32x4_t __m128i; @@ -3073,37 +3138,39 @@ typedef uint32x4_t __m128i; #endif /* end of WASM_ENABLE_SIMD != 0 */ typedef void (*GenericFunctionPointer)(); -int64 invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks); - -typedef float64 (*Float64FuncPtr)(GenericFunctionPointer, uint64*, uint64); -typedef float32 (*Float32FuncPtr)(GenericFunctionPointer, uint64*, uint64); -typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint64*, uint64); -typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint64*, uint64); -typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint64*, uint64); - -static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)(uintptr_t)invokeNative; -static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)(uintptr_t)invokeNative; +int64 +invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks); + +typedef float64 (*Float64FuncPtr)(GenericFunctionPointer, uint64 *, uint64); +typedef float32 (*Float32FuncPtr)(GenericFunctionPointer, uint64 *, uint64); +typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint64 *, uint64); +typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint64 *, uint64); +typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint64 *, uint64); + +static Float64FuncPtr invokeNative_Float64 = + (Float64FuncPtr)(uintptr_t)invokeNative; +static Float32FuncPtr invokeNative_Float32 = + (Float32FuncPtr)(uintptr_t)invokeNative; static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)(uintptr_t)invokeNative; static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)(uintptr_t)invokeNative; static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)(uintptr_t)invokeNative; #if WASM_ENABLE_SIMD != 0 -typedef v128 (*V128FuncPtr)(GenericFunctionPointer, uint64*, uint64); +typedef v128 (*V128FuncPtr)(GenericFunctionPointer, uint64 *, uint64); static V128FuncPtr invokeNative_V128 = (V128FuncPtr)(uintptr_t)invokeNative; #endif #if defined(_WIN32) || defined(_WIN32_) -#define MAX_REG_FLOATS 4 -#define MAX_REG_INTS 4 +#define MAX_REG_FLOATS 4 +#define MAX_REG_INTS 4 #else /* else of defined(_WIN32) || defined(_WIN32_) */ -#define MAX_REG_FLOATS 8 -#if defined(BUILD_TARGET_AARCH64) \ - || defined(BUILD_TARGET_RISCV64_LP64D) \ +#define MAX_REG_FLOATS 8 +#if defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ || defined(BUILD_TARGET_RISCV64_LP64) -#define MAX_REG_INTS 8 +#define MAX_REG_INTS 8 #else -#define MAX_REG_INTS 6 -#endif /* end of defined(BUILD_TARGET_AARCH64) \ +#define MAX_REG_INTS 6 +#endif /* end of defined(BUILD_TARGET_AARCH64) \ || defined(BUILD_TARGET_RISCV64_LP64D) \ || defined(BUILD_TARGET_RISCV64_LP64) */ #endif /* end of defined(_WIN32) || defined(_WIN32_) */ @@ -3111,8 +3178,8 @@ static V128FuncPtr invokeNative_V128 = (V128FuncPtr)(uintptr_t)invokeNative; bool wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, - void *attachment, - uint32 *argv, uint32 argc, uint32 *argv_ret) + void *attachment, uint32 *argv, uint32 argc, + uint32 *argv_ret) { WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env); uint64 argv_buf[32], *argv1 = argv_buf, *ints, *stacks, size, arg_i64; @@ -3139,16 +3206,15 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, #endif #if WASM_ENABLE_SIMD == 0 - argc1 = 1 + MAX_REG_FLOATS + (uint32)func_type->param_count - + ext_ret_count; + argc1 = 1 + MAX_REG_FLOATS + (uint32)func_type->param_count + ext_ret_count; #else argc1 = 1 + MAX_REG_FLOATS * 2 + (uint32)func_type->param_count * 2 - + ext_ret_count; + + ext_ret_count; #endif if (argc1 > sizeof(argv_buf) / sizeof(uint64)) { size = sizeof(uint64) * (uint64)argc1; - if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, - NULL, 0))) { + if (!(argv1 = runtime_malloc((uint32)size, exec_env->module_inst, NULL, + 0))) { return false; } } @@ -3161,7 +3227,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, fps = (v128 *)argv1; ints = (uint64 *)(fps + MAX_REG_FLOATS); #endif -#else /* else of BUILD_TARGET_RISCV64_LP64 */ +#else /* else of BUILD_TARGET_RISCV64_LP64 */ ints = argv1; #endif /* end of BUILD_TARGET_RISCV64_LP64 */ stacks = ints + MAX_REG_INTS; @@ -3184,19 +3250,21 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, /* pointer without length followed */ ptr_len = 1; - if (!wasm_runtime_validate_app_addr(module, arg_i32, ptr_len)) + if (!wasm_runtime_validate_app_addr(module, arg_i32, + ptr_len)) goto fail; - arg_i64 = (uintptr_t) - wasm_runtime_addr_app_to_native(module, arg_i32); + arg_i64 = (uintptr_t)wasm_runtime_addr_app_to_native( + module, arg_i32); } else if (signature[i + 1] == '$') { /* param is a string */ - if (!wasm_runtime_validate_app_str_addr(module, arg_i32)) + if (!wasm_runtime_validate_app_str_addr(module, + arg_i32)) goto fail; - arg_i64 = (uintptr_t) - wasm_runtime_addr_app_to_native(module, arg_i32); + arg_i64 = (uintptr_t)wasm_runtime_addr_app_to_native( + module, arg_i32); } } if (n_ints < MAX_REG_INTS) @@ -3207,25 +3275,25 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, } case VALUE_TYPE_I64: if (n_ints < MAX_REG_INTS) - ints[n_ints++] = *(uint64*)argv_src; + ints[n_ints++] = *(uint64 *)argv_src; else - stacks[n_stacks++] = *(uint64*)argv_src; + stacks[n_stacks++] = *(uint64 *)argv_src; argv_src += 2; break; case VALUE_TYPE_F32: if (n_fps < MAX_REG_FLOATS) { - *(float32*)&fps[n_fps++] = *(float32*)argv_src++; + *(float32 *)&fps[n_fps++] = *(float32 *)argv_src++; } else { - *(float32*)&stacks[n_stacks++] = *(float32*)argv_src++; + *(float32 *)&stacks[n_stacks++] = *(float32 *)argv_src++; } break; case VALUE_TYPE_F64: if (n_fps < MAX_REG_FLOATS) { - *(float64*)&fps[n_fps++] = *(float64*)argv_src; + *(float64 *)&fps[n_fps++] = *(float64 *)argv_src; } else { - *(float64*)&stacks[n_stacks++] = *(float64*)argv_src; + *(float64 *)&stacks[n_stacks++] = *(float64 *)argv_src; } argv_src += 2; break; @@ -3241,10 +3309,10 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, #if WASM_ENABLE_SIMD != 0 case VALUE_TYPE_V128: if (n_fps < MAX_REG_FLOATS) { - *(v128*)&fps[n_fps++] = *(v128*)argv_src; + *(v128 *)&fps[n_fps++] = *(v128 *)argv_src; } else { - *(v128*)&stacks[n_stacks++] = *(v128*)argv_src; + *(v128 *)&stacks[n_stacks++] = *(v128 *)argv_src; n_stacks++; } argv_src += 4; @@ -3259,9 +3327,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, /* Save extra result values' address to argv1 */ for (i = 0; i < ext_ret_count; i++) { if (n_ints < MAX_REG_INTS) - ints[n_ints++] = *(uint64*)argv_src; + ints[n_ints++] = *(uint64 *)argv_src; else - stacks[n_stacks++] = *(uint64*)argv_src; + stacks[n_stacks++] = *(uint64 *)argv_src; argv_src += 2; } @@ -3277,20 +3345,25 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, case VALUE_TYPE_FUNCREF: case VALUE_TYPE_EXTERNREF: #endif - argv_ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); + argv_ret[0] = + (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); break; case VALUE_TYPE_I64: - PUT_I64_TO_ADDR(argv_ret, invokeNative_Int64(func_ptr, argv1, n_stacks)); + PUT_I64_TO_ADDR(argv_ret, + invokeNative_Int64(func_ptr, argv1, n_stacks)); break; case VALUE_TYPE_F32: - *(float32*)argv_ret = invokeNative_Float32(func_ptr, argv1, n_stacks); + *(float32 *)argv_ret = + invokeNative_Float32(func_ptr, argv1, n_stacks); break; case VALUE_TYPE_F64: - PUT_F64_TO_ADDR(argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); + PUT_F64_TO_ADDR( + argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); break; #if WASM_ENABLE_SIMD != 0 case VALUE_TYPE_V128: - *(v128*)argv_ret = invokeNative_V128(func_ptr, argv1, n_stacks); + *(v128 *)argv_ret = + invokeNative_V128(func_ptr, argv1, n_stacks); break; #endif default: @@ -3308,15 +3381,14 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, return ret; } -#endif /* end of defined(BUILD_TARGET_X86_64) \ - || defined(BUILD_TARGET_AMD_64) \ - || defined(BUILD_TARGET_AARCH64) \ +#endif /* end of defined(BUILD_TARGET_X86_64) \ + || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_AARCH64) \ || defined(BUILD_TARGET_RISCV64_LP64D) \ || defined(BUILD_TARGET_RISCV64_LP64) */ bool -wasm_runtime_call_indirect(WASMExecEnv *exec_env, - uint32_t element_indices, +wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32_t element_indices, uint32_t argc, uint32_t argv[]) { if (!wasm_runtime_exec_env_check(exec_env)) { @@ -3372,8 +3444,8 @@ wasm_runtime_read_v128(const uint8 *bytes, uint64 *ret1, uint64 *ret2) bh_memcpy_s(&u2, 8, bytes + 8, 8); if (!is_little_endian()) { - exchange_uint64((uint8*)&u1); - exchange_uint64((uint8*)&u2); + exchange_uint64((uint8 *)&u1); + exchange_uint64((uint8 *)&u2); *ret1 = u2; *ret2 = u1; } @@ -3402,7 +3474,7 @@ wasm_runtime_destroy_spawned_exec_env(WASMExecEnv *exec_env) wasm_cluster_destroy_spawned_exec_env(exec_env); } -static void* +static void * wasm_runtime_thread_routine(void *arg) { WASMThreadArg *thread_arg = (WASMThreadArg *)arg; @@ -3495,13 +3567,11 @@ wasm_externref_map_init() if (os_mutex_init(&externref_lock) != 0) return false; - if (!(externref_map = bh_hash_map_create(32, false, - wasm_externref_hash, - wasm_externref_equal, - NULL, + if (!(externref_map = bh_hash_map_create(32, false, wasm_externref_hash, + wasm_externref_equal, NULL, wasm_runtime_free))) { - os_mutex_destroy(&externref_lock); - return false; + os_mutex_destroy(&externref_lock); + return false; } externref_global_id = 1; @@ -3526,8 +3596,8 @@ lookup_extobj_callback(void *key, void *value, void *user_data) { uint32 externref_idx = (uint32)(uintptr_t)key; ExternRefMapNode *node = (ExternRefMapNode *)value; - LookupExtObj_UserData *user_data_lookup = (LookupExtObj_UserData *) - user_data; + LookupExtObj_UserData *user_data_lookup = + (LookupExtObj_UserData *)user_data; if (node->extern_obj == user_data_lookup->node.extern_obj && node->module_inst == user_data_lookup->node.module_inst) { @@ -3537,8 +3607,8 @@ lookup_extobj_callback(void *key, void *value, void *user_data) } bool -wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, - void *extern_obj, uint32 *p_externref_idx) +wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj, + uint32 *p_externref_idx) { LookupExtObj_UserData lookup_user_data; ExternRefMapNode *node; @@ -3552,7 +3622,7 @@ wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, /* Lookup hashmap firstly */ bh_hash_map_traverse(externref_map, lookup_extobj_callback, - (void*)&lookup_user_data); + (void *)&lookup_user_data); if (lookup_user_data.found) { *p_externref_idx = lookup_user_data.externref_idx; os_mutex_unlock(&externref_lock); @@ -3560,8 +3630,7 @@ wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, } /* Not found in hashmap */ - if (externref_global_id == NULL_REF - || externref_global_id == 0) { + if (externref_global_id == NULL_REF || externref_global_id == 0) { goto fail1; } @@ -3575,9 +3644,8 @@ wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, externref_idx = externref_global_id; - if (!bh_hash_map_insert(externref_map, - (void*)(uintptr_t)externref_idx, - (void*)node)) { + if (!bh_hash_map_insert(externref_map, (void *)(uintptr_t)externref_idx, + (void *)node)) { goto fail2; } @@ -3602,8 +3670,7 @@ wasm_externref_ref2obj(uint32 externref_idx, void **p_extern_obj) } os_mutex_lock(&externref_lock); - node = bh_hash_map_find(externref_map, - (void*)(uintptr_t)externref_idx); + node = bh_hash_map_find(externref_map, (void *)(uintptr_t)externref_idx); os_mutex_unlock(&externref_lock); if (!node) @@ -3617,8 +3684,8 @@ static void reclaim_extobj_callback(void *key, void *value, void *user_data) { ExternRefMapNode *node = (ExternRefMapNode *)value; - WASMModuleInstanceCommon *module_inst = (WASMModuleInstanceCommon *) - user_data; + WASMModuleInstanceCommon *module_inst = + (WASMModuleInstanceCommon *)user_data; if (node->module_inst == module_inst) { if (!node->marked && !node->retained) { @@ -3637,8 +3704,8 @@ mark_externref(uint32 externref_idx) ExternRefMapNode *node; if (externref_idx != NULL_REF) { - node = bh_hash_map_find(externref_map, - (void*)(uintptr_t)externref_idx); + node = + bh_hash_map_find(externref_map, (void *)(uintptr_t)externref_idx); if (node) { node->marked = true; } @@ -3657,7 +3724,7 @@ interp_mark_all_externrefs(WASMModuleInstance *module_inst) global = module_inst->globals; for (i = 0; i < module_inst->global_count; i++, global++) { if (global->type == VALUE_TYPE_EXTERNREF) { - externref_idx = *(uint32*)(global_data + global->data_offset); + externref_idx = *(uint32 *)(global_data + global->data_offset); mark_externref(externref_idx); } } @@ -3684,7 +3751,7 @@ aot_mark_all_externrefs(AOTModuleInstance *module_inst) const AOTTable *table = module->tables; const AOTGlobal *global = module->globals; const AOTTableInstance *table_inst = - (AOTTableInstance *)module_inst->tables.ptr; + (AOTTableInstance *)module_inst->tables.ptr; for (i = 0; i < module->global_count; i++, global++) { if (global->type == VALUE_TYPE_EXTERNREF) { @@ -3711,15 +3778,15 @@ wasm_externref_reclaim(WASMModuleInstanceCommon *module_inst) os_mutex_lock(&externref_lock); #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) - interp_mark_all_externrefs((WASMModuleInstance*)module_inst); + interp_mark_all_externrefs((WASMModuleInstance *)module_inst); #endif #if WASM_ENABLE_AOT != 0 if (module_inst->module_type == Wasm_Module_AoT) - aot_mark_all_externrefs((AOTModuleInstance*)module_inst); + aot_mark_all_externrefs((AOTModuleInstance *)module_inst); #endif bh_hash_map_traverse(externref_map, reclaim_extobj_callback, - (void*)module_inst); + (void *)module_inst); os_mutex_unlock(&externref_lock); } @@ -3727,8 +3794,8 @@ static void cleanup_extobj_callback(void *key, void *value, void *user_data) { ExternRefMapNode *node = (ExternRefMapNode *)value; - WASMModuleInstanceCommon *module_inst = (WASMModuleInstanceCommon *) - user_data; + WASMModuleInstanceCommon *module_inst = + (WASMModuleInstanceCommon *)user_data; if (node->module_inst == module_inst) { bh_hash_map_remove(externref_map, key, NULL, NULL); @@ -3741,7 +3808,7 @@ wasm_externref_cleanup(WASMModuleInstanceCommon *module_inst) { os_mutex_lock(&externref_lock); bh_hash_map_traverse(externref_map, cleanup_extobj_callback, - (void*)module_inst); + (void *)module_inst); os_mutex_unlock(&externref_lock); } @@ -3753,8 +3820,8 @@ wasm_externref_retain(uint32 externref_idx) os_mutex_lock(&externref_lock); if (externref_idx != NULL_REF) { - node = bh_hash_map_find(externref_map, - (void*)(uintptr_t)externref_idx); + node = + bh_hash_map_find(externref_map, (void *)(uintptr_t)externref_idx); if (node) { node->retained = true; os_mutex_unlock(&externref_lock); @@ -3771,8 +3838,8 @@ wasm_externref_retain(uint32 externref_idx) void wasm_runtime_dump_call_stack(WASMExecEnv *exec_env) { - WASMModuleInstanceCommon *module_inst - = wasm_exec_env_get_module_inst(exec_env); + WASMModuleInstanceCommon *module_inst = + wasm_exec_env_get_module_inst(exec_env); #if WASM_ENABLE_INTERP != 0 if (module_inst->module_type == Wasm_Module_Bytecode) { wasm_interp_dump_call_stack(exec_env); @@ -3788,21 +3855,19 @@ wasm_runtime_dump_call_stack(WASMExecEnv *exec_env) bool wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm, - const WASMExport *export, - WASMType **out) + const WASMExport *export, WASMType **out) { #if WASM_ENABLE_INTERP != 0 if (module_comm->module_type == Wasm_Module_Bytecode) { WASMModule *module = (WASMModule *)module_comm; if (export->index < module->import_function_count) { - *out = - module->import_functions[export->index].u.function.func_type; + *out = module->import_functions[export->index].u.function.func_type; } else { *out = - module->functions[export->index - module->import_function_count] - ->func_type; + module->functions[export->index - module->import_function_count] + ->func_type; } return true; } @@ -3814,12 +3879,12 @@ wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm, if (export->index < module->import_func_count) { *out = module->func_types[module->import_funcs[export->index] - .func_type_index]; + .func_type_index]; } else { - *out = - module->func_types[module->func_type_indexes - [export->index - module->import_func_count]]; + *out = module->func_types + [module->func_type_indexes[export->index + - module->import_func_count]]; } return true; } @@ -3830,8 +3895,7 @@ wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm, bool wasm_runtime_get_export_global_type(const WASMModuleCommon *module_comm, const WASMExport *export, - uint8 *out_val_type, - bool *out_mutability) + uint8 *out_val_type, bool *out_mutability) { #if WASM_ENABLE_INTERP != 0 if (module_comm->module_type == Wasm_Module_Bytecode) { @@ -3839,13 +3903,13 @@ wasm_runtime_get_export_global_type(const WASMModuleCommon *module_comm, if (export->index < module->import_global_count) { WASMGlobalImport *import_global = - &((module->import_globals + export->index)->u.global); + &((module->import_globals + export->index)->u.global); *out_val_type = import_global->type; *out_mutability = import_global->is_mutable; } else { WASMGlobal *global = - module->globals + (export->index - module->import_global_count); + module->globals + (export->index - module->import_global_count); *out_val_type = global->type; *out_mutability = global->is_mutable; } @@ -3859,13 +3923,13 @@ wasm_runtime_get_export_global_type(const WASMModuleCommon *module_comm, if (export->index < module->import_global_count) { AOTImportGlobal *import_global = - module->import_globals + export->index; + module->import_globals + export->index; *out_val_type = import_global->type; *out_mutability = import_global->is_mutable; } else { AOTGlobal *global = - module->globals + (export->index - module->import_global_count); + module->globals + (export->index - module->import_global_count); *out_val_type = global->type; *out_mutability = global->is_mutable; } @@ -3878,8 +3942,7 @@ wasm_runtime_get_export_global_type(const WASMModuleCommon *module_comm, bool wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm, const WASMExport *export, - uint32 *out_min_page, - uint32 *out_max_page) + uint32 *out_min_page, uint32 *out_max_page) { #if WASM_ENABLE_INTERP != 0 if (module_comm->module_type == Wasm_Module_Bytecode) { @@ -3887,13 +3950,14 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm, if (export->index < module->import_memory_count) { WASMMemoryImport *import_memory = - &((module->import_memories + export->index)->u.memory); + &((module->import_memories + export->index)->u.memory); *out_min_page = import_memory->init_page_count; *out_max_page = import_memory->max_page_count; } else { WASMMemory *memory = - module->memories + (export->index - module->import_memory_count); + module->memories + + (export->index - module->import_memory_count); *out_min_page = memory->init_page_count; *out_max_page = memory->max_page_count; } @@ -3907,13 +3971,13 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm, if (export->index < module->import_memory_count) { AOTImportMemory *import_memory = - module->import_memories + export->index; + module->import_memories + export->index; *out_min_page = import_memory->mem_init_page_count; *out_max_page = import_memory->mem_max_page_count; } else { - AOTMemory *memory = - module->memories + (export->index - module->import_memory_count); + AOTMemory *memory = module->memories + + (export->index - module->import_memory_count); *out_min_page = memory->mem_init_page_count; *out_max_page = memory->mem_max_page_count; } @@ -3926,8 +3990,7 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm, bool wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm, const WASMExport *export, - uint8 *out_elem_type, - uint32 *out_min_size, + uint8 *out_elem_type, uint32 *out_min_size, uint32 *out_max_size) { #if WASM_ENABLE_INTERP != 0 @@ -3936,14 +3999,14 @@ wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm, if (export->index < module->import_table_count) { WASMTableImport *import_table = - &((module->import_tables + export->index)->u.table); + &((module->import_tables + export->index)->u.table); *out_elem_type = import_table->elem_type; *out_min_size = import_table->init_size; *out_max_size = import_table->max_size; } else { WASMTable *table = - module->tables + (export->index - module->import_table_count); + module->tables + (export->index - module->import_table_count); *out_elem_type = table->elem_type; *out_min_size = table->init_size; *out_max_size = table->max_size; @@ -3958,14 +4021,14 @@ wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm, if (export->index < module->import_table_count) { AOTImportTable *import_table = - module->import_tables + export->index; + module->import_tables + export->index; *out_elem_type = VALUE_TYPE_FUNCREF; *out_min_size = import_table->table_init_size; *out_max_size = import_table->table_max_size; } else { AOTTable *table = - module->tables + (export->index - module->import_table_count); + module->tables + (export->index - module->import_table_count); *out_elem_type = table->elem_type; *out_min_size = table->table_init_size; *out_max_size = table->table_max_size; @@ -3973,64 +4036,11 @@ wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm, return true; } #endif - return false; -} - -uint8 * -wasm_runtime_get_memory_data(const WASMModuleInstanceCommon *module_inst_comm, - uint32 memory_inst_idx) -{ -#if WASM_ENABLE_INTERP != 0 - if (module_inst_comm->module_type == Wasm_Module_Bytecode) { - WASMModuleInstance *module_inst = - (WASMModuleInstance *)module_inst_comm; - WASMMemoryInstance *memory_inst = - module_inst->memories[memory_inst_idx]; - return memory_inst->memory_data; - } -#endif - -#if WASM_ENABLE_AOT != 0 - if (module_inst_comm->module_type == Wasm_Module_AoT) { - AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm; - AOTMemoryInstance *memory_inst = - ((AOTMemoryInstance**)module_inst->memories.ptr)[memory_inst_idx]; - return memory_inst->memory_data.ptr; - } -#endif - return NULL; -} - -uint32 -wasm_runtime_get_memory_data_size( - const WASMModuleInstanceCommon *module_inst_comm, - uint32 memory_inst_idx) -{ -#if WASM_ENABLE_INTERP != 0 - if (module_inst_comm->module_type == Wasm_Module_Bytecode) { - WASMModuleInstance *module_inst = - (WASMModuleInstance *)module_inst_comm; - WASMMemoryInstance *memory_inst = - module_inst->memories[memory_inst_idx]; - return memory_inst->cur_page_count * memory_inst->num_bytes_per_page; - } -#endif - -#if WASM_ENABLE_AOT != 0 - if (module_inst_comm->module_type == Wasm_Module_AoT) { - AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm; - AOTMemoryInstance *memory_inst = - ((AOTMemoryInstance**)module_inst->memories.ptr)[memory_inst_idx]; - return memory_inst->cur_page_count * memory_inst->num_bytes_per_page; - } -#endif - return 0; + return false; } static inline bool -argv_to_params(wasm_val_t *out_params, - const uint32 *argv, - WASMType *func_type) +argv_to_params(wasm_val_t *out_params, const uint32 *argv, WASMType *func_type) { wasm_val_t *param = out_params; uint32 i = 0, *u32; @@ -4057,6 +4067,23 @@ argv_to_params(wasm_val_t *out_params, u32[0] = *argv++; u32[1] = *argv++; break; +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_EXTERNREF: + param->kind = WASM_ANYREF; + + if (NULL_REF == *argv) { + param->of.ref = NULL; + } + else { + if (!wasm_externref_ref2obj(*argv, + (void **)¶m->of.ref)) { + return false; + } + } + + argv++; + break; +#endif default: return false; } @@ -4066,9 +4093,8 @@ argv_to_params(wasm_val_t *out_params, } static inline bool -results_to_argv(uint32 *out_argv, - const wasm_val_t *results, - WASMType *func_type) +results_to_argv(WASMModuleInstanceCommon *module_inst, uint32 *out_argv, + const wasm_val_t *results, WASMType *func_type) { const wasm_val_t *result = results; uint32 *argv = out_argv, *u32, i; @@ -4086,6 +4112,15 @@ results_to_argv(uint32 *out_argv, *argv++ = u32[0]; *argv++ = u32[1]; break; +#if WASM_ENABLE_REF_TYPES != 0 + case VALUE_TYPE_EXTERNREF: + if (!wasm_externref_obj2ref(module_inst, result->of.ref, + argv)) { + return false; + } + argv++; + break; +#endif default: return false; } @@ -4097,13 +4132,14 @@ results_to_argv(uint32 *out_argv, bool wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst, void *func_ptr, WASMType *func_type, - uint32 argc, uint32 *argv, - bool with_env, void *wasm_c_api_env) + uint32 argc, uint32 *argv, bool with_env, + void *wasm_c_api_env) { wasm_val_t params_buf[16], results_buf[4]; wasm_val_t *params = params_buf, *results = results_buf; wasm_trap_t *trap = NULL; bool ret = false; + wasm_val_vec_t params_vec, results_vec; if (func_type->param_count > 16 && !(params = wasm_runtime_malloc(sizeof(wasm_val_t) @@ -4117,45 +4153,55 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst, goto fail; } + if (func_type->result_count > 4 + && !(results = wasm_runtime_malloc(sizeof(wasm_val_t) + * func_type->result_count))) { + wasm_runtime_set_exception(module_inst, "allocate memory failed"); + goto fail; + } + + params_vec.data = params; + params_vec.num_elems = func_type->param_count; + params_vec.size = func_type->param_count; + params_vec.size_of_elem = sizeof(wasm_val_t); + + results_vec.data = results; + results_vec.num_elems = 0; + results_vec.size = func_type->result_count; + results_vec.size_of_elem = sizeof(wasm_val_t); + if (!with_env) { wasm_func_callback_t callback = (wasm_func_callback_t)func_ptr; - trap = callback(params, results); + trap = callback(¶ms_vec, &results_vec); } else { wasm_func_callback_with_env_t callback = - (wasm_func_callback_with_env_t)func_ptr; - trap = callback(wasm_c_api_env, params, results); + (wasm_func_callback_with_env_t)func_ptr; + trap = callback(wasm_c_api_env, ¶ms_vec, &results_vec); } if (trap) { if (trap->message->data) { /* since trap->message->data does not end with '\0' */ char trap_message[128] = { 0 }; - bh_memcpy_s( - trap_message, 127, trap->message->data, - (trap->message->size < 127 ? trap->message->size : 127)); + bh_memcpy_s(trap_message, 127, trap->message->data, + (trap->message->size < 127 ? (uint32)trap->message->size + : 127)); wasm_runtime_set_exception(module_inst, trap_message); } else { wasm_runtime_set_exception( - module_inst, "native function throw unknown exception"); + module_inst, "native function throw unknown exception"); } wasm_trap_delete(trap); goto fail; } - if (func_type->result_count > 4 - && !(results = wasm_runtime_malloc(sizeof(wasm_val_t) - * func_type->result_count))) { - wasm_runtime_set_exception(module_inst, "allocate memory failed"); - goto fail; - } - - if (!results_to_argv(argv, results, func_type)) { + if (!results_to_argv(module_inst, argv, results, func_type)) { wasm_runtime_set_exception(module_inst, "unsupported result type"); goto fail; } - + results_vec.num_elems = func_type->result_count; ret = true; fail: diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 83fd82dcc3..b115a8a121 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -27,152 +27,187 @@ extern "C" { #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 -#define PUT_I64_TO_ADDR(addr, value) do { \ - *(int64*)(addr) = (int64)(value); \ - } while (0) -#define PUT_F64_TO_ADDR(addr, value) do { \ - *(float64*)(addr) = (float64)(value); \ - } while (0) - -#define GET_I64_FROM_ADDR(addr) (*(int64*)(addr)) -#define GET_F64_FROM_ADDR(addr) (*(float64*)(addr)) +#define PUT_I64_TO_ADDR(addr, value) \ + do { \ + *(int64 *)(addr) = (int64)(value); \ + } while (0) +#define PUT_F64_TO_ADDR(addr, value) \ + do { \ + *(float64 *)(addr) = (float64)(value); \ + } while (0) + +#define GET_I64_FROM_ADDR(addr) (*(int64 *)(addr)) +#define GET_F64_FROM_ADDR(addr) (*(float64 *)(addr)) /* For STORE opcodes */ #define STORE_I64 PUT_I64_TO_ADDR -#define STORE_U32(addr, value) do { \ - *(uint32*)(addr) = (uint32)(value); \ - } while (0) -#define STORE_U16(addr, value) do { \ - *(uint16*)(addr) = (uint16)(value); \ - } while (0) +#define STORE_U32(addr, value) \ + do { \ + *(uint32 *)(addr) = (uint32)(value); \ + } while (0) +#define STORE_U16(addr, value) \ + do { \ + *(uint16 *)(addr) = (uint16)(value); \ + } while (0) /* For LOAD opcodes */ -#define LOAD_I64(addr) (*(int64*)(addr)) -#define LOAD_F64(addr) (*(float64*)(addr)) -#define LOAD_I32(addr) (*(int32*)(addr)) -#define LOAD_U32(addr) (*(uint32*)(addr)) -#define LOAD_I16(addr) (*(int16*)(addr)) -#define LOAD_U16(addr) (*(uint16*)(addr)) - -#define STORE_PTR(addr, ptr) do { \ - *(void**)addr = (void*)ptr; \ - } while (0) -#define LOAD_PTR(addr) (*(void**)(addr)) - -#else /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */ - -#define PUT_I64_TO_ADDR(addr, value) do { \ - uint32 *addr_u32 = (uint32*)(addr); \ - union { int64 val; uint32 parts[2]; } u; \ - u.val = (int64)(value); \ - addr_u32[0] = u.parts[0]; \ - addr_u32[1] = u.parts[1]; \ - } while (0) -#define PUT_F64_TO_ADDR(addr, value) do { \ - uint32 *addr_u32 = (uint32*)(addr); \ - union { float64 val; uint32 parts[2]; } u; \ - u.val = (value); \ - addr_u32[0] = u.parts[0]; \ - addr_u32[1] = u.parts[1]; \ - } while (0) +#define LOAD_I64(addr) (*(int64 *)(addr)) +#define LOAD_F64(addr) (*(float64 *)(addr)) +#define LOAD_I32(addr) (*(int32 *)(addr)) +#define LOAD_U32(addr) (*(uint32 *)(addr)) +#define LOAD_I16(addr) (*(int16 *)(addr)) +#define LOAD_U16(addr) (*(uint16 *)(addr)) + +#define STORE_PTR(addr, ptr) \ + do { \ + *(void **)addr = (void *)ptr; \ + } while (0) + +#else /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */ + +#define PUT_I64_TO_ADDR(addr, value) \ + do { \ + uint32 *addr_u32 = (uint32 *)(addr); \ + union { \ + int64 val; \ + uint32 parts[2]; \ + } u; \ + u.val = (int64)(value); \ + addr_u32[0] = u.parts[0]; \ + addr_u32[1] = u.parts[1]; \ + } while (0) +#define PUT_F64_TO_ADDR(addr, value) \ + do { \ + uint32 *addr_u32 = (uint32 *)(addr); \ + union { \ + float64 val; \ + uint32 parts[2]; \ + } u; \ + u.val = (value); \ + addr_u32[0] = u.parts[0]; \ + addr_u32[1] = u.parts[1]; \ + } while (0) static inline int64 GET_I64_FROM_ADDR(uint32 *addr) { - union { int64 val; uint32 parts[2]; } u; + union { + int64 val; + uint32 parts[2]; + } u; u.parts[0] = addr[0]; u.parts[1] = addr[1]; return u.val; } static inline float64 -GET_F64_FROM_ADDR (uint32 *addr) +GET_F64_FROM_ADDR(uint32 *addr) { - union { float64 val; uint32 parts[2]; } u; + union { + float64 val; + uint32 parts[2]; + } u; u.parts[0] = addr[0]; u.parts[1] = addr[1]; return u.val; } /* For STORE opcodes */ -#define STORE_I64(addr, value) do { \ - uintptr_t addr1 = (uintptr_t)(addr); \ - union { int64 val; uint32 u32[2]; \ - uint16 u16[4]; uint8 u8[8]; } u; \ - if ((addr1 & (uintptr_t)7) == 0) \ - *(int64*)(addr) = (int64)(value); \ - else { \ - u.val = (int64)(value); \ - if ((addr1 & (uintptr_t)3) == 0) { \ - ((uint32*)(addr))[0] = u.u32[0]; \ - ((uint32*)(addr))[1] = u.u32[1]; \ - } \ - else if ((addr1 & (uintptr_t)1) == 0) { \ - ((uint16*)(addr))[0] = u.u16[0]; \ - ((uint16*)(addr))[1] = u.u16[1]; \ - ((uint16*)(addr))[2] = u.u16[2]; \ - ((uint16*)(addr))[3] = u.u16[3]; \ - } \ - else { \ - int32 t; \ - for (t = 0; t < 8; t++) \ - ((uint8*)(addr))[t] = u.u8[t]; \ - } \ - } \ - } while (0) - -#define STORE_U32(addr, value) do { \ - uintptr_t addr1 = (uintptr_t)(addr); \ - union { uint32 val; \ - uint16 u16[2]; uint8 u8[4]; } u; \ - if ((addr1 & (uintptr_t)3) == 0) \ - *(uint32*)(addr) = (uint32)(value); \ - else { \ - u.val = (uint32)(value); \ - if ((addr1 & (uintptr_t)1) == 0) { \ - ((uint16*)(addr))[0] = u.u16[0]; \ - ((uint16*)(addr))[1] = u.u16[1]; \ - } \ - else { \ - ((uint8*)(addr))[0] = u.u8[0]; \ - ((uint8*)(addr))[1] = u.u8[1]; \ - ((uint8*)(addr))[2] = u.u8[2]; \ - ((uint8*)(addr))[3] = u.u8[3]; \ - } \ - } \ - } while (0) - -#define STORE_U16(addr, value) do { \ - union { uint16 val; uint8 u8[2]; } u; \ - u.val = (uint16)(value); \ - ((uint8*)(addr))[0] = u.u8[0]; \ - ((uint8*)(addr))[1] = u.u8[1]; \ - } while (0) +#define STORE_I64(addr, value) \ + do { \ + uintptr_t addr1 = (uintptr_t)(addr); \ + union { \ + int64 val; \ + uint32 u32[2]; \ + uint16 u16[4]; \ + uint8 u8[8]; \ + } u; \ + if ((addr1 & (uintptr_t)7) == 0) \ + *(int64 *)(addr) = (int64)(value); \ + else { \ + u.val = (int64)(value); \ + if ((addr1 & (uintptr_t)3) == 0) { \ + ((uint32 *)(addr))[0] = u.u32[0]; \ + ((uint32 *)(addr))[1] = u.u32[1]; \ + } \ + else if ((addr1 & (uintptr_t)1) == 0) { \ + ((uint16 *)(addr))[0] = u.u16[0]; \ + ((uint16 *)(addr))[1] = u.u16[1]; \ + ((uint16 *)(addr))[2] = u.u16[2]; \ + ((uint16 *)(addr))[3] = u.u16[3]; \ + } \ + else { \ + int32 t; \ + for (t = 0; t < 8; t++) \ + ((uint8 *)(addr))[t] = u.u8[t]; \ + } \ + } \ + } while (0) + +#define STORE_U32(addr, value) \ + do { \ + uintptr_t addr1 = (uintptr_t)(addr); \ + union { \ + uint32 val; \ + uint16 u16[2]; \ + uint8 u8[4]; \ + } u; \ + if ((addr1 & (uintptr_t)3) == 0) \ + *(uint32 *)(addr) = (uint32)(value); \ + else { \ + u.val = (uint32)(value); \ + if ((addr1 & (uintptr_t)1) == 0) { \ + ((uint16 *)(addr))[0] = u.u16[0]; \ + ((uint16 *)(addr))[1] = u.u16[1]; \ + } \ + else { \ + ((uint8 *)(addr))[0] = u.u8[0]; \ + ((uint8 *)(addr))[1] = u.u8[1]; \ + ((uint8 *)(addr))[2] = u.u8[2]; \ + ((uint8 *)(addr))[3] = u.u8[3]; \ + } \ + } \ + } while (0) + +#define STORE_U16(addr, value) \ + do { \ + union { \ + uint16 val; \ + uint8 u8[2]; \ + } u; \ + u.val = (uint16)(value); \ + ((uint8 *)(addr))[0] = u.u8[0]; \ + ((uint8 *)(addr))[1] = u.u8[1]; \ + } while (0) /* For LOAD opcodes */ static inline int64 LOAD_I64(void *addr) { uintptr_t addr1 = (uintptr_t)addr; - union { int64 val; uint32 u32[2]; - uint16 u16[4]; uint8 u8[8]; } u; + union { + int64 val; + uint32 u32[2]; + uint16 u16[4]; + uint8 u8[8]; + } u; if ((addr1 & (uintptr_t)7) == 0) - return *(int64*)addr; + return *(int64 *)addr; if ((addr1 & (uintptr_t)3) == 0) { - u.u32[0] = ((uint32*)addr)[0]; - u.u32[1] = ((uint32*)addr)[1]; + u.u32[0] = ((uint32 *)addr)[0]; + u.u32[1] = ((uint32 *)addr)[1]; } else if ((addr1 & (uintptr_t)1) == 0) { - u.u16[0] = ((uint16*)addr)[0]; - u.u16[1] = ((uint16*)addr)[1]; - u.u16[2] = ((uint16*)addr)[2]; - u.u16[3] = ((uint16*)addr)[3]; + u.u16[0] = ((uint16 *)addr)[0]; + u.u16[1] = ((uint16 *)addr)[1]; + u.u16[2] = ((uint16 *)addr)[2]; + u.u16[3] = ((uint16 *)addr)[3]; } else { int32 t; for (t = 0; t < 8; t++) - u.u8[t] = ((uint8*)addr)[t]; + u.u8[t] = ((uint8 *)addr)[t]; } return u.val; } @@ -181,25 +216,29 @@ static inline float64 LOAD_F64(void *addr) { uintptr_t addr1 = (uintptr_t)addr; - union { float64 val; uint32 u32[2]; - uint16 u16[4]; uint8 u8[8]; } u; + union { + float64 val; + uint32 u32[2]; + uint16 u16[4]; + uint8 u8[8]; + } u; if ((addr1 & (uintptr_t)7) == 0) - return *(float64*)addr; + return *(float64 *)addr; if ((addr1 & (uintptr_t)3) == 0) { - u.u32[0] = ((uint32*)addr)[0]; - u.u32[1] = ((uint32*)addr)[1]; + u.u32[0] = ((uint32 *)addr)[0]; + u.u32[1] = ((uint32 *)addr)[1]; } else if ((addr1 & (uintptr_t)1) == 0) { - u.u16[0] = ((uint16*)addr)[0]; - u.u16[1] = ((uint16*)addr)[1]; - u.u16[2] = ((uint16*)addr)[2]; - u.u16[3] = ((uint16*)addr)[3]; + u.u16[0] = ((uint16 *)addr)[0]; + u.u16[1] = ((uint16 *)addr)[1]; + u.u16[2] = ((uint16 *)addr)[2]; + u.u16[3] = ((uint16 *)addr)[3]; } else { int32 t; for (t = 0; t < 8; t++) - u.u8[t] = ((uint8*)addr)[t]; + u.u8[t] = ((uint8 *)addr)[t]; } return u.val; } @@ -208,19 +247,23 @@ static inline int32 LOAD_I32(void *addr) { uintptr_t addr1 = (uintptr_t)addr; - union { int32 val; uint16 u16[2]; uint8 u8[4]; } u; + union { + int32 val; + uint16 u16[2]; + uint8 u8[4]; + } u; if ((addr1 & (uintptr_t)3) == 0) - return *(int32*)addr; + return *(int32 *)addr; if ((addr1 & (uintptr_t)1) == 0) { - u.u16[0] = ((uint16*)addr)[0]; - u.u16[1] = ((uint16*)addr)[1]; + u.u16[0] = ((uint16 *)addr)[0]; + u.u16[1] = ((uint16 *)addr)[1]; } else { - u.u8[0] = ((uint8*)addr)[0]; - u.u8[1] = ((uint8*)addr)[1]; - u.u8[2] = ((uint8*)addr)[2]; - u.u8[3] = ((uint8*)addr)[3]; + u.u8[0] = ((uint8 *)addr)[0]; + u.u8[1] = ((uint8 *)addr)[1]; + u.u8[2] = ((uint8 *)addr)[2]; + u.u8[3] = ((uint8 *)addr)[3]; } return u.val; } @@ -229,13 +272,16 @@ static inline int16 LOAD_I16(void *addr) { uintptr_t addr1 = (uintptr_t)addr; - union { int16 val; uint8 u8[2]; } u; + union { + int16 val; + uint8 u8[2]; + } u; if ((addr1 & (uintptr_t)1)) { - u.u8[0] = ((uint8*)addr)[0]; - u.u8[1] = ((uint8*)addr)[1]; + u.u8[0] = ((uint8 *)addr)[0]; + u.u8[1] = ((uint8 *)addr)[1]; return u.val; } - return *(int16*)addr; + return *(int16 *)addr; } #define LOAD_U32(addr) ((uint32)LOAD_I32(addr)) @@ -247,7 +293,7 @@ LOAD_I16(void *addr) #define STORE_PTR(addr, ptr) STORE_I64(addr, (uintptr_t)ptr) #endif -#endif /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */ +#endif /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */ typedef struct WASMModuleCommon { /* Module type, for module loaded from WASM bytecode binary, @@ -336,6 +382,14 @@ typedef struct WASMMemoryInstanceCommon { typedef package_type_t PackageType; typedef wasm_section_t WASMSection, AOTSection; +typedef struct wasm_frame_t { + /* wasm_instance_t */ + void *instance; + uint32 module_offset; + uint32 func_index; + uint32 func_offset; +} WASMCApiFrame; + /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_init(void); @@ -354,8 +408,8 @@ get_package_type(const uint8 *buf, uint32 size); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN WASMModuleCommon * -wasm_runtime_load(const uint8 *buf, uint32 size, - char *error_buf, uint32 error_buf_size); +wasm_runtime_load(const uint8 *buf, uint32 size, char *error_buf, + uint32 error_buf_size); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN WASMModuleCommon * @@ -379,9 +433,9 @@ wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst, /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon * -wasm_runtime_instantiate(WASMModuleCommon *module, - uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size); +wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size, + uint32 heap_size, char *error_buf, + uint32 error_buf_size); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN void @@ -389,7 +443,7 @@ wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon * -wasm_runtime_lookup_function(WASMModuleInstanceCommon * const module_inst, +wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst, const char *name, const char *signature); /* Internal API */ @@ -425,8 +479,8 @@ wasm_runtime_get_user_data(WASMExecEnv *exec_env); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_call_wasm(WASMExecEnv *exec_env, - WASMFunctionInstanceCommon *function, - uint32 argc, uint32 argv[]); + WASMFunctionInstanceCommon *function, uint32 argc, + uint32 argv[]); WASM_RUNTIME_API_EXTERN bool wasm_runtime_call_wasm_a(WASMExecEnv *exec_env, @@ -458,14 +512,13 @@ wasm_runtime_call_wasm_v(WASMExecEnv *exec_env, * the caller can call wasm_runtime_get_exception to get exception info. */ bool -wasm_runtime_call_indirect(WASMExecEnv *exec_env, - uint32 element_indices, +wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices, uint32 argc, uint32 argv[]); bool -wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst, - WASMFunctionInstanceCommon *function, - uint32 argc, uint32 argv[]); +wasm_runtime_create_exec_env_and_call_wasm( + WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function, + uint32 argc, uint32 argv[]); bool wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst); @@ -475,8 +528,8 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool -wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, - int32 argc, char *argv[]); +wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, + char *argv[]); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool @@ -552,8 +605,7 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst, /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst, - uint32 app_offset, - uint32 *p_app_start_offset, + uint32 app_offset, uint32 *p_app_start_offset, uint32 *p_app_end_offset); /* See wasm_export.h for description */ @@ -593,8 +645,7 @@ wasm_runtime_register_module_internal(const char *module_name, WASMModuleCommon *module, uint8 *orig_file_buf, uint32 orig_file_buf_size, - char *error_buf, - uint32 error_buf_size); + char *error_buf, uint32 error_buf_size); void wasm_runtime_unregister_module(const WASMModuleCommon *module); @@ -603,8 +654,8 @@ bool wasm_runtime_is_module_registered(const char *module_name); bool -wasm_runtime_add_loading_module(const char *module_name, - char *error_buf, uint32 error_buf_size); +wasm_runtime_add_loading_module(const char *module_name, char *error_buf, + uint32 error_buf_size); void wasm_runtime_delete_loading_module(const char *module_name); @@ -621,30 +672,28 @@ wasm_runtime_is_built_in_module(const char *module_name); #if WASM_ENABLE_THREAD_MGR != 0 bool -wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env, - uint32 *start_offset, uint32 *size); +wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, + uint32 *size); bool -wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, - uint32 start_offset, uint32 size); +wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, + uint32 size); #endif #if WASM_ENABLE_LIBC_WASI != 0 WASM_RUNTIME_API_EXTERN void -wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module, - const char *dir_list[], uint32 dir_count, - const char *map_dir_list[], uint32 map_dir_count, - const char *env_list[], uint32 env_count, - char *argv[], int argc, - int stdinfd, int stdoutfd, int stderrfd); +wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module, const char *dir_list[], + uint32 dir_count, const char *map_dir_list[], + uint32 map_dir_count, const char *env_list[], + uint32 env_count, char *argv[], int argc, + int stdinfd, int stdoutfd, int stderrfd); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN void -wasm_runtime_set_wasi_args(WASMModuleCommon *module, - const char *dir_list[], uint32 dir_count, - const char *map_dir_list[], uint32 map_dir_count, - const char *env_list[], uint32 env_count, - char *argv[], int argc); +wasm_runtime_set_wasi_args(WASMModuleCommon *module, const char *dir_list[], + uint32 dir_count, const char *map_dir_list[], + uint32 map_dir_count, const char *env_list[], + uint32 env_count, char *argv[], int argc); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool @@ -658,9 +707,8 @@ bool wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, const char *dir_list[], uint32 dir_count, const char *map_dir_list[], uint32 map_dir_count, - const char *env[], uint32 env_count, - char *argv[], uint32 argc, - int stdinfd, int stdoutfd, int stderrfd, + const char *env[], uint32 env_count, char *argv[], + uint32 argc, int stdinfd, int stdoutfd, int stderrfd, char *error_buf, uint32 error_buf_size); void @@ -678,8 +726,8 @@ wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst); #if WASM_ENABLE_REF_TYPES != 0 /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool -wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, - void *extern_obj, uint32 *p_externref_idx); +wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj, + uint32 *p_externref_idx); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool @@ -704,7 +752,7 @@ wasm_externref_cleanup(WASMModuleInstanceCommon *module_inst); #endif /* end of WASM_ENABLE_REF_TYPES */ /* Get module of the current exec_env */ -WASMModuleCommon* +WASMModuleCommon * wasm_exec_env_get_module(WASMExecEnv *exec_env); /** @@ -715,7 +763,8 @@ wasm_exec_env_get_module(WASMExecEnv *exec_env); * @return return true if enlarge successfully, false otherwise */ bool -wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, uint32 inc_page_count); +wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, + uint32 inc_page_count); /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool @@ -732,14 +781,14 @@ wasm_runtime_register_natives_raw(const char *module_name, bool wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, - void *attachment, - uint32 *argv, uint32 argc, uint32 *ret); + void *attachment, uint32 *argv, uint32 argc, + uint32 *ret); bool wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr, const WASMType *func_type, const char *signature, - void *attachment, - uint32 *argv, uint32 argc, uint32 *ret); + void *attachment, uint32 *argv, uint32 argc, + uint32 *ret); void wasm_runtime_read_v128(const uint8 *bytes, uint64 *ret1, uint64 *ret2); @@ -748,8 +797,8 @@ void wasm_runtime_dump_module_mem_consumption(const WASMModuleCommon *module); void -wasm_runtime_dump_module_inst_mem_consumption(const WASMModuleInstanceCommon - *module_inst); +wasm_runtime_dump_module_inst_mem_consumption( + const WASMModuleInstanceCommon *module_inst); void wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env); @@ -766,45 +815,32 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env, bool wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm, - const WASMExport *export, - WASMType **out); + const WASMExport *export_, WASMType **out); bool wasm_runtime_get_export_global_type(const WASMModuleCommon *module_comm, - const WASMExport *export, - uint8 *out_val_type, - bool *out_mutability); + const WASMExport *export_, + uint8 *out_val_type, bool *out_mutability); bool wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm, - const WASMExport *export, - uint32 *out_min_page, - uint32 *out_max_page); + const WASMExport *export_, + uint32 *out_min_page, uint32 *out_max_page); bool wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm, - const WASMExport *export, - uint8 *out_elem_type, - uint32 *out_min_size, + const WASMExport *export_, + uint8 *out_elem_type, uint32 *out_min_size, uint32 *out_max_size); -uint8 * -wasm_runtime_get_memory_data(const WASMModuleInstanceCommon *module_inst_comm, - uint32 memory_inst_idx); - -uint32 -wasm_runtime_get_memory_data_size(const WASMModuleInstanceCommon *module_inst_comm, - uint32 memory_inst_idx); - bool wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst, void *func_ptr, WASMType *func_type, - uint32 argc, uint32 *argv, - bool with_env, void *wasm_c_api_env); + uint32 argc, uint32 *argv, bool with_env, + void *wasm_c_api_env); #ifdef __cplusplus } #endif #endif /* end of _WASM_COMMON_H */ - diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index cef0aa364d..65c98d4ef3 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -10,9 +10,12 @@ static bh_list shared_memory_list_head; static bh_list *const shared_memory_list = &shared_memory_list_head; static korp_mutex shared_memory_list_lock; +/* clang-format off */ enum { - S_WAITING, S_NOTIFIED + S_WAITING, + S_NOTIFIED }; +/* clang-format on */ typedef struct AtomicWaitInfo { korp_mutex wait_list_lock; @@ -45,11 +48,9 @@ wasm_shared_memory_init() if (os_mutex_init(&shared_memory_list_lock) != 0) return false; /* wait map not exists, create new map */ - if (!(wait_map = - bh_hash_map_create(32, true, - (HashFunc)wait_address_hash, - (KeyEqualFunc)wait_address_equal, - NULL, destroy_wait_info))) { + if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash, + (KeyEqualFunc)wait_address_equal, NULL, + destroy_wait_info))) { os_mutex_destroy(&shared_memory_list_lock); return false; } @@ -66,7 +67,7 @@ wasm_shared_memory_destroy() } } -static WASMSharedMemNode* +static WASMSharedMemNode * search_module(WASMModuleCommon *module) { WASMSharedMemNode *node; @@ -86,7 +87,7 @@ search_module(WASMModuleCommon *module) return NULL; } -WASMSharedMemNode* +WASMSharedMemNode * wasm_module_get_shared_memory(WASMModuleCommon *module) { return search_module(module); @@ -128,13 +129,13 @@ shared_memory_dec_reference(WASMModuleCommon *module) return -1; } -WASMMemoryInstanceCommon* +WASMMemoryInstanceCommon * shared_memory_get_memory_inst(WASMSharedMemNode *node) { return node->memory_inst; } -WASMSharedMemNode* +WASMSharedMemNode * shared_memory_set_memory_inst(WASMModuleCommon *module, WASMMemoryInstanceCommon *memory) { @@ -223,16 +224,15 @@ acquire_wait_info(void *address, bool create) AtomicWaitInfo *wait_info = NULL; bh_list_status ret; - wait_info = (AtomicWaitInfo *) - bh_hash_map_find(wait_map, address); + wait_info = (AtomicWaitInfo *)bh_hash_map_find(wait_map, address); if (!create) return wait_info; /* No wait info on this address, create new info */ if (!wait_info) { - if (!(wait_info = - (AtomicWaitInfo *)wasm_runtime_malloc(sizeof(AtomicWaitInfo)))) + if (!(wait_info = (AtomicWaitInfo *)wasm_runtime_malloc( + sizeof(AtomicWaitInfo)))) return NULL; memset(wait_info, 0, sizeof(AtomicWaitInfo)); @@ -247,8 +247,7 @@ acquire_wait_info(void *address, bool create) return NULL; } - if (!bh_hash_map_insert(wait_map, address, - (void *)wait_info)) { + if (!bh_hash_map_insert(wait_map, address, (void *)wait_info)) { os_mutex_destroy(&wait_info->wait_list_lock); wasm_runtime_free(wait_info); return NULL; @@ -283,8 +282,7 @@ destroy_wait_info(void *wait_info) } static void -release_wait_info(HashMap *wait_map, - AtomicWaitInfo *wait_info, void *address) +release_wait_info(HashMap *wait_map, AtomicWaitInfo *wait_info, void *address) { if (wait_info->wait_list->len == 0) { bh_hash_map_remove(wait_map, address, NULL, NULL); @@ -333,8 +331,8 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, os_mutex_lock(&wait_info->wait_list_lock); - if ((!wait64 && *(uint32*)address != (uint32)expect) - || (wait64 && *(uint64*)address != expect)) { + if ((!wait64 && *(uint32 *)address != (uint32)expect) + || (wait64 && *(uint64 *)address != expect)) { os_mutex_unlock(&wait_info->wait_list_lock); return 1; } @@ -375,8 +373,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, if (timeout < 0) timeout = BHT_WAIT_FOREVER; - os_cond_reltimedwait(&wait_node->wait_cond, - &wait_node->wait_lock, timeout); + os_cond_reltimedwait(&wait_node->wait_cond, &wait_node->wait_lock, timeout); os_mutex_unlock(&wait_node->wait_lock); @@ -400,8 +397,8 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, } uint32 -wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, - void *address, uint32 count) +wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, + uint32 count) { uint32 notify_result; AtomicWaitInfo *wait_info; diff --git a/core/iwasm/common/wasm_shared_memory.h b/core/iwasm/common/wasm_shared_memory.h index f05e595782..bc6f8945cf 100644 --- a/core/iwasm/common/wasm_shared_memory.h +++ b/core/iwasm/common/wasm_shared_memory.h @@ -37,7 +37,7 @@ wasm_shared_memory_init(); void wasm_shared_memory_destroy(); -WASMSharedMemNode* +WASMSharedMemNode * wasm_module_get_shared_memory(WASMModuleCommon *module); int32 @@ -46,10 +46,10 @@ shared_memory_inc_reference(WASMModuleCommon *module); int32 shared_memory_dec_reference(WASMModuleCommon *module); -WASMMemoryInstanceCommon* +WASMMemoryInstanceCommon * shared_memory_get_memory_inst(WASMSharedMemNode *node); -WASMSharedMemNode* +WASMSharedMemNode * shared_memory_set_memory_inst(WASMModuleCommon *module, WASMMemoryInstanceCommon *memory); @@ -58,8 +58,8 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, uint64 expect, int64 timeout, bool wait64); uint32 -wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, - void *address, uint32 count); +wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, + uint32 count); #ifdef __cplusplus } diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c index 3ab580cc50..d26a943afd 100644 --- a/core/iwasm/compilation/aot.c +++ b/core/iwasm/compilation/aot.c @@ -5,13 +5,12 @@ #include "aot.h" - static char aot_error[128]; -char* +char * aot_get_last_error() { - return aot_error[0] == '\0' ? "" : aot_error; + return aot_error[0] == '\0' ? "" : aot_error; } void @@ -26,558 +25,561 @@ aot_set_last_error_v(const char *format, ...) void aot_set_last_error(const char *error) { - if (error) - snprintf(aot_error, sizeof(aot_error), "Error: %s", error); - else - aot_error[0] = '\0'; + if (error) + snprintf(aot_error, sizeof(aot_error), "Error: %s", error); + else + aot_error[0] = '\0'; } static void aot_destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count) { - uint32 i; - for (i = 0; i < count; i++) - if (data_list[i]) - wasm_runtime_free(data_list[i]); - wasm_runtime_free(data_list); + uint32 i; + for (i = 0; i < count; i++) + if (data_list[i]) + wasm_runtime_free(data_list[i]); + wasm_runtime_free(data_list); } static AOTMemInitData ** aot_create_mem_init_data_list(const WASMModule *module) { - AOTMemInitData **data_list; - uint64 size; - uint32 i; - - /* Allocate memory */ - size = sizeof(AOTMemInitData *) * (uint64)module->data_seg_count; - if (size >= UINT32_MAX - || !(data_list = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - return NULL; - } + AOTMemInitData **data_list; + uint64 size; + uint32 i; - memset(data_list, 0, size); - - /* Create each memory data segment */ - for (i = 0; i < module->data_seg_count; i++) { - size = offsetof(AOTMemInitData, bytes) + - (uint64)module->data_segments[i]->data_length; + /* Allocate memory */ + size = sizeof(AOTMemInitData *) * (uint64)module->data_seg_count; if (size >= UINT32_MAX - || !(data_list[i] = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - goto fail; + || !(data_list = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; } + memset(data_list, 0, size); + + /* Create each memory data segment */ + for (i = 0; i < module->data_seg_count; i++) { + size = offsetof(AOTMemInitData, bytes) + + (uint64)module->data_segments[i]->data_length; + if (size >= UINT32_MAX + || !(data_list[i] = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + #if WASM_ENABLE_BULK_MEMORY != 0 - data_list[i]->is_passive = module->data_segments[i]->is_passive; - data_list[i]->memory_index = module->data_segments[i]->memory_index; + data_list[i]->is_passive = module->data_segments[i]->is_passive; + data_list[i]->memory_index = module->data_segments[i]->memory_index; #endif - data_list[i]->offset = module->data_segments[i]->base_offset; - data_list[i]->byte_count = module->data_segments[i]->data_length; - memcpy(data_list[i]->bytes, module->data_segments[i]->data, - module->data_segments[i]->data_length); - } + data_list[i]->offset = module->data_segments[i]->base_offset; + data_list[i]->byte_count = module->data_segments[i]->data_length; + memcpy(data_list[i]->bytes, module->data_segments[i]->data, + module->data_segments[i]->data_length); + } - return data_list; + return data_list; fail: - aot_destroy_mem_init_data_list(data_list, module->data_seg_count); - return NULL; + aot_destroy_mem_init_data_list(data_list, module->data_seg_count); + return NULL; } static void aot_destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count) { - uint32 i; - for (i = 0; i < count; i++) - if (data_list[i]) - wasm_runtime_free(data_list[i]); - wasm_runtime_free(data_list); + uint32 i; + for (i = 0; i < count; i++) + if (data_list[i]) + wasm_runtime_free(data_list[i]); + wasm_runtime_free(data_list); } static AOTTableInitData ** aot_create_table_init_data_list(const WASMModule *module) { - AOTTableInitData **data_list; - uint64 size; - uint32 i; - - /* Allocate memory */ - size = sizeof(AOTTableInitData *) * (uint64)module->table_seg_count; - if (size >= UINT32_MAX - || !(data_list = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - return NULL; - } - - memset(data_list, 0, size); + AOTTableInitData **data_list; + uint64 size; + uint32 i; - /* Create each table data segment */ - for (i = 0; i < module->table_seg_count; i++) { - size = offsetof(AOTTableInitData, func_indexes) + - sizeof(uint32) * (uint64)module->table_segments[i].function_count; + /* Allocate memory */ + size = sizeof(AOTTableInitData *) * (uint64)module->table_seg_count; if (size >= UINT32_MAX - || !(data_list[i] = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - goto fail; + || !(data_list = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(data_list, 0, size); + + /* Create each table data segment */ + for (i = 0; i < module->table_seg_count; i++) { + size = + offsetof(AOTTableInitData, func_indexes) + + sizeof(uint32) * (uint64)module->table_segments[i].function_count; + if (size >= UINT32_MAX + || !(data_list[i] = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + + data_list[i]->offset = module->table_segments[i].base_offset; + data_list[i]->func_index_count = + module->table_segments[i].function_count; + data_list[i]->mode = module->table_segments[i].mode; + data_list[i]->elem_type = module->table_segments[i].elem_type; + /* runtime control it */ + data_list[i]->is_dropped = false; + data_list[i]->table_index = module->table_segments[i].table_index; + bh_memcpy_s(&data_list[i]->offset, sizeof(AOTInitExpr), + &module->table_segments[i].base_offset, + sizeof(AOTInitExpr)); + data_list[i]->func_index_count = + module->table_segments[i].function_count; + bh_memcpy_s(data_list[i]->func_indexes, + sizeof(uint32) * module->table_segments[i].function_count, + module->table_segments[i].func_indexes, + sizeof(uint32) * module->table_segments[i].function_count); } - data_list[i]->offset = module->table_segments[i].base_offset; - data_list[i]->func_index_count = module->table_segments[i].function_count; - data_list[i]->mode = module->table_segments[i].mode; - data_list[i]->elem_type = module->table_segments[i].elem_type; - /* runtime control it */ - data_list[i]->is_dropped = false; - data_list[i]->table_index = module->table_segments[i].table_index; - bh_memcpy_s(&data_list[i]->offset, sizeof(AOTInitExpr), - &module->table_segments[i].base_offset, sizeof(AOTInitExpr)); - data_list[i]->func_index_count = module->table_segments[i].function_count; - bh_memcpy_s(data_list[i]->func_indexes, - sizeof(uint32) * module->table_segments[i].function_count, - module->table_segments[i].func_indexes, - sizeof(uint32) * module->table_segments[i].function_count); - } - - return data_list; + return data_list; fail: - aot_destroy_table_init_data_list(data_list, module->table_seg_count); - return NULL; + aot_destroy_table_init_data_list(data_list, module->table_seg_count); + return NULL; } static AOTImportGlobal * aot_create_import_globals(const WASMModule *module, uint32 *p_import_global_data_size) { - AOTImportGlobal *import_globals; - uint64 size; - uint32 i, data_offset = 0; - - /* Allocate memory */ - size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count; - if (size >= UINT32_MAX - || !(import_globals = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - return NULL; - } - - memset(import_globals, 0, (uint32)size); - - /* Create each import global */ - for (i = 0; i < module->import_global_count; i++) { - WASMGlobalImport *import_global = &module->import_globals[i].u.global; - import_globals[i].module_name = import_global->module_name; - import_globals[i].global_name = import_global->field_name; - import_globals[i].type = import_global->type; - import_globals[i].is_mutable = import_global->is_mutable; - import_globals[i].global_data_linked = import_global->global_data_linked; - import_globals[i].size = wasm_value_type_size(import_global->type); - /* Calculate data offset */ - import_globals[i].data_offset = data_offset; - data_offset += wasm_value_type_size(import_global->type); - } - - *p_import_global_data_size = data_offset; - return import_globals; + AOTImportGlobal *import_globals; + uint64 size; + uint32 i, data_offset = 0; + + /* Allocate memory */ + size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count; + if (size >= UINT32_MAX + || !(import_globals = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(import_globals, 0, (uint32)size); + + /* Create each import global */ + for (i = 0; i < module->import_global_count; i++) { + WASMGlobalImport *import_global = &module->import_globals[i].u.global; + import_globals[i].module_name = import_global->module_name; + import_globals[i].global_name = import_global->field_name; + import_globals[i].type = import_global->type; + import_globals[i].is_mutable = import_global->is_mutable; + import_globals[i].global_data_linked = + import_global->global_data_linked; + import_globals[i].size = wasm_value_type_size(import_global->type); + /* Calculate data offset */ + import_globals[i].data_offset = data_offset; + data_offset += wasm_value_type_size(import_global->type); + } + + *p_import_global_data_size = data_offset; + return import_globals; } static AOTGlobal * -aot_create_globals(const WASMModule *module, - uint32 global_data_start_offset, +aot_create_globals(const WASMModule *module, uint32 global_data_start_offset, uint32 *p_global_data_size) { - AOTGlobal *globals; - uint64 size; - uint32 i, data_offset = global_data_start_offset; - - /* Allocate memory */ - size = sizeof(AOTGlobal) * (uint64)module->global_count; - if (size >= UINT32_MAX - || !(globals = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - return NULL; - } - - memset(globals, 0, (uint32)size); - - /* Create each global */ - for (i = 0; i < module->global_count; i++) { - WASMGlobal *global = &module->globals[i]; - globals[i].type = global->type; - globals[i].is_mutable = global->is_mutable; - globals[i].size = wasm_value_type_size(global->type); - memcpy(&globals[i].init_expr, &global->init_expr, - sizeof(global->init_expr)); - /* Calculate data offset */ - globals[i].data_offset = data_offset; - data_offset += wasm_value_type_size(global->type); - } - - *p_global_data_size = data_offset - global_data_start_offset; - return globals; + AOTGlobal *globals; + uint64 size; + uint32 i, data_offset = global_data_start_offset; + + /* Allocate memory */ + size = sizeof(AOTGlobal) * (uint64)module->global_count; + if (size >= UINT32_MAX || !(globals = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(globals, 0, (uint32)size); + + /* Create each global */ + for (i = 0; i < module->global_count; i++) { + WASMGlobal *global = &module->globals[i]; + globals[i].type = global->type; + globals[i].is_mutable = global->is_mutable; + globals[i].size = wasm_value_type_size(global->type); + memcpy(&globals[i].init_expr, &global->init_expr, + sizeof(global->init_expr)); + /* Calculate data offset */ + globals[i].data_offset = data_offset; + data_offset += wasm_value_type_size(global->type); + } + + *p_global_data_size = data_offset - global_data_start_offset; + return globals; } static void aot_destroy_func_types(AOTFuncType **func_types, uint32 count) { - uint32 i; - for (i = 0; i < count; i++) - if (func_types[i]) - wasm_runtime_free(func_types[i]); - wasm_runtime_free(func_types); + uint32 i; + for (i = 0; i < count; i++) + if (func_types[i]) + wasm_runtime_free(func_types[i]); + wasm_runtime_free(func_types); } static AOTFuncType ** aot_create_func_types(const WASMModule *module) { - AOTFuncType **func_types; - uint64 size; - uint32 i; - - /* Allocate memory */ - size = sizeof(AOTFuncType*) * (uint64)module->type_count; - if (size >= UINT32_MAX - || !(func_types = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - return NULL; - } + AOTFuncType **func_types; + uint64 size; + uint32 i; - memset(func_types, 0, size); - - /* Create each function type */ - for (i = 0; i < module->type_count; i++) { - size = offsetof(AOTFuncType, types) + - (uint64)module->types[i]->param_count + - (uint64)module->types[i]->result_count; + /* Allocate memory */ + size = sizeof(AOTFuncType *) * (uint64)module->type_count; if (size >= UINT32_MAX - || !(func_types[i] = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - goto fail; + || !(func_types = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(func_types, 0, size); + + /* Create each function type */ + for (i = 0; i < module->type_count; i++) { + size = offsetof(AOTFuncType, types) + + (uint64)module->types[i]->param_count + + (uint64)module->types[i]->result_count; + if (size >= UINT32_MAX + || !(func_types[i] = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + memcpy(func_types[i], module->types[i], size); } - memcpy(func_types[i], module->types[i], size); - } - return func_types; + return func_types; fail: - aot_destroy_func_types(func_types, module->type_count); - return NULL; + aot_destroy_func_types(func_types, module->type_count); + return NULL; } static AOTImportFunc * aot_create_import_funcs(const WASMModule *module) { - AOTImportFunc *import_funcs; - uint64 size; - uint32 i, j; - - /* Allocate memory */ - size = sizeof(AOTImportFunc) * (uint64)module->import_function_count; - if (size >= UINT32_MAX - || !(import_funcs = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - return NULL; - } - - /* Create each import function */ - for (i = 0; i < module->import_function_count; i++) { - WASMFunctionImport *import_func = &module->import_functions[i].u.function; - import_funcs[i].module_name = import_func->module_name; - import_funcs[i].func_name = import_func->field_name; - import_funcs[i].func_ptr_linked = import_func->func_ptr_linked; - import_funcs[i].func_type = import_func->func_type; - import_funcs[i].signature = import_func->signature; - import_funcs[i].attachment = import_func->attachment; - import_funcs[i].call_conv_raw = import_func->call_conv_raw; - import_funcs[i].call_conv_wasm_c_api = false; - /* Resolve function type index */ - for (j = 0; j < module->type_count; j++) - if (import_func->func_type == module->types[j]) { - import_funcs[i].func_type_index = j; - break; - } - } - - return import_funcs; + AOTImportFunc *import_funcs; + uint64 size; + uint32 i, j; + + /* Allocate memory */ + size = sizeof(AOTImportFunc) * (uint64)module->import_function_count; + if (size >= UINT32_MAX + || !(import_funcs = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + /* Create each import function */ + for (i = 0; i < module->import_function_count; i++) { + WASMFunctionImport *import_func = + &module->import_functions[i].u.function; + import_funcs[i].module_name = import_func->module_name; + import_funcs[i].func_name = import_func->field_name; + import_funcs[i].func_ptr_linked = import_func->func_ptr_linked; + import_funcs[i].func_type = import_func->func_type; + import_funcs[i].signature = import_func->signature; + import_funcs[i].attachment = import_func->attachment; + import_funcs[i].call_conv_raw = import_func->call_conv_raw; + import_funcs[i].call_conv_wasm_c_api = false; + /* Resolve function type index */ + for (j = 0; j < module->type_count; j++) + if (import_func->func_type == module->types[j]) { + import_funcs[i].func_type_index = j; + break; + } + } + + return import_funcs; } static void aot_destroy_funcs(AOTFunc **funcs, uint32 count) { - uint32 i; + uint32 i; - for (i = 0; i < count; i++) - if (funcs[i]) - wasm_runtime_free(funcs[i]); - wasm_runtime_free(funcs); + for (i = 0; i < count; i++) + if (funcs[i]) + wasm_runtime_free(funcs[i]); + wasm_runtime_free(funcs); } static AOTFunc ** aot_create_funcs(const WASMModule *module) { - AOTFunc **funcs; - uint64 size; - uint32 i, j; - - /* Allocate memory */ - size = sizeof(AOTFunc*) * (uint64)module->function_count; - if (size >= UINT32_MAX - || !(funcs = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - return NULL; - } - - memset(funcs, 0, size); - - /* Create each function */ - for (i = 0; i < module->function_count; i++) { - WASMFunction *func = module->functions[i]; - size = sizeof (AOTFunc); - if (!(funcs[i] = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("allocate memory failed."); - goto fail; + AOTFunc **funcs; + uint64 size; + uint32 i, j; + + /* Allocate memory */ + size = sizeof(AOTFunc *) * (uint64)module->function_count; + if (size >= UINT32_MAX || !(funcs = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; } - funcs[i]->func_type = func->func_type; - - /* Resolve function type index */ - for (j = 0; j < module->type_count; j++) - if (func->func_type == module->types[j]) { - funcs[i]->func_type_index = j; - break; - } - - /* Resolve local variable info and code info */ - funcs[i]->local_count = func->local_count; - funcs[i]->local_types = func->local_types; - funcs[i]->param_cell_num = func->param_cell_num; - funcs[i]->local_cell_num = func->local_cell_num; - funcs[i]->code = func->code; - funcs[i]->code_size = func->code_size; - } + memset(funcs, 0, size); + + /* Create each function */ + for (i = 0; i < module->function_count; i++) { + WASMFunction *func = module->functions[i]; + size = sizeof(AOTFunc); + if (!(funcs[i] = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + + funcs[i]->func_type = func->func_type; + + /* Resolve function type index */ + for (j = 0; j < module->type_count; j++) + if (func->func_type == module->types[j]) { + funcs[i]->func_type_index = j; + break; + } + + /* Resolve local variable info and code info */ + funcs[i]->local_count = func->local_count; + funcs[i]->local_types = func->local_types; + funcs[i]->param_cell_num = func->param_cell_num; + funcs[i]->local_cell_num = func->local_cell_num; + funcs[i]->code = func->code; + funcs[i]->code_size = func->code_size; + } - return funcs; + return funcs; fail: - aot_destroy_funcs(funcs, module->function_count); - return NULL; + aot_destroy_funcs(funcs, module->function_count); + return NULL; } -AOTCompData* +AOTCompData * aot_create_comp_data(WASMModule *module) { - AOTCompData *comp_data; - uint32 import_global_data_size = 0, global_data_size = 0, i, j; - uint64 size; - - /* Allocate memory */ - if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) { - aot_set_last_error("create compile data failed.\n"); - return NULL; - } - - memset(comp_data, 0, sizeof(AOTCompData)); - - comp_data->memory_count = module->import_memory_count + module->memory_count; - - /* TODO: create import memories */ - - /* Allocate memory for memory array, reserve one AOTMemory space at least */ - if (!comp_data->memory_count) - comp_data->memory_count = 1; - - size = (uint64)comp_data->memory_count * sizeof(AOTMemory); - if (size >= UINT32_MAX - || !(comp_data->memories = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("create memories array failed.\n"); - goto fail; - } - memset(comp_data->memories, 0, size); - - if (!(module->import_memory_count + module->memory_count)) { - comp_data->memories[0].num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; - } - - /* Set memory page count */ - for (i = 0; i < module->import_memory_count + module->memory_count; i++) { - if (i < module->import_memory_count) { - comp_data->memories[i].memory_flags = - module->import_memories[i].u.memory.flags; - comp_data->memories[i].num_bytes_per_page = - module->import_memories[i].u.memory.num_bytes_per_page; - comp_data->memories[i].mem_init_page_count = - module->import_memories[i].u.memory.init_page_count; - comp_data->memories[i].mem_max_page_count = - module->import_memories[i].u.memory.max_page_count; - comp_data->memories[i].num_bytes_per_page = - module->import_memories[i].u.memory.num_bytes_per_page; - } - else { - j = i - module->import_memory_count; - comp_data->memories[i].memory_flags = - module->memories[j].flags; - comp_data->memories[i].num_bytes_per_page = - module->memories[j].num_bytes_per_page; - comp_data->memories[i].mem_init_page_count = - module->memories[j].init_page_count; - comp_data->memories[i].mem_max_page_count = - module->memories[j].max_page_count; - comp_data->memories[i].num_bytes_per_page = - module->memories[j].num_bytes_per_page; + AOTCompData *comp_data; + uint32 import_global_data_size = 0, global_data_size = 0, i, j; + uint64 size; + + /* Allocate memory */ + if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) { + aot_set_last_error("create compile data failed.\n"); + return NULL; } - } - /* Create memory data segments */ - comp_data->mem_init_data_count = module->data_seg_count; - if (comp_data->mem_init_data_count > 0 - && !(comp_data->mem_init_data_list = - aot_create_mem_init_data_list(module))) - goto fail; + memset(comp_data, 0, sizeof(AOTCompData)); - /* Create tables */ - comp_data->table_count = module->import_table_count + module->table_count; + comp_data->memory_count = + module->import_memory_count + module->memory_count; - if (comp_data->table_count > 0) { - size = sizeof(AOTTable) * (uint64)comp_data->table_count; + /* TODO: create import memories */ + + /* Allocate memory for memory array, reserve one AOTMemory space at least */ + if (!comp_data->memory_count) + comp_data->memory_count = 1; + + size = (uint64)comp_data->memory_count * sizeof(AOTMemory); if (size >= UINT32_MAX - || !(comp_data->tables = wasm_runtime_malloc((uint32)size))) { - aot_set_last_error("create memories array failed.\n"); - goto fail; + || !(comp_data->memories = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("create memories array failed.\n"); + goto fail; + } + memset(comp_data->memories, 0, size); + + if (!(module->import_memory_count + module->memory_count)) { + comp_data->memories[0].num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE; + } + + /* Set memory page count */ + for (i = 0; i < module->import_memory_count + module->memory_count; i++) { + if (i < module->import_memory_count) { + comp_data->memories[i].memory_flags = + module->import_memories[i].u.memory.flags; + comp_data->memories[i].num_bytes_per_page = + module->import_memories[i].u.memory.num_bytes_per_page; + comp_data->memories[i].mem_init_page_count = + module->import_memories[i].u.memory.init_page_count; + comp_data->memories[i].mem_max_page_count = + module->import_memories[i].u.memory.max_page_count; + comp_data->memories[i].num_bytes_per_page = + module->import_memories[i].u.memory.num_bytes_per_page; + } + else { + j = i - module->import_memory_count; + comp_data->memories[i].memory_flags = module->memories[j].flags; + comp_data->memories[i].num_bytes_per_page = + module->memories[j].num_bytes_per_page; + comp_data->memories[i].mem_init_page_count = + module->memories[j].init_page_count; + comp_data->memories[i].mem_max_page_count = + module->memories[j].max_page_count; + comp_data->memories[i].num_bytes_per_page = + module->memories[j].num_bytes_per_page; + } } - memset(comp_data->tables, 0, size); - for (i = 0; i < comp_data->table_count; i++) { - if (i < module->import_table_count) { - comp_data->tables[i].elem_type = - module->import_tables[i].u.table.elem_type; - comp_data->tables[i].table_flags = - module->import_tables[i].u.table.flags; - comp_data->tables[i].table_init_size = - module->import_tables[i].u.table.init_size; - comp_data->tables[i].table_max_size = - module->import_tables[i].u.table.max_size; - comp_data->tables[i].possible_grow = - module->import_tables[i].u.table.possible_grow; - } - else { - j = i - module->import_table_count; - comp_data->tables[i].elem_type = module->tables[i].elem_type; - comp_data->tables[i].table_flags = module->tables[i].flags; - comp_data->tables[i].table_init_size = module->tables[i].init_size; - comp_data->tables[i].table_max_size = module->tables[i].max_size; - comp_data->tables[i].possible_grow = module->tables[i].possible_grow; - } + + /* Create memory data segments */ + comp_data->mem_init_data_count = module->data_seg_count; + if (comp_data->mem_init_data_count > 0 + && !(comp_data->mem_init_data_list = + aot_create_mem_init_data_list(module))) + goto fail; + + /* Create tables */ + comp_data->table_count = module->import_table_count + module->table_count; + + if (comp_data->table_count > 0) { + size = sizeof(AOTTable) * (uint64)comp_data->table_count; + if (size >= UINT32_MAX + || !(comp_data->tables = wasm_runtime_malloc((uint32)size))) { + aot_set_last_error("create memories array failed.\n"); + goto fail; + } + memset(comp_data->tables, 0, size); + for (i = 0; i < comp_data->table_count; i++) { + if (i < module->import_table_count) { + comp_data->tables[i].elem_type = + module->import_tables[i].u.table.elem_type; + comp_data->tables[i].table_flags = + module->import_tables[i].u.table.flags; + comp_data->tables[i].table_init_size = + module->import_tables[i].u.table.init_size; + comp_data->tables[i].table_max_size = + module->import_tables[i].u.table.max_size; + comp_data->tables[i].possible_grow = + module->import_tables[i].u.table.possible_grow; + } + else { + j = i - module->import_table_count; + comp_data->tables[i].elem_type = module->tables[j].elem_type; + comp_data->tables[i].table_flags = module->tables[j].flags; + comp_data->tables[i].table_init_size = + module->tables[j].init_size; + comp_data->tables[i].table_max_size = + module->tables[j].max_size; + comp_data->tables[i].possible_grow = + module->tables[j].possible_grow; + } + } } - } - - /* Create table data segments */ - comp_data->table_init_data_count = module->table_seg_count; - if (comp_data->table_init_data_count > 0 - && !(comp_data->table_init_data_list = - aot_create_table_init_data_list(module))) - goto fail; - - /* Create import globals */ - comp_data->import_global_count = module->import_global_count; - if (comp_data->import_global_count > 0 - && !(comp_data->import_globals = - aot_create_import_globals(module, &import_global_data_size))) - goto fail; - - /* Create globals */ - comp_data->global_count = module->global_count; - if (comp_data->global_count - && !(comp_data->globals = aot_create_globals - (module, import_global_data_size, &global_data_size))) - goto fail; - - comp_data->global_data_size = import_global_data_size + - global_data_size; - - /* Create function types */ - comp_data->func_type_count = module->type_count; - if (comp_data->func_type_count - && !(comp_data->func_types = aot_create_func_types(module))) - goto fail; - - /* Create import functions */ - comp_data->import_func_count = module->import_function_count; - if (comp_data->import_func_count - && !(comp_data->import_funcs = aot_create_import_funcs(module))) - goto fail; - - /* Create functions */ - comp_data->func_count = module->function_count; - if (comp_data->func_count - && !(comp_data->funcs = aot_create_funcs(module))) - goto fail; - - /* Create aux data/heap/stack information */ - comp_data->aux_data_end_global_index = module->aux_data_end_global_index; - comp_data->aux_data_end = module->aux_data_end; - comp_data->aux_heap_base_global_index = module->aux_heap_base_global_index; - comp_data->aux_heap_base = module->aux_heap_base; - comp_data->aux_stack_top_global_index = module->aux_stack_top_global_index; - comp_data->aux_stack_bottom = module->aux_stack_bottom; - comp_data->aux_stack_size = module->aux_stack_size; - - comp_data->start_func_index = module->start_function; - comp_data->malloc_func_index = module->malloc_function; - comp_data->free_func_index = module->free_function; - comp_data->retain_func_index = module->retain_function; - - comp_data->wasm_module = module; - - return comp_data; + + /* Create table data segments */ + comp_data->table_init_data_count = module->table_seg_count; + if (comp_data->table_init_data_count > 0 + && !(comp_data->table_init_data_list = + aot_create_table_init_data_list(module))) + goto fail; + + /* Create import globals */ + comp_data->import_global_count = module->import_global_count; + if (comp_data->import_global_count > 0 + && !(comp_data->import_globals = + aot_create_import_globals(module, &import_global_data_size))) + goto fail; + + /* Create globals */ + comp_data->global_count = module->global_count; + if (comp_data->global_count + && !(comp_data->globals = aot_create_globals( + module, import_global_data_size, &global_data_size))) + goto fail; + + comp_data->global_data_size = import_global_data_size + global_data_size; + + /* Create function types */ + comp_data->func_type_count = module->type_count; + if (comp_data->func_type_count + && !(comp_data->func_types = aot_create_func_types(module))) + goto fail; + + /* Create import functions */ + comp_data->import_func_count = module->import_function_count; + if (comp_data->import_func_count + && !(comp_data->import_funcs = aot_create_import_funcs(module))) + goto fail; + + /* Create functions */ + comp_data->func_count = module->function_count; + if (comp_data->func_count && !(comp_data->funcs = aot_create_funcs(module))) + goto fail; + + /* Create aux data/heap/stack information */ + comp_data->aux_data_end_global_index = module->aux_data_end_global_index; + comp_data->aux_data_end = module->aux_data_end; + comp_data->aux_heap_base_global_index = module->aux_heap_base_global_index; + comp_data->aux_heap_base = module->aux_heap_base; + comp_data->aux_stack_top_global_index = module->aux_stack_top_global_index; + comp_data->aux_stack_bottom = module->aux_stack_bottom; + comp_data->aux_stack_size = module->aux_stack_size; + + comp_data->start_func_index = module->start_function; + comp_data->malloc_func_index = module->malloc_function; + comp_data->free_func_index = module->free_function; + comp_data->retain_func_index = module->retain_function; + + comp_data->wasm_module = module; + + return comp_data; fail: - aot_destroy_comp_data(comp_data); - return NULL; + aot_destroy_comp_data(comp_data); + return NULL; } void aot_destroy_comp_data(AOTCompData *comp_data) { - if (!comp_data) - return; + if (!comp_data) + return; - if (comp_data->import_memories) - wasm_runtime_free(comp_data->import_memories); + if (comp_data->import_memories) + wasm_runtime_free(comp_data->import_memories); - if (comp_data->memories) - wasm_runtime_free(comp_data->memories); + if (comp_data->memories) + wasm_runtime_free(comp_data->memories); - if (comp_data->mem_init_data_list) - aot_destroy_mem_init_data_list(comp_data->mem_init_data_list, - comp_data->mem_init_data_count); + if (comp_data->mem_init_data_list) + aot_destroy_mem_init_data_list(comp_data->mem_init_data_list, + comp_data->mem_init_data_count); - if (comp_data->import_tables) - wasm_runtime_free(comp_data->import_tables); + if (comp_data->import_tables) + wasm_runtime_free(comp_data->import_tables); - if (comp_data->tables) - wasm_runtime_free(comp_data->tables); + if (comp_data->tables) + wasm_runtime_free(comp_data->tables); - if (comp_data->table_init_data_list) - aot_destroy_table_init_data_list(comp_data->table_init_data_list, - comp_data->table_init_data_count); + if (comp_data->table_init_data_list) + aot_destroy_table_init_data_list(comp_data->table_init_data_list, + comp_data->table_init_data_count); - if (comp_data->import_globals) - wasm_runtime_free(comp_data->import_globals); + if (comp_data->import_globals) + wasm_runtime_free(comp_data->import_globals); - if (comp_data->globals) - wasm_runtime_free(comp_data->globals); + if (comp_data->globals) + wasm_runtime_free(comp_data->globals); - if (comp_data->func_types) - aot_destroy_func_types(comp_data->func_types, - comp_data->func_type_count); + if (comp_data->func_types) + aot_destroy_func_types(comp_data->func_types, + comp_data->func_type_count); - if (comp_data->import_funcs) - wasm_runtime_free(comp_data->import_funcs); + if (comp_data->import_funcs) + wasm_runtime_free(comp_data->import_funcs); - if (comp_data->funcs) - aot_destroy_funcs(comp_data->funcs, comp_data->func_count); + if (comp_data->funcs) + aot_destroy_funcs(comp_data->funcs, comp_data->func_count); - wasm_runtime_free(comp_data); + wasm_runtime_free(comp_data); } - diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index 44f98cf1ef..599d483214 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -21,27 +21,55 @@ typedef InitializerExpression AOTInitExpr; typedef WASMType AOTFuncType; typedef WASMExport AOTExport; +#if WASM_ENABLE_DEBUG_AOT != 0 +typedef void *dwar_extractor_handle_t; +#endif + +typedef enum AOTIntCond { + INT_EQZ = 0, + INT_EQ, + INT_NE, + INT_LT_S, + INT_LT_U, + INT_GT_S, + INT_GT_U, + INT_LE_S, + INT_LE_U, + INT_GE_S, + INT_GE_U +} AOTIntCond; + +typedef enum AOTFloatCond { + FLOAT_EQ = 0, + FLOAT_NE, + FLOAT_LT, + FLOAT_GT, + FLOAT_LE, + FLOAT_GE, + FLOAT_UNO +} AOTFloatCond; + /** * Import memory */ typedef struct AOTImportMemory { - char *module_name; - char *memory_name; - uint32 memory_flags; - uint32 num_bytes_per_page; - uint32 mem_init_page_count; - uint32 mem_max_page_count; + char *module_name; + char *memory_name; + uint32 memory_flags; + uint32 num_bytes_per_page; + uint32 mem_init_page_count; + uint32 mem_max_page_count; } AOTImportMemory; /** * Memory information */ typedef struct AOTMemory { - /* memory info */ - uint32 memory_flags; - uint32 num_bytes_per_page; - uint32 mem_init_page_count; - uint32 mem_max_page_count; + /* memory info */ + uint32 memory_flags; + uint32 num_bytes_per_page; + uint32 mem_init_page_count; + uint32 mem_max_page_count; } AOTMemory; /** @@ -49,193 +77,202 @@ typedef struct AOTMemory { */ typedef struct AOTMemInitData { #if WASM_ENABLE_BULK_MEMORY != 0 - /* Passive flag */ - bool is_passive; - /* memory index */ - uint32 memory_index; + /* Passive flag */ + bool is_passive; + /* memory index */ + uint32 memory_index; #endif - /* Start address of init data */ - AOTInitExpr offset; - /* Byte count */ - uint32 byte_count; - /* Byte array */ - uint8 bytes[1]; + /* Start address of init data */ + AOTInitExpr offset; + /* Byte count */ + uint32 byte_count; + /* Byte array */ + uint8 bytes[1]; } AOTMemInitData; /** * Import table */ typedef struct AOTImportTable { - char *module_name; - char *table_name; - uint32 table_flags; - uint32 table_init_size; - uint32 table_max_size; - bool possible_grow; + char *module_name; + char *table_name; + uint32 table_flags; + uint32 table_init_size; + uint32 table_max_size; + bool possible_grow; } AOTImportTable; /** * Table */ typedef struct AOTTable { - uint32 elem_type; - uint32 table_flags; - uint32 table_init_size; - uint32 table_max_size; - bool possible_grow; + uint32 elem_type; + uint32 table_flags; + uint32 table_init_size; + uint32 table_max_size; + bool possible_grow; } AOTTable; /** * A segment of table init data */ typedef struct AOTTableInitData { - /* 0 to 7 */ - uint32 mode; - /* funcref or externref, elemkind will be considered as funcref */ - uint32 elem_type; - bool is_dropped; - /* optional, only for active */ - uint32 table_index; - /* Start address of init data */ - AOTInitExpr offset; - /* Function index count */ - uint32 func_index_count; - /* Function index array */ - uint32 func_indexes[1]; + /* 0 to 7 */ + uint32 mode; + /* funcref or externref, elemkind will be considered as funcref */ + uint32 elem_type; + bool is_dropped; + /* optional, only for active */ + uint32 table_index; + /* Start address of init data */ + AOTInitExpr offset; + /* Function index count */ + uint32 func_index_count; + /* Function index array */ + uint32 func_indexes[1]; } AOTTableInitData; /** * Import global variable */ typedef struct AOTImportGlobal { - char *module_name; - char *global_name; - /* VALUE_TYPE_I32/I64/F32/F64 */ - uint8 type; - bool is_mutable; - uint32 size; - /* The data offset of current global in global data */ - uint32 data_offset; - /* global data after linked */ - WASMValue global_data_linked; + char *module_name; + char *global_name; + /* VALUE_TYPE_I32/I64/F32/F64 */ + uint8 type; + bool is_mutable; + uint32 size; + /* The data offset of current global in global data */ + uint32 data_offset; + /* global data after linked */ + WASMValue global_data_linked; } AOTImportGlobal; /** * Global variable */ typedef struct AOTGlobal { - /* VALUE_TYPE_I32/I64/F32/F64 */ - uint8 type; - bool is_mutable; - uint32 size; - /* The data offset of current global in global data */ - uint32 data_offset; - AOTInitExpr init_expr; + /* VALUE_TYPE_I32/I64/F32/F64 */ + uint8 type; + bool is_mutable; + uint32 size; + /* The data offset of current global in global data */ + uint32 data_offset; + AOTInitExpr init_expr; } AOTGlobal; /** * Import function */ typedef struct AOTImportFunc { - char *module_name; - char *func_name; - AOTFuncType *func_type; - uint32 func_type_index; - /* function pointer after linked */ - void *func_ptr_linked; - /* signature from registered native symbols */ - const char *signature; - /* attachment */ - void *attachment; - bool call_conv_raw; - bool call_conv_wasm_c_api; - bool wasm_c_api_with_env; + char *module_name; + char *func_name; + AOTFuncType *func_type; + uint32 func_type_index; + /* function pointer after linked */ + void *func_ptr_linked; + /* signature from registered native symbols */ + const char *signature; + /* attachment */ + void *attachment; + bool call_conv_raw; + bool call_conv_wasm_c_api; + bool wasm_c_api_with_env; } AOTImportFunc; /** * Function */ typedef struct AOTFunc { - AOTFuncType *func_type; - uint32 func_type_index; - uint32 local_count; - uint8 *local_types; - uint16 param_cell_num; - uint16 local_cell_num; - uint32 code_size; - uint8 *code; + AOTFuncType *func_type; + uint32 func_type_index; + uint32 local_count; + uint8 *local_types; + uint16 param_cell_num; + uint16 local_cell_num; + uint32 code_size; + uint8 *code; } AOTFunc; typedef struct AOTCompData { - /* Import memories */ - uint32 import_memory_count; - AOTImportMemory *import_memories; - - /* Memories */ - uint32 memory_count; - AOTMemory *memories; - - /* Memory init data info */ - uint32 mem_init_data_count; - AOTMemInitData **mem_init_data_list; - - /* Import tables */ - uint32 import_table_count; - AOTImportTable *import_tables; - - /* Tables */ - uint32 table_count; - AOTTable *tables; - - /* Table init data info */ - uint32 table_init_data_count; - AOTTableInitData **table_init_data_list; - - /* Import globals */ - uint32 import_global_count; - AOTImportGlobal *import_globals; - - /* Globals */ - uint32 global_count; - AOTGlobal *globals; - - /* Function types */ - uint32 func_type_count; - AOTFuncType **func_types; - - /* Import functions */ - uint32 import_func_count; - AOTImportFunc *import_funcs; - - /* Functions */ - uint32 func_count; - AOTFunc **funcs; - - uint32 global_data_size; - - uint32 start_func_index; - uint32 malloc_func_index; - uint32 free_func_index; - uint32 retain_func_index; - - uint32 aux_data_end_global_index; - uint32 aux_data_end; - uint32 aux_heap_base_global_index; - uint32 aux_heap_base; - uint32 aux_stack_top_global_index; - uint32 aux_stack_bottom; - uint32 aux_stack_size; - - WASMModule *wasm_module; + /* Import memories */ + uint32 import_memory_count; + AOTImportMemory *import_memories; + + /* Memories */ + uint32 memory_count; + AOTMemory *memories; + + /* Memory init data info */ + uint32 mem_init_data_count; + AOTMemInitData **mem_init_data_list; + + /* Import tables */ + uint32 import_table_count; + AOTImportTable *import_tables; + + /* Tables */ + uint32 table_count; + AOTTable *tables; + + /* Table init data info */ + uint32 table_init_data_count; + AOTTableInitData **table_init_data_list; + + /* Import globals */ + uint32 import_global_count; + AOTImportGlobal *import_globals; + + /* Globals */ + uint32 global_count; + AOTGlobal *globals; + + /* Function types */ + uint32 func_type_count; + AOTFuncType **func_types; + + /* Import functions */ + uint32 import_func_count; + AOTImportFunc *import_funcs; + + /* Functions */ + uint32 func_count; + AOTFunc **funcs; + + uint32 global_data_size; + + uint32 start_func_index; + uint32 malloc_func_index; + uint32 free_func_index; + uint32 retain_func_index; + + uint32 aux_data_end_global_index; + uint32 aux_data_end; + uint32 aux_heap_base_global_index; + uint32 aux_heap_base; + uint32 aux_stack_top_global_index; + uint32 aux_stack_bottom; + uint32 aux_stack_size; + + WASMModule *wasm_module; +#if WASM_ENABLE_DEBUG_AOT != 0 + dwar_extractor_handle_t extractor; +#endif } AOTCompData; -AOTCompData* +typedef struct AOTNativeSymbol { + bh_list_link link; + const char *symbol; + int32 index; +} AOTNativeSymbol; + +AOTCompData * aot_create_comp_data(WASMModule *module); void aot_destroy_comp_data(AOTCompData *comp_data); -char* +char * aot_get_last_error(); void @@ -245,14 +282,16 @@ void aot_set_last_error_v(const char *format, ...); #if BH_DEBUG != 0 -#define HANDLE_FAILURE(callee) do { \ - aot_set_last_error_v("call %s failed in %s:%d", (callee),\ - __FUNCTION__, __LINE__); \ - } while (0) +#define HANDLE_FAILURE(callee) \ + do { \ + aot_set_last_error_v("call %s failed in %s:%d", (callee), \ + __FUNCTION__, __LINE__); \ + } while (0) #else -#define HANDLE_FAILURE(callee) do { \ - aot_set_last_error_v("call %s failed", (callee)); \ - } while (0) +#define HANDLE_FAILURE(callee) \ + do { \ + aot_set_last_error_v("call %s failed", (callee)); \ + } while (0) #endif static inline uint32 @@ -272,4 +311,3 @@ aot_get_imp_tbl_data_slots(const AOTImportTable *tbl) #endif #endif /* end of _AOT_H_ */ - diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 3232448eee..eb0f8baba2 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -21,6 +21,7 @@ #include "simd/simd_bitwise_ops.h" #include "simd/simd_bool_reductions.h" #include "simd/simd_comparisons.h" +#include "simd/simd_conversions.h" #include "simd/simd_construct_values.h" #include "simd/simd_conversions.h" #include "simd/simd_floating_point.h" @@ -31,2061 +32,2530 @@ #include "../interpreter/wasm_opcode.h" #include +#if WASM_ENABLE_DEBUG_AOT != 0 +#include "debug/dwarf_extractor.h" +#endif -#define CHECK_BUF(buf, buf_end, length) do { \ - if (buf + length > buf_end) { \ - aot_set_last_error("read leb failed: unexpected end."); \ - return false; \ - } \ -} while (0) +#define CHECK_BUF(buf, buf_end, length) \ + do { \ + if (buf + length > buf_end) { \ + aot_set_last_error("read leb failed: unexpected end."); \ + return false; \ + } \ + } while (0) static bool -read_leb(const uint8 *buf, const uint8 *buf_end, - uint32 *p_offset, uint32 maxbits, - bool sign, uint64 *p_result) +read_leb(const uint8 *buf, const uint8 *buf_end, uint32 *p_offset, + uint32 maxbits, bool sign, uint64 *p_result) { - uint64 result = 0; - uint32 shift = 0; - uint32 bcnt = 0; - uint64 byte; - - while (true) { - CHECK_BUF(buf, buf_end, 1); - byte = buf[*p_offset]; - *p_offset += 1; - result |= ((byte & 0x7f) << shift); - shift += 7; - if ((byte & 0x80) == 0) { - break; + uint64 result = 0; + uint32 shift = 0; + uint32 bcnt = 0; + uint64 byte; + + while (true) { + CHECK_BUF(buf, buf_end, 1); + byte = buf[*p_offset]; + *p_offset += 1; + result |= ((byte & 0x7f) << shift); + shift += 7; + if ((byte & 0x80) == 0) { + break; + } + bcnt += 1; } - bcnt += 1; - } - if (bcnt > (((maxbits + 8) >> 3) - (maxbits + 8))) { - aot_set_last_error("read leb failed: unsigned leb overflow."); - return false; - } - if (sign && (shift < maxbits) && (byte & 0x40)) { - /* Sign extend */ - result |= (uint64)(- (((uint64)1) << shift)); - } - *p_result = result; - return true; + if (bcnt > (((maxbits + 8) >> 3) - (maxbits + 8))) { + aot_set_last_error("read leb failed: unsigned leb overflow."); + return false; + } + if (sign && (shift < maxbits) && (byte & 0x40)) { + /* Sign extend */ + result |= (~((uint64)0)) << shift; + } + *p_result = result; + return true; } -#define read_leb_uint32(p, p_end, res) do { \ - uint32 off = 0; \ - uint64 res64; \ - if (!read_leb(p, p_end, &off, 32, false, &res64)) \ - return false; \ - p += off; \ - res = (uint32)res64; \ -} while (0) - -#define read_leb_int32(p, p_end, res) do { \ - uint32 off = 0; \ - uint64 res64; \ - if (!read_leb(p, p_end, &off, 32, true, &res64)) \ - return false; \ - p += off; \ - res = (int32)res64; \ -} while (0) - -#define read_leb_int64(p, p_end, res) do { \ - uint32 off = 0; \ - uint64 res64; \ - if (!read_leb(p, p_end, &off, 64, true, &res64)) \ - return false; \ - p += off; \ - res = (int64)res64; \ -} while (0) - -#define COMPILE_ATOMIC_RMW(OP, NAME) \ - case WASM_OP_ATOMIC_RMW_I32_##NAME: \ - bytes = 4; \ - op_type = VALUE_TYPE_I32; \ - goto OP_ATOMIC_##OP; \ - case WASM_OP_ATOMIC_RMW_I64_##NAME: \ - bytes = 8; \ - op_type = VALUE_TYPE_I64; \ - goto OP_ATOMIC_##OP; \ - case WASM_OP_ATOMIC_RMW_I32_##NAME##8_U: \ - bytes = 1; \ - op_type = VALUE_TYPE_I32; \ - goto OP_ATOMIC_##OP; \ - case WASM_OP_ATOMIC_RMW_I32_##NAME##16_U: \ - bytes = 2; \ - op_type = VALUE_TYPE_I32; \ - goto OP_ATOMIC_##OP; \ - case WASM_OP_ATOMIC_RMW_I64_##NAME##8_U: \ - bytes = 1; \ - op_type = VALUE_TYPE_I64; \ - goto OP_ATOMIC_##OP; \ - case WASM_OP_ATOMIC_RMW_I64_##NAME##16_U: \ - bytes = 2; \ - op_type = VALUE_TYPE_I64; \ - goto OP_ATOMIC_##OP; \ - case WASM_OP_ATOMIC_RMW_I64_##NAME##32_U: \ - bytes = 4; \ - op_type = VALUE_TYPE_I64; \ -OP_ATOMIC_##OP: \ - bin_op = LLVMAtomicRMWBinOp##OP; \ - goto build_atomic_rmw; +#define read_leb_uint32(p, p_end, res) \ + do { \ + uint32 off = 0; \ + uint64 res64; \ + if (!read_leb(p, p_end, &off, 32, false, &res64)) \ + return false; \ + p += off; \ + res = (uint32)res64; \ + } while (0) + +#define read_leb_int32(p, p_end, res) \ + do { \ + uint32 off = 0; \ + uint64 res64; \ + if (!read_leb(p, p_end, &off, 32, true, &res64)) \ + return false; \ + p += off; \ + res = (int32)res64; \ + } while (0) + +#define read_leb_int64(p, p_end, res) \ + do { \ + uint32 off = 0; \ + uint64 res64; \ + if (!read_leb(p, p_end, &off, 64, true, &res64)) \ + return false; \ + p += off; \ + res = (int64)res64; \ + } while (0) + +#define COMPILE_ATOMIC_RMW(OP, NAME) \ + case WASM_OP_ATOMIC_RMW_I32_##NAME: \ + bytes = 4; \ + op_type = VALUE_TYPE_I32; \ + goto OP_ATOMIC_##OP; \ + case WASM_OP_ATOMIC_RMW_I64_##NAME: \ + bytes = 8; \ + op_type = VALUE_TYPE_I64; \ + goto OP_ATOMIC_##OP; \ + case WASM_OP_ATOMIC_RMW_I32_##NAME##8_U: \ + bytes = 1; \ + op_type = VALUE_TYPE_I32; \ + goto OP_ATOMIC_##OP; \ + case WASM_OP_ATOMIC_RMW_I32_##NAME##16_U: \ + bytes = 2; \ + op_type = VALUE_TYPE_I32; \ + goto OP_ATOMIC_##OP; \ + case WASM_OP_ATOMIC_RMW_I64_##NAME##8_U: \ + bytes = 1; \ + op_type = VALUE_TYPE_I64; \ + goto OP_ATOMIC_##OP; \ + case WASM_OP_ATOMIC_RMW_I64_##NAME##16_U: \ + bytes = 2; \ + op_type = VALUE_TYPE_I64; \ + goto OP_ATOMIC_##OP; \ + case WASM_OP_ATOMIC_RMW_I64_##NAME##32_U: \ + bytes = 4; \ + op_type = VALUE_TYPE_I64; \ + OP_ATOMIC_##OP : bin_op = LLVMAtomicRMWBinOp##OP; \ + goto build_atomic_rmw; static bool aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) { - AOTFuncContext *func_ctx = comp_ctx->func_ctxes[func_index]; - uint8 *frame_ip = func_ctx->aot_func->code, opcode, *p_f32, *p_f64; - uint8 *frame_ip_end = frame_ip + func_ctx->aot_func->code_size; - uint8 *param_types = NULL; - uint8 *result_types = NULL; - uint8 value_type; - uint16 param_count; - uint16 result_count; - uint32 br_depth, *br_depths, br_count; - uint32 func_idx, type_idx, mem_idx, local_idx, global_idx, i; - uint32 bytes = 4, align, offset; - uint32 type_index; - bool sign = true; - int32 i32_const; - int64 i64_const; - float32 f32_const; - float64 f64_const; - AOTFuncType *func_type = NULL; - - /* Start to translate the opcodes */ - LLVMPositionBuilderAtEnd(comp_ctx->builder, - func_ctx->block_stack.block_list_head - ->llvm_entry_block); - while (frame_ip < frame_ip_end) { - opcode = *frame_ip++; - switch (opcode) { - case WASM_OP_UNREACHABLE: - if (!aot_compile_op_unreachable(comp_ctx, func_ctx, &frame_ip)) - return false; - break; - - case WASM_OP_NOP: - break; - - case WASM_OP_BLOCK: - case WASM_OP_LOOP: - case WASM_OP_IF: - value_type = *frame_ip++; - if (value_type == VALUE_TYPE_I32 - || value_type == VALUE_TYPE_I64 - || value_type == VALUE_TYPE_F32 - || value_type == VALUE_TYPE_F64 - || value_type == VALUE_TYPE_V128 - || value_type == VALUE_TYPE_VOID - || value_type == VALUE_TYPE_FUNCREF - || value_type == VALUE_TYPE_EXTERNREF) { - param_count = 0; - param_types = NULL; - if (value_type == VALUE_TYPE_VOID) { - result_count = 0; - result_types = NULL; - } - else { - result_count = 1; - result_types = &value_type; - } - } - else { - frame_ip--; - read_leb_uint32(frame_ip, frame_ip_end, type_index); - func_type = comp_ctx->comp_data->func_types[type_index]; - param_count = func_type->param_count; - param_types = func_type->types; - result_count = func_type->result_count; - result_types = func_type->types + param_count; - } - if (!aot_compile_op_block(comp_ctx, func_ctx, - &frame_ip, frame_ip_end, - (uint32)(LABEL_TYPE_BLOCK + opcode - WASM_OP_BLOCK), - param_count, param_types, - result_count, result_types)) - return false; - break; - - case WASM_OP_ELSE: - if (!aot_compile_op_else(comp_ctx, func_ctx, &frame_ip)) - return false; - break; - - case WASM_OP_END: - if (!aot_compile_op_end(comp_ctx, func_ctx, &frame_ip)) - return false; - break; - - case WASM_OP_BR: - read_leb_uint32(frame_ip, frame_ip_end, br_depth); - if (!aot_compile_op_br(comp_ctx, func_ctx, br_depth, &frame_ip)) - return false; - break; - - case WASM_OP_BR_IF: - read_leb_uint32(frame_ip, frame_ip_end, br_depth); - if (!aot_compile_op_br_if(comp_ctx, func_ctx, br_depth, &frame_ip)) - return false; - break; - - case WASM_OP_BR_TABLE: - read_leb_uint32(frame_ip, frame_ip_end, br_count); - if (!(br_depths = - wasm_runtime_malloc((uint32)sizeof(uint32) * (br_count + 1)))) { - aot_set_last_error("allocate memory failed."); - goto fail; - } - for (i = 0; i <= br_count; i++) - read_leb_uint32(frame_ip, frame_ip_end, br_depths[i]); - - if (!aot_compile_op_br_table(comp_ctx, func_ctx, - br_depths, br_count, &frame_ip)) { - wasm_runtime_free(br_depths); - return false; - } - - wasm_runtime_free(br_depths); - break; - - case WASM_OP_RETURN: - if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip)) - return false; - break; + AOTFuncContext *func_ctx = comp_ctx->func_ctxes[func_index]; + uint8 *frame_ip = func_ctx->aot_func->code, opcode, *p_f32, *p_f64; + uint8 *frame_ip_end = frame_ip + func_ctx->aot_func->code_size; + uint8 *param_types = NULL; + uint8 *result_types = NULL; + uint8 value_type; + uint16 param_count; + uint16 result_count; + uint32 br_depth, *br_depths, br_count; + uint32 func_idx, type_idx, mem_idx, local_idx, global_idx, i; + uint32 bytes = 4, align, offset; + uint32 type_index; + bool sign = true; + int32 i32_const; + int64 i64_const; + float32 f32_const; + float64 f64_const; + AOTFuncType *func_type = NULL; +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMMetadataRef location; +#endif - case WASM_OP_CALL: - read_leb_uint32(frame_ip, frame_ip_end, func_idx); - if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, false)) - return false; - break; + /* Start to translate the opcodes */ + LLVMPositionBuilderAtEnd( + comp_ctx->builder, + func_ctx->block_stack.block_list_head->llvm_entry_block); + while (frame_ip < frame_ip_end) { + opcode = *frame_ip++; - case WASM_OP_CALL_INDIRECT: - { - uint32 tbl_idx; +#if WASM_ENABLE_DEBUG_AOT != 0 + location = dwarf_gen_location( + comp_ctx, func_ctx, + (frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code); + LLVMSetCurrentDebugLocation2(comp_ctx->builder, location); +#endif - read_leb_uint32(frame_ip, frame_ip_end, type_idx); + switch (opcode) { + case WASM_OP_UNREACHABLE: + if (!aot_compile_op_unreachable(comp_ctx, func_ctx, &frame_ip)) + return false; + break; + + case WASM_OP_NOP: + break; + + case WASM_OP_BLOCK: + case WASM_OP_LOOP: + case WASM_OP_IF: + value_type = *frame_ip++; + if (value_type == VALUE_TYPE_I32 || value_type == VALUE_TYPE_I64 + || value_type == VALUE_TYPE_F32 + || value_type == VALUE_TYPE_F64 + || value_type == VALUE_TYPE_V128 + || value_type == VALUE_TYPE_VOID + || value_type == VALUE_TYPE_FUNCREF + || value_type == VALUE_TYPE_EXTERNREF) { + param_count = 0; + param_types = NULL; + if (value_type == VALUE_TYPE_VOID) { + result_count = 0; + result_types = NULL; + } + else { + result_count = 1; + result_types = &value_type; + } + } + else { + frame_ip--; + read_leb_uint32(frame_ip, frame_ip_end, type_index); + func_type = comp_ctx->comp_data->func_types[type_index]; + param_count = func_type->param_count; + param_types = func_type->types; + result_count = func_type->result_count; + result_types = func_type->types + param_count; + } + if (!aot_compile_op_block( + comp_ctx, func_ctx, &frame_ip, frame_ip_end, + (uint32)(LABEL_TYPE_BLOCK + opcode - WASM_OP_BLOCK), + param_count, param_types, result_count, result_types)) + return false; + break; + + case WASM_OP_ELSE: + if (!aot_compile_op_else(comp_ctx, func_ctx, &frame_ip)) + return false; + break; + + case WASM_OP_END: + if (!aot_compile_op_end(comp_ctx, func_ctx, &frame_ip)) + return false; + break; + + case WASM_OP_BR: + read_leb_uint32(frame_ip, frame_ip_end, br_depth); + if (!aot_compile_op_br(comp_ctx, func_ctx, br_depth, &frame_ip)) + return false; + break; + + case WASM_OP_BR_IF: + read_leb_uint32(frame_ip, frame_ip_end, br_depth); + if (!aot_compile_op_br_if(comp_ctx, func_ctx, br_depth, + &frame_ip)) + return false; + break; + + case WASM_OP_BR_TABLE: + read_leb_uint32(frame_ip, frame_ip_end, br_count); + if (!(br_depths = wasm_runtime_malloc((uint32)sizeof(uint32) + * (br_count + 1)))) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + for (i = 0; i <= br_count; i++) + read_leb_uint32(frame_ip, frame_ip_end, br_depths[i]); + + if (!aot_compile_op_br_table(comp_ctx, func_ctx, br_depths, + br_count, &frame_ip)) { + wasm_runtime_free(br_depths); + return false; + } + + wasm_runtime_free(br_depths); + break; + + case WASM_OP_RETURN: + if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip)) + return false; + break; + + case WASM_OP_CALL: + read_leb_uint32(frame_ip, frame_ip_end, func_idx); + if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, false)) + return false; + break; + + case WASM_OP_CALL_INDIRECT: + { + uint32 tbl_idx; + + read_leb_uint32(frame_ip, frame_ip_end, type_idx); #if WASM_ENABLE_REF_TYPES != 0 - if (comp_ctx->enable_ref_types) { - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - } - else + if (comp_ctx->enable_ref_types) { + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + } + else #endif - { - frame_ip++; - tbl_idx = 0; - } + { + frame_ip++; + tbl_idx = 0; + } - if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx, - tbl_idx)) - return false; - break; - } + if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx, + tbl_idx)) + return false; + break; + } #if WASM_ENABLE_TAIL_CALL != 0 - case WASM_OP_RETURN_CALL: - if (!comp_ctx->enable_tail_call) { - aot_set_last_error("unsupported opcode"); - return false; - } - read_leb_uint32(frame_ip, frame_ip_end, func_idx); - if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, true)) - return false; - if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip)) - return false; - break; - - case WASM_OP_RETURN_CALL_INDIRECT: - { - uint32 tbl_idx; - - if (!comp_ctx->enable_tail_call) { - aot_set_last_error("unsupported opcode"); - return false; - } - - read_leb_uint32(frame_ip, frame_ip_end, type_idx); + case WASM_OP_RETURN_CALL: + if (!comp_ctx->enable_tail_call) { + aot_set_last_error("unsupported opcode"); + return false; + } + read_leb_uint32(frame_ip, frame_ip_end, func_idx); + if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, true)) + return false; + if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip)) + return false; + break; + + case WASM_OP_RETURN_CALL_INDIRECT: + { + uint32 tbl_idx; + + if (!comp_ctx->enable_tail_call) { + aot_set_last_error("unsupported opcode"); + return false; + } + + read_leb_uint32(frame_ip, frame_ip_end, type_idx); #if WASM_ENABLE_REF_TYPES != 0 - if (comp_ctx->enable_ref_types) { - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - } - else + if (comp_ctx->enable_ref_types) { + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + } + else #endif - { - frame_ip++; - tbl_idx = 0; - } - - if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx, - tbl_idx)) - return false; - if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip)) - return false; - break; - } + { + frame_ip++; + tbl_idx = 0; + } + + if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx, + tbl_idx)) + return false; + if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip)) + return false; + break; + } #endif /* end of WASM_ENABLE_TAIL_CALL */ - case WASM_OP_DROP: - if (!aot_compile_op_drop(comp_ctx, func_ctx, true)) - return false; - break; + case WASM_OP_DROP: + if (!aot_compile_op_drop(comp_ctx, func_ctx, true)) + return false; + break; - case WASM_OP_DROP_64: - if (!aot_compile_op_drop(comp_ctx, func_ctx, false)) - return false; - break; + case WASM_OP_DROP_64: + if (!aot_compile_op_drop(comp_ctx, func_ctx, false)) + return false; + break; - case WASM_OP_SELECT: - if (!aot_compile_op_select(comp_ctx, func_ctx, true)) - return false; - break; + case WASM_OP_SELECT: + if (!aot_compile_op_select(comp_ctx, func_ctx, true)) + return false; + break; - case WASM_OP_SELECT_64: - if (!aot_compile_op_select(comp_ctx, func_ctx, false)) - return false; - break; + case WASM_OP_SELECT_64: + if (!aot_compile_op_select(comp_ctx, func_ctx, false)) + return false; + break; #if WASM_ENABLE_REF_TYPES != 0 - case WASM_OP_SELECT_T: - { - uint32 vec_len; - - if (!comp_ctx->enable_ref_types) { - goto unsupport_ref_types; - } - - read_leb_uint32(frame_ip, frame_ip_end, vec_len); - bh_assert(vec_len == 1); - vec_len = vec_len; - - type_idx = *frame_ip++; - if (!aot_compile_op_select(comp_ctx, func_ctx, - (type_idx != VALUE_TYPE_I64) - && (type_idx != VALUE_TYPE_F64))) - return false; - break; - } - case WASM_OP_TABLE_GET: - { - uint32 tbl_idx; - - if (!comp_ctx->enable_ref_types) { - goto unsupport_ref_types; - } - - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - if (!aot_compile_op_table_get(comp_ctx, func_ctx, tbl_idx)) - return false; - break; - } - case WASM_OP_TABLE_SET: - { - uint32 tbl_idx; - - if (!comp_ctx->enable_ref_types) { - goto unsupport_ref_types; - } - - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - if (!aot_compile_op_table_set(comp_ctx, func_ctx, tbl_idx)) - return false; - break; - } - case WASM_OP_REF_NULL: - { - uint32 type; - - if (!comp_ctx->enable_ref_types) { - goto unsupport_ref_types; - } - - read_leb_uint32(frame_ip, frame_ip_end, type); - - if (!aot_compile_op_ref_null(comp_ctx, func_ctx)) - return false; - - (void)type; - break; - } - case WASM_OP_REF_IS_NULL: - { - if (!comp_ctx->enable_ref_types) { - goto unsupport_ref_types; - } - - if (!aot_compile_op_ref_is_null(comp_ctx, func_ctx)) - return false; - break; - } - case WASM_OP_REF_FUNC: - { - uint32 func_idx; - - if (!comp_ctx->enable_ref_types) { - goto unsupport_ref_types; - } - - read_leb_uint32(frame_ip, frame_ip_end, func_idx); - if (!aot_compile_op_ref_func(comp_ctx, func_ctx, func_idx)) - return false; - break; - } + case WASM_OP_SELECT_T: + { + uint32 vec_len; + + if (!comp_ctx->enable_ref_types) { + goto unsupport_ref_types; + } + + read_leb_uint32(frame_ip, frame_ip_end, vec_len); + bh_assert(vec_len == 1); + (void)vec_len; + + type_idx = *frame_ip++; + if (!aot_compile_op_select(comp_ctx, func_ctx, + (type_idx != VALUE_TYPE_I64) + && (type_idx != VALUE_TYPE_F64))) + return false; + break; + } + case WASM_OP_TABLE_GET: + { + uint32 tbl_idx; + + if (!comp_ctx->enable_ref_types) { + goto unsupport_ref_types; + } + + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + if (!aot_compile_op_table_get(comp_ctx, func_ctx, tbl_idx)) + return false; + break; + } + case WASM_OP_TABLE_SET: + { + uint32 tbl_idx; + + if (!comp_ctx->enable_ref_types) { + goto unsupport_ref_types; + } + + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + if (!aot_compile_op_table_set(comp_ctx, func_ctx, tbl_idx)) + return false; + break; + } + case WASM_OP_REF_NULL: + { + uint32 type; + + if (!comp_ctx->enable_ref_types) { + goto unsupport_ref_types; + } + + read_leb_uint32(frame_ip, frame_ip_end, type); + + if (!aot_compile_op_ref_null(comp_ctx, func_ctx)) + return false; + + (void)type; + break; + } + case WASM_OP_REF_IS_NULL: + { + if (!comp_ctx->enable_ref_types) { + goto unsupport_ref_types; + } + + if (!aot_compile_op_ref_is_null(comp_ctx, func_ctx)) + return false; + break; + } + case WASM_OP_REF_FUNC: + { + uint32 func_idx; + + if (!comp_ctx->enable_ref_types) { + goto unsupport_ref_types; + } + + read_leb_uint32(frame_ip, frame_ip_end, func_idx); + if (!aot_compile_op_ref_func(comp_ctx, func_ctx, func_idx)) + return false; + break; + } #endif - case WASM_OP_GET_LOCAL: - read_leb_uint32(frame_ip, frame_ip_end, local_idx); - if (!aot_compile_op_get_local(comp_ctx, func_ctx, local_idx)) - return false; - break; - - case WASM_OP_SET_LOCAL: - read_leb_uint32(frame_ip, frame_ip_end, local_idx); - if (!aot_compile_op_set_local(comp_ctx, func_ctx, local_idx)) - return false; - break; - - case WASM_OP_TEE_LOCAL: - read_leb_uint32(frame_ip, frame_ip_end, local_idx); - if (!aot_compile_op_tee_local(comp_ctx, func_ctx, local_idx)) - return false; - break; - - case WASM_OP_GET_GLOBAL: - read_leb_uint32(frame_ip, frame_ip_end, global_idx); - if (!aot_compile_op_get_global(comp_ctx, func_ctx, global_idx)) - return false; - break; - - case WASM_OP_SET_GLOBAL: - case WASM_OP_SET_GLOBAL_64: - case WASM_OP_SET_GLOBAL_AUX_STACK: - read_leb_uint32(frame_ip, frame_ip_end, global_idx); - if (!aot_compile_op_set_global(comp_ctx, func_ctx, global_idx, - opcode == WASM_OP_SET_GLOBAL_AUX_STACK - ? true : false)) - return false; - break; - - case WASM_OP_I32_LOAD: - bytes = 4; - sign = true; - goto op_i32_load; - case WASM_OP_I32_LOAD8_S: - case WASM_OP_I32_LOAD8_U: - bytes = 1; - sign = (opcode == WASM_OP_I32_LOAD8_S) ? true : false; - goto op_i32_load; - case WASM_OP_I32_LOAD16_S: - case WASM_OP_I32_LOAD16_U: - bytes = 2; - sign = (opcode == WASM_OP_I32_LOAD16_S) ? true : false; - op_i32_load: - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_op_i32_load(comp_ctx, func_ctx, align, offset, - bytes, sign, false)) - return false; - break; - - case WASM_OP_I64_LOAD: - bytes = 8; - sign = true; - goto op_i64_load; - case WASM_OP_I64_LOAD8_S: - case WASM_OP_I64_LOAD8_U: - bytes = 1; - sign = (opcode == WASM_OP_I64_LOAD8_S) ? true : false; - goto op_i64_load; - case WASM_OP_I64_LOAD16_S: - case WASM_OP_I64_LOAD16_U: - bytes = 2; - sign = (opcode == WASM_OP_I64_LOAD16_S) ? true : false; - goto op_i64_load; - case WASM_OP_I64_LOAD32_S: - case WASM_OP_I64_LOAD32_U: - bytes = 4; - sign = (opcode == WASM_OP_I64_LOAD32_S) ? true : false; - op_i64_load: - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_op_i64_load(comp_ctx, func_ctx, align, offset, - bytes, sign, false)) - return false; - break; - - case WASM_OP_F32_LOAD: - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_op_f32_load(comp_ctx, func_ctx, align, offset)) - return false; - break; - - case WASM_OP_F64_LOAD: - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_op_f64_load(comp_ctx, func_ctx, align, offset)) - return false; - break; - - case WASM_OP_I32_STORE: - bytes = 4; - goto op_i32_store; - case WASM_OP_I32_STORE8: - bytes = 1; - goto op_i32_store; - case WASM_OP_I32_STORE16: - bytes = 2; - op_i32_store: - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_op_i32_store(comp_ctx, func_ctx, align, - offset, bytes, false)) - return false; - break; - - case WASM_OP_I64_STORE: - bytes = 8; - goto op_i64_store; - case WASM_OP_I64_STORE8: - bytes = 1; - goto op_i64_store; - case WASM_OP_I64_STORE16: - bytes = 2; - goto op_i64_store; - case WASM_OP_I64_STORE32: - bytes = 4; - op_i64_store: - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_op_i64_store(comp_ctx, func_ctx, align, - offset, bytes, false)) - return false; - break; - - case WASM_OP_F32_STORE: - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset)) - return false; - break; - - case WASM_OP_F64_STORE: - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset)) - return false; - break; - - case WASM_OP_MEMORY_SIZE: - read_leb_uint32(frame_ip, frame_ip_end, mem_idx); - if (!aot_compile_op_memory_size(comp_ctx, func_ctx)) - return false; - (void)mem_idx; - break; - - case WASM_OP_MEMORY_GROW: - read_leb_uint32(frame_ip, frame_ip_end, mem_idx); - if (!aot_compile_op_memory_grow(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I32_CONST: - read_leb_int32(frame_ip, frame_ip_end, i32_const); - if (!aot_compile_op_i32_const(comp_ctx, func_ctx, i32_const)) - return false; - break; - - case WASM_OP_I64_CONST: - read_leb_int64(frame_ip, frame_ip_end, i64_const); - if (!aot_compile_op_i64_const(comp_ctx, func_ctx, i64_const)) - return false; - break; - - case WASM_OP_F32_CONST: - p_f32 = (uint8*)&f32_const; - for (i = 0; i < sizeof(float32); i++) - *p_f32++ = *frame_ip++; - if (!aot_compile_op_f32_const(comp_ctx, func_ctx, f32_const)) - return false; - break; - - case WASM_OP_F64_CONST: - p_f64 = (uint8*)&f64_const; - for (i = 0; i < sizeof(float64); i++) - *p_f64++ = *frame_ip++; - if (!aot_compile_op_f64_const(comp_ctx, func_ctx, f64_const)) - return false; - break; - - case WASM_OP_I32_EQZ: - case WASM_OP_I32_EQ: - case WASM_OP_I32_NE: - case WASM_OP_I32_LT_S: - case WASM_OP_I32_LT_U: - case WASM_OP_I32_GT_S: - case WASM_OP_I32_GT_U: - case WASM_OP_I32_LE_S: - case WASM_OP_I32_LE_U: - case WASM_OP_I32_GE_S: - case WASM_OP_I32_GE_U: - if (!aot_compile_op_i32_compare(comp_ctx, func_ctx, - INT_EQZ + opcode - WASM_OP_I32_EQZ)) - return false; - break; - - case WASM_OP_I64_EQZ: - case WASM_OP_I64_EQ: - case WASM_OP_I64_NE: - case WASM_OP_I64_LT_S: - case WASM_OP_I64_LT_U: - case WASM_OP_I64_GT_S: - case WASM_OP_I64_GT_U: - case WASM_OP_I64_LE_S: - case WASM_OP_I64_LE_U: - case WASM_OP_I64_GE_S: - case WASM_OP_I64_GE_U: - if (!aot_compile_op_i64_compare(comp_ctx, func_ctx, - INT_EQZ + opcode - WASM_OP_I64_EQZ)) - return false; - break; - - case WASM_OP_F32_EQ: - case WASM_OP_F32_NE: - case WASM_OP_F32_LT: - case WASM_OP_F32_GT: - case WASM_OP_F32_LE: - case WASM_OP_F32_GE: - if (!aot_compile_op_f32_compare(comp_ctx, func_ctx, - FLOAT_EQ + opcode - WASM_OP_F32_EQ)) - return false; - break; - - case WASM_OP_F64_EQ: - case WASM_OP_F64_NE: - case WASM_OP_F64_LT: - case WASM_OP_F64_GT: - case WASM_OP_F64_LE: - case WASM_OP_F64_GE: - if (!aot_compile_op_f64_compare(comp_ctx, func_ctx, - FLOAT_EQ + opcode - WASM_OP_F64_EQ)) - return false; - break; - - case WASM_OP_I32_CLZ: - if (!aot_compile_op_i32_clz(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I32_CTZ: - if (!aot_compile_op_i32_ctz(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I32_POPCNT: - if (!aot_compile_op_i32_popcnt(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I32_ADD: - case WASM_OP_I32_SUB: - case WASM_OP_I32_MUL: - case WASM_OP_I32_DIV_S: - case WASM_OP_I32_DIV_U: - case WASM_OP_I32_REM_S: - case WASM_OP_I32_REM_U: - if (!aot_compile_op_i32_arithmetic(comp_ctx, func_ctx, - INT_ADD + opcode - WASM_OP_I32_ADD, - &frame_ip)) - return false; - break; - - case WASM_OP_I32_AND: - case WASM_OP_I32_OR: - case WASM_OP_I32_XOR: - if (!aot_compile_op_i32_bitwise(comp_ctx, func_ctx, - INT_SHL + opcode - WASM_OP_I32_AND)) - return false; - break; - - case WASM_OP_I32_SHL: - case WASM_OP_I32_SHR_S: - case WASM_OP_I32_SHR_U: - case WASM_OP_I32_ROTL: - case WASM_OP_I32_ROTR: - if (!aot_compile_op_i32_shift(comp_ctx, func_ctx, - INT_SHL + opcode - WASM_OP_I32_SHL)) - return false; - break; - - case WASM_OP_I64_CLZ: - if (!aot_compile_op_i64_clz(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I64_CTZ: - if (!aot_compile_op_i64_ctz(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I64_POPCNT: - if (!aot_compile_op_i64_popcnt(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I64_ADD: - case WASM_OP_I64_SUB: - case WASM_OP_I64_MUL: - case WASM_OP_I64_DIV_S: - case WASM_OP_I64_DIV_U: - case WASM_OP_I64_REM_S: - case WASM_OP_I64_REM_U: - if (!aot_compile_op_i64_arithmetic(comp_ctx, func_ctx, - INT_ADD + opcode - WASM_OP_I64_ADD, - &frame_ip)) - return false; - break; - - case WASM_OP_I64_AND: - case WASM_OP_I64_OR: - case WASM_OP_I64_XOR: - if (!aot_compile_op_i64_bitwise(comp_ctx, func_ctx, - INT_SHL + opcode - WASM_OP_I64_AND)) - return false; - break; - - case WASM_OP_I64_SHL: - case WASM_OP_I64_SHR_S: - case WASM_OP_I64_SHR_U: - case WASM_OP_I64_ROTL: - case WASM_OP_I64_ROTR: - if (!aot_compile_op_i64_shift(comp_ctx, func_ctx, - INT_SHL + opcode - WASM_OP_I64_SHL)) - return false; - break; - - case WASM_OP_F32_ABS: - case WASM_OP_F32_NEG: - case WASM_OP_F32_CEIL: - case WASM_OP_F32_FLOOR: - case WASM_OP_F32_TRUNC: - case WASM_OP_F32_NEAREST: - case WASM_OP_F32_SQRT: - if (!aot_compile_op_f32_math(comp_ctx, func_ctx, - FLOAT_ABS + opcode - WASM_OP_F32_ABS)) - return false; - break; - - case WASM_OP_F32_ADD: - case WASM_OP_F32_SUB: - case WASM_OP_F32_MUL: - case WASM_OP_F32_DIV: - case WASM_OP_F32_MIN: - case WASM_OP_F32_MAX: - if (!aot_compile_op_f32_arithmetic(comp_ctx, func_ctx, - FLOAT_ADD + opcode - WASM_OP_F32_ADD)) - return false; - break; - - case WASM_OP_F32_COPYSIGN: - if (!aot_compile_op_f32_copysign(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_F64_ABS: - case WASM_OP_F64_NEG: - case WASM_OP_F64_CEIL: - case WASM_OP_F64_FLOOR: - case WASM_OP_F64_TRUNC: - case WASM_OP_F64_NEAREST: - case WASM_OP_F64_SQRT: - if (!aot_compile_op_f64_math(comp_ctx, func_ctx, - FLOAT_ABS + opcode - WASM_OP_F64_ABS)) - return false; - break; - - case WASM_OP_F64_ADD: - case WASM_OP_F64_SUB: - case WASM_OP_F64_MUL: - case WASM_OP_F64_DIV: - case WASM_OP_F64_MIN: - case WASM_OP_F64_MAX: - if (!aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, - FLOAT_ADD + opcode - WASM_OP_F64_ADD)) - return false; - break; - - case WASM_OP_F64_COPYSIGN: - if (!aot_compile_op_f64_copysign(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I32_WRAP_I64: - if (!aot_compile_op_i32_wrap_i64(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I32_TRUNC_S_F32: - case WASM_OP_I32_TRUNC_U_F32: - sign = (opcode == WASM_OP_I32_TRUNC_S_F32) ? true : false; - if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign, false)) - return false; - break; - - case WASM_OP_I32_TRUNC_S_F64: - case WASM_OP_I32_TRUNC_U_F64: - sign = (opcode == WASM_OP_I32_TRUNC_S_F64) ? true : false; - if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign, false)) - return false; - break; - - case WASM_OP_I64_EXTEND_S_I32: - case WASM_OP_I64_EXTEND_U_I32: - sign = (opcode == WASM_OP_I64_EXTEND_S_I32) ? true : false; - if (!aot_compile_op_i64_extend_i32(comp_ctx, func_ctx, sign)) - return false; - break; - - case WASM_OP_I64_TRUNC_S_F32: - case WASM_OP_I64_TRUNC_U_F32: - sign = (opcode == WASM_OP_I64_TRUNC_S_F32) ? true : false; - if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign, false)) - return false; - break; - - case WASM_OP_I64_TRUNC_S_F64: - case WASM_OP_I64_TRUNC_U_F64: - sign = (opcode == WASM_OP_I64_TRUNC_S_F64) ? true : false; - if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign, false)) - return false; - break; - - case WASM_OP_F32_CONVERT_S_I32: - case WASM_OP_F32_CONVERT_U_I32: - sign = (opcode == WASM_OP_F32_CONVERT_S_I32) ? true : false; - if (!aot_compile_op_f32_convert_i32(comp_ctx, func_ctx, sign)) - return false; - break; - - case WASM_OP_F32_CONVERT_S_I64: - case WASM_OP_F32_CONVERT_U_I64: - sign = (opcode == WASM_OP_F32_CONVERT_S_I64) ? true : false; - if (!aot_compile_op_f32_convert_i64(comp_ctx, func_ctx, sign)) - return false; - break; - - case WASM_OP_F32_DEMOTE_F64: - if (!aot_compile_op_f32_demote_f64(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_F64_CONVERT_S_I32: - case WASM_OP_F64_CONVERT_U_I32: - sign = (opcode == WASM_OP_F64_CONVERT_S_I32) ? true : false; - if (!aot_compile_op_f64_convert_i32(comp_ctx, func_ctx, sign)) - return false; - break; - - case WASM_OP_F64_CONVERT_S_I64: - case WASM_OP_F64_CONVERT_U_I64: - sign = (opcode == WASM_OP_F64_CONVERT_S_I64) ? true : false; - if (!aot_compile_op_f64_convert_i64(comp_ctx, func_ctx, sign)) - return false; - break; - - case WASM_OP_F64_PROMOTE_F32: - if (!aot_compile_op_f64_promote_f32(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I32_REINTERPRET_F32: - if (!aot_compile_op_i32_reinterpret_f32(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I64_REINTERPRET_F64: - if (!aot_compile_op_i64_reinterpret_f64(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_F32_REINTERPRET_I32: - if (!aot_compile_op_f32_reinterpret_i32(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_F64_REINTERPRET_I64: - if (!aot_compile_op_f64_reinterpret_i64(comp_ctx, func_ctx)) - return false; - break; - - case WASM_OP_I32_EXTEND8_S: - if (!aot_compile_op_i32_extend_i32(comp_ctx, func_ctx, 8)) - return false; - break; - - case WASM_OP_I32_EXTEND16_S: - if (!aot_compile_op_i32_extend_i32(comp_ctx, func_ctx, 16)) - return false; - break; - - case WASM_OP_I64_EXTEND8_S: - if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 8)) - return false; - break; - - case WASM_OP_I64_EXTEND16_S: - if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 16)) - return false; - break; - - case WASM_OP_I64_EXTEND32_S: - if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 32)) - return false; - break; - - case WASM_OP_MISC_PREFIX: - { - uint32 opcode1; - - read_leb_uint32(frame_ip, frame_ip_end, opcode1); - opcode = (uint32)opcode1; - - //TODO: --enable-bulk-memory ? + case WASM_OP_GET_LOCAL: + read_leb_uint32(frame_ip, frame_ip_end, local_idx); + if (!aot_compile_op_get_local(comp_ctx, func_ctx, local_idx)) + return false; + break; + + case WASM_OP_SET_LOCAL: + read_leb_uint32(frame_ip, frame_ip_end, local_idx); + if (!aot_compile_op_set_local(comp_ctx, func_ctx, local_idx)) + return false; + break; + + case WASM_OP_TEE_LOCAL: + read_leb_uint32(frame_ip, frame_ip_end, local_idx); + if (!aot_compile_op_tee_local(comp_ctx, func_ctx, local_idx)) + return false; + break; + + case WASM_OP_GET_GLOBAL: + read_leb_uint32(frame_ip, frame_ip_end, global_idx); + if (!aot_compile_op_get_global(comp_ctx, func_ctx, global_idx)) + return false; + break; + + case WASM_OP_SET_GLOBAL: + case WASM_OP_SET_GLOBAL_64: + case WASM_OP_SET_GLOBAL_AUX_STACK: + read_leb_uint32(frame_ip, frame_ip_end, global_idx); + if (!aot_compile_op_set_global( + comp_ctx, func_ctx, global_idx, + opcode == WASM_OP_SET_GLOBAL_AUX_STACK ? true : false)) + return false; + break; + + case WASM_OP_I32_LOAD: + bytes = 4; + sign = true; + goto op_i32_load; + case WASM_OP_I32_LOAD8_S: + case WASM_OP_I32_LOAD8_U: + bytes = 1; + sign = (opcode == WASM_OP_I32_LOAD8_S) ? true : false; + goto op_i32_load; + case WASM_OP_I32_LOAD16_S: + case WASM_OP_I32_LOAD16_U: + bytes = 2; + sign = (opcode == WASM_OP_I32_LOAD16_S) ? true : false; + op_i32_load: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_i32_load(comp_ctx, func_ctx, align, offset, + bytes, sign, false)) + return false; + break; + + case WASM_OP_I64_LOAD: + bytes = 8; + sign = true; + goto op_i64_load; + case WASM_OP_I64_LOAD8_S: + case WASM_OP_I64_LOAD8_U: + bytes = 1; + sign = (opcode == WASM_OP_I64_LOAD8_S) ? true : false; + goto op_i64_load; + case WASM_OP_I64_LOAD16_S: + case WASM_OP_I64_LOAD16_U: + bytes = 2; + sign = (opcode == WASM_OP_I64_LOAD16_S) ? true : false; + goto op_i64_load; + case WASM_OP_I64_LOAD32_S: + case WASM_OP_I64_LOAD32_U: + bytes = 4; + sign = (opcode == WASM_OP_I64_LOAD32_S) ? true : false; + op_i64_load: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_i64_load(comp_ctx, func_ctx, align, offset, + bytes, sign, false)) + return false; + break; + + case WASM_OP_F32_LOAD: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_f32_load(comp_ctx, func_ctx, align, offset)) + return false; + break; + + case WASM_OP_F64_LOAD: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_f64_load(comp_ctx, func_ctx, align, offset)) + return false; + break; + + case WASM_OP_I32_STORE: + bytes = 4; + goto op_i32_store; + case WASM_OP_I32_STORE8: + bytes = 1; + goto op_i32_store; + case WASM_OP_I32_STORE16: + bytes = 2; + op_i32_store: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset, + bytes, false)) + return false; + break; + + case WASM_OP_I64_STORE: + bytes = 8; + goto op_i64_store; + case WASM_OP_I64_STORE8: + bytes = 1; + goto op_i64_store; + case WASM_OP_I64_STORE16: + bytes = 2; + goto op_i64_store; + case WASM_OP_I64_STORE32: + bytes = 4; + op_i64_store: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset, + bytes, false)) + return false; + break; + + case WASM_OP_F32_STORE: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_f32_store(comp_ctx, func_ctx, align, + offset)) + return false; + break; + + case WASM_OP_F64_STORE: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_f64_store(comp_ctx, func_ctx, align, + offset)) + return false; + break; + + case WASM_OP_MEMORY_SIZE: + read_leb_uint32(frame_ip, frame_ip_end, mem_idx); + if (!aot_compile_op_memory_size(comp_ctx, func_ctx)) + return false; + (void)mem_idx; + break; + + case WASM_OP_MEMORY_GROW: + read_leb_uint32(frame_ip, frame_ip_end, mem_idx); + if (!aot_compile_op_memory_grow(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_CONST: + read_leb_int32(frame_ip, frame_ip_end, i32_const); + if (!aot_compile_op_i32_const(comp_ctx, func_ctx, i32_const)) + return false; + break; + + case WASM_OP_I64_CONST: + read_leb_int64(frame_ip, frame_ip_end, i64_const); + if (!aot_compile_op_i64_const(comp_ctx, func_ctx, i64_const)) + return false; + break; + + case WASM_OP_F32_CONST: + p_f32 = (uint8 *)&f32_const; + for (i = 0; i < sizeof(float32); i++) + *p_f32++ = *frame_ip++; + if (!aot_compile_op_f32_const(comp_ctx, func_ctx, f32_const)) + return false; + break; + + case WASM_OP_F64_CONST: + p_f64 = (uint8 *)&f64_const; + for (i = 0; i < sizeof(float64); i++) + *p_f64++ = *frame_ip++; + if (!aot_compile_op_f64_const(comp_ctx, func_ctx, f64_const)) + return false; + break; + + case WASM_OP_I32_EQZ: + case WASM_OP_I32_EQ: + case WASM_OP_I32_NE: + case WASM_OP_I32_LT_S: + case WASM_OP_I32_LT_U: + case WASM_OP_I32_GT_S: + case WASM_OP_I32_GT_U: + case WASM_OP_I32_LE_S: + case WASM_OP_I32_LE_U: + case WASM_OP_I32_GE_S: + case WASM_OP_I32_GE_U: + if (!aot_compile_op_i32_compare( + comp_ctx, func_ctx, INT_EQZ + opcode - WASM_OP_I32_EQZ)) + return false; + break; + + case WASM_OP_I64_EQZ: + case WASM_OP_I64_EQ: + case WASM_OP_I64_NE: + case WASM_OP_I64_LT_S: + case WASM_OP_I64_LT_U: + case WASM_OP_I64_GT_S: + case WASM_OP_I64_GT_U: + case WASM_OP_I64_LE_S: + case WASM_OP_I64_LE_U: + case WASM_OP_I64_GE_S: + case WASM_OP_I64_GE_U: + if (!aot_compile_op_i64_compare( + comp_ctx, func_ctx, INT_EQZ + opcode - WASM_OP_I64_EQZ)) + return false; + break; + + case WASM_OP_F32_EQ: + case WASM_OP_F32_NE: + case WASM_OP_F32_LT: + case WASM_OP_F32_GT: + case WASM_OP_F32_LE: + case WASM_OP_F32_GE: + if (!aot_compile_op_f32_compare( + comp_ctx, func_ctx, FLOAT_EQ + opcode - WASM_OP_F32_EQ)) + return false; + break; + + case WASM_OP_F64_EQ: + case WASM_OP_F64_NE: + case WASM_OP_F64_LT: + case WASM_OP_F64_GT: + case WASM_OP_F64_LE: + case WASM_OP_F64_GE: + if (!aot_compile_op_f64_compare( + comp_ctx, func_ctx, FLOAT_EQ + opcode - WASM_OP_F64_EQ)) + return false; + break; + + case WASM_OP_I32_CLZ: + if (!aot_compile_op_i32_clz(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_CTZ: + if (!aot_compile_op_i32_ctz(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_POPCNT: + if (!aot_compile_op_i32_popcnt(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_ADD: + case WASM_OP_I32_SUB: + case WASM_OP_I32_MUL: + case WASM_OP_I32_DIV_S: + case WASM_OP_I32_DIV_U: + case WASM_OP_I32_REM_S: + case WASM_OP_I32_REM_U: + if (!aot_compile_op_i32_arithmetic( + comp_ctx, func_ctx, INT_ADD + opcode - WASM_OP_I32_ADD, + &frame_ip)) + return false; + break; + + case WASM_OP_I32_AND: + case WASM_OP_I32_OR: + case WASM_OP_I32_XOR: + if (!aot_compile_op_i32_bitwise( + comp_ctx, func_ctx, INT_SHL + opcode - WASM_OP_I32_AND)) + return false; + break; + + case WASM_OP_I32_SHL: + case WASM_OP_I32_SHR_S: + case WASM_OP_I32_SHR_U: + case WASM_OP_I32_ROTL: + case WASM_OP_I32_ROTR: + if (!aot_compile_op_i32_shift( + comp_ctx, func_ctx, INT_SHL + opcode - WASM_OP_I32_SHL)) + return false; + break; + + case WASM_OP_I64_CLZ: + if (!aot_compile_op_i64_clz(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I64_CTZ: + if (!aot_compile_op_i64_ctz(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I64_POPCNT: + if (!aot_compile_op_i64_popcnt(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I64_ADD: + case WASM_OP_I64_SUB: + case WASM_OP_I64_MUL: + case WASM_OP_I64_DIV_S: + case WASM_OP_I64_DIV_U: + case WASM_OP_I64_REM_S: + case WASM_OP_I64_REM_U: + if (!aot_compile_op_i64_arithmetic( + comp_ctx, func_ctx, INT_ADD + opcode - WASM_OP_I64_ADD, + &frame_ip)) + return false; + break; + + case WASM_OP_I64_AND: + case WASM_OP_I64_OR: + case WASM_OP_I64_XOR: + if (!aot_compile_op_i64_bitwise( + comp_ctx, func_ctx, INT_SHL + opcode - WASM_OP_I64_AND)) + return false; + break; + + case WASM_OP_I64_SHL: + case WASM_OP_I64_SHR_S: + case WASM_OP_I64_SHR_U: + case WASM_OP_I64_ROTL: + case WASM_OP_I64_ROTR: + if (!aot_compile_op_i64_shift( + comp_ctx, func_ctx, INT_SHL + opcode - WASM_OP_I64_SHL)) + return false; + break; + + case WASM_OP_F32_ABS: + case WASM_OP_F32_NEG: + case WASM_OP_F32_CEIL: + case WASM_OP_F32_FLOOR: + case WASM_OP_F32_TRUNC: + case WASM_OP_F32_NEAREST: + case WASM_OP_F32_SQRT: + if (!aot_compile_op_f32_math(comp_ctx, func_ctx, + FLOAT_ABS + opcode + - WASM_OP_F32_ABS)) + return false; + break; + + case WASM_OP_F32_ADD: + case WASM_OP_F32_SUB: + case WASM_OP_F32_MUL: + case WASM_OP_F32_DIV: + case WASM_OP_F32_MIN: + case WASM_OP_F32_MAX: + if (!aot_compile_op_f32_arithmetic(comp_ctx, func_ctx, + FLOAT_ADD + opcode + - WASM_OP_F32_ADD)) + return false; + break; + + case WASM_OP_F32_COPYSIGN: + if (!aot_compile_op_f32_copysign(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_F64_ABS: + case WASM_OP_F64_NEG: + case WASM_OP_F64_CEIL: + case WASM_OP_F64_FLOOR: + case WASM_OP_F64_TRUNC: + case WASM_OP_F64_NEAREST: + case WASM_OP_F64_SQRT: + if (!aot_compile_op_f64_math(comp_ctx, func_ctx, + FLOAT_ABS + opcode + - WASM_OP_F64_ABS)) + return false; + break; + + case WASM_OP_F64_ADD: + case WASM_OP_F64_SUB: + case WASM_OP_F64_MUL: + case WASM_OP_F64_DIV: + case WASM_OP_F64_MIN: + case WASM_OP_F64_MAX: + if (!aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, + FLOAT_ADD + opcode + - WASM_OP_F64_ADD)) + return false; + break; + + case WASM_OP_F64_COPYSIGN: + if (!aot_compile_op_f64_copysign(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_WRAP_I64: + if (!aot_compile_op_i32_wrap_i64(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_TRUNC_S_F32: + case WASM_OP_I32_TRUNC_U_F32: + sign = (opcode == WASM_OP_I32_TRUNC_S_F32) ? true : false; + if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign, + false)) + return false; + break; + + case WASM_OP_I32_TRUNC_S_F64: + case WASM_OP_I32_TRUNC_U_F64: + sign = (opcode == WASM_OP_I32_TRUNC_S_F64) ? true : false; + if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign, + false)) + return false; + break; + + case WASM_OP_I64_EXTEND_S_I32: + case WASM_OP_I64_EXTEND_U_I32: + sign = (opcode == WASM_OP_I64_EXTEND_S_I32) ? true : false; + if (!aot_compile_op_i64_extend_i32(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_I64_TRUNC_S_F32: + case WASM_OP_I64_TRUNC_U_F32: + sign = (opcode == WASM_OP_I64_TRUNC_S_F32) ? true : false; + if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign, + false)) + return false; + break; + + case WASM_OP_I64_TRUNC_S_F64: + case WASM_OP_I64_TRUNC_U_F64: + sign = (opcode == WASM_OP_I64_TRUNC_S_F64) ? true : false; + if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign, + false)) + return false; + break; + + case WASM_OP_F32_CONVERT_S_I32: + case WASM_OP_F32_CONVERT_U_I32: + sign = (opcode == WASM_OP_F32_CONVERT_S_I32) ? true : false; + if (!aot_compile_op_f32_convert_i32(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_F32_CONVERT_S_I64: + case WASM_OP_F32_CONVERT_U_I64: + sign = (opcode == WASM_OP_F32_CONVERT_S_I64) ? true : false; + if (!aot_compile_op_f32_convert_i64(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_F32_DEMOTE_F64: + if (!aot_compile_op_f32_demote_f64(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_F64_CONVERT_S_I32: + case WASM_OP_F64_CONVERT_U_I32: + sign = (opcode == WASM_OP_F64_CONVERT_S_I32) ? true : false; + if (!aot_compile_op_f64_convert_i32(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_F64_CONVERT_S_I64: + case WASM_OP_F64_CONVERT_U_I64: + sign = (opcode == WASM_OP_F64_CONVERT_S_I64) ? true : false; + if (!aot_compile_op_f64_convert_i64(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_F64_PROMOTE_F32: + if (!aot_compile_op_f64_promote_f32(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_REINTERPRET_F32: + if (!aot_compile_op_i32_reinterpret_f32(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I64_REINTERPRET_F64: + if (!aot_compile_op_i64_reinterpret_f64(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_F32_REINTERPRET_I32: + if (!aot_compile_op_f32_reinterpret_i32(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_F64_REINTERPRET_I64: + if (!aot_compile_op_f64_reinterpret_i64(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_EXTEND8_S: + if (!aot_compile_op_i32_extend_i32(comp_ctx, func_ctx, 8)) + return false; + break; + + case WASM_OP_I32_EXTEND16_S: + if (!aot_compile_op_i32_extend_i32(comp_ctx, func_ctx, 16)) + return false; + break; + + case WASM_OP_I64_EXTEND8_S: + if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 8)) + return false; + break; + + case WASM_OP_I64_EXTEND16_S: + if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 16)) + return false; + break; + + case WASM_OP_I64_EXTEND32_S: + if (!aot_compile_op_i64_extend_i64(comp_ctx, func_ctx, 32)) + return false; + break; + + case WASM_OP_MISC_PREFIX: + { + uint32 opcode1; + + read_leb_uint32(frame_ip, frame_ip_end, opcode1); + opcode = (uint32)opcode1; + + /* TODO: --enable-bulk-memory ? */ #if WASM_ENABLE_REF_TYPES != 0 - if (WASM_OP_TABLE_INIT <= opcode && opcode <= WASM_OP_TABLE_FILL - && !comp_ctx->enable_ref_types) { - goto unsupport_ref_types; - } + if (WASM_OP_TABLE_INIT <= opcode && opcode <= WASM_OP_TABLE_FILL + && !comp_ctx->enable_ref_types) { + goto unsupport_ref_types; + } #endif - switch (opcode) { - case WASM_OP_I32_TRUNC_SAT_S_F32: - case WASM_OP_I32_TRUNC_SAT_U_F32: - sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F32) ? true : false; - if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign, true)) - return false; - break; - case WASM_OP_I32_TRUNC_SAT_S_F64: - case WASM_OP_I32_TRUNC_SAT_U_F64: - sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F64) ? true : false; - if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign, true)) - return false; - break; - case WASM_OP_I64_TRUNC_SAT_S_F32: - case WASM_OP_I64_TRUNC_SAT_U_F32: - sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F32) ? true : false; - if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign, true)) - return false; - break; - case WASM_OP_I64_TRUNC_SAT_S_F64: - case WASM_OP_I64_TRUNC_SAT_U_F64: - sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F64) ? true : false; - if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign, true)) - return false; - break; + switch (opcode) { + case WASM_OP_I32_TRUNC_SAT_S_F32: + case WASM_OP_I32_TRUNC_SAT_U_F32: + sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F32) ? true + : false; + if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, + sign, true)) + return false; + break; + case WASM_OP_I32_TRUNC_SAT_S_F64: + case WASM_OP_I32_TRUNC_SAT_U_F64: + sign = (opcode == WASM_OP_I32_TRUNC_SAT_S_F64) ? true + : false; + if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, + sign, true)) + return false; + break; + case WASM_OP_I64_TRUNC_SAT_S_F32: + case WASM_OP_I64_TRUNC_SAT_U_F32: + sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F32) ? true + : false; + if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, + sign, true)) + return false; + break; + case WASM_OP_I64_TRUNC_SAT_S_F64: + case WASM_OP_I64_TRUNC_SAT_U_F64: + sign = (opcode == WASM_OP_I64_TRUNC_SAT_S_F64) ? true + : false; + if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, + sign, true)) + return false; + break; #if WASM_ENABLE_BULK_MEMORY != 0 - case WASM_OP_MEMORY_INIT: - { - uint32 seg_index; - read_leb_uint32(frame_ip, frame_ip_end, seg_index); - frame_ip ++; - if (!aot_compile_op_memory_init(comp_ctx, func_ctx, seg_index)) - return false; - break; - } - case WASM_OP_DATA_DROP: - { - uint32 seg_index; - read_leb_uint32(frame_ip, frame_ip_end, seg_index); - if (!aot_compile_op_data_drop(comp_ctx, func_ctx, seg_index)) - return false; - break; - } - case WASM_OP_MEMORY_COPY: - { - frame_ip += 2; - if (!aot_compile_op_memory_copy(comp_ctx, func_ctx)) - return false; - break; - } - case WASM_OP_MEMORY_FILL: - { - frame_ip ++; - if (!aot_compile_op_memory_fill(comp_ctx, func_ctx)) - return false; - break; - } + case WASM_OP_MEMORY_INIT: + { + uint32 seg_index; + read_leb_uint32(frame_ip, frame_ip_end, seg_index); + frame_ip++; + if (!aot_compile_op_memory_init(comp_ctx, func_ctx, + seg_index)) + return false; + break; + } + case WASM_OP_DATA_DROP: + { + uint32 seg_index; + read_leb_uint32(frame_ip, frame_ip_end, seg_index); + if (!aot_compile_op_data_drop(comp_ctx, func_ctx, + seg_index)) + return false; + break; + } + case WASM_OP_MEMORY_COPY: + { + frame_ip += 2; + if (!aot_compile_op_memory_copy(comp_ctx, func_ctx)) + return false; + break; + } + case WASM_OP_MEMORY_FILL: + { + frame_ip++; + if (!aot_compile_op_memory_fill(comp_ctx, func_ctx)) + return false; + break; + } #endif /* WASM_ENABLE_BULK_MEMORY */ #if WASM_ENABLE_REF_TYPES != 0 - case WASM_OP_TABLE_INIT: - { - uint32 tbl_idx, tbl_seg_idx; - - read_leb_uint32(frame_ip, frame_ip_end, tbl_seg_idx); - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - if (!aot_compile_op_table_init(comp_ctx, func_ctx, tbl_idx, - tbl_seg_idx)) - return false; - break; - } - case WASM_OP_ELEM_DROP: - { - uint32 tbl_seg_idx; - - read_leb_uint32(frame_ip, frame_ip_end, tbl_seg_idx); - if (!aot_compile_op_elem_drop(comp_ctx, func_ctx, tbl_seg_idx)) - return false; - break; - } - case WASM_OP_TABLE_COPY: - { - uint32 src_tbl_idx, dst_tbl_idx; - - read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx); - read_leb_uint32(frame_ip, frame_ip_end, src_tbl_idx); - if (!aot_compile_op_table_copy(comp_ctx, func_ctx, src_tbl_idx, - dst_tbl_idx)) - return false; - break; - } - case WASM_OP_TABLE_GROW: - { - uint32 tbl_idx; - - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - if (!aot_compile_op_table_grow(comp_ctx, func_ctx, tbl_idx)) - return false; - break; - } - - case WASM_OP_TABLE_SIZE: - { - uint32 tbl_idx; - - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - if (!aot_compile_op_table_size(comp_ctx, func_ctx, tbl_idx)) - return false; - break; - } - case WASM_OP_TABLE_FILL: - { - uint32 tbl_idx; - - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - if (!aot_compile_op_table_fill(comp_ctx, func_ctx, tbl_idx)) - return false; - break; - } + case WASM_OP_TABLE_INIT: + { + uint32 tbl_idx, tbl_seg_idx; + + read_leb_uint32(frame_ip, frame_ip_end, tbl_seg_idx); + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + if (!aot_compile_op_table_init(comp_ctx, func_ctx, + tbl_idx, tbl_seg_idx)) + return false; + break; + } + case WASM_OP_ELEM_DROP: + { + uint32 tbl_seg_idx; + + read_leb_uint32(frame_ip, frame_ip_end, tbl_seg_idx); + if (!aot_compile_op_elem_drop(comp_ctx, func_ctx, + tbl_seg_idx)) + return false; + break; + } + case WASM_OP_TABLE_COPY: + { + uint32 src_tbl_idx, dst_tbl_idx; + + read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx); + read_leb_uint32(frame_ip, frame_ip_end, src_tbl_idx); + if (!aot_compile_op_table_copy( + comp_ctx, func_ctx, src_tbl_idx, dst_tbl_idx)) + return false; + break; + } + case WASM_OP_TABLE_GROW: + { + uint32 tbl_idx; + + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + if (!aot_compile_op_table_grow(comp_ctx, func_ctx, + tbl_idx)) + return false; + break; + } + + case WASM_OP_TABLE_SIZE: + { + uint32 tbl_idx; + + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + if (!aot_compile_op_table_size(comp_ctx, func_ctx, + tbl_idx)) + return false; + break; + } + case WASM_OP_TABLE_FILL: + { + uint32 tbl_idx; + + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + if (!aot_compile_op_table_fill(comp_ctx, func_ctx, + tbl_idx)) + return false; + break; + } #endif /* WASM_ENABLE_REF_TYPES */ - default: - aot_set_last_error("unsupported opcode"); - return false; - } - break; - } + default: + aot_set_last_error("unsupported opcode"); + return false; + } + break; + } #if WASM_ENABLE_SHARED_MEMORY != 0 - case WASM_OP_ATOMIC_PREFIX: - { - uint8 bin_op, op_type; - - 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); - } - switch (opcode) { - case WASM_OP_ATOMIC_WAIT32: - if (!aot_compile_op_atomic_wait(comp_ctx, func_ctx, VALUE_TYPE_I32, - align, offset, 4)) - return false; - break; - case WASM_OP_ATOMIC_WAIT64: - if (!aot_compile_op_atomic_wait(comp_ctx, func_ctx, VALUE_TYPE_I64, - align, offset, 8)) - return false; - break; - case WASM_OP_ATOMIC_NOTIFY: - if (!aot_compiler_op_atomic_notify(comp_ctx, func_ctx, align, - offset, bytes)) - return false; - break; - case WASM_OP_ATOMIC_I32_LOAD: - bytes = 4; - goto op_atomic_i32_load; - case WASM_OP_ATOMIC_I32_LOAD8_U: - bytes = 1; - goto op_atomic_i32_load; - case WASM_OP_ATOMIC_I32_LOAD16_U: - bytes = 2; - op_atomic_i32_load: - if (!aot_compile_op_i32_load(comp_ctx, func_ctx, align, - offset, bytes, sign, true)) - return false; - break; - - case WASM_OP_ATOMIC_I64_LOAD: - bytes = 8; - goto op_atomic_i64_load; - case WASM_OP_ATOMIC_I64_LOAD8_U: - bytes = 1; - goto op_atomic_i64_load; - case WASM_OP_ATOMIC_I64_LOAD16_U: - bytes = 2; - goto op_atomic_i64_load; - case WASM_OP_ATOMIC_I64_LOAD32_U: - bytes = 4; - op_atomic_i64_load: - if (!aot_compile_op_i64_load(comp_ctx, func_ctx, align, - offset, bytes, sign, true)) - return false; - break; - - case WASM_OP_ATOMIC_I32_STORE: - bytes = 4; - goto op_atomic_i32_store; - case WASM_OP_ATOMIC_I32_STORE8: - bytes = 1; - goto op_atomic_i32_store; - case WASM_OP_ATOMIC_I32_STORE16: - bytes = 2; - op_atomic_i32_store: - if (!aot_compile_op_i32_store(comp_ctx, func_ctx, align, - offset, bytes, true)) - return false; - break; - - case WASM_OP_ATOMIC_I64_STORE: - bytes = 8; - goto op_atomic_i64_store; - case WASM_OP_ATOMIC_I64_STORE8: - bytes = 1; - goto op_atomic_i64_store; - case WASM_OP_ATOMIC_I64_STORE16: - bytes = 2; - goto op_atomic_i64_store; - case WASM_OP_ATOMIC_I64_STORE32: - bytes = 4; - op_atomic_i64_store: - if (!aot_compile_op_i64_store(comp_ctx, func_ctx, align, - offset, bytes, true)) - return false; - break; - - case WASM_OP_ATOMIC_RMW_I32_CMPXCHG: - bytes = 4; - op_type = VALUE_TYPE_I32; - goto op_atomic_cmpxchg; - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG: - bytes = 8; - op_type = VALUE_TYPE_I64; - goto op_atomic_cmpxchg; - case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U: - bytes = 1; - op_type = VALUE_TYPE_I32; - goto op_atomic_cmpxchg; - case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U: - bytes = 2; - op_type = VALUE_TYPE_I32; - goto op_atomic_cmpxchg; - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U: - bytes = 1; - op_type = VALUE_TYPE_I64; - goto op_atomic_cmpxchg; - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U: - bytes = 2; - op_type = VALUE_TYPE_I64; - goto op_atomic_cmpxchg; - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U: - bytes = 4; - op_type = VALUE_TYPE_I64; - op_atomic_cmpxchg: - if (!aot_compile_op_atomic_cmpxchg(comp_ctx, func_ctx, - op_type, align, - offset, bytes)) - return false; - break; - - COMPILE_ATOMIC_RMW(Add, ADD); - COMPILE_ATOMIC_RMW(Sub, SUB); - COMPILE_ATOMIC_RMW(And, AND); - COMPILE_ATOMIC_RMW(Or, OR); - COMPILE_ATOMIC_RMW(Xor, XOR); - COMPILE_ATOMIC_RMW(Xchg, XCHG); - -build_atomic_rmw: - if (!aot_compile_op_atomic_rmw(comp_ctx, func_ctx, - bin_op, op_type, - align, offset, bytes)) - return false; - break; - - default: - aot_set_last_error("unsupported opcode"); - return false; - } - break; - } + case WASM_OP_ATOMIC_PREFIX: + { + uint8 bin_op, op_type; + + 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); + } + switch (opcode) { + case WASM_OP_ATOMIC_WAIT32: + if (!aot_compile_op_atomic_wait(comp_ctx, func_ctx, + VALUE_TYPE_I32, align, + offset, 4)) + return false; + break; + case WASM_OP_ATOMIC_WAIT64: + if (!aot_compile_op_atomic_wait(comp_ctx, func_ctx, + VALUE_TYPE_I64, align, + offset, 8)) + return false; + break; + case WASM_OP_ATOMIC_NOTIFY: + if (!aot_compiler_op_atomic_notify( + comp_ctx, func_ctx, align, offset, bytes)) + return false; + break; + case WASM_OP_ATOMIC_I32_LOAD: + bytes = 4; + goto op_atomic_i32_load; + case WASM_OP_ATOMIC_I32_LOAD8_U: + bytes = 1; + goto op_atomic_i32_load; + case WASM_OP_ATOMIC_I32_LOAD16_U: + bytes = 2; + op_atomic_i32_load: + if (!aot_compile_op_i32_load(comp_ctx, func_ctx, align, + offset, bytes, sign, true)) + return false; + break; + + case WASM_OP_ATOMIC_I64_LOAD: + bytes = 8; + goto op_atomic_i64_load; + case WASM_OP_ATOMIC_I64_LOAD8_U: + bytes = 1; + goto op_atomic_i64_load; + case WASM_OP_ATOMIC_I64_LOAD16_U: + bytes = 2; + goto op_atomic_i64_load; + case WASM_OP_ATOMIC_I64_LOAD32_U: + bytes = 4; + op_atomic_i64_load: + if (!aot_compile_op_i64_load(comp_ctx, func_ctx, align, + offset, bytes, sign, true)) + return false; + break; + + case WASM_OP_ATOMIC_I32_STORE: + bytes = 4; + goto op_atomic_i32_store; + case WASM_OP_ATOMIC_I32_STORE8: + bytes = 1; + goto op_atomic_i32_store; + case WASM_OP_ATOMIC_I32_STORE16: + bytes = 2; + op_atomic_i32_store: + if (!aot_compile_op_i32_store(comp_ctx, func_ctx, align, + offset, bytes, true)) + return false; + break; + + case WASM_OP_ATOMIC_I64_STORE: + bytes = 8; + goto op_atomic_i64_store; + case WASM_OP_ATOMIC_I64_STORE8: + bytes = 1; + goto op_atomic_i64_store; + case WASM_OP_ATOMIC_I64_STORE16: + bytes = 2; + goto op_atomic_i64_store; + case WASM_OP_ATOMIC_I64_STORE32: + bytes = 4; + op_atomic_i64_store: + if (!aot_compile_op_i64_store(comp_ctx, func_ctx, align, + offset, bytes, true)) + return false; + break; + + case WASM_OP_ATOMIC_RMW_I32_CMPXCHG: + bytes = 4; + op_type = VALUE_TYPE_I32; + goto op_atomic_cmpxchg; + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG: + bytes = 8; + op_type = VALUE_TYPE_I64; + goto op_atomic_cmpxchg; + case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U: + bytes = 1; + op_type = VALUE_TYPE_I32; + goto op_atomic_cmpxchg; + case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U: + bytes = 2; + op_type = VALUE_TYPE_I32; + goto op_atomic_cmpxchg; + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U: + bytes = 1; + op_type = VALUE_TYPE_I64; + goto op_atomic_cmpxchg; + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U: + bytes = 2; + op_type = VALUE_TYPE_I64; + goto op_atomic_cmpxchg; + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U: + bytes = 4; + op_type = VALUE_TYPE_I64; + op_atomic_cmpxchg: + if (!aot_compile_op_atomic_cmpxchg(comp_ctx, func_ctx, + op_type, align, + offset, bytes)) + return false; + break; + + COMPILE_ATOMIC_RMW(Add, ADD); + COMPILE_ATOMIC_RMW(Sub, SUB); + COMPILE_ATOMIC_RMW(And, AND); + COMPILE_ATOMIC_RMW(Or, OR); + COMPILE_ATOMIC_RMW(Xor, XOR); + COMPILE_ATOMIC_RMW(Xchg, XCHG); + + build_atomic_rmw: + if (!aot_compile_op_atomic_rmw(comp_ctx, func_ctx, + bin_op, op_type, align, + offset, bytes)) + return false; + break; + + default: + aot_set_last_error("unsupported opcode"); + return false; + } + break; + } #endif /* end of WASM_ENABLE_SHARED_MEMORY */ #if WASM_ENABLE_SIMD != 0 - case WASM_OP_SIMD_PREFIX: - { - if (!comp_ctx->enable_simd) { - goto unsupport_simd; - } - - opcode = *frame_ip++; - switch (opcode) { - case SIMD_v128_load: - { - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_simd_v128_load(comp_ctx, func_ctx, align, offset)) - return false; - break; - } - - case SIMD_i16x8_load8x8_s: - case SIMD_i16x8_load8x8_u: - case SIMD_i32x4_load16x4_s: - case SIMD_i32x4_load16x4_u: - case SIMD_i64x2_load32x2_s: - case SIMD_i64x2_load32x2_u: - { - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_simd_load_extend(comp_ctx, func_ctx, - opcode, align, offset)) - return false; - break; - } - - case SIMD_v8x16_load_splat: - case SIMD_v16x8_load_splat: - case SIMD_v32x4_load_splat: - case SIMD_v64x2_load_splat: - { - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_simd_load_splat(comp_ctx, func_ctx, - opcode, align, offset)) - return false; - break; - } - - case SIMD_v128_store: - { - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - if (!aot_compile_simd_v128_store(comp_ctx, func_ctx, align, offset)) - return false; - break; - } - - case SIMD_v128_const: - { - if (!aot_compile_simd_v128_const(comp_ctx, func_ctx, frame_ip)) - return false; - frame_ip += 16; - break; - } - - case SIMD_v8x16_shuffle: - { - if (!aot_compile_simd_shuffle(comp_ctx, func_ctx, frame_ip)) - return false; - frame_ip += 16; - break; - } - - case SIMD_v8x16_swizzle: - { - if (!aot_compile_simd_swizzle(comp_ctx, func_ctx)) - return false; - break; - } - - case SIMD_i8x16_splat: - case SIMD_i16x8_splat: - case SIMD_i32x4_splat: - case SIMD_i64x2_splat: - case SIMD_f32x4_splat: - case SIMD_f64x2_splat: - { - if (!aot_compile_simd_splat(comp_ctx, func_ctx, opcode)) - return false; - break; - } - - case SIMD_i8x16_extract_lane_s: - { - if (!aot_compile_simd_extract_i8x16(comp_ctx, func_ctx, *frame_ip++, - true)) - return false; - break; - } - case SIMD_i8x16_extract_lane_u: - { - if (!aot_compile_simd_extract_i8x16(comp_ctx, func_ctx, *frame_ip++, - false)) - return false; - break; - } - case SIMD_i16x8_extract_lane_s: - { - if (!aot_compile_simd_extract_i16x8(comp_ctx, func_ctx, *frame_ip++, - true)) - return false; - break; - } - case SIMD_i16x8_extract_lane_u: - { - if (!aot_compile_simd_extract_i16x8(comp_ctx, func_ctx, *frame_ip++, - false)) - return false; - break; - } - case SIMD_i32x4_extract_lane: - { - if (!aot_compile_simd_extract_i32x4(comp_ctx, func_ctx, *frame_ip++)) - return false; - break; - } - case SIMD_i64x2_extract_lane: - { - if (!aot_compile_simd_extract_i64x2(comp_ctx, func_ctx, *frame_ip++)) - return false; - break; - } - case SIMD_f32x4_extract_lane: - { - if (!aot_compile_simd_extract_f32x4(comp_ctx, func_ctx, *frame_ip++)) - return false; - break; - } - case SIMD_f64x2_extract_lane: - { - if (!aot_compile_simd_extract_f64x2(comp_ctx, func_ctx, *frame_ip++)) - return false; - break; - } - - case SIMD_i8x16_replace_lane: - { - if (!aot_compile_simd_replace_i8x16(comp_ctx, func_ctx, *frame_ip++)) - return false; - break; - } - case SIMD_i16x8_replace_lane: - { - if (!aot_compile_simd_replace_i16x8(comp_ctx, func_ctx, *frame_ip++)) - return false; - break; - } - case SIMD_i32x4_replace_lane: - { - if (!aot_compile_simd_replace_i32x4(comp_ctx, func_ctx, *frame_ip++)) - return false; - break; - } - case SIMD_i64x2_replace_lane: - { - if (!aot_compile_simd_replace_i64x2(comp_ctx, func_ctx, *frame_ip++)) - return false; - break; - } - case SIMD_f32x4_replace_lane: - { - if (!aot_compile_simd_replace_f32x4(comp_ctx, func_ctx, *frame_ip++)) - return false; - break; - } - case SIMD_f64x2_replace_lane: - { - if (!aot_compile_simd_replace_f64x2(comp_ctx, func_ctx, *frame_ip++)) - return false; - break; - } - - case SIMD_i8x16_eq: - case SIMD_i8x16_ne: - case SIMD_i8x16_lt_s: - case SIMD_i8x16_lt_u: - case SIMD_i8x16_gt_s: - case SIMD_i8x16_gt_u: - case SIMD_i8x16_le_s: - case SIMD_i8x16_le_u: - case SIMD_i8x16_ge_s: - case SIMD_i8x16_ge_u: - { - if (!aot_compile_simd_i8x16_compare(comp_ctx, func_ctx, - INT_EQ + opcode - SIMD_i8x16_eq)) - return false; - break; - } - - case SIMD_i16x8_eq: - case SIMD_i16x8_ne: - case SIMD_i16x8_lt_s: - case SIMD_i16x8_lt_u: - case SIMD_i16x8_gt_s: - case SIMD_i16x8_gt_u: - case SIMD_i16x8_le_s: - case SIMD_i16x8_le_u: - case SIMD_i16x8_ge_s: - case SIMD_i16x8_ge_u: - { - if (!aot_compile_simd_i16x8_compare(comp_ctx, func_ctx, - INT_EQ + opcode - SIMD_i16x8_eq)) - return false; - break; - } - - case SIMD_i32x4_eq: - case SIMD_i32x4_ne: - case SIMD_i32x4_lt_s: - case SIMD_i32x4_lt_u: - case SIMD_i32x4_gt_s: - case SIMD_i32x4_gt_u: - case SIMD_i32x4_le_s: - case SIMD_i32x4_le_u: - case SIMD_i32x4_ge_s: - case SIMD_i32x4_ge_u: - { - if (!aot_compile_simd_i32x4_compare(comp_ctx, func_ctx, - INT_EQ + opcode - SIMD_i32x4_eq)) - return false; - break; - } - - case SIMD_f32x4_eq: - case SIMD_f32x4_ne: - case SIMD_f32x4_lt: - case SIMD_f32x4_gt: - case SIMD_f32x4_le: - case SIMD_f32x4_ge: - { - if (!aot_compile_simd_f32x4_compare(comp_ctx, func_ctx, - FLOAT_EQ + opcode - SIMD_f32x4_eq)) - return false; - break; - } - - case SIMD_f64x2_eq: - case SIMD_f64x2_ne: - case SIMD_f64x2_lt: - case SIMD_f64x2_gt: - case SIMD_f64x2_le: - case SIMD_f64x2_ge: - { - if (!aot_compile_simd_f64x2_compare(comp_ctx, func_ctx, - FLOAT_EQ + opcode - SIMD_f64x2_eq)) - return false; - break; - } - - case SIMD_v128_not: - case SIMD_v128_and: - case SIMD_v128_andnot: - case SIMD_v128_or: - case SIMD_v128_xor: - case SIMD_v128_bitselect: - { - if (!aot_compile_simd_v128_bitwise(comp_ctx, func_ctx, - V128_NOT + opcode - SIMD_v128_not)) - return false; - break; - } - - case SIMD_i8x16_add: - case SIMD_i8x16_sub: - { - V128Arithmetic arith_op = (opcode == SIMD_i8x16_add) - ? V128_ADD : V128_SUB; - if (!aot_compile_simd_i8x16_arith(comp_ctx, func_ctx, arith_op)) - return false; - break; - } - - case SIMD_i16x8_add: - case SIMD_i16x8_sub: - case SIMD_i16x8_mul: - { - V128Arithmetic arith_op = V128_ADD; - if (opcode == SIMD_i16x8_sub) - arith_op = V128_SUB; - else if (opcode == SIMD_i16x8_mul) - arith_op = V128_MUL; - if (!aot_compile_simd_i16x8_arith(comp_ctx, func_ctx, arith_op)) - return false; - break; - } - - case SIMD_i32x4_add: - case SIMD_i32x4_sub: - case SIMD_i32x4_mul: - { - V128Arithmetic arith_op = V128_ADD; - if (opcode == SIMD_i32x4_sub) - arith_op = V128_SUB; - else if (opcode == SIMD_i32x4_mul) - arith_op = V128_MUL; - if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx, arith_op)) - return false; - break; - } - - case SIMD_i64x2_add: - case SIMD_i64x2_sub: - case SIMD_i64x2_mul: - { - V128Arithmetic arith_op = V128_ADD; - if (opcode == SIMD_i64x2_sub) - arith_op = V128_SUB; - else if (opcode == SIMD_i64x2_mul) - arith_op = V128_MUL; - if (!aot_compile_simd_i64x2_arith(comp_ctx, func_ctx, arith_op)) - return false; - break; - } - - case SIMD_i8x16_neg: - { - if (!aot_compile_simd_i8x16_neg(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i16x8_neg: - { - if (!aot_compile_simd_i16x8_neg(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i32x4_neg: - { - if (!aot_compile_simd_i32x4_neg(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i64x2_neg: - { - if (!aot_compile_simd_i64x2_neg(comp_ctx, func_ctx)) - return false; - break; - } - - case SIMD_i8x16_add_saturate_s: - case SIMD_i8x16_add_saturate_u: - { - if (!aot_compile_simd_i8x16_saturate(comp_ctx, func_ctx, V128_ADD, - opcode == SIMD_i8x16_add_saturate_s - ? true : false)) - return false; - break; - } - case SIMD_i8x16_sub_saturate_s: - case SIMD_i8x16_sub_saturate_u: - { - if (!aot_compile_simd_i8x16_saturate(comp_ctx, func_ctx, V128_SUB, - opcode == SIMD_i8x16_sub_saturate_s - ? true : false)) - return false; - break; - } - case SIMD_i16x8_add_saturate_s: - case SIMD_i16x8_add_saturate_u: - { - if (!aot_compile_simd_i16x8_saturate(comp_ctx, func_ctx, V128_ADD, - opcode == SIMD_i16x8_add_saturate_s - ? true : false)) - return false; - break; - } - case SIMD_i16x8_sub_saturate_s: - case SIMD_i16x8_sub_saturate_u: - { - if (!aot_compile_simd_i16x8_saturate(comp_ctx, func_ctx, V128_SUB, - opcode == SIMD_i16x8_sub_saturate_s - ? true : false)) - return false; - break; - } - - case SIMD_i8x16_min_s: - case SIMD_i8x16_min_u: - { - if (!aot_compile_simd_i8x16_cmp(comp_ctx, func_ctx, V128_MIN, - opcode == SIMD_i8x16_min_s - ? true : false)) - return false; - break; - } - case SIMD_i8x16_max_s: - case SIMD_i8x16_max_u: - { - if (!aot_compile_simd_i8x16_cmp(comp_ctx, func_ctx, V128_MAX, - opcode == SIMD_i8x16_max_s - ? true : false)) - return false; - break; - } - case SIMD_i16x8_min_s: - case SIMD_i16x8_min_u: - { - if (!aot_compile_simd_i16x8_cmp(comp_ctx, func_ctx, V128_MIN, - opcode == SIMD_i16x8_min_s - ? true : false)) - return false; - break; - } - case SIMD_i16x8_max_s: - case SIMD_i16x8_max_u: - { - if (!aot_compile_simd_i16x8_cmp(comp_ctx, func_ctx, V128_MAX, - opcode == SIMD_i16x8_max_s - ? true : false)) - return false; - break; - } - case SIMD_i32x4_min_s: - case SIMD_i32x4_min_u: - { - if (!aot_compile_simd_i32x4_cmp(comp_ctx, func_ctx, V128_MIN, - opcode == SIMD_i32x4_min_s - ? true : false)) - return false; - break; - } - case SIMD_i32x4_max_s: - case SIMD_i32x4_max_u: - { - if (!aot_compile_simd_i32x4_cmp(comp_ctx, func_ctx, V128_MAX, - opcode == SIMD_i32x4_max_s - ? true : false)) - return false; - break; - } - - case SIMD_i8x16_abs: - { - if (!aot_compile_simd_i8x16_abs(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i16x8_abs: - { - if (!aot_compile_simd_i16x8_abs(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i32x4_abs: - { - if (!aot_compile_simd_i32x4_abs(comp_ctx, func_ctx)) - return false; - break; - } - - case SIMD_i8x16_avgr_u: - { - if (!aot_compile_simd_i8x16_avgr_u(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i16x8_avgr_u: - { - if (!aot_compile_simd_i16x8_avgr_u(comp_ctx, func_ctx)) - return false; - break; - } - - case SIMD_i8x16_any_true: - { - if (!aot_compile_simd_i8x16_any_true(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i16x8_any_true: - { - if (!aot_compile_simd_i16x8_any_true(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i32x4_any_true: - { - if (!aot_compile_simd_i32x4_any_true(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i8x16_all_true: - { - if (!aot_compile_simd_i8x16_all_true(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i16x8_all_true: - { - if (!aot_compile_simd_i16x8_all_true(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i32x4_all_true: - { - if (!aot_compile_simd_i32x4_all_true(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i8x16_bitmask: - { - if (!aot_compile_simd_i8x16_bitmask(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i16x8_bitmask: - { - if (!aot_compile_simd_i16x8_bitmask(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_i32x4_bitmask: - { - if (!aot_compile_simd_i32x4_bitmask(comp_ctx, func_ctx)) - return false; - break; - } - - case SIMD_i8x16_shl: - case SIMD_i8x16_shr_s: - case SIMD_i8x16_shr_u: - { - if (!aot_compile_simd_i8x16_shift(comp_ctx, func_ctx, - INT_SHL + opcode - SIMD_i8x16_shl)) - return false; - break; - } - case SIMD_i16x8_shl: - case SIMD_i16x8_shr_s: - case SIMD_i16x8_shr_u: - { - if (!aot_compile_simd_i16x8_shift(comp_ctx, func_ctx, - INT_SHL + opcode - SIMD_i16x8_shl)) - return false; - break; - } - case SIMD_i32x4_shl: - case SIMD_i32x4_shr_s: - case SIMD_i32x4_shr_u: - { - if (!aot_compile_simd_i32x4_shift(comp_ctx, func_ctx, - INT_SHL + opcode - SIMD_i32x4_shl)) - return false; - break; - } - case SIMD_i64x2_shl: - case SIMD_i64x2_shr_s: - case SIMD_i64x2_shr_u: - { - if (!aot_compile_simd_i64x2_shift(comp_ctx, func_ctx, - INT_SHL + opcode - SIMD_i64x2_shl)) - return false; - break; - } - - case SIMD_i8x16_narrow_i16x8_s: - case SIMD_i8x16_narrow_i16x8_u: - { - bool is_signed = (opcode == SIMD_i8x16_narrow_i16x8_s) - ? true : false; - if (!aot_compile_simd_i8x16_narrow_i16x8(comp_ctx, func_ctx, - is_signed)) - return false; - break; - } - case SIMD_i16x8_narrow_i32x4_s: - case SIMD_i16x8_narrow_i32x4_u: - { - bool is_signed = (opcode == SIMD_i16x8_narrow_i32x4_s) - ? true : false; - if (!aot_compile_simd_i16x8_narrow_i32x4(comp_ctx, func_ctx, - is_signed)) - return false; - break; - } - case SIMD_i16x8_widen_low_i8x16_s: - case SIMD_i16x8_widen_high_i8x16_s: - { - bool is_low = (opcode == SIMD_i16x8_widen_low_i8x16_s) - ? true : false; - if (!aot_compile_simd_i16x8_widen_i8x16(comp_ctx, func_ctx, - is_low, true)) - return false; - break; - } - case SIMD_i16x8_widen_low_i8x16_u: - case SIMD_i16x8_widen_high_i8x16_u: - { - bool is_low = (opcode == SIMD_i16x8_widen_low_i8x16_u) - ? true : false; - if (!aot_compile_simd_i16x8_widen_i8x16(comp_ctx, func_ctx, - is_low, false)) - return false; - break; - } - case SIMD_i32x4_widen_low_i16x8_s: - case SIMD_i32x4_widen_high_i16x8_s: - { - bool is_low = (opcode == SIMD_i32x4_widen_low_i16x8_s) - ? true : false; - if (!aot_compile_simd_i32x4_widen_i16x8(comp_ctx, func_ctx, - is_low, true)) - return false; - break; - } - case SIMD_i32x4_widen_low_i16x8_u: - case SIMD_i32x4_widen_high_i16x8_u: - { - bool is_low = (opcode == SIMD_i32x4_widen_low_i16x8_u) - ? true : false; - if (!aot_compile_simd_i32x4_widen_i16x8(comp_ctx, func_ctx, - is_low, false)) - return false; - break; - } - - case SIMD_i32x4_trunc_sat_f32x4_s: - case SIMD_i32x4_trunc_sat_f32x4_u: - { - bool is_signed = (opcode == SIMD_i32x4_trunc_sat_f32x4_s) - ? true : false; - if (!aot_compile_simd_i32x4_trunc_sat_f32x4(comp_ctx, func_ctx, - is_signed)) - return false; - break; - } - case SIMD_f32x4_convert_i32x4_s: - case SIMD_f32x4_convert_i32x4_u: - { - bool is_signed = (opcode == SIMD_f32x4_convert_i32x4_s) - ? true : false; - if (!aot_compile_simd_f32x4_convert_i32x4(comp_ctx, func_ctx, - is_signed)) - return false; - break; - } - - case SIMD_f32x4_add: - case SIMD_f32x4_sub: - case SIMD_f32x4_mul: - case SIMD_f32x4_div: - case SIMD_f32x4_min: - case SIMD_f32x4_max: - { - if (!aot_compile_simd_f32x4_arith(comp_ctx, func_ctx, - FLOAT_ADD + opcode - SIMD_f32x4_add)) - return false; - break; - } - case SIMD_f64x2_add: - case SIMD_f64x2_sub: - case SIMD_f64x2_mul: - case SIMD_f64x2_div: - case SIMD_f64x2_min: - case SIMD_f64x2_max: - { - if (!aot_compile_simd_f64x2_arith(comp_ctx, func_ctx, - FLOAT_ADD + opcode - SIMD_f64x2_add)) - return false; - break; - } - - case SIMD_f32x4_neg: - { - if (!aot_compile_simd_f32x4_neg(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f64x2_neg: - { - if (!aot_compile_simd_f64x2_neg(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f32x4_abs: - { - if (!aot_compile_simd_f32x4_abs(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f64x2_abs: - { - if (!aot_compile_simd_f64x2_abs(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f32x4_sqrt: - { - if (!aot_compile_simd_f32x4_sqrt(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f64x2_sqrt: - { - if (!aot_compile_simd_f64x2_sqrt(comp_ctx, func_ctx)) - return false; - break; - } - - case SIMD_f32x4_ceil: - { - if (!aot_compile_simd_f32x4_ceil(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f64x2_ceil: - { - if (!aot_compile_simd_f64x2_ceil(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f32x4_floor: - { - if (!aot_compile_simd_f32x4_floor(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f64x2_floor: - { - if (!aot_compile_simd_f64x2_floor(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f32x4_trunc: - { - if (!aot_compile_simd_f32x4_trunc(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f64x2_trunc: - { - if (!aot_compile_simd_f64x2_trunc(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f32x4_nearest: - { - if (!aot_compile_simd_f32x4_nearest(comp_ctx, func_ctx)) - return false; - break; - } - case SIMD_f64x2_nearest: - { - if (!aot_compile_simd_f64x2_nearest(comp_ctx, func_ctx)) - return false; - break; - } + case WASM_OP_SIMD_PREFIX: + { + if (!comp_ctx->enable_simd) { + goto unsupport_simd; + } + + opcode = *frame_ip++; + /* follow the order of enum WASMSimdEXTOpcode in + wasm_opcode.h */ + switch (opcode) { + /* Memory instruction */ + case SIMD_v128_load: + { + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_simd_v128_load(comp_ctx, func_ctx, + align, offset)) + return false; + break; + } + + case SIMD_v128_load8x8_s: + case SIMD_v128_load8x8_u: + case SIMD_v128_load16x4_s: + case SIMD_v128_load16x4_u: + case SIMD_v128_load32x2_s: + case SIMD_v128_load32x2_u: + { + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_simd_load_extend( + comp_ctx, func_ctx, opcode, align, offset)) + return false; + break; + } + + case SIMD_v128_load8_splat: + case SIMD_v128_load16_splat: + case SIMD_v128_load32_splat: + case SIMD_v128_load64_splat: + { + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_simd_load_splat(comp_ctx, func_ctx, + opcode, align, offset)) + return false; + break; + } + + case SIMD_v128_store: + { + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_simd_v128_store(comp_ctx, func_ctx, + align, offset)) + return false; + break; + } + + /* Basic operation */ + case SIMD_v128_const: + { + if (!aot_compile_simd_v128_const(comp_ctx, func_ctx, + frame_ip)) + return false; + frame_ip += 16; + break; + } + + case SIMD_v8x16_shuffle: + { + if (!aot_compile_simd_shuffle(comp_ctx, func_ctx, + frame_ip)) + return false; + frame_ip += 16; + break; + } + + case SIMD_v8x16_swizzle: + { + if (!aot_compile_simd_swizzle(comp_ctx, func_ctx)) + return false; + break; + } + + /* Splat operation */ + case SIMD_i8x16_splat: + case SIMD_i16x8_splat: + case SIMD_i32x4_splat: + case SIMD_i64x2_splat: + case SIMD_f32x4_splat: + case SIMD_f64x2_splat: + { + if (!aot_compile_simd_splat(comp_ctx, func_ctx, opcode)) + return false; + break; + } + + /* Lane operation */ + case SIMD_i8x16_extract_lane_s: + case SIMD_i8x16_extract_lane_u: + { + if (!aot_compile_simd_extract_i8x16( + comp_ctx, func_ctx, *frame_ip++, + SIMD_i8x16_extract_lane_s == opcode)) + return false; + break; + } + + case SIMD_i8x16_replace_lane: + { + if (!aot_compile_simd_replace_i8x16(comp_ctx, func_ctx, + *frame_ip++)) + return false; + break; + } + + case SIMD_i16x8_extract_lane_s: + case SIMD_i16x8_extract_lane_u: + { + if (!aot_compile_simd_extract_i16x8( + comp_ctx, func_ctx, *frame_ip++, + SIMD_i16x8_extract_lane_s == opcode)) + return false; + break; + } + + case SIMD_i16x8_replace_lane: + { + if (!aot_compile_simd_replace_i16x8(comp_ctx, func_ctx, + *frame_ip++)) + return false; + break; + } + + case SIMD_i32x4_extract_lane: + { + if (!aot_compile_simd_extract_i32x4(comp_ctx, func_ctx, + *frame_ip++)) + return false; + break; + } + + case SIMD_i32x4_replace_lane: + { + if (!aot_compile_simd_replace_i32x4(comp_ctx, func_ctx, + *frame_ip++)) + return false; + break; + } + + case SIMD_i64x2_extract_lane: + { + if (!aot_compile_simd_extract_i64x2(comp_ctx, func_ctx, + *frame_ip++)) + return false; + break; + } + + case SIMD_i64x2_replace_lane: + { + if (!aot_compile_simd_replace_i64x2(comp_ctx, func_ctx, + *frame_ip++)) + return false; + break; + } + + case SIMD_f32x4_extract_lane: + { + if (!aot_compile_simd_extract_f32x4(comp_ctx, func_ctx, + *frame_ip++)) + return false; + break; + } + + case SIMD_f32x4_replace_lane: + { + if (!aot_compile_simd_replace_f32x4(comp_ctx, func_ctx, + *frame_ip++)) + return false; + break; + } + + case SIMD_f64x2_extract_lane: + { + if (!aot_compile_simd_extract_f64x2(comp_ctx, func_ctx, + *frame_ip++)) + return false; + break; + } + + case SIMD_f64x2_replace_lane: + { + if (!aot_compile_simd_replace_f64x2(comp_ctx, func_ctx, + *frame_ip++)) + return false; + break; + } + + /* i8x16 Cmp */ + case SIMD_i8x16_eq: + case SIMD_i8x16_ne: + case SIMD_i8x16_lt_s: + case SIMD_i8x16_lt_u: + case SIMD_i8x16_gt_s: + case SIMD_i8x16_gt_u: + case SIMD_i8x16_le_s: + case SIMD_i8x16_le_u: + case SIMD_i8x16_ge_s: + case SIMD_i8x16_ge_u: + { + if (!aot_compile_simd_i8x16_compare( + comp_ctx, func_ctx, + INT_EQ + opcode - SIMD_i8x16_eq)) + return false; + break; + } + + /* i16x8 Cmp */ + case SIMD_i16x8_eq: + case SIMD_i16x8_ne: + case SIMD_i16x8_lt_s: + case SIMD_i16x8_lt_u: + case SIMD_i16x8_gt_s: + case SIMD_i16x8_gt_u: + case SIMD_i16x8_le_s: + case SIMD_i16x8_le_u: + case SIMD_i16x8_ge_s: + case SIMD_i16x8_ge_u: + { + if (!aot_compile_simd_i16x8_compare( + comp_ctx, func_ctx, + INT_EQ + opcode - SIMD_i16x8_eq)) + return false; + break; + } + + /* i32x4 Cmp */ + case SIMD_i32x4_eq: + case SIMD_i32x4_ne: + case SIMD_i32x4_lt_s: + case SIMD_i32x4_lt_u: + case SIMD_i32x4_gt_s: + case SIMD_i32x4_gt_u: + case SIMD_i32x4_le_s: + case SIMD_i32x4_le_u: + case SIMD_i32x4_ge_s: + case SIMD_i32x4_ge_u: + { + if (!aot_compile_simd_i32x4_compare( + comp_ctx, func_ctx, + INT_EQ + opcode - SIMD_i32x4_eq)) + return false; + break; + } + + /* f32x4 Cmp */ + case SIMD_f32x4_eq: + case SIMD_f32x4_ne: + case SIMD_f32x4_lt: + case SIMD_f32x4_gt: + case SIMD_f32x4_le: + case SIMD_f32x4_ge: + { + if (!aot_compile_simd_f32x4_compare( + comp_ctx, func_ctx, + FLOAT_EQ + opcode - SIMD_f32x4_eq)) + return false; + break; + } + + /* f64x2 Cmp */ + case SIMD_f64x2_eq: + case SIMD_f64x2_ne: + case SIMD_f64x2_lt: + case SIMD_f64x2_gt: + case SIMD_f64x2_le: + case SIMD_f64x2_ge: + { + if (!aot_compile_simd_f64x2_compare( + comp_ctx, func_ctx, + FLOAT_EQ + opcode - SIMD_f64x2_eq)) + return false; + break; + } + + /* v128 Op */ + case SIMD_v128_not: + case SIMD_v128_and: + case SIMD_v128_andnot: + case SIMD_v128_or: + case SIMD_v128_xor: + case SIMD_v128_bitselect: + { + if (!aot_compile_simd_v128_bitwise(comp_ctx, func_ctx, + V128_NOT + opcode + - SIMD_v128_not)) + return false; + break; + } + + case SIMD_v128_any_true: + { + if (!aot_compile_simd_v128_any_true(comp_ctx, func_ctx)) + return false; + break; + } + + /* Load Lane Op */ + case SIMD_v128_load8_lane: + case SIMD_v128_load16_lane: + case SIMD_v128_load32_lane: + case SIMD_v128_load64_lane: + { + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_simd_load_lane(comp_ctx, func_ctx, + opcode, align, offset, + *frame_ip++)) + return false; + break; + } + + case SIMD_v128_store8_lane: + case SIMD_v128_store16_lane: + case SIMD_v128_store32_lane: + case SIMD_v128_store64_lane: + { + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_simd_store_lane(comp_ctx, func_ctx, + opcode, align, offset, + *frame_ip++)) + return false; + break; + } + + case SIMD_v128_load32_zero: + case SIMD_v128_load64_zero: + { + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_simd_load_zero(comp_ctx, func_ctx, + opcode, align, offset)) + return false; + break; + } + + /* Float conversion */ + case SIMD_f32x4_demote_f64x2_zero: + { + if (!aot_compile_simd_f64x2_demote(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f64x2_promote_low_f32x4_zero: + { + if (!aot_compile_simd_f32x4_promote(comp_ctx, func_ctx)) + return false; + break; + } + + /* i8x16 Op */ + case SIMD_i8x16_abs: + { + if (!aot_compile_simd_i8x16_abs(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i8x16_neg: + { + if (!aot_compile_simd_i8x16_neg(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i8x16_popcnt: + { + if (!aot_compile_simd_i8x16_popcnt(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i8x16_all_true: + { + if (!aot_compile_simd_i8x16_all_true(comp_ctx, + func_ctx)) + return false; + break; + } + + case SIMD_i8x16_bitmask: + { + if (!aot_compile_simd_i8x16_bitmask(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i8x16_narrow_i16x8_s: + case SIMD_i8x16_narrow_i16x8_u: + { + if (!aot_compile_simd_i8x16_narrow_i16x8( + comp_ctx, func_ctx, + (opcode == SIMD_i8x16_narrow_i16x8_s))) + return false; + break; + } + + case SIMD_f32x4_ceil: + { + if (!aot_compile_simd_f32x4_ceil(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f32x4_floor: + { + if (!aot_compile_simd_f32x4_floor(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f32x4_trunc: + { + if (!aot_compile_simd_f32x4_trunc(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f32x4_nearest: + { + if (!aot_compile_simd_f32x4_nearest(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i8x16_shl: + case SIMD_i8x16_shr_s: + case SIMD_i8x16_shr_u: + { + if (!aot_compile_simd_i8x16_shift(comp_ctx, func_ctx, + INT_SHL + opcode + - SIMD_i8x16_shl)) + return false; + break; + } + + case SIMD_i8x16_add: + { + if (!aot_compile_simd_i8x16_arith(comp_ctx, func_ctx, + V128_ADD)) + return false; + break; + } + + case SIMD_i8x16_add_sat_s: + case SIMD_i8x16_add_sat_u: + { + if (!aot_compile_simd_i8x16_saturate( + comp_ctx, func_ctx, V128_ADD, + opcode == SIMD_i8x16_add_sat_s)) + return false; + break; + } + + case SIMD_i8x16_sub: + { + if (!aot_compile_simd_i8x16_arith(comp_ctx, func_ctx, + V128_SUB)) + return false; + break; + } + + case SIMD_i8x16_sub_sat_s: + case SIMD_i8x16_sub_sat_u: + { + if (!aot_compile_simd_i8x16_saturate( + comp_ctx, func_ctx, V128_SUB, + opcode == SIMD_i8x16_sub_sat_s)) + return false; + break; + } + + case SIMD_f64x2_ceil: + { + if (!aot_compile_simd_f64x2_ceil(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f64x2_floor: + { + if (!aot_compile_simd_f64x2_floor(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i8x16_min_s: + case SIMD_i8x16_min_u: + { + if (!aot_compile_simd_i8x16_cmp( + comp_ctx, func_ctx, V128_MIN, + opcode == SIMD_i8x16_min_s)) + return false; + break; + } + + case SIMD_i8x16_max_s: + case SIMD_i8x16_max_u: + { + if (!aot_compile_simd_i8x16_cmp( + comp_ctx, func_ctx, V128_MAX, + opcode == SIMD_i8x16_max_s)) + return false; + break; + } + + case SIMD_f64x2_trunc: + { + if (!aot_compile_simd_f64x2_trunc(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i8x16_avgr_u: + { + if (!aot_compile_simd_i8x16_avgr_u(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i16x8_extadd_pairwise_i8x16_s: + case SIMD_i16x8_extadd_pairwise_i8x16_u: + { + if (!aot_compile_simd_i16x8_extadd_pairwise_i8x16( + comp_ctx, func_ctx, + SIMD_i16x8_extadd_pairwise_i8x16_s == opcode)) + return false; + break; + } + + case SIMD_i32x4_extadd_pairwise_i16x8_s: + case SIMD_i32x4_extadd_pairwise_i16x8_u: + { + if (!aot_compile_simd_i32x4_extadd_pairwise_i16x8( + comp_ctx, func_ctx, + SIMD_i32x4_extadd_pairwise_i16x8_s == opcode)) + return false; + break; + } + + /* i16x8 Op */ + case SIMD_i16x8_abs: + { + if (!aot_compile_simd_i16x8_abs(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i16x8_neg: + { + if (!aot_compile_simd_i16x8_neg(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i16x8_q15mulr_sat_s: + { + if (!aot_compile_simd_i16x8_q15mulr_sat(comp_ctx, + func_ctx)) + return false; + break; + } + + case SIMD_i16x8_all_true: + { + if (!aot_compile_simd_i16x8_all_true(comp_ctx, + func_ctx)) + return false; + break; + } + + case SIMD_i16x8_bitmask: + { + if (!aot_compile_simd_i16x8_bitmask(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i16x8_narrow_i32x4_s: + case SIMD_i16x8_narrow_i32x4_u: + { + if (!aot_compile_simd_i16x8_narrow_i32x4( + comp_ctx, func_ctx, + SIMD_i16x8_narrow_i32x4_s == opcode)) + return false; + break; + } + + case SIMD_i16x8_extend_low_i8x16_s: + case SIMD_i16x8_extend_high_i8x16_s: + { + if (!aot_compile_simd_i16x8_extend_i8x16( + comp_ctx, func_ctx, + SIMD_i16x8_extend_low_i8x16_s == opcode, true)) + return false; + break; + } + + case SIMD_i16x8_extend_low_i8x16_u: + case SIMD_i16x8_extend_high_i8x16_u: + { + if (!aot_compile_simd_i16x8_extend_i8x16( + comp_ctx, func_ctx, + SIMD_i16x8_extend_low_i8x16_u == opcode, false)) + return false; + break; + } + + case SIMD_i16x8_shl: + case SIMD_i16x8_shr_s: + case SIMD_i16x8_shr_u: + { + if (!aot_compile_simd_i16x8_shift(comp_ctx, func_ctx, + INT_SHL + opcode + - SIMD_i16x8_shl)) + return false; + break; + } + + case SIMD_i16x8_add: + { + if (!aot_compile_simd_i16x8_arith(comp_ctx, func_ctx, + V128_ADD)) + return false; + break; + } + + case SIMD_i16x8_add_sat_s: + case SIMD_i16x8_add_sat_u: + { + if (!aot_compile_simd_i16x8_saturate( + comp_ctx, func_ctx, V128_ADD, + opcode == SIMD_i16x8_add_sat_s ? true : false)) + return false; + break; + } + + case SIMD_i16x8_sub: + { + if (!aot_compile_simd_i16x8_arith(comp_ctx, func_ctx, + V128_SUB)) + return false; + break; + } + + case SIMD_i16x8_sub_sat_s: + case SIMD_i16x8_sub_sat_u: + { + if (!aot_compile_simd_i16x8_saturate( + comp_ctx, func_ctx, V128_SUB, + opcode == SIMD_i16x8_sub_sat_s ? true : false)) + return false; + break; + } + + case SIMD_f64x2_nearest: + { + if (!aot_compile_simd_f64x2_nearest(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i16x8_mul: + { + if (!aot_compile_simd_i16x8_arith(comp_ctx, func_ctx, + V128_MUL)) + return false; + break; + } + + case SIMD_i16x8_min_s: + case SIMD_i16x8_min_u: + { + if (!aot_compile_simd_i16x8_cmp( + comp_ctx, func_ctx, V128_MIN, + opcode == SIMD_i16x8_min_s)) + return false; + break; + } + + case SIMD_i16x8_max_s: + case SIMD_i16x8_max_u: + { + if (!aot_compile_simd_i16x8_cmp( + comp_ctx, func_ctx, V128_MAX, + opcode == SIMD_i16x8_max_s)) + return false; + break; + } + + case SIMD_i16x8_avgr_u: + { + if (!aot_compile_simd_i16x8_avgr_u(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i16x8_extmul_low_i8x16_s: + case SIMD_i16x8_extmul_high_i8x16_s: + { + if (!(aot_compile_simd_i16x8_extmul_i8x16( + comp_ctx, func_ctx, + SIMD_i16x8_extmul_low_i8x16_s == opcode, true))) + return false; + break; + } + + case SIMD_i16x8_extmul_low_i8x16_u: + case SIMD_i16x8_extmul_high_i8x16_u: + { + if (!(aot_compile_simd_i16x8_extmul_i8x16( + comp_ctx, func_ctx, + SIMD_i16x8_extmul_low_i8x16_u == opcode, + false))) + return false; + break; + } + + /* i32x4 Op */ + case SIMD_i32x4_abs: + { + if (!aot_compile_simd_i32x4_abs(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i32x4_neg: + { + if (!aot_compile_simd_i32x4_neg(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i32x4_all_true: + { + if (!aot_compile_simd_i32x4_all_true(comp_ctx, + func_ctx)) + return false; + break; + } + + case SIMD_i32x4_bitmask: + { + if (!aot_compile_simd_i32x4_bitmask(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i32x4_narrow_i64x2_s: + case SIMD_i32x4_narrow_i64x2_u: + { + if (!aot_compile_simd_i32x4_narrow_i64x2( + comp_ctx, func_ctx, + SIMD_i32x4_narrow_i64x2_s == opcode)) + return false; + break; + } + + case SIMD_i32x4_extend_low_i16x8_s: + case SIMD_i32x4_extend_high_i16x8_s: + { + if (!aot_compile_simd_i32x4_extend_i16x8( + comp_ctx, func_ctx, + SIMD_i32x4_extend_low_i16x8_s == opcode, true)) + return false; + break; + } + + case SIMD_i32x4_extend_low_i16x8_u: + case SIMD_i32x4_extend_high_i16x8_u: + { + if (!aot_compile_simd_i32x4_extend_i16x8( + comp_ctx, func_ctx, + SIMD_i32x4_extend_low_i16x8_u == opcode, false)) + return false; + break; + } + + case SIMD_i32x4_shl: + case SIMD_i32x4_shr_s: + case SIMD_i32x4_shr_u: + { + if (!aot_compile_simd_i32x4_shift(comp_ctx, func_ctx, + INT_SHL + opcode + - SIMD_i32x4_shl)) + return false; + break; + } + + case SIMD_i32x4_add: + { + if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx, + V128_ADD)) + return false; + break; + } + + case SIMD_i32x4_add_sat_s: + case SIMD_i32x4_add_sat_u: + { + if (!aot_compile_simd_i32x4_saturate( + comp_ctx, func_ctx, V128_ADD, + opcode == SIMD_i32x4_add_sat_s)) + return false; + break; + } + + case SIMD_i32x4_sub: + { + if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx, + V128_SUB)) + return false; + break; + } + + case SIMD_i32x4_sub_sat_s: + case SIMD_i32x4_sub_sat_u: + { + if (!aot_compile_simd_i32x4_saturate( + comp_ctx, func_ctx, V128_SUB, + opcode == SIMD_i32x4_add_sat_s)) + return false; + break; + } + + case SIMD_i32x4_mul: + { + if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx, + V128_MUL)) + return false; + break; + } + + case SIMD_i32x4_min_s: + case SIMD_i32x4_min_u: + { + if (!aot_compile_simd_i32x4_cmp( + comp_ctx, func_ctx, V128_MIN, + SIMD_i32x4_min_s == opcode)) + return false; + break; + } + + case SIMD_i32x4_max_s: + case SIMD_i32x4_max_u: + { + if (!aot_compile_simd_i32x4_cmp( + comp_ctx, func_ctx, V128_MAX, + SIMD_i32x4_max_s == opcode)) + return false; + break; + } + + case SIMD_i32x4_dot_i16x8_s: + { + if (!aot_compile_simd_i32x4_dot_i16x8(comp_ctx, + func_ctx)) + return false; + break; + } + + case SIMD_i32x4_avgr_u: + { + if (!aot_compile_simd_i32x4_avgr_u(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i32x4_extmul_low_i16x8_s: + case SIMD_i32x4_extmul_high_i16x8_s: + { + if (!aot_compile_simd_i32x4_extmul_i16x8( + comp_ctx, func_ctx, + SIMD_i32x4_extmul_low_i16x8_s == opcode, true)) + return false; + break; + } + + case SIMD_i32x4_extmul_low_i16x8_u: + case SIMD_i32x4_extmul_high_i16x8_u: + { + if (!aot_compile_simd_i32x4_extmul_i16x8( + comp_ctx, func_ctx, + SIMD_i32x4_extmul_low_i16x8_u == opcode, false)) + return false; + break; + } + + /* i64x2 Op */ + case SIMD_i64x2_abs: + { + if (!aot_compile_simd_i64x2_abs(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i64x2_neg: + { + if (!aot_compile_simd_i64x2_neg(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i64x2_all_true: + { + if (!aot_compile_simd_i64x2_all_true(comp_ctx, + func_ctx)) + return false; + break; + } + + case SIMD_i64x2_bitmask: + { + if (!aot_compile_simd_i64x2_bitmask(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_i64x2_extend_low_i32x4_s: + case SIMD_i64x2_extend_high_i32x4_s: + { + if (!aot_compile_simd_i64x2_extend_i32x4( + comp_ctx, func_ctx, + SIMD_i64x2_extend_low_i32x4_s == opcode, true)) + return false; + break; + } + + case SIMD_i64x2_extend_low_i32x4_u: + case SIMD_i64x2_extend_high_i32x4_u: + { + if (!aot_compile_simd_i64x2_extend_i32x4( + comp_ctx, func_ctx, + SIMD_i64x2_extend_low_i32x4_u == opcode, false)) + return false; + break; + } + + case SIMD_i64x2_shl: + case SIMD_i64x2_shr_s: + case SIMD_i64x2_shr_u: + { + if (!aot_compile_simd_i64x2_shift(comp_ctx, func_ctx, + INT_SHL + opcode + - SIMD_i64x2_shl)) + return false; + break; + } + + case SIMD_i64x2_add: + { + if (!aot_compile_simd_i64x2_arith(comp_ctx, func_ctx, + V128_ADD)) + return false; + break; + } + + case SIMD_i64x2_sub: + { + if (!aot_compile_simd_i64x2_arith(comp_ctx, func_ctx, + V128_SUB)) + return false; + break; + } + + case SIMD_i64x2_mul: + { + if (!aot_compile_simd_i64x2_arith(comp_ctx, func_ctx, + V128_MUL)) + return false; + break; + } + + case SIMD_i64x2_eq: + case SIMD_i64x2_ne: + case SIMD_i64x2_lt_s: + case SIMD_i64x2_gt_s: + case SIMD_i64x2_le_s: + case SIMD_i64x2_ge_s: + { + IntCond icond[] = { INT_EQ, INT_NE, INT_LT_S, + INT_GT_S, INT_LE_S, INT_GE_S }; + if (!aot_compile_simd_i64x2_compare( + comp_ctx, func_ctx, + icond[opcode - SIMD_i64x2_eq])) + return false; + break; + } + + case SIMD_i64x2_extmul_low_i32x4_s: + case SIMD_i64x2_extmul_high_i32x4_s: + { + if (!aot_compile_simd_i64x2_extmul_i32x4( + comp_ctx, func_ctx, + SIMD_i64x2_extmul_low_i32x4_s == opcode, true)) + return false; + break; + } + + case SIMD_i64x2_extmul_low_i32x4_u: + case SIMD_i64x2_extmul_high_i32x4_u: + { + if (!aot_compile_simd_i64x2_extmul_i32x4( + comp_ctx, func_ctx, + SIMD_i64x2_extmul_low_i32x4_u == opcode, false)) + return false; + break; + } + + /* f32x4 Op */ + case SIMD_f32x4_abs: + { + if (!aot_compile_simd_f32x4_abs(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f32x4_neg: + { + if (!aot_compile_simd_f32x4_neg(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f32x4_round: + { + if (!aot_compile_simd_f32x4_round(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f32x4_sqrt: + { + if (!aot_compile_simd_f32x4_sqrt(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f32x4_add: + case SIMD_f32x4_sub: + case SIMD_f32x4_mul: + case SIMD_f32x4_div: + { + if (!aot_compile_simd_f32x4_arith(comp_ctx, func_ctx, + FLOAT_ADD + opcode + - SIMD_f32x4_add)) + return false; + break; + } + + case SIMD_f32x4_min: + case SIMD_f32x4_max: + { + if (!aot_compile_simd_f32x4_min_max( + comp_ctx, func_ctx, SIMD_f32x4_min == opcode)) + return false; + break; + } + + case SIMD_f32x4_pmin: + case SIMD_f32x4_pmax: + { + if (!aot_compile_simd_f32x4_pmin_pmax( + comp_ctx, func_ctx, SIMD_f32x4_pmin == opcode)) + return false; + break; + } + + /* f64x2 Op */ + + case SIMD_f64x2_abs: + { + if (!aot_compile_simd_f64x2_abs(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f64x2_neg: + { + if (!aot_compile_simd_f64x2_neg(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f64x2_round: + { + if (!aot_compile_simd_f64x2_round(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f64x2_sqrt: + { + if (!aot_compile_simd_f64x2_sqrt(comp_ctx, func_ctx)) + return false; + break; + } + + case SIMD_f64x2_add: + case SIMD_f64x2_sub: + case SIMD_f64x2_mul: + case SIMD_f64x2_div: + { + if (!aot_compile_simd_f64x2_arith(comp_ctx, func_ctx, + FLOAT_ADD + opcode + - SIMD_f64x2_add)) + return false; + break; + } + + case SIMD_f64x2_min: + case SIMD_f64x2_max: + { + if (!aot_compile_simd_f64x2_min_max( + comp_ctx, func_ctx, SIMD_f64x2_min == opcode)) + return false; + break; + } + + case SIMD_f64x2_pmin: + case SIMD_f64x2_pmax: + { + if (!aot_compile_simd_f64x2_pmin_pmax( + comp_ctx, func_ctx, SIMD_f64x2_pmin == opcode)) + return false; + break; + } + + /* Conversion Op */ + case SIMD_i32x4_trunc_sat_f32x4_s: + case SIMD_i32x4_trunc_sat_f32x4_u: + { + if (!aot_compile_simd_i32x4_trunc_sat_f32x4( + comp_ctx, func_ctx, + SIMD_i32x4_trunc_sat_f32x4_s == opcode)) + return false; + break; + } + + case SIMD_f32x4_convert_i32x4_s: + case SIMD_f32x4_convert_i32x4_u: + { + if (!aot_compile_simd_f32x4_convert_i32x4( + comp_ctx, func_ctx, + SIMD_f32x4_convert_i32x4_s == opcode)) + return false; + break; + } + + case SIMD_i32x4_trunc_sat_f64x2_s_zero: + case SIMD_i32x4_trunc_sat_f64x2_u_zero: + { + if (!aot_compile_simd_i32x4_trunc_sat_f64x2( + comp_ctx, func_ctx, + SIMD_i32x4_trunc_sat_f64x2_s_zero == opcode)) + return false; + break; + } + + case SIMD_f64x2_convert_low_i32x4_s: + case SIMD_f64x2_convert_low_i32x4_u: + { + if (!aot_compile_simd_f64x2_convert_i32x4( + comp_ctx, func_ctx, + SIMD_f64x2_convert_low_i32x4_s == opcode)) + return false; + break; + } + + default: + aot_set_last_error("unsupported opcode"); + return false; + } + break; + } +#endif /* end of WASM_ENABLE_SIMD */ - default: - aot_set_last_error("unsupported opcode"); - return false; + default: + aot_set_last_error("unsupported opcode"); + return false; } - break; - } -#endif /* end of WASM_ENABLE_SIMD */ + } - default: - aot_set_last_error("unsupported opcode"); - return false; + /* Move func_return block to the bottom */ + if (func_ctx->func_return_block) { + LLVMBasicBlockRef last_block = LLVMGetLastBasicBlock(func_ctx->func); + if (last_block != func_ctx->func_return_block) + LLVMMoveBasicBlockAfter(func_ctx->func_return_block, last_block); + } + + /* Move got_exception block to the bottom */ + if (func_ctx->got_exception_block) { + LLVMBasicBlockRef last_block = LLVMGetLastBasicBlock(func_ctx->func); + if (last_block != func_ctx->got_exception_block) + LLVMMoveBasicBlockAfter(func_ctx->got_exception_block, last_block); } - } - - /* Move func_return block to the bottom */ - if (func_ctx->func_return_block) { - LLVMBasicBlockRef last_block = - LLVMGetLastBasicBlock(func_ctx->func); - if (last_block != func_ctx->func_return_block) - LLVMMoveBasicBlockAfter(func_ctx->func_return_block, - last_block); - } - - /* Move got_exception block to the bottom */ - if (func_ctx->got_exception_block) { - LLVMBasicBlockRef last_block = - LLVMGetLastBasicBlock(func_ctx->func); - if (last_block != func_ctx->got_exception_block) - LLVMMoveBasicBlockAfter(func_ctx->got_exception_block, - last_block); - } - return true; + return true; #if WASM_ENABLE_SIMD != 0 unsupport_simd: - aot_set_last_error("SIMD instruction was found, " - "try adding --enable-simd option?"); - return false; + aot_set_last_error("SIMD instruction was found, " + "try adding --enable-simd option?"); + return false; #endif #if WASM_ENABLE_REF_TYPES != 0 unsupport_ref_types: - aot_set_last_error("reference type instruction was found, " - "try adding --enable-ref-types option?"); - return false; + aot_set_last_error("reference type instruction was found, " + "try adding --enable-ref-types option?"); + return false; #endif fail: - return false; + return false; } bool aot_compile_wasm(AOTCompContext *comp_ctx) { - char *msg = NULL; - bool ret; - uint32 i; + char *msg = NULL; + bool ret; + uint32 i; - bh_print_time("Begin to compile WASM bytecode to LLVM IR"); + bh_print_time("Begin to compile WASM bytecode to LLVM IR"); - for (i = 0; i < comp_ctx->func_ctx_count; i++) - if (!aot_compile_func(comp_ctx, i)) { + for (i = 0; i < comp_ctx->func_ctx_count; i++) + if (!aot_compile_func(comp_ctx, i)) { #if 0 - LLVMDumpModule(comp_ctx->module); - char *err; - LLVMTargetMachineEmitToFile(comp_ctx->target_machine, comp_ctx->module, - "./test.o", LLVMObjectFile, &err); + LLVMDumpModule(comp_ctx->module); + char *err; + LLVMTargetMachineEmitToFile(comp_ctx->target_machine, + comp_ctx->module, "./test.o", + LLVMObjectFile, &err); #endif - return false; - } + return false; + } #if 0 - LLVMDumpModule(comp_ctx->module); - /* Clear error no, LLVMDumpModule may set errno */ - errno = 0; + LLVMDumpModule(comp_ctx->module); + /* Clear error no, LLVMDumpModule may set errno */ + errno = 0; #endif - bh_print_time("Begin to verify LLVM module"); +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMDIBuilderFinalize(comp_ctx->debug_builder); +#endif - ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg); - if (!ret && msg) { - if (msg[0] != '\0') { - aot_set_last_error(msg); - LLVMDisposeMessage(msg); - return false; - } - LLVMDisposeMessage(msg); - } + bh_print_time("Begin to verify LLVM module"); - bh_print_time("Begin to run function optimization passes"); + ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg); + if (!ret && msg) { + if (msg[0] != '\0') { + aot_set_last_error(msg); + LLVMDisposeMessage(msg); + return false; + } + LLVMDisposeMessage(msg); + } - if (comp_ctx->optimize) { - LLVMInitializeFunctionPassManager(comp_ctx->pass_mgr); - for (i = 0; i < comp_ctx->func_ctx_count; i++) - LLVMRunFunctionPassManager(comp_ctx->pass_mgr, - comp_ctx->func_ctxes[i]->func); - } + bh_print_time("Begin to run function optimization passes"); + + if (comp_ctx->optimize) { + LLVMInitializeFunctionPassManager(comp_ctx->pass_mgr); + for (i = 0; i < comp_ctx->func_ctx_count; i++) + LLVMRunFunctionPassManager(comp_ctx->pass_mgr, + comp_ctx->func_ctxes[i]->func); + } - return true; + return true; } bool @@ -2111,19 +2581,24 @@ bool aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name) { char *err = NULL; + LLVMCodeGenFileType file_type = LLVMObjectFile; + LLVMTargetRef target = LLVMGetTargetMachineTarget(comp_ctx->target_machine); bh_print_time("Begin to emit object file"); - if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine, - comp_ctx->module, - file_name, - LLVMObjectFile, - &err) != 0) { + if (!strncmp(LLVMGetTargetName(target), "arc", 3)) + /* Emit to assmelby file instead for arc target + as it cannot emit to object file */ + file_type = LLVMAssemblyFile; + + if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine, comp_ctx->module, + file_name, file_type, &err) + != 0) { if (err) { LLVMDisposeMessage(err); err = NULL; } - aot_set_last_error("emit elf to memory buffer failed."); + aot_set_last_error("emit elf to object file failed."); return false; } @@ -2135,19 +2610,81 @@ extern void wasm_set_ref_types_flag(bool enable); #endif -uint8* +typedef struct AOTFileMap { + uint8 *wasm_file_buf; + uint32 wasm_file_size; + uint8 *aot_file_buf; + uint32 aot_file_size; + struct AOTFileMap *next; +} AOTFileMap; + +static bool aot_compile_wasm_file_inited = false; +static AOTFileMap *aot_file_maps = NULL; +static korp_mutex aot_file_map_lock; + +bool +aot_compile_wasm_file_init() +{ + if (aot_compile_wasm_file_inited) { + return true; + } + + if (BHT_OK != os_mutex_init(&aot_file_map_lock)) { + return false; + } + + aot_file_maps = NULL; + aot_compile_wasm_file_inited = true; + return true; +} + +void +aot_compile_wasm_file_destroy() +{ + AOTFileMap *file_map = aot_file_maps, *file_map_next; + + if (!aot_compile_wasm_file_inited) { + return; + } + + while (file_map) { + file_map_next = file_map->next; + + wasm_runtime_free(file_map->wasm_file_buf); + wasm_runtime_free(file_map->aot_file_buf); + wasm_runtime_free(file_map); + + file_map = file_map_next; + } + + aot_file_maps = NULL; + os_mutex_destroy(&aot_file_map_lock); + aot_compile_wasm_file_inited = false; +} + +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) { + snprintf(error_buf, error_buf_size, "WASM module load failed: %s", + string); + } +} + +uint8 * aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size, - uint32 opt_level, uint32 size_level, - uint32 *p_aot_file_size) + uint32 opt_level, uint32 size_level, char *error_buf, + uint32 error_buf_size, uint32 *p_aot_file_size) { - WASMModuleCommon *wasm_module = NULL; + WASMModule *wasm_module = NULL; AOTCompData *comp_data = NULL; AOTCompContext *comp_ctx = NULL; RuntimeInitArgs init_args; AOTCompOption option = { 0 }; + AOTFileMap *file_map = NULL, *file_map_next; + uint8 *wasm_file_buf_cloned = NULL; uint8 *aot_file_buf = NULL; uint32 aot_file_size; - char error_buf[128]; option.is_jit_mode = false; option.opt_level = opt_level; @@ -2155,7 +2692,6 @@ aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size, option.output_format = AOT_FORMAT_FILE; /* default value, enable or disable depends on the platform */ option.bounds_checks = 2; - option.enable_simd = true; option.enable_aux_stack_check = true; #if WASM_ENABLE_BULK_MEMORY != 0 option.enable_bulk_memory = true; @@ -2164,10 +2700,10 @@ aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size, option.enable_thread_mgr = true; #endif #if WASM_ENABLE_TAIL_CALL != 0 - option.enable_tail_call = true; + option.enable_tail_call = true; #endif #if WASM_ENABLE_SIMD != 0 - option.enable_simd = true; + option.enable_simd = true; #endif #if WASM_ENABLE_REF_TYPES != 0 option.enable_ref_types = true; @@ -2187,46 +2723,94 @@ aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size, init_args.mem_alloc_option.allocator.realloc_func = realloc; init_args.mem_alloc_option.allocator.free_func = free; - /* load WASM module */ - if (!(wasm_module = (WASMModuleCommon*) - wasm_load(wasm_file_buf, wasm_file_size, - error_buf, sizeof(error_buf)))) { - os_printf("%s\n", error_buf); - aot_set_last_error(error_buf); - return NULL; + os_mutex_lock(&aot_file_map_lock); + + /* lookup the file maps */ + file_map = aot_file_maps; + while (file_map) { + file_map_next = file_map->next; + + if (wasm_file_size == file_map->wasm_file_size + && memcmp(wasm_file_buf, file_map->wasm_file_buf, wasm_file_size) + == 0) { + os_mutex_unlock(&aot_file_map_lock); + /* found */ + *p_aot_file_size = file_map->aot_file_size; + return file_map->aot_file_buf; + } + + file_map = file_map_next; } - if (!(comp_data = aot_create_comp_data((WASMModule*)wasm_module))) { - os_printf("%s\n", aot_get_last_error()); + /* not found, initialize file map and clone wasm file */ + if (!(file_map = wasm_runtime_malloc(sizeof(AOTFileMap))) + || !(wasm_file_buf_cloned = wasm_runtime_malloc(wasm_file_size))) { + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); goto fail1; } - if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) { - os_printf("%s\n", aot_get_last_error()); + bh_memcpy_s(wasm_file_buf_cloned, wasm_file_size, wasm_file_buf, + wasm_file_size); + memset(file_map, 0, sizeof(AOTFileMap)); + file_map->wasm_file_buf = wasm_file_buf_cloned; + file_map->wasm_file_size = wasm_file_size; + + /* load WASM module */ + if (!(wasm_module = wasm_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)))) { + goto fail1; + } + + if (!(comp_data = aot_create_comp_data(wasm_module))) { + set_error_buf(error_buf, error_buf_size, aot_get_last_error()); goto fail2; } - if (!aot_compile_wasm(comp_ctx)) { - os_printf("%s\n", aot_get_last_error()); + if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) { + set_error_buf(error_buf, error_buf_size, aot_get_last_error()); goto fail3; } - if (!(aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data, - &aot_file_size))) { - os_printf("%s\n", aot_get_last_error()); - goto fail3; + if (!aot_compile_wasm(comp_ctx)) { + set_error_buf(error_buf, error_buf_size, aot_get_last_error()); + goto fail4; + } + + if (!(aot_file_buf = + aot_emit_aot_file_buf(comp_ctx, comp_data, &aot_file_size))) { + set_error_buf(error_buf, error_buf_size, aot_get_last_error()); + goto fail4; + } + + file_map->aot_file_buf = aot_file_buf; + file_map->aot_file_size = aot_file_size; + + if (!aot_file_maps) + aot_file_maps = file_map; + else { + file_map->next = aot_file_maps; + aot_file_maps = file_map; } *p_aot_file_size = aot_file_size; -fail3: +fail4: /* Destroy compiler context */ aot_destroy_comp_context(comp_ctx); -fail2: - /* Destroy compile data */ +fail3: + /* Destroy compile data */ aot_destroy_comp_data(comp_data); +fail2: + wasm_unload(wasm_module); fail1: - wasm_runtime_unload(wasm_module); + if (!aot_file_buf) { + if (wasm_file_buf_cloned) + wasm_runtime_free(wasm_file_buf_cloned); + if (file_map) + wasm_runtime_free(file_map); + } + + os_mutex_unlock(&aot_file_map_lock); return aot_file_buf; } diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h index feb2eaff4b..67faa600fc 100644 --- a/core/iwasm/compilation/aot_compiler.h +++ b/core/iwasm/compilation/aot_compiler.h @@ -13,170 +13,148 @@ extern "C" { #endif -typedef enum IntCond { - INT_EQZ = 0, - INT_EQ, - INT_NE, - INT_LT_S, - INT_LT_U, - INT_GT_S, - INT_GT_U, - INT_LE_S, - INT_LE_U, - INT_GE_S, - INT_GE_U -} IntCond; - -typedef enum FloatCond { - FLOAT_EQ = 0, - FLOAT_NE, - FLOAT_LT, - FLOAT_GT, - FLOAT_LE, - FLOAT_GE -} FloatCond; +typedef AOTIntCond IntCond; +typedef AOTFloatCond FloatCond; typedef enum IntArithmetic { - INT_ADD = 0, - INT_SUB, - INT_MUL, - INT_DIV_S, - INT_DIV_U, - INT_REM_S, - INT_REM_U + INT_ADD = 0, + INT_SUB, + INT_MUL, + INT_DIV_S, + INT_DIV_U, + INT_REM_S, + INT_REM_U } IntArithmetic; typedef enum V128Arithmetic { - V128_ADD = 0, - V128_ADD_SATURATE_S, - V128_ADD_SATURATE_U, - V128_SUB, - V128_SUB_SATURATE_S, - V128_SUB_SATURATE_U, - V128_MUL, - V128_DIV, - V128_NEG, - V128_MIN, - V128_MAX, + V128_ADD = 0, + V128_SUB, + V128_MUL, + V128_DIV, + V128_NEG, + V128_MIN, + V128_MAX, } V128Arithmetic; typedef enum IntBitwise { - INT_AND = 0, - INT_OR, - INT_XOR, + INT_AND = 0, + INT_OR, + INT_XOR, } IntBitwise; typedef enum V128Bitwise { - V128_NOT, - V128_AND, - V128_ANDNOT, - V128_OR, - V128_XOR, - V128_BITSELECT + V128_NOT, + V128_AND, + V128_ANDNOT, + V128_OR, + V128_XOR, + V128_BITSELECT, } V128Bitwise; typedef enum IntShift { - INT_SHL = 0, - INT_SHR_S, - INT_SHR_U, - INT_ROTL, - INT_ROTR + INT_SHL = 0, + INT_SHR_S, + INT_SHR_U, + INT_ROTL, + INT_ROTR } IntShift; typedef enum FloatMath { - FLOAT_ABS = 0, - FLOAT_NEG, - FLOAT_CEIL, - FLOAT_FLOOR, - FLOAT_TRUNC, - FLOAT_NEAREST, - FLOAT_SQRT + FLOAT_ABS = 0, + FLOAT_NEG, + FLOAT_CEIL, + FLOAT_FLOOR, + FLOAT_TRUNC, + FLOAT_NEAREST, + FLOAT_SQRT } FloatMath; typedef enum FloatArithmetic { - FLOAT_ADD = 0, - FLOAT_SUB, - FLOAT_MUL, - FLOAT_DIV, - FLOAT_MIN, - FLOAT_MAX + FLOAT_ADD = 0, + FLOAT_SUB, + FLOAT_MUL, + FLOAT_DIV, + FLOAT_MIN, + FLOAT_MAX, } FloatArithmetic; static inline bool check_type_compatible(uint8 src_type, uint8 dst_type) { - if (src_type == dst_type) { - return true; - } - - /* ext i1 to i32 */ - if (src_type == VALUE_TYPE_I1 && dst_type == VALUE_TYPE_I32) { - return true; - } - - /* i32 <==> func.ref, i32 <==> extern.ref */ - if (src_type == VALUE_TYPE_I32 - && (dst_type == VALUE_TYPE_EXTERNREF - || dst_type == VALUE_TYPE_FUNCREF)) { - return true; - } - - if (dst_type == VALUE_TYPE_I32 - && (src_type == VALUE_TYPE_FUNCREF - || src_type == VALUE_TYPE_EXTERNREF)) { - return true; - } - - return false; + if (src_type == dst_type) { + return true; + } + + /* ext i1 to i32 */ + if (src_type == VALUE_TYPE_I1 && dst_type == VALUE_TYPE_I32) { + return true; + } + + /* i32 <==> func.ref, i32 <==> extern.ref */ + if (src_type == VALUE_TYPE_I32 + && (dst_type == VALUE_TYPE_EXTERNREF + || dst_type == VALUE_TYPE_FUNCREF)) { + return true; + } + + if (dst_type == VALUE_TYPE_I32 + && (src_type == VALUE_TYPE_FUNCREF + || src_type == VALUE_TYPE_EXTERNREF)) { + return true; + } + + return false; } -#define CHECK_STACK() do { \ - if (!func_ctx->block_stack.block_list_end) { \ - aot_set_last_error("WASM block stack underflow."); \ - goto fail; \ - } \ - if (!func_ctx->block_stack.block_list_end-> \ - value_stack.value_list_end) { \ - aot_set_last_error("WASM data stack underflow."); \ - goto fail; \ - } \ - } while (0) - -#define POP(llvm_value, value_type) do { \ - AOTValue *aot_value; \ - CHECK_STACK(); \ - aot_value = aot_value_stack_pop \ - (&func_ctx->block_stack.block_list_end->value_stack); \ - if (!check_type_compatible(aot_value->type, \ - value_type)) { \ - aot_set_last_error("invalid WASM stack data type."); \ - wasm_runtime_free(aot_value); \ - goto fail; \ - } \ - if (aot_value->type == value_type) \ - llvm_value = aot_value->value; \ - else { \ - if (aot_value->type == VALUE_TYPE_I1) { \ - if (!(llvm_value = LLVMBuildZExt(comp_ctx->builder, \ - aot_value->value, I32_TYPE, "i1toi32"))) { \ - aot_set_last_error("invalid WASM stack " \ - "data type."); \ - wasm_runtime_free(aot_value); \ - goto fail; \ - } \ - } \ - else { \ - bh_assert(aot_value->type == VALUE_TYPE_I32 \ - || aot_value->type == VALUE_TYPE_FUNCREF \ - || aot_value->type == VALUE_TYPE_EXTERNREF); \ - bh_assert(value_type == VALUE_TYPE_I32 \ - || value_type == VALUE_TYPE_FUNCREF \ - || value_type == VALUE_TYPE_EXTERNREF); \ - llvm_value = aot_value->value; \ - } \ - } \ - wasm_runtime_free(aot_value); \ - } while (0) +#define CHECK_STACK() \ + do { \ + if (!func_ctx->block_stack.block_list_end) { \ + aot_set_last_error("WASM block stack underflow."); \ + goto fail; \ + } \ + if (!func_ctx->block_stack.block_list_end->value_stack \ + .value_list_end) { \ + aot_set_last_error("WASM data stack underflow."); \ + goto fail; \ + } \ + } while (0) + +#define POP(llvm_value, value_type) \ + do { \ + AOTValue *aot_value; \ + CHECK_STACK(); \ + aot_value = aot_value_stack_pop( \ + &func_ctx->block_stack.block_list_end->value_stack); \ + if (!check_type_compatible(aot_value->type, value_type)) { \ + aot_set_last_error("invalid WASM stack data type."); \ + wasm_runtime_free(aot_value); \ + goto fail; \ + } \ + if (aot_value->type == value_type) \ + llvm_value = aot_value->value; \ + else { \ + if (aot_value->type == VALUE_TYPE_I1) { \ + if (!(llvm_value = \ + LLVMBuildZExt(comp_ctx->builder, aot_value->value, \ + I32_TYPE, "i1toi32"))) { \ + aot_set_last_error("invalid WASM stack " \ + "data type."); \ + wasm_runtime_free(aot_value); \ + goto fail; \ + } \ + } \ + else { \ + bh_assert(aot_value->type == VALUE_TYPE_I32 \ + || aot_value->type == VALUE_TYPE_FUNCREF \ + || aot_value->type == VALUE_TYPE_EXTERNREF); \ + bh_assert(value_type == VALUE_TYPE_I32 \ + || value_type == VALUE_TYPE_FUNCREF \ + || value_type == VALUE_TYPE_EXTERNREF); \ + llvm_value = aot_value->value; \ + } \ + } \ + wasm_runtime_free(aot_value); \ + } while (0) #define POP_I32(v) POP(v, VALUE_TYPE_I32) #define POP_I64(v) POP(v, VALUE_TYPE_I64) @@ -186,49 +164,50 @@ check_type_compatible(uint8 src_type, uint8 dst_type) #define POP_FUNCREF(v) POP(v, VALUE_TYPE_FUNCREF) #define POP_EXTERNREF(v) POP(v, VALUE_TYPE_EXTERNREF) -#define POP_COND(llvm_value) do { \ - AOTValue *aot_value; \ - CHECK_STACK(); \ - aot_value = aot_value_stack_pop \ - (&func_ctx->block_stack.block_list_end->value_stack); \ - if (aot_value->type != VALUE_TYPE_I1 \ - && aot_value->type != VALUE_TYPE_I32) { \ - aot_set_last_error("invalid WASM stack data type."); \ - wasm_runtime_free(aot_value); \ - goto fail; \ - } \ - if (aot_value->type == VALUE_TYPE_I1) \ - llvm_value = aot_value->value; \ - else { \ - if (!(llvm_value = LLVMBuildICmp(comp_ctx->builder, \ - LLVMIntNE, aot_value->value, I32_ZERO, \ - "i1_cond"))){ \ - aot_set_last_error("llvm build trunc failed."); \ - wasm_runtime_free(aot_value); \ - goto fail; \ - } \ - } \ - wasm_runtime_free(aot_value); \ - } while (0) - -#define PUSH(llvm_value, value_type) do { \ - AOTValue *aot_value; \ - if (!func_ctx->block_stack.block_list_end) { \ - aot_set_last_error("WASM block stack underflow."); \ - goto fail; \ - } \ - aot_value = wasm_runtime_malloc(sizeof(AOTValue)); \ - if (!aot_value) { \ - aot_set_last_error("allocate memory failed."); \ - goto fail; \ - } \ - memset(aot_value, 0, sizeof(AOTValue)); \ - aot_value->type = value_type; \ - aot_value->value = llvm_value; \ - aot_value_stack_push \ - (&func_ctx->block_stack.block_list_end->value_stack,\ - aot_value); \ - } while (0) +#define POP_COND(llvm_value) \ + do { \ + AOTValue *aot_value; \ + CHECK_STACK(); \ + aot_value = aot_value_stack_pop( \ + &func_ctx->block_stack.block_list_end->value_stack); \ + if (aot_value->type != VALUE_TYPE_I1 \ + && aot_value->type != VALUE_TYPE_I32) { \ + aot_set_last_error("invalid WASM stack data type."); \ + wasm_runtime_free(aot_value); \ + goto fail; \ + } \ + if (aot_value->type == VALUE_TYPE_I1) \ + llvm_value = aot_value->value; \ + else { \ + if (!(llvm_value = \ + LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, \ + aot_value->value, I32_ZERO, "i1_cond"))) { \ + aot_set_last_error("llvm build trunc failed."); \ + wasm_runtime_free(aot_value); \ + goto fail; \ + } \ + } \ + wasm_runtime_free(aot_value); \ + } while (0) + +#define PUSH(llvm_value, value_type) \ + do { \ + AOTValue *aot_value; \ + if (!func_ctx->block_stack.block_list_end) { \ + aot_set_last_error("WASM block stack underflow."); \ + goto fail; \ + } \ + aot_value = wasm_runtime_malloc(sizeof(AOTValue)); \ + if (!aot_value) { \ + aot_set_last_error("allocate memory failed."); \ + goto fail; \ + } \ + memset(aot_value, 0, sizeof(AOTValue)); \ + aot_value->type = value_type; \ + aot_value->value = llvm_value; \ + aot_value_stack_push( \ + &func_ctx->block_stack.block_list_end->value_stack, aot_value); \ + } while (0) #define PUSH_I32(v) PUSH(v, VALUE_TYPE_I32) #define PUSH_I64(v) PUSH(v, VALUE_TYPE_I64) @@ -266,30 +245,32 @@ check_type_compatible(uint8 src_type, uint8 dst_type) #define F64_CONST(v) LLVMConstReal(F64_TYPE, v) #define I8_CONST(v) LLVMConstInt(INT8_TYPE, v, true) -#define I8_ZERO (comp_ctx->llvm_consts.i8_zero) -#define I32_ZERO (comp_ctx->llvm_consts.i32_zero) -#define I64_ZERO (comp_ctx->llvm_consts.i64_zero) -#define F32_ZERO (comp_ctx->llvm_consts.f32_zero) -#define F64_ZERO (comp_ctx->llvm_consts.f64_zero) -#define I32_ONE (comp_ctx->llvm_consts.i32_one) -#define I32_TWO (comp_ctx->llvm_consts.i32_two) -#define I32_THREE (comp_ctx->llvm_consts.i32_three) -#define I32_FOUR (comp_ctx->llvm_consts.i32_four) -#define I32_FIVE (comp_ctx->llvm_consts.i32_five) -#define I32_SIX (comp_ctx->llvm_consts.i32_six) -#define I32_SEVEN (comp_ctx->llvm_consts.i32_seven) -#define I32_EIGHT (comp_ctx->llvm_consts.i32_eight) -#define I32_NEG_ONE (comp_ctx->llvm_consts.i32_neg_one) -#define I64_NEG_ONE (comp_ctx->llvm_consts.i64_neg_one) -#define I32_MIN (comp_ctx->llvm_consts.i32_min) -#define I64_MIN (comp_ctx->llvm_consts.i64_min) -#define I32_31 (comp_ctx->llvm_consts.i32_31) -#define I32_32 (comp_ctx->llvm_consts.i32_32) -#define I64_63 (comp_ctx->llvm_consts.i64_63) -#define I64_64 (comp_ctx->llvm_consts.i64_64) - -#define V128_TYPE comp_ctx->basic_types.v128_type -#define V128_PTR_TYPE comp_ctx->basic_types.v128_ptr_type +#define LLVM_CONST(name) (comp_ctx->llvm_consts.name) +#define I8_ZERO LLVM_CONST(i8_zero) +#define I32_ZERO LLVM_CONST(i32_zero) +#define I64_ZERO LLVM_CONST(i64_zero) +#define F32_ZERO LLVM_CONST(f32_zero) +#define F64_ZERO LLVM_CONST(f64_zero) +#define I32_ONE LLVM_CONST(i32_one) +#define I32_TWO LLVM_CONST(i32_two) +#define I32_THREE LLVM_CONST(i32_three) +#define I32_FOUR LLVM_CONST(i32_four) +#define I32_FIVE LLVM_CONST(i32_five) +#define I32_SIX LLVM_CONST(i32_six) +#define I32_SEVEN LLVM_CONST(i32_seven) +#define I32_EIGHT LLVM_CONST(i32_eight) +#define I32_NEG_ONE LLVM_CONST(i32_neg_one) +#define I64_NEG_ONE LLVM_CONST(i64_neg_one) +#define I32_MIN LLVM_CONST(i32_min) +#define I64_MIN LLVM_CONST(i64_min) +#define I32_31 LLVM_CONST(i32_31) +#define I32_32 LLVM_CONST(i32_32) +#define I64_63 LLVM_CONST(i64_63) +#define I64_64 LLVM_CONST(i64_64) +#define REF_NULL I32_NEG_ONE + +#define V128_TYPE comp_ctx->basic_types.v128_type +#define V128_PTR_TYPE comp_ctx->basic_types.v128_ptr_type #define V128_i8x16_TYPE comp_ctx->basic_types.i8x16_vec_type #define V128_i16x8_TYPE comp_ctx->basic_types.i16x8_vec_type #define V128_i32x4_TYPE comp_ctx->basic_types.i32x4_vec_type @@ -297,65 +278,64 @@ check_type_compatible(uint8 src_type, uint8 dst_type) #define V128_f32x4_TYPE comp_ctx->basic_types.f32x4_vec_type #define V128_f64x2_TYPE comp_ctx->basic_types.f64x2_vec_type -#define V128_ZERO (comp_ctx->llvm_consts.v128_zero) -#define V128_i8x16_ZERO (comp_ctx->llvm_consts.i8x16_vec_zero) -#define V128_i16x8_ZERO (comp_ctx->llvm_consts.i16x8_vec_zero) -#define V128_i32x4_ZERO (comp_ctx->llvm_consts.i32x4_vec_zero) -#define V128_i64x2_ZERO (comp_ctx->llvm_consts.i64x2_vec_zero) -#define V128_f32x4_ZERO (comp_ctx->llvm_consts.f32x4_vec_zero) -#define V128_f64x2_ZERO (comp_ctx->llvm_consts.f64x2_vec_zero) - -#define REF_NULL (comp_ctx->llvm_consts.i32_neg_one) - -#define TO_V128_i8x16(v) LLVMBuildBitCast(comp_ctx->builder, v, \ - V128_i8x16_TYPE, "i8x16_val") -#define TO_V128_i16x8(v) LLVMBuildBitCast(comp_ctx->builder, v, \ - V128_i16x8_TYPE, "i16x8_val") -#define TO_V128_i32x4(v) LLVMBuildBitCast(comp_ctx->builder, v, \ - V128_i32x4_TYPE, "i32x4_val") -#define TO_V128_i64x2(v) LLVMBuildBitCast(comp_ctx->builder, v, \ - V128_i64x2_TYPE, "i64x2_val") -#define TO_V128_f32x4(v) LLVMBuildBitCast(comp_ctx->builder, v, \ - V128_f32x4_TYPE, "f32x4_val") -#define TO_V128_f64x2(v) LLVMBuildBitCast(comp_ctx->builder, v, \ - V128_f64x2_TYPE, "f64x2_val") - -#define CHECK_LLVM_CONST(v) do { \ - if (!v) { \ - aot_set_last_error("create llvm const failed."); \ - goto fail; \ - } \ - } while (0) - -#define GET_AOT_FUNCTION(name, argc) do { \ - if (!(func_type = LLVMFunctionType(ret_type, param_types, \ - argc, false))) { \ - aot_set_last_error("llvm add function type failed."); \ - return false; \ - } \ - if (comp_ctx->is_jit_mode) { \ - /* JIT mode, call the function directly */ \ - if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { \ - aot_set_last_error("llvm add pointer type failed."); \ - return false; \ - } \ - if (!(value = I64_CONST((uint64)(uintptr_t)name)) \ - || !(func = LLVMConstIntToPtr(value, func_ptr_type))) { \ - aot_set_last_error("create LLVM value failed."); \ - return false; \ - } \ - } \ - else { \ - char *func_name = #name; \ - /* AOT mode, delcare the function */ \ - if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) \ - && !(func = LLVMAddFunction(comp_ctx->module, \ - func_name, func_type))) { \ - aot_set_last_error("llvm add function failed."); \ - return false; \ - } \ - } \ - } while (0) +#define V128_i8x16_ZERO LLVM_CONST(i8x16_vec_zero) +#define V128_i16x8_ZERO LLVM_CONST(i16x8_vec_zero) +#define V128_i32x4_ZERO LLVM_CONST(i32x4_vec_zero) +#define V128_i64x2_ZERO LLVM_CONST(i64x2_vec_zero) +#define V128_f32x4_ZERO LLVM_CONST(f32x4_vec_zero) +#define V128_f64x2_ZERO LLVM_CONST(f64x2_vec_zero) + +#define TO_V128_i8x16(v) \ + LLVMBuildBitCast(comp_ctx->builder, v, V128_i8x16_TYPE, "i8x16_val") +#define TO_V128_i16x8(v) \ + LLVMBuildBitCast(comp_ctx->builder, v, V128_i16x8_TYPE, "i16x8_val") +#define TO_V128_i32x4(v) \ + LLVMBuildBitCast(comp_ctx->builder, v, V128_i32x4_TYPE, "i32x4_val") +#define TO_V128_i64x2(v) \ + LLVMBuildBitCast(comp_ctx->builder, v, V128_i64x2_TYPE, "i64x2_val") +#define TO_V128_f32x4(v) \ + LLVMBuildBitCast(comp_ctx->builder, v, V128_f32x4_TYPE, "f32x4_val") +#define TO_V128_f64x2(v) \ + LLVMBuildBitCast(comp_ctx->builder, v, V128_f64x2_TYPE, "f64x2_val") + +#define CHECK_LLVM_CONST(v) \ + do { \ + if (!v) { \ + aot_set_last_error("create llvm const failed."); \ + goto fail; \ + } \ + } while (0) + +#define GET_AOT_FUNCTION(name, argc) \ + do { \ + if (!(func_type = \ + LLVMFunctionType(ret_type, param_types, argc, false))) { \ + aot_set_last_error("llvm add function type failed."); \ + return false; \ + } \ + if (comp_ctx->is_jit_mode) { \ + /* JIT mode, call the function directly */ \ + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { \ + aot_set_last_error("llvm add pointer type failed."); \ + return false; \ + } \ + if (!(value = I64_CONST((uint64)(uintptr_t)name)) \ + || !(func = LLVMConstIntToPtr(value, func_ptr_type))) { \ + aot_set_last_error("create LLVM value failed."); \ + return false; \ + } \ + } \ + else { \ + char *func_name = #name; \ + /* AOT mode, delcare the function */ \ + if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) \ + && !(func = LLVMAddFunction(comp_ctx->module, func_name, \ + func_type))) { \ + aot_set_last_error("llvm add function failed."); \ + return false; \ + } \ + } \ + } while (0) bool aot_compile_wasm(AOTCompContext *comp_ctx); @@ -364,26 +344,23 @@ bool aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name); bool -aot_emit_aot_file(AOTCompContext *comp_ctx, - AOTCompData *comp_data, +aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data, const char *file_name); -uint8_t* -aot_emit_aot_file_buf(AOTCompContext *comp_ctx, - AOTCompData *comp_data, - uint32_t *p_aot_file_size); +uint8 * +aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data, + uint32 *p_aot_file_size); bool aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name); -uint8_t* -aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size, - uint32_t opt_level, uint32_t size_level, - uint32_t *p_aot_file_size); +uint8 * +aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size, + uint32 opt_level, uint32 size_level, char *error_buf, + uint32 error_buf_size, uint32 *p_aot_file_size); #ifdef __cplusplus } /* end of extern "C" */ #endif #endif /* end of _AOT_COMPILER_H_ */ - diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 64c04e2a3f..789935d432 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -6,19 +6,24 @@ #include "aot_compiler.h" #include "../aot/aot_runtime.h" -#define PUT_U64_TO_ADDR(addr, value) do { \ - union { uint64 val; uint32 parts[2]; } u; \ - u.val = (value); \ - ((uint32*)(addr))[0] = u.parts[0]; \ - ((uint32*)(addr))[1] = u.parts[1]; \ - } while (0) - -#define CHECK_SIZE(size) do { \ - if (size == (uint32)-1) { \ - aot_set_last_error("get symbol size failed."); \ - return (uint32)-1; \ - } \ - } while (0) +#define PUT_U64_TO_ADDR(addr, value) \ + do { \ + union { \ + uint64 val; \ + uint32 parts[2]; \ + } u; \ + u.val = (value); \ + ((uint32 *)(addr))[0] = u.parts[0]; \ + ((uint32 *)(addr))[1] = u.parts[1]; \ + } while (0) + +#define CHECK_SIZE(size) \ + do { \ + if (size == (uint32)-1) { \ + aot_set_last_error("get symbol size failed."); \ + return (uint32)-1; \ + } \ + } while (0) /* Internal function in object file */ typedef struct AOTObjectFunc { @@ -124,9 +129,8 @@ get_mem_init_data_size(AOTMemInitData *mem_init_data) { /* init expr type (4 bytes) + init expr value (8 bytes) + byte count (4 bytes) + bytes */ - uint32 total_size = - (uint32)(sizeof(uint32) + sizeof(uint64) - + sizeof(uint32) + mem_init_data->byte_count); + uint32 total_size = (uint32)(sizeof(uint32) + sizeof(uint64) + + sizeof(uint32) + mem_init_data->byte_count); /* bulk_memory enabled: is_passive (4 bytes) + memory_index (4 bytes) @@ -173,8 +177,7 @@ get_mem_info_size(AOTCompData *comp_data) { /* import_memory_size + memory_size + init_data_count + init_data_list */ - return get_import_memory_size(comp_data) - + get_memory_size(comp_data) + return get_import_memory_size(comp_data) + get_memory_size(comp_data) + (uint32)sizeof(uint32) + get_mem_init_data_list_size(comp_data->mem_init_data_list, comp_data->mem_init_data_count); @@ -186,7 +189,8 @@ get_table_init_data_size(AOTTableInitData *table_init_data) /* * mode (4 bytes), elem_type (4 bytes), do not need is_dropped field * - * table_index(4 bytes) + init expr type (4 bytes) + init expr value (8 bytes) + * table_index(4 bytes) + init expr type (4 bytes) + init expr value (8 + * bytes) * + func index count (4 bytes) + func indexes */ return (uint32)(sizeof(uint32) * 2 + sizeof(uint32) + sizeof(uint32) @@ -238,8 +242,7 @@ get_import_table_size(AOTCompData *comp_data) * ------------------------------ */ return (uint32)(sizeof(uint32) - + comp_data->import_table_count - * (sizeof(uint32) * 3)); + + comp_data->import_table_count * (sizeof(uint32) * 3)); } static uint32 @@ -257,8 +260,7 @@ get_table_size(AOTCompData *comp_data) * ------------------------------ */ return (uint32)(sizeof(uint32) - + comp_data->table_count - * (sizeof(uint32) * 5)); + + comp_data->table_count * (sizeof(uint32) * 5)); } static uint32 @@ -294,8 +296,8 @@ static uint32 get_func_type_size(AOTFuncType *func_type) { /* param count + result count + types */ - return (uint32)sizeof(uint32) * 2 - + func_type->param_count + func_type->result_count; + return (uint32)sizeof(uint32) * 2 + func_type->param_count + + func_type->result_count; } static uint32 @@ -324,8 +326,8 @@ static uint32 get_import_global_size(AOTImportGlobal *import_global) { /* type (1 byte) + is_mutable (1 byte) + module_name + global_name */ - uint32 size = (uint32)sizeof(uint8) * 2 - + get_string_size(import_global->module_name); + uint32 size = + (uint32)sizeof(uint8) * 2 + get_string_size(import_global->module_name); size = align_uint(size, 2); size += get_string_size(import_global->global_name); return size; @@ -385,24 +387,22 @@ get_global_info_size(AOTCompData *comp_data) { /* global count + globals */ return (uint32)sizeof(uint32) - + get_globals_size(comp_data->globals, - comp_data->global_count); + + get_globals_size(comp_data->globals, comp_data->global_count); } static uint32 get_import_func_size(AOTImportFunc *import_func) { /* type index (2 bytes) + module_name + func_name */ - uint32 size = (uint32)sizeof(uint16) - + get_string_size(import_func->module_name); + uint32 size = + (uint32)sizeof(uint16) + get_string_size(import_func->module_name); size = align_uint(size, 2); size += get_string_size(import_func->func_name); return size; } static uint32 -get_import_funcs_size(AOTImportFunc *import_funcs, - uint32 import_func_count) +get_import_funcs_size(AOTImportFunc *import_funcs, uint32 import_func_count) { AOTImportFunc *import_func = import_funcs; uint32 size = 0, i; @@ -493,7 +493,8 @@ get_init_data_section_size(AOTCompData *comp_data, AOTObjectData *obj_data) static uint32 get_text_section_size(AOTObjectData *obj_data) { - return (sizeof(uint32) + obj_data->literal_size + obj_data->text_size + 3) & ~3; + return (sizeof(uint32) + obj_data->literal_size + obj_data->text_size + 3) + & ~3; } static uint32 @@ -525,7 +526,7 @@ get_exports_size(AOTExport *exports, uint32 export_count) AOTExport *export = exports; uint32 size = 0, i; - for (i = 0; i < export_count; i++, export++) { + for (i = 0; i < export_count; i++, export ++) { size = align_uint(size, 4); size += get_export_size(export); } @@ -549,15 +550,14 @@ get_relocation_size(AOTRelocation *relocation, bool is_32bin) if (is_32bin) size = sizeof(uint32) * 2; /* offset and addend */ else - size = sizeof(uint64) * 2; /* offset and addend */ + size = sizeof(uint64) * 2; /* offset and addend */ size += (uint32)sizeof(uint32); /* relocation type */ size += (uint32)sizeof(uint32); /* symbol name index */ return size; } static uint32 -get_relocations_size(AOTRelocation *relocations, - uint32 relocation_count, +get_relocations_size(AOTRelocation *relocations, uint32 relocation_count, bool is_32bin) { AOTRelocation *relocation = relocations; @@ -571,23 +571,20 @@ get_relocations_size(AOTRelocation *relocations, } static uint32 -get_relocation_group_size(AOTRelocationGroup *relocation_group, - bool is_32bin) +get_relocation_group_size(AOTRelocationGroup *relocation_group, bool is_32bin) { uint32 size = 0; /* section name index + relocation count + relocations */ size += (uint32)sizeof(uint32); size += (uint32)sizeof(uint32); size += get_relocations_size(relocation_group->relocations, - relocation_group->relocation_count, - is_32bin); + relocation_group->relocation_count, is_32bin); return size; } static uint32 get_relocation_groups_size(AOTRelocationGroup *relocation_groups, - uint32 relocation_group_count, - bool is_32bin) + uint32 relocation_group_count, bool is_32bin) { AOTRelocationGroup *relocation_group = relocation_groups; uint32 size = 0, i; @@ -602,8 +599,7 @@ get_relocation_groups_size(AOTRelocationGroup *relocation_groups, /* return the index (in order of insertion) of the symbol, create if not exits, -1 if failed */ static uint32 -get_relocation_symbol_index(const char *symbol_name, - bool *is_new, +get_relocation_symbol_index(const char *symbol_name, bool *is_new, AOTSymbolList *symbol_list) { AOTSymbolNode *sym; @@ -618,7 +614,7 @@ get_relocation_symbol_index(const char *symbol_name, } sym = sym->next; - index ++; + index++; } /* Not found in symbol_list, add it */ @@ -638,7 +634,7 @@ get_relocation_symbol_index(const char *symbol_name, symbol_list->end->next = sym; symbol_list->end = sym; } - symbol_list->len ++; + symbol_list->len++; if (is_new) *is_new = true; @@ -652,7 +648,8 @@ get_relocation_symbol_size(AOTRelocation *relocation, uint32 size = 0, index = 0; bool is_new = false; - index = get_relocation_symbol_index(relocation->symbol_name, &is_new, symbol_list); + index = get_relocation_symbol_index(relocation->symbol_name, &is_new, + symbol_list); CHECK_SIZE(index); if (is_new) { @@ -666,8 +663,7 @@ get_relocation_symbol_size(AOTRelocation *relocation, } static uint32 -get_relocations_symbol_size(AOTRelocation *relocations, - uint32 relocation_count, +get_relocations_symbol_size(AOTRelocation *relocations, uint32 relocation_count, AOTSymbolList *symbol_list) { AOTRelocation *relocation = relocations; @@ -689,8 +685,7 @@ get_relocation_group_symbol_size(AOTRelocationGroup *relocation_group, uint32 size = 0, index = 0, curr_size; bool is_new = false; - index = get_relocation_symbol_index(relocation_group->section_name, - &is_new, + index = get_relocation_symbol_index(relocation_group->section_name, &is_new, symbol_list); CHECK_SIZE(index); @@ -720,8 +715,8 @@ get_relocation_groups_symbol_size(AOTRelocationGroup *relocation_groups, uint32 size = 0, curr_size, i; for (i = 0; i < relocation_group_count; i++, relocation_group++) { - curr_size = get_relocation_group_symbol_size(relocation_group, - symbol_list); + curr_size = + get_relocation_group_symbol_size(relocation_group, symbol_list); CHECK_SIZE(curr_size); size += curr_size; } @@ -756,18 +751,17 @@ get_relocation_section_symbol_size(AOTObjectData *obj_data) get symbol size from symbol list directly in the second calculation */ if (obj_data->symbol_list.len > 0) { symbol_table_size = - get_symbol_size_from_symbol_list(&obj_data->symbol_list); + get_symbol_size_from_symbol_list(&obj_data->symbol_list); } else { - symbol_table_size = - get_relocation_groups_symbol_size(relocation_groups, - relocation_group_count, - &obj_data->symbol_list); + symbol_table_size = get_relocation_groups_symbol_size( + relocation_groups, relocation_group_count, &obj_data->symbol_list); } CHECK_SIZE(symbol_table_size); string_count = obj_data->symbol_list.len; - /* string_count + string_offsets + total_string_len + [str (string_len + str)] */ + /* string_count + string_offsets + total_string_len + + [str (string_len + str)] */ return (uint32)(sizeof(uint32) + sizeof(uint32) * string_count + sizeof(uint32) + symbol_table_size); } @@ -790,6 +784,23 @@ get_relocation_section_size(AOTObjectData *obj_data) is_32bit_binary(obj_data->binary)); } +static uint32 +get_native_symbol_list_size(AOTCompContext *comp_ctx) +{ + uint32 len = 0; + AOTNativeSymbol *sym = NULL; + + sym = bh_list_first_elem(&comp_ctx->native_symbols); + + while (sym) { + len = align_uint(len, 2); + len += get_string_size(sym->symbol); + sym = bh_list_elem_next(sym); + } + + return len; +} + static uint32 get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data, AOTObjectData *obj_data) @@ -835,6 +846,14 @@ get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data, size += (uint32)sizeof(uint32) * 2; size += get_relocation_section_size(obj_data); + if (get_native_symbol_list_size(comp_ctx) > 0) { + /* emit only when threre are native symbols */ + size = align_uint(size, 4); + /* section id + section size + sub section id + symbol count */ + size += (uint32)sizeof(uint32) * 4; + size += get_native_symbol_list_size(comp_ctx); + } + return size; } @@ -876,9 +895,9 @@ static void exchange_uint128(uint8 *pData) { /* swap high 64bit and low 64bit */ - uint64 value = *(uint64*)pData; - *(uint64*)pData = *(uint64*)(pData + 8); - *(uint64*)(pData + 8) = value; + uint64 value = *(uint64 *)pData; + *(uint64 *)pData = *(uint64 *)(pData + 8); + *(uint64 *)(pData + 8) = value; /* exchange high 64bit */ exchange_uint64(pData); /* exchange low 64bit */ @@ -892,68 +911,76 @@ static union { #define is_little_endian() (__ue.b == 1) -#define CHECK_BUF(length) do { \ - if (buf + offset + length > buf_end) { \ - aot_set_last_error("buf overflow"); \ - return false; \ - } \ -} while (0) - -#define EMIT_U8(v) do { \ - CHECK_BUF(1); \ - *(uint8*)(buf + offset) = (uint8)v; \ - offset++; \ - } while (0) - -#define EMIT_U16(v) do { \ - uint16 t = (uint16)v; \ - CHECK_BUF(2); \ - if (!is_little_endian()) \ - exchange_uint16((uint8*)&t); \ - *(uint16*)(buf + offset) = t; \ - offset += (uint32)sizeof(uint16); \ - } while (0) - -#define EMIT_U32(v) do { \ - uint32 t = (uint32)v; \ - CHECK_BUF(4); \ - if (!is_little_endian()) \ - exchange_uint32((uint8*)&t); \ - *(uint32*)(buf + offset) = t; \ - offset += (uint32)sizeof(uint32); \ - } while (0) - -#define EMIT_U64(v) do { \ - uint64 t = (uint64)v; \ - CHECK_BUF(8); \ - if (!is_little_endian()) \ - exchange_uint64((uint8*)&t); \ - PUT_U64_TO_ADDR(buf + offset, t); \ - offset += (uint32)sizeof(uint64); \ - } while (0) - -#define EMIT_V128(v) do { \ - uint64 *t = (uint64*)v.i64x2; \ - CHECK_BUF(16); \ - if (!is_little_endian()) \ - exchange_uint128((uint8 *)t); \ - PUT_U64_TO_ADDR(buf + offset, t[0]); \ - offset += (uint32)sizeof(uint64); \ - PUT_U64_TO_ADDR(buf + offset, t[1]); \ - offset += (uint32)sizeof(uint64); \ - } while (0) - -#define EMIT_BUF(v, len) do { \ - CHECK_BUF(len); \ - memcpy(buf + offset, v, len); \ - offset += len; \ - } while (0) - -#define EMIT_STR(s) do { \ - uint32 str_len = (uint32)strlen(s); \ - EMIT_U16(str_len); \ - EMIT_BUF(s, str_len); \ - } while (0) +#define CHECK_BUF(length) \ + do { \ + if (buf + offset + length > buf_end) { \ + aot_set_last_error("buf overflow"); \ + return false; \ + } \ + } while (0) + +#define EMIT_U8(v) \ + do { \ + CHECK_BUF(1); \ + *(uint8 *)(buf + offset) = (uint8)v; \ + offset++; \ + } while (0) + +#define EMIT_U16(v) \ + do { \ + uint16 t = (uint16)v; \ + CHECK_BUF(2); \ + if (!is_little_endian()) \ + exchange_uint16((uint8 *)&t); \ + *(uint16 *)(buf + offset) = t; \ + offset += (uint32)sizeof(uint16); \ + } while (0) + +#define EMIT_U32(v) \ + do { \ + uint32 t = (uint32)v; \ + CHECK_BUF(4); \ + if (!is_little_endian()) \ + exchange_uint32((uint8 *)&t); \ + *(uint32 *)(buf + offset) = t; \ + offset += (uint32)sizeof(uint32); \ + } while (0) + +#define EMIT_U64(v) \ + do { \ + uint64 t = (uint64)v; \ + CHECK_BUF(8); \ + if (!is_little_endian()) \ + exchange_uint64((uint8 *)&t); \ + PUT_U64_TO_ADDR(buf + offset, t); \ + offset += (uint32)sizeof(uint64); \ + } while (0) + +#define EMIT_V128(v) \ + do { \ + uint64 *t = (uint64 *)v.i64x2; \ + CHECK_BUF(16); \ + if (!is_little_endian()) \ + exchange_uint128((uint8 *)t); \ + PUT_U64_TO_ADDR(buf + offset, t[0]); \ + offset += (uint32)sizeof(uint64); \ + PUT_U64_TO_ADDR(buf + offset, t[1]); \ + offset += (uint32)sizeof(uint64); \ + } while (0) + +#define EMIT_BUF(v, len) \ + do { \ + CHECK_BUF(len); \ + memcpy(buf + offset, v, len); \ + offset += len; \ + } while (0) + +#define EMIT_STR(s) \ + do { \ + uint32 str_len = (uint32)strlen(s); \ + EMIT_U16(str_len); \ + EMIT_BUF(s, str_len); \ + } while (0) static bool aot_emit_file_header(uint8 *buf, uint8 *buf_end, uint32 *p_offset, @@ -1286,9 +1313,11 @@ aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, if (!aot_emit_mem_info(buf, buf_end, &offset, comp_ctx, comp_data, obj_data) || !aot_emit_table_info(buf, buf_end, &offset, comp_data, obj_data) || !aot_emit_func_type_info(buf, buf_end, &offset, comp_data, obj_data) - || !aot_emit_import_global_info(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_import_global_info(buf, buf_end, &offset, comp_data, + obj_data) || !aot_emit_global_info(buf, buf_end, &offset, comp_data, obj_data) - || !aot_emit_import_func_info(buf, buf_end, &offset, comp_data, obj_data)) + || !aot_emit_import_func_info(buf, buf_end, &offset, comp_data, + obj_data)) return false; offset = align_uint(offset, 4); @@ -1395,7 +1424,7 @@ aot_emit_export_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, EMIT_U32(section_size); EMIT_U32(export_count); - for (i = 0; i < export_count; i++, export++) { + for (i = 0; i < export_count; i++, export ++) { offset = align_uint(offset, 4); EMIT_U32(export->index); EMIT_U8(export->kind); @@ -1415,7 +1444,8 @@ aot_emit_export_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, static bool aot_emit_relocation_symbol_table(uint8 *buf, uint8 *buf_end, uint32 *p_offset, - AOTCompData *comp_data, AOTObjectData *obj_data) + AOTCompData *comp_data, + AOTObjectData *obj_data) { uint32 symbol_offset = 0, total_string_len = 0; uint32 offset = *p_offset; @@ -1425,7 +1455,7 @@ aot_emit_relocation_symbol_table(uint8 *buf, uint8 *buf_end, uint32 *p_offset, /* emit symbol offsets */ sym = (AOTSymbolNode *)(obj_data->symbol_list.head); - while(sym) { + while (sym) { EMIT_U32(symbol_offset); /* string_len + str[0 .. string_len - 1] */ symbol_offset += (uint32)sizeof(uint16) + sym->str_len; @@ -1465,7 +1495,8 @@ aot_emit_relocation_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, EMIT_U32(AOT_SECTION_TYPE_RELOCATION); EMIT_U32(section_size); - aot_emit_relocation_symbol_table(buf, buf_end, &offset, comp_data, obj_data); + aot_emit_relocation_symbol_table(buf, buf_end, &offset, comp_data, + obj_data); offset = align_uint(offset, 4); EMIT_U32(obj_data->relocation_group_count); @@ -1505,10 +1536,42 @@ aot_emit_relocation_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, return true; } +static bool +aot_emit_native_symbol(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompContext *comp_ctx) +{ + uint32 offset = *p_offset; + AOTNativeSymbol *sym = NULL; + + if (bh_list_length(&comp_ctx->native_symbols) == 0) + /* emit only when threre are native symbols */ + return true; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(AOT_SECTION_TYPE_CUSTOM); + /* sub section id + symbol count + symbol list */ + EMIT_U32(sizeof(uint32) * 2 + get_native_symbol_list_size(comp_ctx)); + EMIT_U32(AOT_CUSTOM_SECTION_NATIVE_SYMBOL); + EMIT_U32(bh_list_length(&comp_ctx->native_symbols)); + + sym = bh_list_first_elem(&comp_ctx->native_symbols); + + while (sym) { + offset = align_uint(offset, 2); + EMIT_STR(sym->symbol); + sym = bh_list_elem_next(sym); + } + + *p_offset = offset; + + return true; +} + typedef uint32 U32; -typedef int32 I32; +typedef int32 I32; typedef uint16 U16; -typedef uint8 U8; +typedef uint8 U8; struct coff_hdr { U16 u16Machine; @@ -1520,35 +1583,35 @@ struct coff_hdr { U16 u16Characs; }; -#define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_I386 0x014c -#define IMAGE_FILE_MACHINE_IA64 0x0200 +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_IA64 0x0200 #define AOT_COFF_BIN_TYPE 6 #define EI_NIDENT 16 -typedef uint32 elf32_word; -typedef int32 elf32_sword; -typedef uint16 elf32_half; -typedef uint32 elf32_off; -typedef uint32 elf32_addr; +typedef uint32 elf32_word; +typedef int32 elf32_sword; +typedef uint16 elf32_half; +typedef uint32 elf32_off; +typedef uint32 elf32_addr; struct elf32_ehdr { - unsigned char e_ident[EI_NIDENT]; /* ident bytes */ - elf32_half e_type; /* file type */ - elf32_half e_machine; /* target machine */ - elf32_word e_version; /* file version */ - elf32_addr e_entry; /* start address */ - elf32_off e_phoff; /* phdr file offset */ - elf32_off e_shoff; /* shdr file offset */ - elf32_word e_flags; /* file flags */ - elf32_half e_ehsize; /* sizeof ehdr */ - elf32_half e_phentsize; /* sizeof phdr */ - elf32_half e_phnum; /* number phdrs */ - elf32_half e_shentsize; /* sizeof shdr */ - elf32_half e_shnum; /* number shdrs */ - elf32_half e_shstrndx; /* shdr string index */ + unsigned char e_ident[EI_NIDENT]; /* ident bytes */ + elf32_half e_type; /* file type */ + elf32_half e_machine; /* target machine */ + elf32_word e_version; /* file version */ + elf32_addr e_entry; /* start address */ + elf32_off e_phoff; /* phdr file offset */ + elf32_off e_shoff; /* shdr file offset */ + elf32_word e_flags; /* file flags */ + elf32_half e_ehsize; /* sizeof ehdr */ + elf32_half e_phentsize; /* sizeof phdr */ + elf32_half e_phnum; /* number phdrs */ + elf32_half e_shentsize; /* sizeof shdr */ + elf32_half e_shnum; /* number shdrs */ + elf32_half e_shstrndx; /* shdr string index */ }; struct elf32_rel { @@ -1562,29 +1625,29 @@ struct elf32_rela { elf32_sword r_addend; } elf32_rela; -typedef uint32 elf64_word; -typedef int32 elf64_sword; -typedef uint64 elf64_xword; -typedef int64 elf64_sxword; -typedef uint16 elf64_half; -typedef uint64 elf64_off; -typedef uint64 elf64_addr; +typedef uint32 elf64_word; +typedef int32 elf64_sword; +typedef uint64 elf64_xword; +typedef int64 elf64_sxword; +typedef uint16 elf64_half; +typedef uint64 elf64_off; +typedef uint64 elf64_addr; struct elf64_ehdr { - unsigned char e_ident[EI_NIDENT]; /* ident bytes */ - elf64_half e_type; /* file type */ - elf64_half e_machine; /* target machine */ - elf64_word e_version; /* file version */ - elf64_addr e_entry; /* start address */ - elf64_off e_phoff; /* phdr file offset */ - elf64_off e_shoff; /* shdr file offset */ - elf64_word e_flags; /* file flags */ - elf64_half e_ehsize; /* sizeof ehdr */ - elf64_half e_phentsize; /* sizeof phdr */ - elf64_half e_phnum; /* number phdrs */ - elf64_half e_shentsize; /* sizeof shdr */ - elf64_half e_shnum; /* number shdrs */ - elf64_half e_shstrndx; /* shdr string index */ + unsigned char e_ident[EI_NIDENT]; /* ident bytes */ + elf64_half e_type; /* file type */ + elf64_half e_machine; /* target machine */ + elf64_word e_version; /* file version */ + elf64_addr e_entry; /* start address */ + elf64_off e_phoff; /* phdr file offset */ + elf64_off e_shoff; /* shdr file offset */ + elf64_word e_flags; /* file flags */ + elf64_half e_ehsize; /* sizeof ehdr */ + elf64_half e_phentsize; /* sizeof phdr */ + elf64_half e_phnum; /* number phdrs */ + elf64_half e_shentsize; /* sizeof shdr */ + elf64_half e_shnum; /* number shdrs */ + elf64_half e_shstrndx; /* shdr string index */ }; typedef struct elf64_rel { @@ -1598,14 +1661,14 @@ typedef struct elf64_rela { elf64_sxword r_addend; } elf64_rela; - -#define SET_TARGET_INFO(f, v, type, little) do { \ - type tmp = elf_header->v; \ - if ((little && !is_little_endian()) \ - || (!little && is_little_endian())) \ - exchange_##type((uint8*)&tmp); \ - obj_data->target_info.f = tmp; \ - } while (0) +#define SET_TARGET_INFO(f, v, type, little) \ + do { \ + type tmp = elf_header->v; \ + if ((little && !is_little_endian()) \ + || (!little && is_little_endian())) \ + exchange_##type((uint8 *)&tmp); \ + obj_data->target_info.f = tmp; \ + } while (0) static bool aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data) @@ -1614,10 +1677,8 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data) const uint8 *elf_buf = (uint8 *)LLVMGetBufferStart(obj_data->mem_buf); uint32 elf_size = (uint32)LLVMGetBufferSize(obj_data->mem_buf); - if (bin_type != LLVMBinaryTypeCOFF - && bin_type != LLVMBinaryTypeELF32L - && bin_type != LLVMBinaryTypeELF32B - && bin_type != LLVMBinaryTypeELF64L + if (bin_type != LLVMBinaryTypeCOFF && bin_type != LLVMBinaryTypeELF32L + && bin_type != LLVMBinaryTypeELF32B && bin_type != LLVMBinaryTypeELF64L && bin_type != LLVMBinaryTypeELF64B && bin_type != LLVMBinaryTypeMachO32L && bin_type != LLVMBinaryTypeMachO32B @@ -1630,7 +1691,7 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data) obj_data->target_info.bin_type = bin_type - LLVMBinaryTypeELF32L; if (bin_type == LLVMBinaryTypeCOFF) { - struct coff_hdr * coff_header; + struct coff_hdr *coff_header; if (!elf_buf || elf_size < sizeof(struct coff_hdr)) { aot_set_last_error("invalid coff_hdr buffer."); @@ -1690,7 +1751,6 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data) return false; } - strncpy(obj_data->target_info.arch, comp_ctx->target_arch, sizeof(obj_data->target_info.arch)); @@ -1700,22 +1760,34 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data) static bool aot_resolve_text(AOTObjectData *obj_data) { - LLVMSectionIteratorRef sec_itr; - char *name; - - if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) { - aot_set_last_error("llvm get section iterator failed."); - return false; +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMBinaryType bin_type = LLVMBinaryGetType(obj_data->binary); + if (bin_type == LLVMBinaryTypeELF32L || bin_type == LLVMBinaryTypeELF64L) { + obj_data->text = (char *)LLVMGetBufferStart(obj_data->mem_buf); + obj_data->text_size = (uint32)LLVMGetBufferSize(obj_data->mem_buf); } - while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { - if ((name = (char *)LLVMGetSectionName(sec_itr)) && !strcmp(name, ".text")) { - obj_data->text = (char *)LLVMGetSectionContents(sec_itr); - obj_data->text_size = (uint32)LLVMGetSectionSize(sec_itr); - break; + else +#endif + { + LLVMSectionIteratorRef sec_itr; + char *name; + + if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) { + aot_set_last_error("llvm get section iterator failed."); + return false; } - LLVMMoveToNextSection(sec_itr); + while ( + !LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { + if ((name = (char *)LLVMGetSectionName(sec_itr)) + && !strcmp(name, ".text")) { + obj_data->text = (char *)LLVMGetSectionContents(sec_itr); + obj_data->text_size = (uint32)LLVMGetSectionSize(sec_itr); + break; + } + LLVMMoveToNextSection(sec_itr); + } + LLVMDisposeSectionIterator(sec_itr); } - LLVMDisposeSectionIterator(sec_itr); return true; } @@ -1731,7 +1803,8 @@ aot_resolve_literal(AOTObjectData *obj_data) return false; } while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { - if ((name = (char *)LLVMGetSectionName(sec_itr)) && !strcmp(name, ".literal")) { + if ((name = (char *)LLVMGetSectionName(sec_itr)) + && !strcmp(name, ".literal")) { obj_data->literal = (char *)LLVMGetSectionContents(sec_itr); obj_data->literal_size = (uint32)LLVMGetSectionSize(sec_itr); break; @@ -1751,7 +1824,7 @@ is_data_section(LLVMSectionIteratorRef sec_itr, char *section_name) { uint32 relocation_count = 0; - return (!strcmp(section_name, ".data") + return (!strcmp(section_name, ".data") || !strcmp(section_name, ".sdata") || !strcmp(section_name, ".rodata") /* ".rodata.cst4/8/16/.." */ || !strncmp(section_name, ".rodata.cst", strlen(".rodata.cst")) @@ -1799,7 +1872,8 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data) if (sections_count > 0) { size = (uint32)sizeof(AOTObjectDataSection) * sections_count; - if (!(data_section = obj_data->data_sections = wasm_runtime_malloc(size))) { + if (!(data_section = obj_data->data_sections = + wasm_runtime_malloc(size))) { aot_set_last_error("allocate memory for data sections failed."); return false; } @@ -1810,7 +1884,8 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data) aot_set_last_error("llvm get section iterator failed."); return false; } - while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { + while ( + !LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { if ((name = (char *)LLVMGetSectionName(sec_itr)) && (is_data_section(sec_itr, name))) { data_section->name = name; @@ -1950,14 +2025,16 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data, /* parse relocation addend from reloction content */ if (has_addend) { if (is_binary_32bit) { - uint32 addend = (uint32)(((struct elf32_rela *)rela_content)->r_addend); + uint32 addend = + (uint32)(((struct elf32_rela *)rela_content)->r_addend); if (is_binary_little_endian != is_little_endian()) exchange_uint32((uint8 *)&addend); relocation->relocation_addend = (uint64)addend; rela_content += sizeof(struct elf32_rela); } else { - uint64 addend = (uint64)(((struct elf64_rela *)rela_content)->r_addend); + uint64 addend = + (uint64)(((struct elf64_rela *)rela_content)->r_addend); if (is_binary_little_endian != is_little_endian()) exchange_uint64((uint8 *)&addend); relocation->relocation_addend = addend; @@ -1970,25 +2047,31 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data, relocation->relocation_type = (uint32)type; relocation->symbol_name = (char *)LLVMGetSymbolName(rel_sym); - /* for ".LCPIxxx" relocation, transform the symbol name to real - * section name and set addend to the symbol address */ + /* for ".LCPIxxx", ".LJTIxxx" and ".LBBxxx" relocation, + * transform the symbol name to real section name and set + * addend to the offset of the symbol in the real section */ if (relocation->symbol_name - && str_starts_with(relocation->symbol_name, ".LCPI")) { - /* change relocation->relocation_addend and relocation->symbol_name */ + && (str_starts_with(relocation->symbol_name, ".LCPI") + || str_starts_with(relocation->symbol_name, ".LJTI") + || str_starts_with(relocation->symbol_name, ".LBB"))) { + /* change relocation->relocation_addend and + relocation->symbol_name */ LLVMSectionIteratorRef contain_section; - if (!(contain_section - = LLVMObjectFileCopySectionIterator(obj_data->binary))) { + if (!(contain_section = + LLVMObjectFileCopySectionIterator(obj_data->binary))) { aot_set_last_error("llvm get section iterator failed."); goto fail; } LLVMMoveToContainingSection(contain_section, rel_sym); - if (LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, contain_section)) { + if (LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, + contain_section)) { LLVMDisposeSectionIterator(contain_section); aot_set_last_error("llvm get containing section failed."); goto fail; } relocation->relocation_addend += LLVMGetSymbolAddress(rel_sym); - relocation->symbol_name = (char *)LLVMGetSectionName(contain_section); + relocation->symbol_name = + (char *)LLVMGetSectionName(contain_section); LLVMDisposeSectionIterator(contain_section); } @@ -2012,6 +2095,8 @@ is_relocation_section_name(char *section_name) || !strcmp(section_name, ".rela.literal") || !strcmp(section_name, ".rela.data") || !strcmp(section_name, ".rel.data") + || !strcmp(section_name, ".rela.sdata") + || !strcmp(section_name, ".rel.sdata") || !strcmp(section_name, ".rela.rodata") || !strcmp(section_name, ".rel.rodata") /* ".rela.rodata.cst4/8/16/.." */ @@ -2076,7 +2161,8 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data) return true; size = (uint32)sizeof(AOTRelocationGroup) * group_count; - if (!(relocation_group = obj_data->relocation_groups = wasm_runtime_malloc(size))) { + if (!(relocation_group = obj_data->relocation_groups = + wasm_runtime_malloc(size))) { aot_set_last_error("allocate memory for relocation groups failed."); return false; } @@ -2092,10 +2178,8 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data) if (is_relocation_section(sec_itr)) { name = (char *)LLVMGetSectionName(sec_itr); relocation_group->section_name = name; - if (!aot_resolve_object_relocation_group( - obj_data, - relocation_group, - sec_itr)) { + if (!aot_resolve_object_relocation_group(obj_data, relocation_group, + sec_itr)) { LLVMDisposeSectionIterator(sec_itr); return false; } @@ -2158,6 +2242,7 @@ aot_obj_data_create(AOTCompContext *comp_ctx) { char *err = NULL; AOTObjectData *obj_data; + LLVMTargetRef target = LLVMGetTargetMachineTarget(comp_ctx->target_machine); bh_print_time("Begin to emit object file to buffer"); @@ -2167,11 +2252,80 @@ aot_obj_data_create(AOTCompContext *comp_ctx) } memset(obj_data, 0, sizeof(AOTObjectData)); - if (LLVMTargetMachineEmitToMemoryBuffer(comp_ctx->target_machine, - comp_ctx->module, - LLVMObjectFile, - &err, - &obj_data->mem_buf) != 0) { + bh_print_time("Begin to emit object file"); + + if (!strncmp(LLVMGetTargetName(target), "arc", 3)) { +#if defined(_WIN32) || defined(_WIN32_) + aot_set_last_error("emit object file on Windows is unsupported."); + goto fail; +#else + /* Emit to assmelby file instead for arc target + as it cannot emit to object file */ + char file_name[] = "wasm-XXXXXX", buf[128]; + int fd, ret; + + if ((fd = mkstemp(file_name)) <= 0) { + aot_set_last_error("make temp file failed."); + goto fail; + } + + /* close and remove temp file */ + close(fd); + unlink(file_name); + + snprintf(buf, sizeof(buf), "%s%s", file_name, ".s"); + if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine, + comp_ctx->module, buf, LLVMAssemblyFile, + &err) + != 0) { + if (err) { + LLVMDisposeMessage(err); + err = NULL; + } + aot_set_last_error("emit elf to object file failed."); + goto fail; + } + + /* call arc gcc to compile assembly file to object file */ + /* TODO: get arc gcc from environment variable firstly + and check whether the toolchain exists actually */ + snprintf(buf, sizeof(buf), "%s%s%s%s%s%s", + "/opt/zephyr-sdk/arc-zephyr-elf/bin/arc-zephyr-elf-gcc ", + "-mcpu=arcem -o ", file_name, ".o -c ", file_name, ".s"); + /* TODO: use try..catch to handle possible exceptions */ + ret = system(buf); + /* remove temp assembly file */ + snprintf(buf, sizeof(buf), "%s%s", file_name, ".s"); + unlink(buf); + + if (ret != 0) { + aot_set_last_error("failed to compile asm file to obj file " + "with arc gcc toolchain."); + goto fail; + } + + /* create memory buffer from object file */ + snprintf(buf, sizeof(buf), "%s%s", file_name, ".o"); + ret = LLVMCreateMemoryBufferWithContentsOfFile(buf, &obj_data->mem_buf, + &err); + /* remove temp object file */ + snprintf(buf, sizeof(buf), "%s%s", file_name, ".o"); + unlink(buf); + + if (ret != 0) { + if (err) { + LLVMDisposeMessage(err); + err = NULL; + } + aot_set_last_error("create mem buffer with file failed."); + goto fail; + } +#endif /* end of defined(_WIN32) || defined(_WIN32_) */ + } + else if (LLVMTargetMachineEmitToMemoryBuffer( + comp_ctx->target_machine, comp_ctx->module, LLVMObjectFile, + &err, &obj_data->mem_buf) + != 0) { if (err) { LLVMDisposeMessage(err); err = NULL; @@ -2180,8 +2334,7 @@ aot_obj_data_create(AOTCompContext *comp_ctx) goto fail; } - if (!(obj_data->binary = - LLVMCreateBinary(obj_data->mem_buf, NULL, &err))) { + if (!(obj_data->binary = LLVMCreateBinary(obj_data->mem_buf, NULL, &err))) { if (err) { LLVMDisposeMessage(err); err = NULL; @@ -2194,8 +2347,7 @@ aot_obj_data_create(AOTCompContext *comp_ctx) /* resolve target info/text/relocations/functions */ if (!aot_resolve_target_info(comp_ctx, obj_data) - || !aot_resolve_text(obj_data) - || !aot_resolve_literal(obj_data) + || !aot_resolve_text(obj_data) || !aot_resolve_literal(obj_data) || !aot_resolve_object_data_sections(obj_data) || !aot_resolve_object_relocation_groups(obj_data) || !aot_resolve_functions(comp_ctx, obj_data)) @@ -2208,9 +2360,8 @@ aot_obj_data_create(AOTCompContext *comp_ctx) return NULL; } -uint8* -aot_emit_aot_file_buf(AOTCompContext *comp_ctx, - AOTCompData *comp_data, +uint8 * +aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data, uint32 *p_aot_file_size) { AOTObjectData *obj_data = aot_obj_data_create(comp_ctx); @@ -2231,12 +2382,16 @@ aot_emit_aot_file_buf(AOTCompContext *comp_ctx, buf_end = buf + aot_file_size; if (!aot_emit_file_header(buf, buf_end, &offset, comp_data, obj_data) - || !aot_emit_target_info_section(buf, buf_end, &offset, comp_data, obj_data) - || !aot_emit_init_data_section(buf, buf_end, &offset, comp_ctx, comp_data, obj_data) + || !aot_emit_target_info_section(buf, buf_end, &offset, comp_data, + obj_data) + || !aot_emit_init_data_section(buf, buf_end, &offset, comp_ctx, + comp_data, obj_data) || !aot_emit_text_section(buf, buf_end, &offset, comp_data, obj_data) || !aot_emit_func_section(buf, buf_end, &offset, comp_data, obj_data) || !aot_emit_export_section(buf, buf_end, &offset, comp_data, obj_data) - || !aot_emit_relocation_section(buf, buf_end, &offset, comp_data, obj_data)) + || !aot_emit_relocation_section(buf, buf_end, &offset, comp_data, + obj_data) + || !aot_emit_native_symbol(buf, buf_end, &offset, comp_ctx)) goto fail2; #if 0 @@ -2272,8 +2427,8 @@ aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data, bh_print_time("Begin to emit AOT file"); - if (!(aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data, - &aot_file_size))) { + if (!(aot_file_buf = + aot_emit_aot_file_buf(comp_ctx, comp_data, &aot_file_size))) { return false; } diff --git a/core/iwasm/compilation/aot_emit_compare.c b/core/iwasm/compilation/aot_emit_compare.c index 94c96a539f..a38263264f 100644 --- a/core/iwasm/compilation/aot_emit_compare.c +++ b/core/iwasm/compilation/aot_emit_compare.c @@ -4,6 +4,7 @@ */ #include "aot_emit_compare.h" +#include "../aot/aot_intrinsic.h" static bool int_cond_to_llvm_op(IntCond cond, LLVMIntPredicate *op) @@ -22,25 +23,25 @@ int_cond_to_llvm_op(IntCond cond, LLVMIntPredicate *op) case INT_LT_S: *op = LLVMIntSLT; break; - case INT_LT_U: + case INT_LT_U: *op = LLVMIntULT; break; case INT_GT_S: *op = LLVMIntSGT; break; - case INT_GT_U: + case INT_GT_U: *op = LLVMIntUGT; break; case INT_LE_S: *op = LLVMIntSLE; break; - case INT_LE_U: + case INT_LE_U: *op = LLVMIntULE; break; case INT_GE_S: *op = LLVMIntSGE; break; - case INT_GE_U: + case INT_GE_U: *op = LLVMIntUGE; break; default: @@ -157,7 +158,25 @@ aot_compile_op_f32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, POP_F32(rhs); POP_F32(lhs); - if (!(res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f32_cmp"))) { + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, "f32_cmp")) { + LLVMTypeRef param_types[3]; + LLVMValueRef opcond = LLVMConstInt(I32_TYPE, cond, true); + param_types[0] = I32_TYPE; + param_types[1] = F32_TYPE; + param_types[2] = F32_TYPE; + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f32_cmp", I32_TYPE, + param_types, 3, opcond, lhs, rhs); + if (!res) { + goto fail; + } + res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast"); + } + else { + res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f32_cmp"); + } + + if (!res) { aot_set_last_error("llvm build compare failed."); return false; } @@ -183,7 +202,25 @@ aot_compile_op_f64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, POP_F64(rhs); POP_F64(lhs); - if (!(res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f64_cmp"))) { + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, "f64_cmp")) { + LLVMTypeRef param_types[3]; + LLVMValueRef opcond = LLVMConstInt(I32_TYPE, cond, true); + param_types[0] = I32_TYPE; + param_types[1] = F64_TYPE; + param_types[2] = F64_TYPE; + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f64_cmp", I32_TYPE, + param_types, 3, opcond, lhs, rhs); + if (!res) { + goto fail; + } + res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast"); + } + else { + res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f64_cmp"); + } + + if (!res) { aot_set_last_error("llvm build compare failed."); return false; } @@ -193,4 +230,3 @@ aot_compile_op_f64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, fail: return false; } - diff --git a/core/iwasm/compilation/aot_emit_compare.h b/core/iwasm/compilation/aot_emit_compare.h index 6b06f5f094..6ac37794c2 100644 --- a/core/iwasm/compilation/aot_emit_compare.h +++ b/core/iwasm/compilation/aot_emit_compare.h @@ -28,10 +28,8 @@ bool aot_compile_op_f64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, FloatCond cond); - #ifdef __cplusplus } /* end of extern "C" */ #endif #endif /* end of _AOT_EMIT_COMPARE_H_ */ - diff --git a/core/iwasm/compilation/aot_emit_const.c b/core/iwasm/compilation/aot_emit_const.c index a862a7d3a5..c5736ca3e9 100644 --- a/core/iwasm/compilation/aot_emit_const.c +++ b/core/iwasm/compilation/aot_emit_const.c @@ -5,111 +5,109 @@ #include "aot_emit_const.h" - bool aot_compile_op_i32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, int32 i32_const) { - LLVMValueRef value = I32_CONST((uint32)i32_const); - CHECK_LLVM_CONST(value); - PUSH_I32(value); - return true; + LLVMValueRef value = I32_CONST((uint32)i32_const); + CHECK_LLVM_CONST(value); + PUSH_I32(value); + return true; fail: - return false; + return false; } bool aot_compile_op_i64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, int64 i64_const) { - LLVMValueRef value = I64_CONST((uint64)i64_const); - CHECK_LLVM_CONST(value); - PUSH_I64(value); - return true; + LLVMValueRef value = I64_CONST((uint64)i64_const); + CHECK_LLVM_CONST(value); + PUSH_I64(value); + return true; fail: - return false; + return false; } bool aot_compile_op_f32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, float32 f32_const) { - LLVMValueRef alloca, value; + LLVMValueRef alloca, value; - if (!isnan(f32_const)) { - value = F32_CONST(f32_const); - CHECK_LLVM_CONST(value); - PUSH_F32(value); - } - else { - int32 i32_const; - memcpy(&i32_const, &f32_const, sizeof(int32)); - if (!(alloca = LLVMBuildAlloca(comp_ctx->builder, - I32_TYPE, "i32_ptr"))) { - aot_set_last_error("llvm build alloca failed."); - return false; - } - if (!LLVMBuildStore(comp_ctx->builder, - I32_CONST((uint32)i32_const), alloca)) { - aot_set_last_error("llvm build store failed."); - return false; - } - if (!(alloca = LLVMBuildBitCast(comp_ctx->builder, - alloca, F32_PTR_TYPE, "f32_ptr"))) { - aot_set_last_error("llvm build bitcast failed."); - return false; - } - if (!(value = LLVMBuildLoad(comp_ctx->builder, alloca, ""))) { - aot_set_last_error("llvm build load failed."); - return false; - } - PUSH_F32(value); - } + if (!isnan(f32_const)) { + value = F32_CONST(f32_const); + CHECK_LLVM_CONST(value); + PUSH_F32(value); + } + else { + int32 i32_const; + memcpy(&i32_const, &f32_const, sizeof(int32)); + if (!(alloca = + LLVMBuildAlloca(comp_ctx->builder, I32_TYPE, "i32_ptr"))) { + aot_set_last_error("llvm build alloca failed."); + return false; + } + if (!LLVMBuildStore(comp_ctx->builder, I32_CONST((uint32)i32_const), + alloca)) { + aot_set_last_error("llvm build store failed."); + return false; + } + if (!(alloca = LLVMBuildBitCast(comp_ctx->builder, alloca, F32_PTR_TYPE, + "f32_ptr"))) { + aot_set_last_error("llvm build bitcast failed."); + return false; + } + if (!(value = LLVMBuildLoad(comp_ctx->builder, alloca, ""))) { + aot_set_last_error("llvm build load failed."); + return false; + } + PUSH_F32(value); + } - return true; + return true; fail: - return false; + return false; } bool aot_compile_op_f64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, float64 f64_const) { - LLVMValueRef alloca, value; + LLVMValueRef alloca, value; - if (!isnan(f64_const)) { - value = F64_CONST(f64_const); - CHECK_LLVM_CONST(value); - PUSH_F64(value); - } - else { - int64 i64_const; - memcpy(&i64_const, &f64_const, sizeof(int64)); - if (!(alloca = LLVMBuildAlloca(comp_ctx->builder, - I64_TYPE, "i64_ptr"))) { - aot_set_last_error("llvm build alloca failed."); - return false; - } - value = I64_CONST((uint64)i64_const); - CHECK_LLVM_CONST(value); - if (!LLVMBuildStore(comp_ctx->builder, value, alloca)) { - aot_set_last_error("llvm build store failed."); - return false; - } - if (!(alloca = LLVMBuildBitCast(comp_ctx->builder, - alloca, F64_PTR_TYPE, "f64_ptr"))) { - aot_set_last_error("llvm build bitcast failed."); - return false; - } - if (!(value = LLVMBuildLoad(comp_ctx->builder, alloca, ""))) { - aot_set_last_error("llvm build load failed."); - return false; - } - PUSH_F64(value); - } + if (!isnan(f64_const)) { + value = F64_CONST(f64_const); + CHECK_LLVM_CONST(value); + PUSH_F64(value); + } + else { + int64 i64_const; + memcpy(&i64_const, &f64_const, sizeof(int64)); + if (!(alloca = + LLVMBuildAlloca(comp_ctx->builder, I64_TYPE, "i64_ptr"))) { + aot_set_last_error("llvm build alloca failed."); + return false; + } + value = I64_CONST((uint64)i64_const); + CHECK_LLVM_CONST(value); + if (!LLVMBuildStore(comp_ctx->builder, value, alloca)) { + aot_set_last_error("llvm build store failed."); + return false; + } + if (!(alloca = LLVMBuildBitCast(comp_ctx->builder, alloca, F64_PTR_TYPE, + "f64_ptr"))) { + aot_set_last_error("llvm build bitcast failed."); + return false; + } + if (!(value = LLVMBuildLoad(comp_ctx->builder, alloca, ""))) { + aot_set_last_error("llvm build load failed."); + return false; + } + PUSH_F64(value); + } - return true; + return true; fail: - return false; + return false; } - diff --git a/core/iwasm/compilation/aot_emit_const.h b/core/iwasm/compilation/aot_emit_const.h index 1d20a7a140..0b56cb13b0 100644 --- a/core/iwasm/compilation/aot_emit_const.h +++ b/core/iwasm/compilation/aot_emit_const.h @@ -33,4 +33,3 @@ aot_compile_op_f64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, #endif #endif /* end of _AOT_EMIT_CONST_H_ */ - diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c index 39f882d41f..c0e62e6dea 100644 --- a/core/iwasm/compilation/aot_emit_control.c +++ b/core/iwasm/compilation/aot_emit_control.c @@ -8,37 +8,40 @@ #include "../aot/aot_runtime.h" #include "../interpreter/wasm_loader.h" +#if WASM_ENABLE_DEBUG_AOT != 0 +#include "debug/dwarf_extractor.h" +#endif + static char *block_name_prefix[] = { "block", "loop", "if" }; static char *block_name_suffix[] = { "begin", "else", "end" }; +/* clang-format off */ enum { LABEL_BEGIN = 0, LABEL_ELSE, LABEL_END }; +/* clang-format on */ static void -format_block_name(char *name, uint32 name_size, - uint32 block_index, uint32 label_type, - uint32 label_id) +format_block_name(char *name, uint32 name_size, uint32 block_index, + uint32 label_type, uint32 label_id) { if (label_type != LABEL_TYPE_FUNCTION) - snprintf(name, name_size, "%s%d%s%s", - block_name_prefix[label_type], block_index, - "_", block_name_suffix[label_id]); + snprintf(name, name_size, "%s%d%s%s", block_name_prefix[label_type], + block_index, "_", block_name_suffix[label_id]); else snprintf(name, name_size, "%s", "func_end"); } -#define CREATE_BLOCK(new_llvm_block, name) do { \ - if (!(new_llvm_block = \ - LLVMAppendBasicBlockInContext(comp_ctx->context, \ - func_ctx->func, \ - name))) { \ - aot_set_last_error("add LLVM basic block failed.");\ - goto fail; \ - } \ - } while (0) +#define CREATE_BLOCK(new_llvm_block, name) \ + do { \ + if (!(new_llvm_block = LLVMAppendBasicBlockInContext( \ + comp_ctx->context, func_ctx->func, name))) { \ + aot_set_last_error("add LLVM basic block failed."); \ + goto fail; \ + } \ + } while (0) #define CURR_BLOCK() LLVMGetInsertBlock(comp_ctx->builder) @@ -51,76 +54,79 @@ format_block_name(char *name, uint32 name_size, #define MOVE_BLOCK_BEFORE(llvm_block, llvm_block_before) \ LLVMMoveBasicBlockBefore(llvm_block, llvm_block_before) -#define BUILD_BR(llvm_block) do { \ - if (!LLVMBuildBr(comp_ctx->builder, llvm_block)) { \ - aot_set_last_error("llvm build br failed."); \ - goto fail; \ - } \ - } while (0) - -#define BUILD_COND_BR(value_if, block_then, block_else) do {\ - if (!LLVMBuildCondBr(comp_ctx->builder, value_if, \ - block_then, block_else)) { \ - aot_set_last_error("llvm build cond br failed."); \ - goto fail; \ - } \ - } while (0) +#define BUILD_BR(llvm_block) \ + do { \ + if (!LLVMBuildBr(comp_ctx->builder, llvm_block)) { \ + aot_set_last_error("llvm build br failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_COND_BR(value_if, block_then, block_else) \ + do { \ + if (!LLVMBuildCondBr(comp_ctx->builder, value_if, block_then, \ + block_else)) { \ + aot_set_last_error("llvm build cond br failed."); \ + goto fail; \ + } \ + } while (0) #define SET_BUILDER_POS(llvm_block) \ LLVMPositionBuilderAtEnd(comp_ctx->builder, llvm_block) -#define CREATE_RESULT_VALUE_PHIS(block) do { \ - if (block->result_count && !block->result_phis) { \ - uint32 i; \ - uint64 size; \ - LLVMBasicBlockRef block_curr = CURR_BLOCK(); \ - /* Allocate memory */ \ - size = sizeof(LLVMValueRef) * (uint64)block->result_count; \ - if (size >= UINT32_MAX \ - || !(block->result_phis = \ - wasm_runtime_malloc((uint32)size))) { \ - aot_set_last_error("allocate memory failed."); \ - goto fail; \ - } \ - SET_BUILDER_POS(block->llvm_end_block); \ - for (i = 0; i < block->result_count; i++) { \ - if (!(block->result_phis[i] = \ - LLVMBuildPhi(comp_ctx->builder, \ - TO_LLVM_TYPE(block->result_types[i]), \ - "phi"))) { \ - aot_set_last_error("llvm build phi failed."); \ - goto fail; \ - } \ - } \ - SET_BUILDER_POS(block_curr); \ - } \ - } while (0) - -#define ADD_TO_RESULT_PHIS(block, value, idx) do { \ - LLVMBasicBlockRef block_curr = CURR_BLOCK(); \ - LLVMTypeRef phi_ty = LLVMTypeOf(block->result_phis[idx]); \ - LLVMTypeRef value_ty = LLVMTypeOf(value); \ - bh_assert(LLVMGetTypeKind(phi_ty) == LLVMGetTypeKind(value_ty)); \ - bh_assert(LLVMGetTypeContext(phi_ty) \ - == LLVMGetTypeContext(value_ty)); \ - LLVMAddIncoming(block->result_phis[idx], &value, &block_curr, 1); \ - (void)phi_ty; \ - (void)value_ty; \ - } while (0) - -#define BUILD_ICMP(op, left, right, res, name) do { \ - if (!(res = LLVMBuildICmp(comp_ctx->builder, op, \ - left, right, name))) { \ - aot_set_last_error("llvm build icmp failed."); \ - goto fail; \ - } \ - } while (0) - -#define ADD_TO_PARAM_PHIS(block, value, idx) do { \ - LLVMBasicBlockRef block_curr = CURR_BLOCK(); \ - LLVMAddIncoming(block->param_phis[idx], \ - &value, &block_curr, 1); \ - } while (0) +#define CREATE_RESULT_VALUE_PHIS(block) \ + do { \ + if (block->result_count && !block->result_phis) { \ + uint32 i; \ + uint64 size; \ + LLVMBasicBlockRef block_curr = CURR_BLOCK(); \ + /* Allocate memory */ \ + size = sizeof(LLVMValueRef) * (uint64)block->result_count; \ + if (size >= UINT32_MAX \ + || !(block->result_phis = \ + wasm_runtime_malloc((uint32)size))) { \ + aot_set_last_error("allocate memory failed."); \ + goto fail; \ + } \ + SET_BUILDER_POS(block->llvm_end_block); \ + for (i = 0; i < block->result_count; i++) { \ + if (!(block->result_phis[i] = LLVMBuildPhi( \ + comp_ctx->builder, \ + TO_LLVM_TYPE(block->result_types[i]), "phi"))) { \ + aot_set_last_error("llvm build phi failed."); \ + goto fail; \ + } \ + } \ + SET_BUILDER_POS(block_curr); \ + } \ + } while (0) + +#define ADD_TO_RESULT_PHIS(block, value, idx) \ + do { \ + LLVMBasicBlockRef block_curr = CURR_BLOCK(); \ + LLVMTypeRef phi_ty = LLVMTypeOf(block->result_phis[idx]); \ + LLVMTypeRef value_ty = LLVMTypeOf(value); \ + bh_assert(LLVMGetTypeKind(phi_ty) == LLVMGetTypeKind(value_ty)); \ + bh_assert(LLVMGetTypeContext(phi_ty) == LLVMGetTypeContext(value_ty)); \ + LLVMAddIncoming(block->result_phis[idx], &value, &block_curr, 1); \ + (void)phi_ty; \ + (void)value_ty; \ + } while (0) + +#define BUILD_ICMP(op, left, right, res, name) \ + do { \ + if (!(res = \ + LLVMBuildICmp(comp_ctx->builder, op, left, right, name))) { \ + aot_set_last_error("llvm build icmp failed."); \ + goto fail; \ + } \ + } while (0) + +#define ADD_TO_PARAM_PHIS(block, value, idx) \ + do { \ + LLVMBasicBlockRef block_curr = CURR_BLOCK(); \ + LLVMAddIncoming(block->param_phis[idx], &value, &block_curr, 1); \ + } while (0) static LLVMBasicBlockRef find_next_llvm_end_block(AOTBlock *block) @@ -131,7 +137,7 @@ find_next_llvm_end_block(AOTBlock *block) return block ? block->llvm_end_block : NULL; } -static AOTBlock* +static AOTBlock * get_target_block(AOTFuncContext *func_ctx, uint32 br_depth) { uint32 i = br_depth; @@ -149,8 +155,7 @@ get_target_block(AOTFuncContext *func_ctx, uint32 br_depth) } static bool -handle_next_reachable_block(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint8 **p_frame_ip) { AOTBlock *block = func_ctx->block_stack.block_list_end; @@ -158,14 +163,20 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, uint8 *frame_ip = NULL; uint32 i; AOTFuncType *func_type; + LLVMValueRef ret; +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMMetadataRef return_location; +#endif aot_checked_addr_list_destroy(func_ctx); - bh_assert(block); - if (block->label_type == LABEL_TYPE_IF - && block->llvm_else_block - && !block->skip_wasm_code_else +#if WASM_ENABLE_DEBUG_AOT != 0 + return_location = dwarf_gen_location( + comp_ctx, func_ctx, + (*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code); +#endif + if (block->label_type == LABEL_TYPE_IF && block->llvm_else_block && *p_frame_ip <= block->wasm_code_else) { /* Clear value stack and start to translate else branch */ aot_value_stack_destroy(&block->value_stack); @@ -182,8 +193,7 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, block = aot_block_stack_pop(&func_ctx->block_stack); if (block->label_type == LABEL_TYPE_IF) { - if (block->llvm_else_block - && !block->skip_wasm_code_else + if (block->llvm_else_block && !block->skip_wasm_code_else && *p_frame_ip <= block->wasm_code_else) { /* Clear value stack and start to translate else branch */ aot_value_stack_destroy(&block->value_stack); @@ -225,9 +235,9 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, /* Store extra return values to function parameters */ if (i != 0) { uint32 param_index = func_type->param_count + i; - if (!LLVMBuildStore(comp_ctx->builder, - block->result_phis[i], - LLVMGetParam(func_ctx->func, param_index))) { + if (!LLVMBuildStore( + comp_ctx->builder, block->result_phis[i], + LLVMGetParam(func_ctx->func, param_index))) { aot_set_last_error("llvm build store failed."); goto fail; } @@ -237,16 +247,23 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, if (block->label_type == LABEL_TYPE_FUNCTION) { if (block->result_count) { /* Return the first return value */ - if (!LLVMBuildRet(comp_ctx->builder, block->result_phis[0])) { + if (!(ret = + LLVMBuildRet(comp_ctx->builder, block->result_phis[0]))) { aot_set_last_error("llvm build return failed."); goto fail; } +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMInstructionSetDebugLoc(ret, return_location); +#endif } else { - if (!LLVMBuildRetVoid(comp_ctx->builder)) { + if (!(ret = LLVMBuildRetVoid(comp_ctx->builder))) { aot_set_last_error("llvm build return void failed."); goto fail; } +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMInstructionSetDebugLoc(ret, return_location); +#endif } } aot_block_destroy(block); @@ -274,8 +291,7 @@ push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx, return false; } - if (block->label_type == LABEL_TYPE_IF - && !block->skip_wasm_code_else + if (block->label_type == LABEL_TYPE_IF && !block->skip_wasm_code_else && !(block->else_param_phis = wasm_runtime_malloc((uint32)size))) { wasm_runtime_free(block->param_phis); block->param_phis = NULL; @@ -287,27 +303,24 @@ push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx, for (i = 0; i < block->param_count; i++) { SET_BUILDER_POS(block->llvm_entry_block); snprintf(name, sizeof(name), "%s%d_phi%d", - block_name_prefix[block->label_type], - block->block_index, i); - if (!(block->param_phis[i] = - LLVMBuildPhi(comp_ctx->builder, - TO_LLVM_TYPE(block->param_types[i]), - name))) { + block_name_prefix[block->label_type], block->block_index, + i); + if (!(block->param_phis[i] = LLVMBuildPhi( + comp_ctx->builder, TO_LLVM_TYPE(block->param_types[i]), + name))) { aot_set_last_error("llvm build phi failed."); goto fail; } if (block->label_type == LABEL_TYPE_IF - && !block->skip_wasm_code_else - && block->llvm_else_block) { + && !block->skip_wasm_code_else && block->llvm_else_block) { /* Build else param phis */ SET_BUILDER_POS(block->llvm_else_block); - snprintf(name, sizeof(name), "else%d_phi%d", - block->block_index, i); - if (!(block->else_param_phis[i] = - LLVMBuildPhi(comp_ctx->builder, - TO_LLVM_TYPE(block->param_types[i]), - name))) { + snprintf(name, sizeof(name), "else%d_phi%d", block->block_index, + i); + if (!(block->else_param_phis[i] = LLVMBuildPhi( + comp_ctx->builder, + TO_LLVM_TYPE(block->param_types[i]), name))) { aot_set_last_error("llvm build phi failed."); goto fail; } @@ -326,8 +339,8 @@ push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx, && !block->skip_wasm_code_else) { if (block->llvm_else_block) { /* has else branch, add to else param phis */ - LLVMAddIncoming(block->else_param_phis[param_index], - &value, &block_curr, 1); + LLVMAddIncoming(block->else_param_phis[param_index], &value, + &block_curr, 1); } else { /* no else branch, add to result phis */ @@ -362,8 +375,8 @@ push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx, bool aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint8 **p_frame_ip, uint8 *frame_ip_end, - uint32 label_type, uint32 param_count, uint8 *param_types, + uint8 **p_frame_ip, uint8 *frame_ip_end, uint32 label_type, + uint32 param_count, uint8 *param_types, uint32 result_count, uint8 *result_types) { BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE]; @@ -381,9 +394,9 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, memset(block_addr_cache, 0, sizeof(block_addr_cache)); /* Get block info */ - if (!(wasm_loader_find_block_addr((BlockAddr*)block_addr_cache, - *p_frame_ip, frame_ip_end, (uint8)label_type, - &else_addr, &end_addr))) { + if (!(wasm_loader_find_block_addr( + NULL, (BlockAddr *)block_addr_cache, *p_frame_ip, frame_ip_end, + (uint8)label_type, &else_addr, &end_addr))) { aot_set_last_error("find block end addr failed."); return false; } @@ -417,11 +430,10 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, block->block_index = func_ctx->block_stack.block_index[label_type]; func_ctx->block_stack.block_index[label_type]++; - if (label_type == LABEL_TYPE_BLOCK - || label_type == LABEL_TYPE_LOOP) { + if (label_type == LABEL_TYPE_BLOCK || label_type == LABEL_TYPE_LOOP) { /* Create block */ - format_block_name(name, sizeof(name), - block->block_index, label_type, LABEL_BEGIN); + format_block_name(name, sizeof(name), block->block_index, label_type, + LABEL_BEGIN); CREATE_BLOCK(block->llvm_entry_block, name); MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block); /* Jump to the entry block */ @@ -435,26 +447,41 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } else if (label_type == LABEL_TYPE_IF) { POP_COND(value); + + if (LLVMIsUndef(value) +#if LLVM_VERSION_NUMBER >= 12 + || LLVMIsPoison(value) +#endif + ) { + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW, + false, NULL, NULL))) { + goto fail; + } + return aot_handle_next_reachable_block(comp_ctx, func_ctx, + p_frame_ip); + } + if (!LLVMIsConstant(value)) { /* Compare value is not constant, create condition br IR */ /* Create entry block */ - format_block_name(name, sizeof(name), - block->block_index, label_type, LABEL_BEGIN); + format_block_name(name, sizeof(name), block->block_index, + label_type, LABEL_BEGIN); CREATE_BLOCK(block->llvm_entry_block, name); MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block); /* Create end block */ - format_block_name(name, sizeof(name), - block->block_index, label_type, LABEL_END); + format_block_name(name, sizeof(name), block->block_index, + label_type, LABEL_END); CREATE_BLOCK(block->llvm_end_block, name); MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_entry_block); if (else_addr) { /* Create else block */ - format_block_name(name, sizeof(name), - block->block_index, label_type, LABEL_ELSE); + format_block_name(name, sizeof(name), block->block_index, + label_type, LABEL_ELSE); CREATE_BLOCK(block->llvm_else_block, name); - MOVE_BLOCK_AFTER(block->llvm_else_block, block->llvm_entry_block); + MOVE_BLOCK_AFTER(block->llvm_else_block, + block->llvm_entry_block); /* Create condition br IR */ BUILD_COND_BR(value, block->llvm_entry_block, block->llvm_else_block); @@ -465,7 +492,8 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, block->llvm_end_block); block->is_reachable = true; } - if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block)) + if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, + block)) goto fail; /* Start to translate if branch of BLOCK if */ SET_BUILDER_POS(block->llvm_entry_block); @@ -476,13 +504,14 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, BLOCK if cannot be reached */ block->skip_wasm_code_else = true; /* Create entry block */ - format_block_name(name, sizeof(name), - block->block_index, label_type, LABEL_BEGIN); + format_block_name(name, sizeof(name), block->block_index, + label_type, LABEL_BEGIN); CREATE_BLOCK(block->llvm_entry_block, name); MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block); /* Jump to the entry block */ BUILD_BR(block->llvm_entry_block); - if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block)) + if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, + block)) goto fail; /* Start to translate the if branch */ SET_BUILDER_POS(block->llvm_entry_block); @@ -492,13 +521,14 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, BLOCK if cannot be reached */ if (else_addr) { /* Create else block */ - format_block_name(name, sizeof(name), - block->block_index, label_type, LABEL_ELSE); + format_block_name(name, sizeof(name), block->block_index, + label_type, LABEL_ELSE); CREATE_BLOCK(block->llvm_else_block, name); MOVE_BLOCK_AFTER_CURR(block->llvm_else_block); /* Jump to the else block */ BUILD_BR(block->llvm_else_block); - if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block)) + if (!push_aot_block_to_stack_and_pass_params( + comp_ctx, func_ctx, block)) goto fail; /* Start to translate the else branch */ SET_BUILDER_POS(block->llvm_else_block); @@ -538,16 +568,15 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } if (block->label_type != LABEL_TYPE_IF - || (!block->skip_wasm_code_else - && !block->llvm_else_block)) { + || (!block->skip_wasm_code_else && !block->llvm_else_block)) { aot_set_last_error("Invalid WASM block type."); return false; } /* Create end block if needed */ if (!block->llvm_end_block) { - format_block_name(name, sizeof(name), - block->block_index, block->label_type, LABEL_END); + format_block_name(name, sizeof(name), block->block_index, + block->label_type, LABEL_END); CREATE_BLOCK(block->llvm_end_block, name); if (block->llvm_else_block) MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_else_block); @@ -568,8 +597,7 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Jump to end block */ BUILD_BR(block->llvm_end_block); - if (!block->skip_wasm_code_else - && block->llvm_else_block) { + if (!block->skip_wasm_code_else && block->llvm_else_block) { /* Clear value stack, recover param values * and start to translate else branch. */ @@ -606,8 +634,8 @@ aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Create the end block */ if (!block->llvm_end_block) { - format_block_name(name, sizeof(name), - block->block_index, block->label_type, LABEL_END); + format_block_name(name, sizeof(name), block->block_index, + block->label_type, LABEL_END); CREATE_BLOCK(block->llvm_end_block, name); if ((next_llvm_end_block = find_next_llvm_end_block(block))) MOVE_BLOCK_BEFORE(block->llvm_end_block, next_llvm_end_block); @@ -645,22 +673,20 @@ check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) offset = I32_FIVE; if (!(terminate_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, - &offset, 1, "terminate_addr"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, + &offset, 1, "terminate_addr"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } if (!(terminate_addr = - LLVMBuildBitCast(comp_ctx->builder, - terminate_addr, - INT32_PTR_TYPE, "terminate_addr_ptr"))) { + LLVMBuildBitCast(comp_ctx->builder, terminate_addr, + INT32_PTR_TYPE, "terminate_addr_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } - if (!(terminate_flags = - LLVMBuildLoad(comp_ctx->builder, - terminate_addr, "terminate_flags"))) { + if (!(terminate_flags = LLVMBuildLoad(comp_ctx->builder, terminate_addr, + "terminate_flags"))) { aot_set_last_error("llvm build bit cast failed"); return false; } @@ -683,9 +709,8 @@ check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) CREATE_BLOCK(terminate_block, "terminate"); MOVE_BLOCK_AFTER_CURR(terminate_block); - if (!(flag = - LLVMBuildAnd(comp_ctx->builder, terminate_flags, - I32_ONE, "termination_flag"))) { + if (!(flag = LLVMBuildAnd(comp_ctx->builder, terminate_flags, I32_ONE, + "termination_flag"))) { aot_set_last_error("llvm build AND failed"); return false; } @@ -695,7 +720,7 @@ check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) /* Move builder to terminate block */ SET_BUILDER_POS(terminate_block); - if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) { + if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) { goto fail; } @@ -744,9 +769,8 @@ aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Dest block is Block/If/Function block */ /* Create the end block */ if (!block_dst->llvm_end_block) { - format_block_name(name, sizeof(name), - block_dst->block_index, block_dst->label_type, - LABEL_END); + format_block_name(name, sizeof(name), block_dst->block_index, + block_dst->label_type, LABEL_END); CREATE_BLOCK(block_dst->llvm_end_block, name); if ((next_llvm_end_block = find_next_llvm_end_block(block_dst))) MOVE_BLOCK_BEFORE(block_dst->llvm_end_block, @@ -791,6 +815,19 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, #endif POP_COND(value_cmp); + + if (LLVMIsUndef(value_cmp) +#if LLVM_VERSION_NUMBER >= 12 + || LLVMIsPoison(value_cmp) +#endif + ) { + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW, + false, NULL, NULL))) { + goto fail; + } + return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); + } + if (!LLVMIsConstant(value_cmp)) { /* Compare value is not constant, create condition br IR */ if (!(block_dst = get_target_block(func_ctx, br_depth))) { @@ -834,9 +871,8 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Dest block is Block/If/Function block */ /* Create the end block */ if (!block_dst->llvm_end_block) { - format_block_name(name, sizeof(name), - block_dst->block_index, block_dst->label_type, - LABEL_END); + format_block_name(name, sizeof(name), block_dst->block_index, + block_dst->label_type, LABEL_END); CREATE_BLOCK(block_dst->llvm_end_block, name); if ((next_llvm_end_block = find_next_llvm_end_block(block_dst))) MOVE_BLOCK_BEFORE(block_dst->llvm_end_block, @@ -895,8 +931,7 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint32 *br_depths, uint32 br_count, - uint8 **p_frame_ip) + uint32 *br_depths, uint32 br_count, uint8 **p_frame_ip) { uint32 i, j; LLVMValueRef value_switch, value_cmp, value_case, value, *values = NULL; @@ -917,6 +952,19 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, #endif POP_I32(value_cmp); + + if (LLVMIsUndef(value_cmp) +#if LLVM_VERSION_NUMBER >= 12 + || LLVMIsPoison(value_cmp) +#endif + ) { + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW, + false, NULL, NULL))) { + goto fail; + } + return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); + } + if (!LLVMIsConstant(value_cmp)) { /* Compare value is not constant, create switch IR */ for (i = 0; i <= br_count; i++) { @@ -930,17 +978,17 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (!target_block->llvm_end_block) { format_block_name(name, sizeof(name), target_block->block_index, - target_block->label_type, - LABEL_END); + target_block->label_type, LABEL_END); CREATE_BLOCK(target_block->llvm_end_block, name); if ((next_llvm_end_block = - find_next_llvm_end_block(target_block))) + find_next_llvm_end_block(target_block))) MOVE_BLOCK_BEFORE(target_block->llvm_end_block, next_llvm_end_block); } /* Handle result values */ if (target_block->result_count) { - size = sizeof(LLVMValueRef) * (uint64)target_block->result_count; + size = sizeof(LLVMValueRef) + * (uint64)target_block->result_count; if (size >= UINT32_MAX || !(values = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); @@ -965,7 +1013,8 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, else { /* Handle Loop parameters */ if (target_block->param_count) { - size = sizeof(LLVMValueRef) * (uint64)target_block->param_count; + size = sizeof(LLVMValueRef) + * (uint64)target_block->param_count; if (size >= UINT32_MAX || !(values = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); @@ -1002,8 +1051,8 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (!target_block) return false; target_llvm_block = target_block->label_type != LABEL_TYPE_LOOP - ? target_block->llvm_end_block - : target_block->llvm_entry_block; + ? target_block->llvm_end_block + : target_block->llvm_entry_block; LLVMAddCase(value_switch, value_case, target_llvm_block); } @@ -1030,20 +1079,28 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, { AOTBlock *block_func = func_ctx->block_stack.block_list_head; LLVMValueRef value; + LLVMValueRef ret; AOTFuncType *func_type; uint32 i, param_index, result_index; +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMMetadataRef return_location; +#endif bh_assert(block_func); func_type = func_ctx->aot_func->func_type; +#if WASM_ENABLE_DEBUG_AOT != 0 + return_location = dwarf_gen_location( + comp_ctx, func_ctx, + (*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code); +#endif if (block_func->result_count) { /* Store extra result values to function parameters */ for (i = 0; i < block_func->result_count - 1; i++) { result_index = block_func->result_count - 1 - i; POP(value, block_func->result_types[result_index]); param_index = func_type->param_count + result_index; - if (!LLVMBuildStore(comp_ctx->builder, - value, + if (!LLVMBuildStore(comp_ctx->builder, value, LLVMGetParam(func_ctx->func, param_index))) { aot_set_last_error("llvm build store failed."); goto fail; @@ -1051,16 +1108,22 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Return the first result value */ POP(value, block_func->result_types[0]); - if (!LLVMBuildRet(comp_ctx->builder, value)) { + if (!(ret = LLVMBuildRet(comp_ctx->builder, value))) { aot_set_last_error("llvm build return failed."); goto fail; } +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMInstructionSetDebugLoc(ret, return_location); +#endif } else { - if (!LLVMBuildRetVoid(comp_ctx->builder)) { + if (!(ret = LLVMBuildRetVoid(comp_ctx->builder))) { aot_set_last_error("llvm build return void failed."); goto fail; } +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMInstructionSetDebugLoc(ret, return_location); +#endif } return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); @@ -1069,12 +1132,11 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } bool -aot_compile_op_unreachable(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_unreachable(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint8 **p_frame_ip) { - if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_UNREACHABLE, - false, NULL, NULL)) + if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_UNREACHABLE, false, NULL, + NULL)) return false; return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); @@ -1082,8 +1144,7 @@ aot_compile_op_unreachable(AOTCompContext *comp_ctx, bool aot_handle_next_reachable_block(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 **p_frame_ip) + AOTFuncContext *func_ctx, uint8 **p_frame_ip) { return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); } diff --git a/core/iwasm/compilation/aot_emit_control.h b/core/iwasm/compilation/aot_emit_control.h index c0c029056f..a203876c13 100644 --- a/core/iwasm/compilation/aot_emit_control.h +++ b/core/iwasm/compilation/aot_emit_control.h @@ -14,8 +14,8 @@ extern "C" { bool aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint8 **p_frame_ip, uint8 *frame_ip_end, - uint32 label_type, uint32 param_count, uint8 *param_types, + uint8 **p_frame_ip, uint8 *frame_ip_end, uint32 label_type, + uint32 param_count, uint8 *param_types, uint32 result_count, uint8 *result_types); bool @@ -36,22 +36,19 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint32 *br_depths, uint32 br_count, - uint8 **p_frame_ip); + uint32 *br_depths, uint32 br_count, uint8 **p_frame_ip); bool aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint8 **p_frame_ip); bool -aot_compile_op_unreachable(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_unreachable(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint8 **p_frame_ip); bool aot_handle_next_reachable_block(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 **p_frame_ip); + AOTFuncContext *func_ctx, uint8 **p_frame_ip); #if WASM_ENABLE_THREAD_MGR != 0 bool @@ -63,4 +60,3 @@ check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); #endif #endif /* end of _AOT_EMIT_CONTROL_H_ */ - diff --git a/core/iwasm/compilation/aot_emit_conversion.c b/core/iwasm/compilation/aot_emit_conversion.c index 7dcb928b2c..93c5a998cc 100644 --- a/core/iwasm/compilation/aot_emit_conversion.c +++ b/core/iwasm/compilation/aot_emit_conversion.c @@ -6,27 +6,46 @@ #include "aot_emit_conversion.h" #include "aot_emit_exception.h" #include "aot_emit_numberic.h" +#include "../aot/aot_intrinsic.h" #include "../aot/aot_runtime.h" static bool trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - LLVMValueRef operand, LLVMTypeRef dest_type, - LLVMValueRef min_value, LLVMValueRef max_value, - char *name, bool sign) + LLVMValueRef operand, LLVMTypeRef src_type, + LLVMTypeRef dest_type, LLVMValueRef min_value, + LLVMValueRef max_value, char *name, bool sign) { LLVMBasicBlockRef check_nan_succ, check_overflow_succ; LLVMValueRef is_less, is_greater, res; - if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, - operand, operand, "fcmp_is_nan"))) { + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability( + comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) { + LLVMTypeRef param_types[3]; + LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_UNO, true); + param_types[0] = I32_TYPE; + param_types[1] = src_type; + param_types[2] = src_type; + res = aot_call_llvm_intrinsic( + comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp", + I32_TYPE, param_types, 3, opcond, operand, operand); + if (!res) { + goto fail; + } + res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast"); + } + else { + res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, operand, operand, + "fcmp_is_nan"); + } + + if (!res) { aot_set_last_error("llvm build fcmp failed."); goto fail; } - if (!(check_nan_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_nan_succ"))) { + if (!(check_nan_succ = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "check_nan_succ"))) { aot_set_last_error("llvm add basic block failed."); goto fail; } @@ -34,32 +53,74 @@ trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMMoveBasicBlockAfter(check_nan_succ, LLVMGetInsertBlock(comp_ctx->builder)); - if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_CONVERSION_TO_INTEGER, - true, res, check_nan_succ))) + if (!(aot_emit_exception(comp_ctx, func_ctx, + EXCE_INVALID_CONVERSION_TO_INTEGER, true, res, + check_nan_succ))) goto fail; - if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand, - min_value, "fcmp_min_value"))) { + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability( + comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) { + LLVMTypeRef param_types[3]; + LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_LE, true); + param_types[0] = I32_TYPE; + param_types[1] = src_type; + param_types[2] = src_type; + is_less = aot_call_llvm_intrinsic( + comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp", + I32_TYPE, param_types, 3, opcond, operand, min_value); + if (!is_less) { + goto fail; + } + is_less = + LLVMBuildIntCast(comp_ctx->builder, is_less, INT1_TYPE, "bit_cast"); + } + else { + is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand, + min_value, "fcmp_min_value"); + } + + if (!is_less) { aot_set_last_error("llvm build fcmp failed."); goto fail; } - if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand, - max_value, "fcmp_max_value"))) { + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability( + comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) { + LLVMTypeRef param_types[3]; + LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_GE, true); + param_types[0] = I32_TYPE; + param_types[1] = src_type; + param_types[2] = src_type; + is_greater = aot_call_llvm_intrinsic( + comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp", + I32_TYPE, param_types, 3, opcond, operand, max_value); + if (!is_greater) { + goto fail; + } + is_greater = LLVMBuildIntCast(comp_ctx->builder, is_greater, INT1_TYPE, + "bit_cast"); + } + else { + is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand, + max_value, "fcmp_min_value"); + } + + if (!is_greater) { aot_set_last_error("llvm build fcmp failed."); goto fail; } - if (!(res = LLVMBuildOr(comp_ctx->builder, is_less, is_greater, "is_overflow"))) { + if (!(res = LLVMBuildOr(comp_ctx->builder, is_less, is_greater, + "is_overflow"))) { aot_set_last_error("llvm build logic and failed."); goto fail; } /* Check if float value out of range */ - if (!(check_overflow_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_overflow_succ"))) { + if (!(check_overflow_succ = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "check_overflow_succ"))) { aot_set_last_error("llvm add basic block failed."); goto fail; } @@ -67,14 +128,24 @@ trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMMoveBasicBlockAfter(check_overflow_succ, LLVMGetInsertBlock(comp_ctx->builder)); - if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW, - true, res, check_overflow_succ))) + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW, true, + res, check_overflow_succ))) goto fail; - if (sign) - res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name); - else - res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name); + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, name)) { + LLVMTypeRef param_types[1]; + param_types[0] = src_type; + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, name, dest_type, + param_types, 1, operand); + } + else { + if (sign) + res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name); + else + res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name); + } + if (!res) { aot_set_last_error("llvm build conversion failed."); return false; @@ -89,22 +160,22 @@ trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } -#define ADD_BASIC_BLOCK(block, name) do { \ - if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \ - func_ctx->func, \ - name))) { \ - aot_set_last_error("llvm add basic block failed."); \ - goto fail; \ - } \ - \ - LLVMMoveBasicBlockAfter(block, LLVMGetInsertBlock(comp_ctx->builder)); \ -} while (0) +#define ADD_BASIC_BLOCK(block, name) \ + do { \ + if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \ + func_ctx->func, name))) { \ + aot_set_last_error("llvm add basic block failed."); \ + goto fail; \ + } \ + \ + LLVMMoveBasicBlockAfter(block, LLVMGetInsertBlock(comp_ctx->builder)); \ + } while (0) static bool trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - LLVMValueRef operand, LLVMTypeRef dest_type, - LLVMValueRef min_value, LLVMValueRef max_value, - char *name, bool sign) + LLVMValueRef operand, LLVMTypeRef src_type, + LLVMTypeRef dest_type, LLVMValueRef min_value, + LLVMValueRef max_value, char *name, bool sign) { LLVMBasicBlockRef check_nan_succ, check_less_succ, check_greater_succ; LLVMBasicBlockRef is_nan_block, is_less_block, is_greater_block, res_block; @@ -112,8 +183,8 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef zero = (dest_type == I32_TYPE) ? I32_ZERO : I64_ZERO; LLVMValueRef vmin, vmax; - if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, - operand, operand, "fcmp_is_nan"))) { + if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, operand, operand, + "fcmp_is_nan"))) { aot_set_last_error("llvm build fcmp failed."); goto fail; } @@ -126,8 +197,8 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, ADD_BASIC_BLOCK(is_greater_block, "is_greater_block"); ADD_BASIC_BLOCK(res_block, "res_block"); - if (!LLVMBuildCondBr(comp_ctx->builder, res, - is_nan_block, check_nan_succ)) { + if (!LLVMBuildCondBr(comp_ctx->builder, res, is_nan_block, + check_nan_succ)) { aot_set_last_error("llvm build cond br failed."); goto fail; } @@ -146,8 +217,8 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, aot_set_last_error("llvm build fcmp failed."); goto fail; } - if (!LLVMBuildCondBr(comp_ctx->builder, is_less, - is_less_block, check_less_succ)) { + if (!LLVMBuildCondBr(comp_ctx->builder, is_less, is_less_block, + check_less_succ)) { aot_set_last_error("llvm build cond br failed."); goto fail; } @@ -166,8 +237,8 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, aot_set_last_error("llvm build fcmp failed."); goto fail; } - if (!LLVMBuildCondBr(comp_ctx->builder, is_greater, - is_greater_block, check_greater_succ)) { + if (!LLVMBuildCondBr(comp_ctx->builder, is_greater, is_greater_block, + check_greater_succ)) { aot_set_last_error("llvm build cond br failed."); goto fail; } @@ -181,10 +252,21 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Start to translate check_greater_succ block */ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_greater_succ); - if (sign) - res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name); - else - res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name); + + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, name)) { + LLVMTypeRef param_types[1]; + param_types[0] = src_type; + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, name, dest_type, + param_types, 1, operand); + } + else { + if (sign) + res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name); + else + res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name); + } + if (!res) { aot_set_last_error("llvm build conversion failed."); return false; @@ -197,8 +279,7 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Start to translate res_block */ LLVMPositionBuilderAtEnd(comp_ctx->builder, res_block); /* Create result phi */ - if (!(phi = LLVMBuildPhi(comp_ctx->builder, - dest_type, + if (!(phi = LLVMBuildPhi(comp_ctx->builder, dest_type, "trunc_sat_result_phi"))) { aot_set_last_error("llvm build phi failed."); return false; @@ -246,7 +327,8 @@ aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) POP_I64(value); - if (!(res = LLVMBuildTrunc(comp_ctx->builder, value, I32_TYPE, "i32_wrap_i64"))) { + if (!(res = LLVMBuildTrunc(comp_ctx->builder, value, I32_TYPE, + "i32_wrap_i64"))) { aot_set_last_error("llvm build conversion failed."); return false; } @@ -276,14 +358,13 @@ aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } if (!saturating) - return trunc_float_to_int(comp_ctx, func_ctx, value, - I32_TYPE, min_value, max_value, - sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign); + return trunc_float_to_int( + comp_ctx, func_ctx, value, F32_TYPE, I32_TYPE, min_value, max_value, + sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign); else - return trunc_sat_float_to_int(comp_ctx, func_ctx, value, - I32_TYPE, min_value, max_value, - sign ? "i32_trunc_sat_f32_s" : - "i32_trunc_sat_f32_u", sign); + return trunc_sat_float_to_int( + comp_ctx, func_ctx, value, F32_TYPE, I32_TYPE, min_value, max_value, + sign ? "i32_trunc_sat_f32_s" : "i32_trunc_sat_f32_u", sign); fail: return false; } @@ -307,30 +388,31 @@ aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } if (!saturating) - return trunc_float_to_int(comp_ctx, func_ctx, value, - I32_TYPE, min_value, max_value, - sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign); + return trunc_float_to_int( + comp_ctx, func_ctx, value, F64_TYPE, I32_TYPE, min_value, max_value, + sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign); else - return trunc_sat_float_to_int(comp_ctx, func_ctx, value, - I32_TYPE, min_value, max_value, - sign ? "i32_trunc_sat_f64_s" : - "i32_trunc_sat_f64_u", sign); + return trunc_sat_float_to_int( + comp_ctx, func_ctx, value, F64_TYPE, I32_TYPE, min_value, max_value, + sign ? "i32_trunc_sat_f64_s" : "i32_trunc_sat_f64_u", sign); fail: return false; } bool -aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool sign) +aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool sign) { LLVMValueRef value, res; POP_I32(value); if (sign) - res = LLVMBuildSExt(comp_ctx->builder, value, I64_TYPE, "i64_extend_i32_s"); + res = LLVMBuildSExt(comp_ctx->builder, value, I64_TYPE, + "i64_extend_i32_s"); else - res = LLVMBuildZExt(comp_ctx->builder, value, I64_TYPE, "i64_extend_i32_u"); + res = LLVMBuildZExt(comp_ctx->builder, value, I64_TYPE, + "i64_extend_i32_u"); if (!res) { aot_set_last_error("llvm build conversion failed."); return false; @@ -343,24 +425,24 @@ aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx } bool -aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - int8 bitwidth) +aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, int8 bitwidth) { LLVMValueRef value, res, cast_value = NULL; POP_I64(value); if (bitwidth == 8) { - cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, - INT8_TYPE, true, "i8_intcast_i64"); + cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, INT8_TYPE, + true, "i8_intcast_i64"); } else if (bitwidth == 16) { - cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, - INT16_TYPE, true, "i16_intcast_i64"); + cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, INT16_TYPE, + true, "i16_intcast_i64"); } else if (bitwidth == 32) { - cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, - I32_TYPE, true, "i32_intcast_i64"); + cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, I32_TYPE, true, + "i32_intcast_i64"); } if (!cast_value) { @@ -368,7 +450,8 @@ aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx return false; } - res = LLVMBuildSExt(comp_ctx->builder, cast_value, I64_TYPE, "i64_extend_i64_s"); + res = LLVMBuildSExt(comp_ctx->builder, cast_value, I64_TYPE, + "i64_extend_i64_s"); if (!res) { aot_set_last_error("llvm build conversion failed."); @@ -382,20 +465,20 @@ aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx } bool -aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - int8 bitwidth) +aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, int8 bitwidth) { LLVMValueRef value, res, cast_value = NULL; POP_I32(value); if (bitwidth == 8) { - cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, - INT8_TYPE, true, "i8_intcast_i32"); + cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, INT8_TYPE, + true, "i8_intcast_i32"); } else if (bitwidth == 16) { - cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, - INT16_TYPE, true, "i16_intcast_i32"); + cast_value = LLVMBuildIntCast2(comp_ctx->builder, value, INT16_TYPE, + true, "i16_intcast_i32"); } if (!cast_value) { @@ -403,7 +486,8 @@ aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx return false; } - res = LLVMBuildSExt(comp_ctx->builder, cast_value, I32_TYPE, "i32_extend_i32_s"); + res = LLVMBuildSExt(comp_ctx->builder, cast_value, I32_TYPE, + "i32_extend_i32_s"); if (!res) { aot_set_last_error("llvm build conversion failed."); @@ -435,14 +519,13 @@ aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } if (!saturating) - return trunc_float_to_int(comp_ctx, func_ctx, value, - I64_TYPE, min_value, max_value, - sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign); + return trunc_float_to_int( + comp_ctx, func_ctx, value, F32_TYPE, I64_TYPE, min_value, max_value, + sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign); else - return trunc_sat_float_to_int(comp_ctx, func_ctx, value, - I64_TYPE, min_value, max_value, - sign ? "i64_trunc_sat_f32_s" : - "i64_trunc_sat_f32_u", sign); + return trunc_sat_float_to_int( + comp_ctx, func_ctx, value, F32_TYPE, I64_TYPE, min_value, max_value, + sign ? "i64_trunc_sat_f32_s" : "i64_trunc_sat_f32_u", sign); fail: return false; } @@ -466,31 +549,44 @@ aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } if (!saturating) - return trunc_float_to_int(comp_ctx, func_ctx, value, - I64_TYPE, min_value, max_value, - sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign); + return trunc_float_to_int( + comp_ctx, func_ctx, value, F64_TYPE, I64_TYPE, min_value, max_value, + sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign); else - return trunc_sat_float_to_int(comp_ctx, func_ctx, value, - I64_TYPE, min_value, max_value, - sign ? "i64_trunc_sat_f64_s" : - "i64_trunc_sat_f64_u", sign); + return trunc_sat_float_to_int( + comp_ctx, func_ctx, value, F64_TYPE, I64_TYPE, min_value, max_value, + sign ? "i64_trunc_sat_f64_s" : "i64_trunc_sat_f64_u", sign); fail: return false; } bool -aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool sign) +aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool sign) { LLVMValueRef value, res; POP_I32(value); - if (sign) - res = LLVMBuildSIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i32_s"); - else - res = LLVMBuildUIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i32_u"); + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability( + comp_ctx, sign ? "f32_convert_i32_s" : "f32_convert_i32_u")) { + LLVMTypeRef param_types[1]; + param_types[0] = I32_TYPE; + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, + sign ? "f32_convert_i32_s" + : "f32_convert_i32_u", + F32_TYPE, param_types, 1, value); + } + else { + if (sign) + res = LLVMBuildSIToFP(comp_ctx->builder, value, F32_TYPE, + "f32_convert_i32_s"); + else + res = LLVMBuildUIToFP(comp_ctx->builder, value, F32_TYPE, + "f32_convert_i32_u"); + } if (!res) { aot_set_last_error("llvm build conversion failed."); return false; @@ -503,17 +599,32 @@ aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ct } bool -aot_compile_op_f32_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool sign) +aot_compile_op_f32_convert_i64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool sign) { LLVMValueRef value, res; POP_I64(value); - if (sign) - res = LLVMBuildSIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i64_s"); - else - res = LLVMBuildUIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i64_u"); + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability( + comp_ctx, sign ? "f32_convert_i64_s" : "f32_convert_i64_u")) { + LLVMTypeRef param_types[1]; + param_types[0] = I64_TYPE; + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, + sign ? "f32_convert_i64_s" + : "f32_convert_i64_u", + F32_TYPE, param_types, 1, value); + } + else { + if (sign) + res = LLVMBuildSIToFP(comp_ctx->builder, value, F32_TYPE, + "f32_convert_i64_s"); + else + res = LLVMBuildUIToFP(comp_ctx->builder, value, F32_TYPE, + "f32_convert_i64_u"); + } + if (!res) { aot_set_last_error("llvm build conversion failed."); return false; @@ -526,13 +637,26 @@ aot_compile_op_f32_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ct } bool -aot_compile_op_f32_demote_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +aot_compile_op_f32_demote_f64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) { LLVMValueRef value, res; POP_F64(value); - if (!(res = LLVMBuildFPTrunc(comp_ctx->builder, value, F32_TYPE, "f32_demote_f64"))) { + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, "f32_demote_f64")) { + LLVMTypeRef param_types[1]; + param_types[0] = F64_TYPE; + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f32_demote_f64", + F32_TYPE, param_types, 1, value); + } + else { + res = LLVMBuildFPTrunc(comp_ctx->builder, value, F32_TYPE, + "f32_demote_f64"); + } + + if (!res) { aot_set_last_error("llvm build conversion failed."); return false; } @@ -544,17 +668,33 @@ aot_compile_op_f32_demote_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx } bool -aot_compile_op_f64_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool sign) +aot_compile_op_f64_convert_i32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool sign) { LLVMValueRef value, res; POP_I32(value); - if (sign) - res = LLVMBuildSIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i32_s"); - else - res = LLVMBuildUIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i32_u"); + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability( + comp_ctx, sign ? "f64_convert_i32_s" : "f64_convert_i32_u")) { + LLVMTypeRef param_types[1]; + param_types[0] = I32_TYPE; + + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, + sign ? "f64_convert_i32_s" + : "f64_convert_i32_u", + F64_TYPE, param_types, 1, value); + } + else { + if (sign) + res = LLVMBuildSIToFP(comp_ctx->builder, value, F64_TYPE, + "f64_convert_i32_s"); + else + res = LLVMBuildUIToFP(comp_ctx->builder, value, F64_TYPE, + "f64_convert_i32_u"); + } + if (!res) { aot_set_last_error("llvm build conversion failed."); return false; @@ -567,17 +707,33 @@ aot_compile_op_f64_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ct } bool -aot_compile_op_f64_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool sign) +aot_compile_op_f64_convert_i64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool sign) { LLVMValueRef value, res; POP_I64(value); - if (sign) - res = LLVMBuildSIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i64_s"); - else - res = LLVMBuildUIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i64_u"); + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability( + comp_ctx, sign ? "f64_convert_i64_s" : "f64_convert_i64_u")) { + LLVMTypeRef param_types[1]; + param_types[0] = I64_TYPE; + + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, + sign ? "f64_convert_i64_s" + : "f64_convert_i64_u", + F64_TYPE, param_types, 1, value); + } + else { + if (sign) + res = LLVMBuildSIToFP(comp_ctx->builder, value, F64_TYPE, + "f64_convert_i64_s"); + else + res = LLVMBuildUIToFP(comp_ctx->builder, value, F64_TYPE, + "f64_convert_i64_u"); + } + if (!res) { aot_set_last_error("llvm build conversion failed."); return false; @@ -590,13 +746,26 @@ aot_compile_op_f64_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ct } bool -aot_compile_op_f64_promote_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +aot_compile_op_f64_promote_f32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) { LLVMValueRef value, res; POP_F32(value); - if (!(res = LLVMBuildFPExt(comp_ctx->builder, value, F64_TYPE, "f64_promote_f32"))) { + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, "f64_promote_f32")) { + LLVMTypeRef param_types[1]; + param_types[0] = F32_TYPE; + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f64_promote_f32", + F64_TYPE, param_types, 1, value); + } + else { + res = LLVMBuildFPExt(comp_ctx->builder, value, F64_TYPE, + "f64_promote_f32"); + } + + if (!res) { aot_set_last_error("llvm build conversion failed."); return false; } @@ -616,8 +785,8 @@ aot_compile_op_i64_reinterpret_f64(AOTCompContext *comp_ctx, { LLVMValueRef value; POP_F64(value); - if (!(value = LLVMBuildBitCast(comp_ctx->builder, value, - I64_TYPE, "i64"))) { + if (!(value = + LLVMBuildBitCast(comp_ctx->builder, value, I64_TYPE, "i64"))) { aot_set_last_error("llvm build fp to si failed."); return false; } @@ -627,15 +796,14 @@ aot_compile_op_i64_reinterpret_f64(AOTCompContext *comp_ctx, return false; } - bool aot_compile_op_i32_reinterpret_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { LLVMValueRef value; POP_F32(value); - if (!(value = LLVMBuildBitCast(comp_ctx->builder, value, - I32_TYPE, "i32"))) { + if (!(value = + LLVMBuildBitCast(comp_ctx->builder, value, I32_TYPE, "i32"))) { aot_set_last_error("llvm build fp to si failed."); return false; } @@ -651,8 +819,8 @@ aot_compile_op_f64_reinterpret_i64(AOTCompContext *comp_ctx, { LLVMValueRef value; POP_I64(value); - if (!(value = LLVMBuildBitCast(comp_ctx->builder, value, - F64_TYPE, "f64"))) { + if (!(value = + LLVMBuildBitCast(comp_ctx->builder, value, F64_TYPE, "f64"))) { aot_set_last_error("llvm build si to fp failed."); return false; } @@ -668,8 +836,8 @@ aot_compile_op_f32_reinterpret_i32(AOTCompContext *comp_ctx, { LLVMValueRef value; POP_I32(value); - if (!(value = LLVMBuildBitCast(comp_ctx->builder, value, - F32_TYPE, "f32"))) { + if (!(value = + LLVMBuildBitCast(comp_ctx->builder, value, F32_TYPE, "f32"))) { aot_set_last_error("llvm build si to fp failed."); return false; } @@ -678,4 +846,3 @@ aot_compile_op_f32_reinterpret_i32(AOTCompContext *comp_ctx, fail: return false; } - diff --git a/core/iwasm/compilation/aot_emit_conversion.h b/core/iwasm/compilation/aot_emit_conversion.h index da80231789..a0e2fcb2ec 100644 --- a/core/iwasm/compilation/aot_emit_conversion.h +++ b/core/iwasm/compilation/aot_emit_conversion.h @@ -24,16 +24,16 @@ aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool sign, bool saturating); bool -aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool sign); +aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool sign); bool -aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - int8 bitwidth); +aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, int8 bitwidth); bool -aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - int8 bitwidth); +aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, int8 bitwidth); bool aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, @@ -44,26 +44,28 @@ aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool sign, bool saturating); bool -aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool sign); +aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool sign); bool -aot_compile_op_f32_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool sign); +aot_compile_op_f32_convert_i64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool sign); bool -aot_compile_op_f32_demote_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_op_f32_demote_f64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); bool -aot_compile_op_f64_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool sign); +aot_compile_op_f64_convert_i32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool sign); bool -aot_compile_op_f64_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool sign); +aot_compile_op_f64_convert_i64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool sign); bool -aot_compile_op_f64_promote_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_op_f64_promote_f32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); bool aot_compile_op_i64_reinterpret_f64(AOTCompContext *comp_ctx, @@ -86,4 +88,3 @@ aot_compile_op_f32_reinterpret_i32(AOTCompContext *comp_ctx, #endif #endif /* end of _AOT_EMIT_CONVERSION_H_ */ - diff --git a/core/iwasm/compilation/aot_emit_exception.c b/core/iwasm/compilation/aot_emit_exception.c index b6eb8429c4..9bc46be041 100644 --- a/core/iwasm/compilation/aot_emit_exception.c +++ b/core/iwasm/compilation/aot_emit_exception.c @@ -8,9 +8,7 @@ bool aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - int32 exception_id, - bool is_cond_br, - LLVMValueRef cond_br_if, + int32 exception_id, bool is_cond_br, LLVMValueRef cond_br_if, LLVMBasicBlockRef cond_br_else_block) { LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder); @@ -24,10 +22,8 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Create got_exception block if needed */ if (!func_ctx->got_exception_block) { - if (!(func_ctx->got_exception_block = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "got_exception"))) { + if (!(func_ctx->got_exception_block = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "got_exception"))) { aot_set_last_error("add LLVM basic block failed."); return false; } @@ -37,7 +33,7 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Create exection id phi */ if (!(func_ctx->exception_id_phi = LLVMBuildPhi( - comp_ctx->builder, I32_TYPE, "exception_id_phi"))) { + comp_ctx->builder, I32_TYPE, "exception_id_phi"))) { aot_set_last_error("llvm build phi failed."); return false; } @@ -48,8 +44,7 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, ret_type = VOID_TYPE; /* Create function type */ - if (!(func_type = LLVMFunctionType(ret_type, param_types, - 2, false))) { + if (!(func_type = LLVMFunctionType(ret_type, param_types, 2, false))) { aot_set_last_error("create LLVM function type failed."); return false; } @@ -62,12 +57,30 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Create LLVM function with const function pointer */ if (!(func_const = - I64_CONST((uint64)(uintptr_t)aot_set_exception_with_id)) + I64_CONST((uint64)(uintptr_t)aot_set_exception_with_id)) || !(func = LLVMConstIntToPtr(func_const, func_ptr_type))) { aot_set_last_error("create LLVM value failed."); return false; } } + else if (comp_ctx->is_indirect_mode) { + int32 func_index; + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + return false; + } + + func_index = aot_get_native_symbol_index( + comp_ctx, "aot_set_exception_with_id"); + if (func_index < 0) { + return false; + } + if (!(func = + aot_get_func_from_table(comp_ctx, func_ctx->native_symbol, + func_ptr_type, func_index))) { + return false; + } + } else { /* Create LLVM function with external function pointer */ if (!(func = LLVMGetNamedFunction(comp_ctx->module, @@ -83,15 +96,14 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Call the aot_set_exception_with_id() function */ param_values[0] = func_ctx->aot_inst; param_values[1] = func_ctx->exception_id_phi; - if (!LLVMBuildCall(comp_ctx->builder, func, param_values, - 2, "")) { + if (!LLVMBuildCall(comp_ctx->builder, func, param_values, 2, "")) { aot_set_last_error("llvm build call failed."); return false; } /* Create return IR */ AOTFuncType *aot_func_type = func_ctx->aot_func->func_type; - if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) { + if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) { return false; } @@ -112,7 +124,8 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, else { /* Create condition br */ if (!LLVMBuildCondBr(comp_ctx->builder, cond_br_if, - func_ctx->got_exception_block, cond_br_else_block)) { + func_ctx->got_exception_block, + cond_br_else_block)) { aot_set_last_error("llvm build cond br failed."); return false; } @@ -124,4 +137,3 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, fail: return false; } - diff --git a/core/iwasm/compilation/aot_emit_exception.h b/core/iwasm/compilation/aot_emit_exception.h index e86faf0360..91c8bd3cf5 100644 --- a/core/iwasm/compilation/aot_emit_exception.h +++ b/core/iwasm/compilation/aot_emit_exception.h @@ -14,9 +14,7 @@ extern "C" { bool aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - int32 exception_id, - bool is_cond_br, - LLVMValueRef cond_br_if, + int32 exception_id, bool is_cond_br, LLVMValueRef cond_br_if, LLVMBasicBlockRef cond_br_else_block); #ifdef __cplusplus @@ -24,4 +22,3 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, #endif #endif /* end of _AOT_EMIT_EXCEPTION_H_ */ - diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index a0fe2412f3..c53dc933e2 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -9,14 +9,14 @@ #include "aot_emit_table.h" #include "../aot/aot_runtime.h" -#define ADD_BASIC_BLOCK(block, name) do { \ - if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \ - func_ctx->func, \ - name))) { \ - aot_set_last_error("llvm add basic block failed."); \ - goto fail; \ - } \ - } while (0) +#define ADD_BASIC_BLOCK(block, name) \ + do { \ + if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \ + func_ctx->func, name))) { \ + aot_set_last_error("llvm add basic block failed."); \ + goto fail; \ + } \ + } while (0) static bool create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) @@ -26,16 +26,16 @@ create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) /* Create function return block if it isn't created */ if (!func_ctx->func_return_block) { - if (!(func_ctx->func_return_block = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, "func_ret"))) { + if (!(func_ctx->func_return_block = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "func_ret"))) { aot_set_last_error("llvm add basic block failed."); return false; } /* Create return IR */ - LLVMPositionBuilderAtEnd(comp_ctx->builder, func_ctx->func_return_block); - if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) { + LLVMPositionBuilderAtEnd(comp_ctx->builder, + func_ctx->func_return_block); + if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) { return false; } } @@ -59,16 +59,15 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) whether it is '\0'. If yes, no exception was thrown. */ if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception, "exce_value")) - || !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, - value, I8_ZERO, "cmp"))) { + || !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, value, I8_ZERO, + "cmp"))) { aot_set_last_error("llvm build icmp failed."); return false; } /* Add check exection success block */ - if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_exce_succ"))) { + if (!(check_exce_succ = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "check_exce_succ"))) { aot_set_last_error("llvm add basic block failed."); return false; } @@ -78,8 +77,8 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); /* Create condition br */ - if (!LLVMBuildCondBr(comp_ctx->builder, cmp, - check_exce_succ, func_ctx->func_return_block)) { + if (!LLVMBuildCondBr(comp_ctx->builder, cmp, check_exce_succ, + func_ctx->func_return_block)) { aot_set_last_error("llvm build cond br failed."); return false; } @@ -100,16 +99,15 @@ check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (!create_func_return_block(comp_ctx, func_ctx)) return false; - if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, - res, I8_ZERO, "cmp"))) { + if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, res, I8_ZERO, + "cmp"))) { aot_set_last_error("llvm build icmp failed."); return false; } /* Add check exection success block */ - if (!(check_call_succ = LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_call_succ"))) { + if (!(check_call_succ = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "check_call_succ"))) { aot_set_last_error("llvm add basic block failed."); return false; } @@ -119,8 +117,8 @@ check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); /* Create condition br */ - if (!LLVMBuildCondBr(comp_ctx->builder, cmp, - check_call_succ, func_ctx->func_return_block)) { + if (!LLVMBuildCondBr(comp_ctx->builder, cmp, check_call_succ, + func_ctx->func_return_block)) { aot_set_last_error("llvm build cond br failed."); return false; } @@ -132,10 +130,11 @@ check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, static bool call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef func_idx, AOTFuncType *aot_func_type, - LLVMTypeRef *param_types, LLVMValueRef *param_values, - uint32 param_count, uint32 param_cell_num, - LLVMTypeRef ret_type, uint8 wasm_ret_type, - LLVMValueRef *p_value_ret, LLVMValueRef *p_res) + LLVMTypeRef *param_types, + LLVMValueRef *param_values, uint32 param_count, + uint32 param_cell_num, LLVMTypeRef ret_type, + uint8 wasm_ret_type, LLVMValueRef *p_value_ret, + LLVMValueRef *p_res) { LLVMTypeRef func_type, func_ptr_type, func_param_types[4]; LLVMTypeRef ret_ptr_type, elem_ptr_type; @@ -145,11 +144,12 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 i, cell_num = 0; /* prepare function type of aot_invoke_native */ - func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */ - func_param_types[1] = I32_TYPE; /* func_idx */ - func_param_types[2] = I32_TYPE; /* argc */ - func_param_types[3] = INT32_PTR_TYPE; /* argv */ - if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 4, false))) { + func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */ + func_param_types[1] = I32_TYPE; /* func_idx */ + func_param_types[2] = I32_TYPE; /* argc */ + func_param_types[3] = INT32_PTR_TYPE; /* argv */ + if (!(func_type = + LLVMFunctionType(INT8_TYPE, func_param_types, 4, false))) { aot_set_last_error("llvm add function type failed."); return false; } @@ -168,10 +168,25 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } } + else if (comp_ctx->is_indirect_mode) { + int32 func_index; + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + return false; + } + func_index = aot_get_native_symbol_index(comp_ctx, func_name); + if (func_index < 0) { + return false; + } + if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol, + func_ptr_type, func_index))) { + return false; + } + } else { if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) - && !(func = LLVMAddFunction(comp_ctx->module, - func_name, func_type))) { + && !(func = + LLVMAddFunction(comp_ctx->module, func_name, func_type))) { aot_set_last_error("add LLVM function failed."); return false; } @@ -192,15 +207,16 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } snprintf(buf, sizeof(buf), "%s%d", "elem", i); - if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->argv_buf, &elem_idx, 1, buf)) + if (!(elem_ptr = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->argv_buf, &elem_idx, 1, buf)) || !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr, elem_ptr_type, buf))) { aot_set_last_error("llvm build bit cast failed."); return false; } - if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) { + if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], + elem_ptr))) { aot_set_last_error("llvm build store failed."); return false; } @@ -220,8 +236,8 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* call aot_invoke_native() function */ - if (!(res = LLVMBuildCall(comp_ctx->builder, func, - func_param_values, 4, "res"))) { + if (!(res = LLVMBuildCall(comp_ctx->builder, func, func_param_values, 4, + "res"))) { aot_set_last_error("llvm build call failed."); return false; } @@ -233,13 +249,14 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } - if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf, - ret_ptr_type, "argv_ret"))) { + if (!(value_ret = + LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf, + ret_ptr_type, "argv_ret"))) { aot_set_last_error("llvm build bit cast failed."); return false; } - if (!(*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, - "value_ret"))) { + if (!(*p_value_ret = + LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret"))) { aot_set_last_error("llvm build load failed."); return false; } @@ -269,15 +286,14 @@ call_aot_alloc_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_values[0] = func_ctx->exec_env; param_values[1] = func_idx; - if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, - param_values, 2, + if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, param_values, 2, "call_aot_alloc_frame"))) { aot_set_last_error("llvm build call failed."); return false; } - if (!(ret_value = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, - ret_value, I8_ZERO, "frame_alloc_ret"))) { + if (!(ret_value = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, ret_value, + I8_ZERO, "frame_alloc_ret"))) { aot_set_last_error("llvm build icmp failed."); return false; } @@ -288,8 +304,8 @@ call_aot_alloc_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMMoveBasicBlockAfter(frame_alloc_fail, block_curr); LLVMMoveBasicBlockAfter(frame_alloc_success, block_curr); - if (!LLVMBuildCondBr(comp_ctx->builder, ret_value, - frame_alloc_success, frame_alloc_fail)) { + if (!LLVMBuildCondBr(comp_ctx->builder, ret_value, frame_alloc_success, + frame_alloc_fail)) { aot_set_last_error("llvm build cond br failed."); return false; } @@ -297,7 +313,7 @@ call_aot_alloc_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* If frame alloc failed, return this function so the runtime can catch the exception */ LLVMPositionBuilderAtEnd(comp_ctx->builder, frame_alloc_fail); - if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) { + if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) { return false; } @@ -322,8 +338,7 @@ call_aot_free_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) param_values[0] = func_ctx->exec_env; - if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, - param_values, 1, + if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, param_values, 1, "call_aot_free_frame"))) { aot_set_last_error("llvm build call failed."); return false; @@ -331,7 +346,7 @@ call_aot_free_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) return true; } -#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) +#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \ || (WASM_ENABLE_PERF_PROFILING != 0) */ static bool @@ -347,17 +362,15 @@ check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } - if (!(stack_bound = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->native_stack_bound, - &callee_local_size, 1, - "stack_bound"))) { + if (!(stack_bound = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->native_stack_bound, + &callee_local_size, 1, "stack_bound"))) { aot_set_last_error("llvm build inbound gep failed."); return false; } - if (!(check_stack = LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_stack"))) { + if (!(check_stack = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "check_stack"))) { aot_set_last_error("llvm add basic block failed."); return false; } @@ -365,14 +378,12 @@ check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMMoveBasicBlockAfter(check_stack, block_curr); if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT, - func_ctx->last_alloca, stack_bound, - "cmp"))) { + func_ctx->last_alloca, stack_bound, "cmp"))) { aot_set_last_error("llvm build icmp failed."); return false; } - if (!aot_emit_exception(comp_ctx, func_ctx, - EXCE_NATIVE_STACK_OVERFLOW, + if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_NATIVE_STACK_OVERFLOW, true, cmp, check_stack)) { return false; } @@ -423,8 +434,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (func_idx < import_func_count) func_type = import_funcs[func_idx].func_type; else - func_type = func_ctxes[func_idx - import_func_count]-> - aot_func->func_type; + func_type = + func_ctxes[func_idx - import_func_count]->aot_func->func_type; /* Get param cell number */ param_cell_num = func_type->param_cell_num; @@ -451,8 +462,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_count = (int32)func_type->param_count; result_count = (int32)func_type->result_count; ext_ret_count = result_count > 1 ? result_count - 1 : 0; - total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1 - + ext_ret_count); + total_size = + sizeof(LLVMValueRef) * (uint64)(param_count + 1 + ext_ret_count); if (total_size >= UINT32_MAX || !(param_values = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("allocate memory failed."); @@ -482,7 +493,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, for (i = 0; i < ext_ret_count; i++) { if (!(ext_ret_idx = I32_CONST(cell_num)) || !(ext_ret_ptr_type = - LLVMPointerType(TO_LLVM_TYPE(ext_ret_types[i]), 0))) { + LLVMPointerType(TO_LLVM_TYPE(ext_ret_types[i]), 0))) { aot_set_last_error("llvm add const or pointer type failed."); goto fail; } @@ -495,9 +506,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } snprintf(buf, sizeof(buf), "ext_ret%d_ptr_cast", i); - if (!(ext_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, - ext_ret_ptr, ext_ret_ptr_type, - buf))) { + if (!(ext_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, ext_ret_ptr, + ext_ret_ptr_type, buf))) { aot_set_last_error("llvm build bit cast failed."); goto fail; } @@ -536,44 +546,62 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* call aot_invoke_native() */ - if (!call_aot_invoke_native_func(comp_ctx, func_ctx, import_func_idx, func_type, - param_types + 1, param_values + 1, - param_count, param_cell_num, - ret_type, wasm_ret_type, &value_ret, &res)) + if (!call_aot_invoke_native_func( + comp_ctx, func_ctx, import_func_idx, func_type, param_types + 1, + param_values + 1, param_count, param_cell_num, ret_type, + wasm_ret_type, &value_ret, &res)) goto fail; - /* Check whether there was exception thrown when executing the function */ + /* Check whether there was exception thrown when executing + the function */ if (!check_call_return(comp_ctx, func_ctx, res)) goto fail; } else { - func = func_ctxes[func_idx - import_func_count]->func; + if (comp_ctx->is_indirect_mode) { + LLVMTypeRef func_ptr_type; + + if (!(func_ptr_type = LLVMPointerType( + func_ctxes[func_idx - import_func_count]->func_type, + 0))) { + aot_set_last_error("construct func ptr type failed."); + goto fail; + } + if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->func_ptrs, + func_ptr_type, func_idx))) { + goto fail; + } + } + else { + func = func_ctxes[func_idx - import_func_count]->func; + } aot_func = func_ctxes[func_idx - import_func_count]->aot_func; - callee_cell_num = aot_func->param_cell_num + aot_func->local_cell_num + 1; + callee_cell_num = + aot_func->param_cell_num + aot_func->local_cell_num + 1; if (comp_ctx->enable_bound_check && !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num)) goto fail; /* Call the function */ - if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func, - param_values, - (uint32)param_count + 1 + ext_ret_count, - (func_type->result_count > 0 - ? "call" : "")))) { + if (!(value_ret = + LLVMBuildCall(comp_ctx->builder, func, param_values, + (uint32)param_count + 1 + ext_ret_count, + (func_type->result_count > 0 ? "call" : "")))) { aot_set_last_error("LLVM build call failed."); goto fail; } - /* Set calling convention for the call with the func's calling convention */ + /* Set calling convention for the call with the func's calling + convention */ LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func)); if (tail_call) LLVMSetTailCall(value_ret, true); - /* Check whether there was exception thrown when executing the function */ - if (!tail_call - && !check_exception_thrown(comp_ctx, func_ctx)) + /* Check whether there was exception thrown when executing + the function */ + if (!tail_call && !check_exception_thrown(comp_ctx, func_ctx)) goto fail; } @@ -583,9 +611,9 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Load extra result from its address and push to stack */ for (i = 0; i < ext_ret_count; i++) { snprintf(buf, sizeof(buf), "func%d_ext_ret%d", func_idx, i); - if (!(ext_ret = LLVMBuildLoad(comp_ctx->builder, - param_values[1 + param_count + i], - buf))) { + if (!(ext_ret = + LLVMBuildLoad(comp_ctx->builder, + param_values[1 + param_count + i], buf))) { aot_set_last_error("llvm build load failed."); goto fail; } @@ -611,12 +639,14 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, static bool call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - AOTFuncType *aot_func_type, LLVMValueRef func_type_idx, - LLVMValueRef table_idx, LLVMValueRef table_elem_idx, - LLVMTypeRef *param_types, LLVMValueRef *param_values, - uint32 param_count, uint32 param_cell_num, - uint32 result_count, uint8 *wasm_ret_types, - LLVMValueRef *value_rets, LLVMValueRef *p_res) + AOTFuncType *aot_func_type, + LLVMValueRef func_type_idx, LLVMValueRef table_idx, + LLVMValueRef table_elem_idx, + LLVMTypeRef *param_types, + LLVMValueRef *param_values, uint32 param_count, + uint32 param_cell_num, uint32 result_count, + uint8 *wasm_ret_types, LLVMValueRef *value_rets, + LLVMValueRef *p_res) { LLVMTypeRef func_type, func_ptr_type, func_param_types[6]; LLVMTypeRef ret_type, ret_ptr_type, elem_ptr_type; @@ -626,12 +656,13 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 i, cell_num = 0, ret_cell_num, argv_cell_num; /* prepare function type of aot_call_indirect */ - func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */ - func_param_types[1] = I32_TYPE; /* table_idx */ - func_param_types[2] = I32_TYPE; /* table_elem_idx */ - func_param_types[3] = I32_TYPE; /* argc */ - func_param_types[4] = INT32_PTR_TYPE; /* argv */ - if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) { + func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */ + func_param_types[1] = I32_TYPE; /* table_idx */ + func_param_types[2] = I32_TYPE; /* table_elem_idx */ + func_param_types[3] = I32_TYPE; /* argc */ + func_param_types[4] = INT32_PTR_TYPE; /* argv */ + if (!(func_type = + LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) { aot_set_last_error("llvm add function type failed."); return false; } @@ -650,17 +681,33 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } } + else if (comp_ctx->is_indirect_mode) { + int32 func_index; + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + return false; + } + func_index = aot_get_native_symbol_index(comp_ctx, func_name); + if (func_index < 0) { + return false; + } + if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol, + func_ptr_type, func_index))) { + return false; + } + } else { if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) - && !(func = LLVMAddFunction(comp_ctx->module, - func_name, func_type))) { + && !(func = + LLVMAddFunction(comp_ctx->module, func_name, func_type))) { aot_set_last_error("add LLVM function failed."); return false; } } ret_cell_num = wasm_get_cell_num(wasm_ret_types, result_count); - argv_cell_num = param_cell_num > ret_cell_num ? param_cell_num : ret_cell_num; + argv_cell_num = + param_cell_num > ret_cell_num ? param_cell_num : ret_cell_num; if (argv_cell_num > 64) { aot_set_last_error("prepare native arguments failed: " "maximum 64 parameter cell number supported."); @@ -676,15 +723,16 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } snprintf(buf, sizeof(buf), "%s%d", "elem", i); - if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->argv_buf, &elem_idx, 1, buf)) + if (!(elem_ptr = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->argv_buf, &elem_idx, 1, buf)) || !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr, elem_ptr_type, buf))) { aot_set_last_error("llvm build bit cast failed."); return false; } - if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) { + if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], + elem_ptr))) { aot_set_last_error("llvm build store failed."); return false; } @@ -705,8 +753,8 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* call aot_call_indirect() function */ - if (!(res = LLVMBuildCall(comp_ctx->builder, func, - func_param_values, 5, "res"))) { + if (!(res = LLVMBuildCall(comp_ctx->builder, func, func_param_values, 5, + "res"))) { aot_set_last_error("llvm build call failed."); return false; } @@ -722,8 +770,8 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } snprintf(buf, sizeof(buf), "argv_ret%d", i); - if (!(ret_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->argv_buf, &ret_idx, 1, buf)) + if (!(ret_ptr = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->argv_buf, &ret_idx, 1, buf)) || !(ret_ptr = LLVMBuildBitCast(comp_ctx->builder, ret_ptr, ret_ptr_type, buf))) { aot_set_last_error("llvm build GEP or bit cast failed."); @@ -799,38 +847,35 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } - if (!(table_size_const = - LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst, &offset, 1, - "cur_size_i8p"))) { + if (!(table_size_const = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "cur_size_i8p"))) { HANDLE_FAILURE("LLVMBuildGEP"); goto fail; } if (!(table_size_const = - LLVMBuildBitCast(comp_ctx->builder, table_size_const, - INT32_PTR_TYPE, "cur_siuze_i32p"))) { + LLVMBuildBitCast(comp_ctx->builder, table_size_const, + INT32_PTR_TYPE, "cur_siuze_i32p"))) { HANDLE_FAILURE("LLVMBuildBitCast"); goto fail; } - if (!(table_size_const = LLVMBuildLoad(comp_ctx->builder, table_size_const, "cur_size"))) { + if (!(table_size_const = + LLVMBuildLoad(comp_ctx->builder, table_size_const, "cur_size"))) { HANDLE_FAILURE("LLVMBuildLoad"); goto fail; } /* Check if (uint32)elem index >= table size */ - if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, - elem_idx, table_size_const, - "cmp_elem_idx"))) { + if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx, + table_size_const, "cmp_elem_idx"))) { aot_set_last_error("llvm build icmp failed."); goto fail; } /* Throw exception if elem index >= table size */ - if (!(check_elem_idx_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_elem_idx_succ"))) { + if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) { aot_set_last_error("llvm add basic block failed."); goto fail; } @@ -838,8 +883,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMMoveBasicBlockAfter(check_elem_idx_succ, LLVMGetInsertBlock(comp_ctx->builder)); - if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNDEFINED_ELEMENT, - true, cmp_elem_idx, check_elem_idx_succ))) + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNDEFINED_ELEMENT, true, + cmp_elem_idx, check_elem_idx_succ))) goto fail; /* load data as i32* */ @@ -862,31 +907,28 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Load function index */ - if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx, - 1, "table_elem"))) { + if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx, 1, + "table_elem"))) { HANDLE_FAILURE("LLVMBuildNUWAdd"); goto fail; } - if (!(func_idx = LLVMBuildLoad(comp_ctx->builder, - table_elem, "func_idx"))) { + if (!(func_idx = + LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) { aot_set_last_error("llvm build load failed."); goto fail; } /* Check if func_idx == -1 */ - if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, - func_idx, I32_NEG_ONE, - "cmp_func_idx"))) { + if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, func_idx, + I32_NEG_ONE, "cmp_func_idx"))) { aot_set_last_error("llvm build icmp failed."); goto fail; } /* Throw exception if func_idx == -1 */ - if (!(check_func_idx_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_func_idx_succ"))) { + if (!(check_func_idx_succ = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "check_func_idx_succ"))) { aot_set_last_error("llvm add basic block failed."); goto fail; } @@ -899,33 +941,29 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; /* Load function type index */ - if (!(ftype_idx_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->func_type_indexes, - &func_idx, 1, - "ftype_idx_ptr"))) { + if (!(ftype_idx_ptr = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->func_type_indexes, &func_idx, 1, + "ftype_idx_ptr"))) { aot_set_last_error("llvm build inbounds gep failed."); goto fail; } - if (!(ftype_idx = LLVMBuildLoad(comp_ctx->builder, ftype_idx_ptr, - "ftype_idx"))) { + if (!(ftype_idx = + LLVMBuildLoad(comp_ctx->builder, ftype_idx_ptr, "ftype_idx"))) { aot_set_last_error("llvm build load failed."); goto fail; } /* Check if function type index not equal */ - if (!(cmp_ftype_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, - ftype_idx, ftype_idx_const, - "cmp_ftype_idx"))) { + if (!(cmp_ftype_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, ftype_idx, + ftype_idx_const, "cmp_ftype_idx"))) { aot_set_last_error("llvm build icmp failed."); goto fail; } /* Throw exception if ftype_idx != ftype_idx_const */ - if (!(check_ftype_idx_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_ftype_idx_succ"))) { + if (!(check_ftype_idx_succ = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "check_ftype_idx_succ"))) { aot_set_last_error("llvm add basic block failed."); goto fail; } @@ -934,17 +972,17 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMGetInsertBlock(comp_ctx->builder)); if (!(aot_emit_exception(comp_ctx, func_ctx, - EXCE_INVALID_FUNCTION_TYPE_INDEX, - true, cmp_ftype_idx, check_ftype_idx_succ))) + EXCE_INVALID_FUNCTION_TYPE_INDEX, true, + cmp_ftype_idx, check_ftype_idx_succ))) goto fail; /* Initialize parameter types of the LLVM function */ total_param_count = 1 + func_param_count; /* Extra function results' addresses (except the first one) are - * appended to aot function parameters. */ + appended to aot function parameters. */ if (func_result_count > 1) - total_param_count += func_result_count - 1; + total_param_count += func_result_count - 1; total_size = sizeof(LLVMTypeRef) * (uint64)total_param_count; if (total_size >= UINT32_MAX @@ -960,8 +998,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_types[j++] = TO_LLVM_TYPE(func_type->types[i]); for (i = 1; i < func_result_count; i++, j++) { - param_types[j] = - TO_LLVM_TYPE(func_type->types[func_param_count + i]); + param_types[j] = TO_LLVM_TYPE(func_type->types[func_param_count + i]); if (!(param_types[j] = LLVMPointerType(param_types[j], 0))) { aot_set_last_error("llvm get pointer type failed."); goto fail; @@ -1001,25 +1038,24 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, CHECK_LLVM_CONST(ext_ret_offset); snprintf(buf, sizeof(buf), "ext_ret%d_ptr", i - 1); - if (!(ext_ret_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->argv_buf, - &ext_ret_offset, 1, buf))) { + if (!(ext_ret_ptr = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->argv_buf, + &ext_ret_offset, 1, buf))) { aot_set_last_error("llvm build GEP failed."); goto fail; } ext_ret_ptr_type = param_types[func_param_count + i]; snprintf(buf, sizeof(buf), "ext_ret%d_ptr_cast", i - 1); - if (!(ext_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, - ext_ret_ptr, ext_ret_ptr_type, - buf))) { + if (!(ext_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, ext_ret_ptr, + ext_ret_ptr_type, buf))) { aot_set_last_error("llvm build bit cast failed."); goto fail; } param_values[func_param_count + i] = ext_ret_ptr; - ext_cell_num += wasm_value_type_cell_num( - func_type->types[func_param_count + i]); + ext_cell_num += + wasm_value_type_cell_num(func_type->types[func_param_count + i]); } if (ext_cell_num > 64) { @@ -1044,15 +1080,12 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, #endif /* Add basic blocks */ - block_call_import = - LLVMAppendBasicBlockInContext(comp_ctx->context, func_ctx->func, - "call_import"); - block_call_non_import = - LLVMAppendBasicBlockInContext(comp_ctx->context, func_ctx->func, - "call_non_import"); - block_return = - LLVMAppendBasicBlockInContext(comp_ctx->context, func_ctx->func, - "func_return"); + block_call_import = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "call_import"); + block_call_non_import = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "call_non_import"); + block_return = LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, "func_return"); if (!block_call_import || !block_call_non_import || !block_return) { aot_set_last_error("llvm add basic block failed."); goto fail; @@ -1067,17 +1100,16 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, CHECK_LLVM_CONST(import_func_count); /* Check if func_idx < import_func_count */ - if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT, - func_idx, import_func_count, - "cmp_func_idx"))) { + if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT, func_idx, + import_func_count, "cmp_func_idx"))) { aot_set_last_error("llvm build icmp failed."); goto fail; } /* If func_idx < import_func_count, jump to call import block, else jump to call non-import block */ - if (!LLVMBuildCondBr(comp_ctx->builder, cmp_func_idx, - block_call_import, block_call_non_import)) { + if (!LLVMBuildCondBr(comp_ctx->builder, cmp_func_idx, block_call_import, + block_call_non_import)) { aot_set_last_error("llvm build cond br failed."); goto fail; } @@ -1096,8 +1128,8 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, for (i = 0; i < func_result_count; i++) { LLVMTypeRef tmp_type = TO_LLVM_TYPE(func_type->types[func_param_count + i]); - if (!(result_phis[i] = LLVMBuildPhi(comp_ctx->builder, - tmp_type, "phi"))) { + if (!(result_phis[i] = + LLVMBuildPhi(comp_ctx->builder, tmp_type, "phi"))) { aot_set_last_error("llvm build phi failed."); goto fail; } @@ -1127,13 +1159,10 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } - if (!call_aot_call_indirect_func(comp_ctx, func_ctx, - func_type, ftype_idx, - tbl_idx_value, elem_idx, - param_types + 1, param_values + 1, - func_param_count, param_cell_num, - func_result_count, wasm_ret_types, - value_rets, &res)) + if (!call_aot_call_indirect_func( + comp_ctx, func_ctx, func_type, ftype_idx, tbl_idx_value, elem_idx, + param_types + 1, param_values + 1, func_param_count, param_cell_num, + func_result_count, wasm_ret_types, value_rets, &res)) goto fail; /* Check whether exception was thrown when executing the function */ @@ -1155,14 +1184,16 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (comp_ctx->enable_bound_check && !check_stack_boundary(comp_ctx, func_ctx, - param_cell_num + ext_cell_num + 1 - /* Reserve some local variables */ - + 16)) + param_cell_num + ext_cell_num + + 1 + /* Reserve some local variables */ + + 16)) goto fail; /* Load function pointer */ - if (!(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs, - &func_idx, 1, "func_ptr_tmp"))) { + if (!(func_ptr = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs, + &func_idx, 1, "func_ptr_tmp"))) { aot_set_last_error("llvm build inbounds gep failed."); goto fail; } @@ -1172,24 +1203,22 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, goto fail; } - if (!(llvm_func_type = LLVMFunctionType(ret_type, param_types, - total_param_count, false)) + if (!(llvm_func_type = + LLVMFunctionType(ret_type, param_types, total_param_count, false)) || !(llvm_func_ptr_type = LLVMPointerType(llvm_func_type, 0))) { aot_set_last_error("llvm add function type failed."); goto fail; } - if (!(func = LLVMBuildBitCast(comp_ctx->builder, - func_ptr, llvm_func_ptr_type, - "indirect_func"))) { + if (!(func = LLVMBuildBitCast(comp_ctx->builder, func_ptr, + llvm_func_ptr_type, "indirect_func"))) { aot_set_last_error("llvm build bit cast failed."); goto fail; } - if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func, - param_values, total_param_count, - func_result_count > 0 - ? "ret" : ""))) { + if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func, param_values, + total_param_count, + func_result_count > 0 ? "ret" : ""))) { aot_set_last_error("llvm build call failed."); goto fail; } @@ -1207,9 +1236,9 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Load extra result from its address and push to stack */ for (i = 1; i < func_result_count; i++) { snprintf(buf, sizeof(buf), "ext_ret%d", i - 1); - if (!(ext_ret = LLVMBuildLoad(comp_ctx->builder, - param_values[func_param_count + i], - buf))) { + if (!(ext_ret = + LLVMBuildLoad(comp_ctx->builder, + param_values[func_param_count + i], buf))) { aot_set_last_error("llvm build load failed."); goto fail; } @@ -1286,8 +1315,7 @@ aot_compile_op_ref_is_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) } bool -aot_compile_op_ref_func(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_ref_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 func_idx) { LLVMValueRef ref_idx; diff --git a/core/iwasm/compilation/aot_emit_function.h b/core/iwasm/compilation/aot_emit_function.h index 23a384da84..26f09c6603 100644 --- a/core/iwasm/compilation/aot_emit_function.h +++ b/core/iwasm/compilation/aot_emit_function.h @@ -17,10 +17,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 func_idx, bool tail_call); bool -aot_compile_op_call_indirect(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 type_idx, - uint32 tbl_idx); +aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 type_idx, uint32 tbl_idx); bool aot_compile_op_ref_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); @@ -29,12 +27,10 @@ bool aot_compile_op_ref_is_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); bool -aot_compile_op_ref_func(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_ref_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 func_idx); #ifdef __cplusplus } /* end of extern "C" */ #endif #endif /* end of _AOT_EMIT_FUNCTION_H_ */ - diff --git a/core/iwasm/compilation/aot_emit_memory.c b/core/iwasm/compilation/aot_emit_memory.c index 0a506143ca..86ddb3c6f7 100644 --- a/core/iwasm/compilation/aot_emit_memory.c +++ b/core/iwasm/compilation/aot_emit_memory.c @@ -7,33 +7,33 @@ #include "aot_emit_exception.h" #include "../aot/aot_runtime.h" -#define BUILD_ICMP(op, left, right, res, name) do { \ - if (!(res = LLVMBuildICmp(comp_ctx->builder, op, \ - left, right, name))) { \ - aot_set_last_error("llvm build icmp failed."); \ - goto fail; \ - } \ - } while (0) - -#define BUILD_OP(Op, left, right, res, name) do { \ - if (!(res = LLVMBuild##Op(comp_ctx->builder, \ - left, right, name))) { \ - aot_set_last_error("llvm build " #Op " fail."); \ - goto fail; \ - } \ - } while (0) - -#define ADD_BASIC_BLOCK(block, name) do { \ - if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \ - func_ctx->func, \ - name))) { \ - aot_set_last_error("llvm add basic block failed."); \ - goto fail; \ - } \ - } while (0) - -#define SET_BUILD_POS(block) \ - LLVMPositionBuilderAtEnd(comp_ctx->builder, block) +#define BUILD_ICMP(op, left, right, res, name) \ + do { \ + if (!(res = \ + LLVMBuildICmp(comp_ctx->builder, op, left, right, name))) { \ + aot_set_last_error("llvm build icmp failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_OP(Op, left, right, res, name) \ + do { \ + if (!(res = LLVMBuild##Op(comp_ctx->builder, left, right, name))) { \ + aot_set_last_error("llvm build " #Op " fail."); \ + goto fail; \ + } \ + } while (0) + +#define ADD_BASIC_BLOCK(block, name) \ + do { \ + if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \ + func_ctx->func, name))) { \ + aot_set_last_error("llvm add basic block failed."); \ + goto fail; \ + } \ + } while (0) + +#define SET_BUILD_POS(block) LLVMPositionBuilderAtEnd(comp_ctx->builder, block) static LLVMValueRef get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, @@ -64,8 +64,7 @@ get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (func_ctx->mem_space_unchanged) return mem_check_bound; - if (!(mem_check_bound = LLVMBuildLoad(comp_ctx->builder, - mem_check_bound, + if (!(mem_check_bound = LLVMBuildLoad(comp_ctx->builder, mem_check_bound, "mem_check_bound"))) { aot_set_last_error("llvm build load failed."); return NULL; @@ -93,8 +92,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, comp_ctx->comp_data->memories[0].memory_flags & 0x02; #endif - is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) - ? true : false; + is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false; CHECK_LLVM_CONST(offset_const); @@ -103,20 +101,20 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, #if WASM_ENABLE_SHARED_MEMORY != 0 || is_shared_memory #endif - ) { + ) { mem_base_addr = func_ctx->mem_info[0].mem_base_addr; } else { - if (!(mem_base_addr = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_base_addr, - "mem_base"))) { + if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_info[0].mem_base_addr, + "mem_base"))) { aot_set_last_error("llvm build load failed."); goto fail; } } - aot_value = func_ctx->block_stack.block_list_end->value_stack.value_list_end; + aot_value = + func_ctx->block_stack.block_list_end->value_stack.value_list_end; if (aot_value) { /* aot_value is freed in the following POP_I32(addr), so save its fields here for further use */ @@ -126,14 +124,22 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, POP_I32(addr); + /* + * Note: not throw the integer-overflow-exception here since it must + * have been thrown when converting float to integer before + */ /* return addres directly if constant offset and inside memory space */ - if (LLVMIsConstant(addr)) { - uint64 mem_offset = (uint64)LLVMConstIntGetZExtValue(addr) - + (uint64)offset; + if (LLVMIsConstant(addr) && !LLVMIsUndef(addr) +#if LLVM_VERSION_NUMBER >= 12 + && !LLVMIsPoison(addr) +#endif + ) { + uint64 mem_offset = + (uint64)LLVMConstIntGetZExtValue(addr) + (uint64)offset; uint32 num_bytes_per_page = - comp_ctx->comp_data->memories[0].num_bytes_per_page; + comp_ctx->comp_data->memories[0].num_bytes_per_page; uint32 init_page_count = - comp_ctx->comp_data->memories[0].mem_init_page_count; + comp_ctx->comp_data->memories[0].mem_init_page_count; uint64 mem_data_size = num_bytes_per_page * init_page_count; if (mem_offset + bytes <= mem_data_size) { @@ -152,8 +158,8 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (is_target_64bit) { if (!(offset_const = LLVMBuildZExt(comp_ctx->builder, offset_const, I64_TYPE, "offset_i64")) - || !(addr = LLVMBuildZExt(comp_ctx->builder, addr, - I64_TYPE, "addr_i64"))) { + || !(addr = LLVMBuildZExt(comp_ctx->builder, addr, I64_TYPE, + "addr_i64"))) { aot_set_last_error("llvm build zero extend failed."); goto fail; } @@ -167,7 +173,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, && aot_checked_addr_list_find(func_ctx, local_idx_of_aot_value, offset, bytes))) { uint32 init_page_count = - comp_ctx->comp_data->memories[0].mem_init_page_count; + comp_ctx->comp_data->memories[0].mem_init_page_count; if (init_page_count == 0) { LLVMValueRef mem_size; @@ -178,8 +184,8 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, ADD_BASIC_BLOCK(check_succ, "check_mem_size_succ"); LLVMMoveBasicBlockAfter(check_succ, block_curr); if (!aot_emit_exception(comp_ctx, func_ctx, - EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, - true, cmp, check_succ)) { + EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp, + check_succ)) { goto fail; } @@ -188,7 +194,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } if (!(mem_check_bound = - get_memory_check_bound(comp_ctx, func_ctx, bytes))) { + get_memory_check_bound(comp_ctx, func_ctx, bytes))) { goto fail; } @@ -207,8 +213,8 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMMoveBasicBlockAfter(check_succ, block_curr); if (!aot_emit_exception(comp_ctx, func_ctx, - EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, - true, cmp, check_succ)) { + EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp, + check_succ)) { goto fail; } @@ -232,55 +238,60 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return NULL; } -#define BUILD_PTR_CAST(ptr_type) do { \ - if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr,\ - ptr_type, "data_ptr"))) {\ - aot_set_last_error("llvm build bit cast failed."); \ - goto fail; \ - } \ - } while (0) - -#define BUILD_LOAD() do { \ - if (!(value = LLVMBuildLoad(comp_ctx->builder, maddr, \ - "data"))) { \ - aot_set_last_error("llvm build load failed."); \ - goto fail; \ - } \ - LLVMSetAlignment(value, 1); \ - } while (0) - -#define BUILD_TRUNC(value, data_type) do { \ - if (!(value = LLVMBuildTrunc(comp_ctx->builder, value, \ - data_type, "val_trunc"))){ \ - aot_set_last_error("llvm build trunc failed."); \ - goto fail; \ - } \ - } while (0) - -#define BUILD_STORE() do { \ - LLVMValueRef res; \ - if (!(res = LLVMBuildStore(comp_ctx->builder, value, maddr))) { \ - aot_set_last_error("llvm build store failed."); \ - goto fail; \ - } \ - LLVMSetAlignment(res, 1); \ - } while (0) - -#define BUILD_SIGN_EXT(dst_type) do { \ - if (!(value = LLVMBuildSExt(comp_ctx->builder, value, \ - dst_type, "data_s_ext"))) { \ - aot_set_last_error("llvm build sign ext failed."); \ - goto fail; \ - } \ - } while (0) - -#define BUILD_ZERO_EXT(dst_type) do { \ - if (!(value = LLVMBuildZExt(comp_ctx->builder, value, \ - dst_type, "data_z_ext"))) { \ - aot_set_last_error("llvm build zero ext failed."); \ - goto fail; \ - } \ - } while (0) +#define BUILD_PTR_CAST(ptr_type) \ + do { \ + if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr, ptr_type, \ + "data_ptr"))) { \ + aot_set_last_error("llvm build bit cast failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_LOAD() \ + do { \ + if (!(value = LLVMBuildLoad(comp_ctx->builder, maddr, "data"))) { \ + aot_set_last_error("llvm build load failed."); \ + goto fail; \ + } \ + LLVMSetAlignment(value, 1); \ + } while (0) + +#define BUILD_TRUNC(value, data_type) \ + do { \ + if (!(value = LLVMBuildTrunc(comp_ctx->builder, value, data_type, \ + "val_trunc"))) { \ + aot_set_last_error("llvm build trunc failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_STORE() \ + do { \ + LLVMValueRef res; \ + if (!(res = LLVMBuildStore(comp_ctx->builder, value, maddr))) { \ + aot_set_last_error("llvm build store failed."); \ + goto fail; \ + } \ + LLVMSetAlignment(res, 1); \ + } while (0) + +#define BUILD_SIGN_EXT(dst_type) \ + do { \ + if (!(value = LLVMBuildSExt(comp_ctx->builder, value, dst_type, \ + "data_s_ext"))) { \ + aot_set_last_error("llvm build sign ext failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_ZERO_EXT(dst_type) \ + do { \ + if (!(value = LLVMBuildZExt(comp_ctx->builder, value, dst_type, \ + "data_z_ext"))) { \ + aot_set_last_error("llvm build zero ext failed."); \ + goto fail; \ + } \ + } while (0) #if WASM_ENABLE_SHARED_MEMORY != 0 bool @@ -295,8 +306,8 @@ check_memory_alignment(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, CHECK_LLVM_CONST(align_mask); /* Convert pointer to int */ - if (!(addr = LLVMBuildPtrToInt(comp_ctx->builder, addr, - I32_TYPE, "address"))) { + if (!(addr = LLVMBuildPtrToInt(comp_ctx->builder, addr, I32_TYPE, + "address"))) { aot_set_last_error("llvm build ptr to int failed."); goto fail; } @@ -309,9 +320,8 @@ check_memory_alignment(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, ADD_BASIC_BLOCK(check_align_succ, "check_align_succ"); LLVMMoveBasicBlockAfter(check_align_succ, block_curr); - if (!aot_emit_exception(comp_ctx, func_ctx, - EXCE_UNALIGNED_ATOMIC, - true, res, check_align_succ)) { + if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_UNALIGNED_ATOMIC, true, + res, check_align_succ)) { goto fail; } @@ -322,39 +332,40 @@ check_memory_alignment(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } -#define BUILD_ATOMIC_LOAD(align) do { \ - if (!(check_memory_alignment(comp_ctx, func_ctx, maddr, align))) { \ - goto fail; \ - } \ - if (!(value = LLVMBuildLoad(comp_ctx->builder, maddr, \ - "data"))) { \ - aot_set_last_error("llvm build load failed."); \ - goto fail; \ - } \ - LLVMSetAlignment(value, 1 << align); \ - LLVMSetVolatile(value, true); \ - LLVMSetOrdering(value, LLVMAtomicOrderingSequentiallyConsistent); \ - } while (0) - -#define BUILD_ATOMIC_STORE(align) do { \ - LLVMValueRef res; \ - if (!(check_memory_alignment(comp_ctx, func_ctx, maddr, align))) { \ - goto fail; \ - } \ - if (!(res = LLVMBuildStore(comp_ctx->builder, value, maddr))) { \ - aot_set_last_error("llvm build store failed."); \ - goto fail; \ - } \ - LLVMSetAlignment(res, 1 << align); \ - LLVMSetVolatile(res, true); \ - LLVMSetOrdering(res, LLVMAtomicOrderingSequentiallyConsistent); \ - } while (0) +#define BUILD_ATOMIC_LOAD(align) \ + do { \ + if (!(check_memory_alignment(comp_ctx, func_ctx, maddr, align))) { \ + goto fail; \ + } \ + if (!(value = LLVMBuildLoad(comp_ctx->builder, maddr, "data"))) { \ + aot_set_last_error("llvm build load failed."); \ + goto fail; \ + } \ + LLVMSetAlignment(value, 1 << align); \ + LLVMSetVolatile(value, true); \ + LLVMSetOrdering(value, LLVMAtomicOrderingSequentiallyConsistent); \ + } while (0) + +#define BUILD_ATOMIC_STORE(align) \ + do { \ + LLVMValueRef res; \ + if (!(check_memory_alignment(comp_ctx, func_ctx, maddr, align))) { \ + goto fail; \ + } \ + if (!(res = LLVMBuildStore(comp_ctx->builder, value, maddr))) { \ + aot_set_last_error("llvm build store failed."); \ + goto fail; \ + } \ + LLVMSetAlignment(res, 1 << align); \ + LLVMSetVolatile(res, true); \ + LLVMSetOrdering(res, LLVMAtomicOrderingSequentiallyConsistent); \ + } while (0) #endif bool aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint32 align, uint32 offset, uint32 bytes, - bool sign, bool atomic) + uint32 align, uint32 offset, uint32 bytes, bool sign, + bool atomic) { LLVMValueRef maddr, value = NULL; @@ -405,8 +416,8 @@ aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint32 align, uint32 offset, uint32 bytes, - bool sign, bool atomic) + uint32 align, uint32 offset, uint32 bytes, bool sign, + bool atomic) { LLVMValueRef maddr, value = NULL; @@ -619,10 +630,9 @@ get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) mem_size = func_ctx->mem_info[0].mem_cur_page_count_addr; } else { - if (!(mem_size = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_cur_page_count_addr, - "mem_size"))) { + if (!(mem_size = LLVMBuildLoad( + comp_ctx->builder, + func_ctx->mem_info[0].mem_cur_page_count_addr, "mem_size"))) { aot_set_last_error("llvm build load failed."); goto fail; } @@ -651,6 +661,7 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) LLVMValueRef mem_size = get_memory_curr_page_count(comp_ctx, func_ctx); LLVMValueRef delta, param_values[2], ret_value, func, value; LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type; + int32 func_index; if (!mem_size) return false; @@ -679,12 +690,27 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) return false; } } + else if (comp_ctx->is_indirect_mode) { + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + return false; + } + func_index = + aot_get_native_symbol_index(comp_ctx, "aot_enlarge_memory"); + if (func_index < 0) { + return false; + } + if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol, + func_ptr_type, func_index))) { + return false; + } + } else { char *func_name = "aot_enlarge_memory"; /* AOT mode, delcare the function */ if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) - && !(func = LLVMAddFunction(comp_ctx->module, - func_name, func_type))) { + && !(func = + LLVMAddFunction(comp_ctx->module, func_name, func_type))) { aot_set_last_error("llvm add function failed."); return false; } @@ -693,8 +719,8 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) /* Call function aot_enlarge_memory() */ param_values[0] = func_ctx->aot_inst; param_values[1] = delta; - if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, - param_values, 2, "call"))) { + if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, param_values, 2, + "call"))) { aot_set_last_error("llvm build call failed."); return false; } @@ -702,9 +728,8 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) BUILD_ICMP(LLVMIntUGT, ret_value, I8_ZERO, ret_value, "mem_grow_ret"); /* ret_value = ret_value == true ? delta : pre_page_count */ - if (!(ret_value = LLVMBuildSelect(comp_ctx->builder, ret_value, - mem_size, I32_NEG_ONE, - "mem_grow_ret"))) { + if (!(ret_value = LLVMBuildSelect(comp_ctx->builder, ret_value, mem_size, + I32_NEG_ONE, "mem_grow_ret"))) { aot_set_last_error("llvm build select failed."); return false; } @@ -715,7 +740,6 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) return false; } - #if WASM_ENABLE_BULK_MEMORY != 0 static LLVMValueRef @@ -740,30 +764,35 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, mem_base_addr = func_ctx->mem_info[0].mem_base_addr; } else { - if (!(mem_base_addr = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_base_addr, - "mem_base"))) { + if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_info[0].mem_base_addr, + "mem_base"))) { aot_set_last_error("llvm build load failed."); goto fail; } } + /* + * Note: not throw the integer-overflow-exception here since it must + * have been thrown when converting float to integer before + */ /* return addres directly if constant offset and inside memory space */ - if (LLVMIsConstant(offset) && LLVMIsConstant(bytes)) { + if (!LLVMIsUndef(offset) && !LLVMIsUndef(bytes) +#if LLVM_VERSION_NUMBER >= 12 + && !LLVMIsPoison(offset) && !LLVMIsPoison(bytes) +#endif + && LLVMIsConstant(offset) && LLVMIsConstant(bytes)) { uint64 mem_offset = (uint64)LLVMConstIntGetZExtValue(offset); uint64 mem_len = (uint64)LLVMConstIntGetZExtValue(bytes); uint32 num_bytes_per_page = - comp_ctx->comp_data->memories[0].num_bytes_per_page; + comp_ctx->comp_data->memories[0].num_bytes_per_page; uint32 init_page_count = - comp_ctx->comp_data->memories[0].mem_init_page_count; + comp_ctx->comp_data->memories[0].mem_init_page_count; uint32 mem_data_size = num_bytes_per_page * init_page_count; - if (mem_data_size > 0 - && mem_offset + mem_len <= mem_data_size) { + if (mem_data_size > 0 && mem_offset + mem_len <= mem_data_size) { /* inside memory space */ /* maddr = mem_base_addr + moffset */ - if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, - mem_base_addr, + if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr, &offset, 1, "maddr"))) { aot_set_last_error("llvm build add failed."); goto fail; @@ -776,10 +805,9 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, mem_size = func_ctx->mem_info[0].mem_data_size_addr; } else { - if (!(mem_size = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_data_size_addr, - "mem_size"))) { + if (!(mem_size = LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_info[0].mem_data_size_addr, + "mem_size"))) { aot_set_last_error("llvm build load failed."); goto fail; } @@ -788,16 +816,17 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, ADD_BASIC_BLOCK(check_succ, "check_succ"); LLVMMoveBasicBlockAfter(check_succ, block_curr); - offset = LLVMBuildZExt(comp_ctx->builder, offset, I64_TYPE, "extend_offset"); + offset = + LLVMBuildZExt(comp_ctx->builder, offset, I64_TYPE, "extend_offset"); bytes = LLVMBuildZExt(comp_ctx->builder, bytes, I64_TYPE, "extend_len"); - mem_size = LLVMBuildZExt(comp_ctx->builder, mem_size, I64_TYPE, "extend_size"); + mem_size = + LLVMBuildZExt(comp_ctx->builder, mem_size, I64_TYPE, "extend_size"); BUILD_OP(Add, offset, bytes, max_addr, "max_addr"); - BUILD_ICMP(LLVMIntUGT, max_addr, mem_size, cmp, - "cmp_max_mem_addr"); + BUILD_ICMP(LLVMIntUGT, max_addr, mem_size, cmp, "cmp_max_mem_addr"); if (!aot_emit_exception(comp_ctx, func_ctx, - EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, - true, cmp, check_succ)) { + EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp, + check_succ)) { goto fail; } @@ -843,8 +872,8 @@ aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_values[2] = offset; param_values[3] = len; param_values[4] = dst; - if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, - param_values, 5, "call"))) { + if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, param_values, 5, + "call"))) { aot_set_last_error("llvm build call failed."); return false; } @@ -857,16 +886,16 @@ aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMMoveBasicBlockAfter(mem_init_fail, block_curr); LLVMMoveBasicBlockAfter(init_success, block_curr); - if (!LLVMBuildCondBr(comp_ctx->builder, ret_value, - init_success, mem_init_fail)) { + if (!LLVMBuildCondBr(comp_ctx->builder, ret_value, init_success, + mem_init_fail)) { aot_set_last_error("llvm build cond br failed."); goto fail; } /* If memory.init failed, return this function - so the runtime can catch the exception */ + so the runtime can catch the exception */ LLVMPositionBuilderAtEnd(comp_ctx->builder, mem_init_fail); - if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) { + if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) { goto fail; } @@ -896,8 +925,8 @@ aot_compile_op_data_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Call function aot_data_drop() */ param_values[0] = func_ctx->aot_inst; param_values[1] = seg; - if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, - param_values, 2, "call"))) { + if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, param_values, 2, + "call"))) { aot_set_last_error("llvm build call failed."); return false; } @@ -916,16 +945,16 @@ aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) POP_I32(src); POP_I32(dst); - if (!(src_addr = - check_bulk_memory_overflow(comp_ctx, func_ctx, src, len))) + if (!(src_addr = check_bulk_memory_overflow(comp_ctx, func_ctx, src, len))) return false; - if (!(dst_addr = - check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len))) + if (!(dst_addr = check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len))) return false; - if (!(res = LLVMBuildMemMove(comp_ctx->builder, dst_addr, 1, - src_addr, 1, len))) { + /* TODO: lookup func ptr of "memmove" to call for XIP mode */ + + if (!(res = LLVMBuildMemMove(comp_ctx->builder, dst_addr, 1, src_addr, 1, + len))) { aot_set_last_error("llvm build memmove failed."); return false; } @@ -943,14 +972,18 @@ aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) POP_I32(val); POP_I32(dst); - if (!(dst_addr = - check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len))) + if (!(dst_addr = check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len))) return false; - val = LLVMBuildIntCast2(comp_ctx->builder, val, INT8_TYPE, true, "mem_set_value"); + if (!(val = LLVMBuildIntCast2(comp_ctx->builder, val, INT8_TYPE, true, + "mem_set_value"))) { + aot_set_last_error("llvm build int cast2 failed."); + return false; + } + + /* TODO: lookup func ptr of "memset" to call for XIP mode */ - if (!(res = LLVMBuildMemSet(comp_ctx->builder, dst_addr, - val, len, 1))) { + if (!(res = LLVMBuildMemSet(comp_ctx->builder, dst_addr, val, len, 1))) { aot_set_last_error("llvm build memset failed."); return false; } @@ -962,11 +995,9 @@ aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) #if WASM_ENABLE_SHARED_MEMORY != 0 bool -aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 atomic_op, uint8 op_type, - uint32 align, uint32 offset, - uint32 bytes) +aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 atomic_op, uint8 op_type, uint32 align, + uint32 offset, uint32 bytes) { LLVMValueRef maddr, value, result; @@ -1003,25 +1034,24 @@ aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx, break; } - if (!(result = - LLVMBuildAtomicRMW(comp_ctx->builder, - atomic_op, maddr, value, - LLVMAtomicOrderingSequentiallyConsistent, false))) { + if (!(result = LLVMBuildAtomicRMW( + comp_ctx->builder, atomic_op, maddr, value, + LLVMAtomicOrderingSequentiallyConsistent, false))) { goto fail; } LLVMSetVolatile(result, true); if (op_type == VALUE_TYPE_I32) { - if (!(result = LLVMBuildZExt(comp_ctx->builder, result, - I32_TYPE, "result_i32"))) { + if (!(result = LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, + "result_i32"))) { goto fail; } PUSH_I32(result); } else { - if (!(result = LLVMBuildZExt(comp_ctx->builder, result, - I64_TYPE, "result_i64"))) { + if (!(result = LLVMBuildZExt(comp_ctx->builder, result, I64_TYPE, + "result_i64"))) { goto fail; } PUSH_I64(result); @@ -1034,9 +1064,8 @@ aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx, bool aot_compile_op_atomic_cmpxchg(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 op_type, uint32 align, - uint32 offset, uint32 bytes) + AOTFuncContext *func_ctx, uint8 op_type, + uint32 align, uint32 offset, uint32 bytes) { LLVMValueRef maddr, value, expect, result; @@ -1081,34 +1110,32 @@ aot_compile_op_atomic_cmpxchg(AOTCompContext *comp_ctx, break; } - if (!(result = - LLVMBuildAtomicCmpXchg(comp_ctx->builder, maddr, expect, value, - LLVMAtomicOrderingSequentiallyConsistent, - LLVMAtomicOrderingSequentiallyConsistent, - false))) { + if (!(result = LLVMBuildAtomicCmpXchg( + comp_ctx->builder, maddr, expect, value, + LLVMAtomicOrderingSequentiallyConsistent, + LLVMAtomicOrderingSequentiallyConsistent, false))) { goto fail; } LLVMSetVolatile(result, true); /* CmpXchg return {i32, i1} structure, - we need to extrack the previous_value from the structure */ - if (!(result = - LLVMBuildExtractValue(comp_ctx->builder, - result, 0, "previous_value"))) { + we need to extrack the previous_value from the structure */ + if (!(result = LLVMBuildExtractValue(comp_ctx->builder, result, 0, + "previous_value"))) { goto fail; } if (op_type == VALUE_TYPE_I32) { - if (!(result = LLVMBuildZExt(comp_ctx->builder, result, - I32_TYPE, "result_i32"))) { + if (!(result = LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, + "result_i32"))) { goto fail; } PUSH_I32(result); } else { - if (!(result = LLVMBuildZExt(comp_ctx->builder, result, - I64_TYPE, "result_i64"))) { + if (!(result = LLVMBuildZExt(comp_ctx->builder, result, I64_TYPE, + "result_i64"))) { goto fail; } PUSH_I64(result); @@ -1121,8 +1148,8 @@ aot_compile_op_atomic_cmpxchg(AOTCompContext *comp_ctx, bool aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint8 op_type, uint32 align, - uint32 offset, uint32 bytes) + uint8 op_type, uint32 align, uint32 offset, + uint32 bytes) { LLVMValueRef maddr, value, timeout, expect, cmp; LLVMValueRef param_values[5], ret_value, func, is_wait64; @@ -1135,9 +1162,8 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (op_type == VALUE_TYPE_I32) { POP_I32(expect); is_wait64 = I8_CONST(false); - if (!(expect = - LLVMBuildZExt(comp_ctx->builder, expect, - I64_TYPE, "expect_i64"))) { + if (!(expect = LLVMBuildZExt(comp_ctx->builder, expect, I64_TYPE, + "expect_i64"))) { goto fail; } } @@ -1169,8 +1195,8 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_values[2] = expect; param_values[3] = timeout; param_values[4] = is_wait64; - if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, - param_values, 5, "call"))) { + if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, param_values, 5, + "call"))) { aot_set_last_error("llvm build call failed."); return false; } @@ -1183,16 +1209,15 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMMoveBasicBlockAfter(wait_fail, block_curr); LLVMMoveBasicBlockAfter(wait_success, block_curr); - if (!LLVMBuildCondBr(comp_ctx->builder, cmp, - wait_success, wait_fail)) { + if (!LLVMBuildCondBr(comp_ctx->builder, cmp, wait_success, wait_fail)) { aot_set_last_error("llvm build cond br failed."); goto fail; } /* If atomic wait failed, return this function - so the runtime can catch the exception */ + so the runtime can catch the exception */ LLVMPositionBuilderAtEnd(comp_ctx->builder, wait_fail); - if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) { + if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) { goto fail; } @@ -1207,8 +1232,8 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 align, uint32 offset, uint32 bytes) + AOTFuncContext *func_ctx, uint32 align, + uint32 offset, uint32 bytes) { LLVMValueRef maddr, value, count; LLVMValueRef param_values[3], ret_value, func; @@ -1233,8 +1258,8 @@ aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx, param_values[0] = func_ctx->aot_inst; param_values[1] = maddr; param_values[2] = count; - if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, - param_values, 3, "call"))) { + if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, param_values, 3, + "call"))) { aot_set_last_error("llvm build call failed."); return false; } diff --git a/core/iwasm/compilation/aot_emit_memory.h b/core/iwasm/compilation/aot_emit_memory.h index f505a23ea9..2c39f725bb 100644 --- a/core/iwasm/compilation/aot_emit_memory.h +++ b/core/iwasm/compilation/aot_emit_memory.h @@ -17,13 +17,13 @@ extern "C" { bool aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint32 align, uint32 offset, uint32 bytes, - bool sign, bool atomic); + uint32 align, uint32 offset, uint32 bytes, bool sign, + bool atomic); bool aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint32 align, uint32 offset, uint32 bytes, - bool sign, bool atomic); + uint32 align, uint32 offset, uint32 bytes, bool sign, + bool atomic); bool aot_compile_op_f32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, @@ -35,11 +35,13 @@ aot_compile_op_f64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool aot_compile_op_i32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint32 align, uint32 offset, uint32 bytes, bool atomic); + uint32 align, uint32 offset, uint32 bytes, + bool atomic); bool aot_compile_op_i64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint32 align, uint32 offset, uint32 bytes, bool atomic); + uint32 align, uint32 offset, uint32 bytes, + bool atomic); bool aot_compile_op_f32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, @@ -77,27 +79,24 @@ aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); #if WASM_ENABLE_SHARED_MEMORY != 0 bool -aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 atomic_op, uint8 op_type, - uint32 align, uint32 offset, - uint32 bytes); +aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 atomic_op, uint8 op_type, uint32 align, + uint32 offset, uint32 bytes); bool aot_compile_op_atomic_cmpxchg(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 op_type, uint32 align, - uint32 offset, uint32 bytes); + AOTFuncContext *func_ctx, uint8 op_type, + uint32 align, uint32 offset, uint32 bytes); bool aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - uint8 op_type, uint32 align, - uint32 offset, uint32 bytes); + uint8 op_type, uint32 align, uint32 offset, + uint32 bytes); bool aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 align, uint32 offset, uint32 bytes); + AOTFuncContext *func_ctx, uint32 align, + uint32 offset, uint32 bytes); #endif #ifdef __cplusplus @@ -105,4 +104,3 @@ aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx, #endif #endif /* end of _AOT_EMIT_MEMORY_H_ */ - diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index dc267d726f..58285ca5f6 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -7,152 +7,178 @@ #include "aot_emit_exception.h" #include "aot_emit_control.h" #include "../aot/aot_runtime.h" +#include "../aot/aot_intrinsic.h" #include -#define LLVM_BUILD_ICMP(op, left, right, res, name) do { \ - if (!(res = LLVMBuildICmp(comp_ctx->builder, op, left, right, name))) { \ - aot_set_last_error("llvm build "name" fail."); \ - return false; \ - } \ -} while (0) - -#define LLVM_BUILD_OP(Op, left, right, res, name, err_ret) do { \ - if (!(res = LLVMBuild##Op(comp_ctx->builder, left, right, name))) { \ - aot_set_last_error("llvm build " #name " fail."); \ - return err_ret; \ - } \ -} while (0) - -#define ADD_BASIC_BLOCK(block, name) do { \ - if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \ - func_ctx->func, \ - name))) { \ - aot_set_last_error("llvm add basic block failed."); \ - goto fail; \ - } \ - \ - LLVMMoveBasicBlockAfter(block, LLVMGetInsertBlock(comp_ctx->builder)); \ -} while (0) - -#define IS_CONST_ZERO(val) \ - (LLVMIsConstant(val) \ - && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \ +#define LLVM_BUILD_ICMP(op, left, right, res, name) \ + do { \ + if (!(res = \ + LLVMBuildICmp(comp_ctx->builder, op, left, right, name))) { \ + aot_set_last_error("llvm build " name " fail."); \ + return false; \ + } \ + } while (0) + +#define LLVM_BUILD_OP(Op, left, right, res, name, err_ret) \ + do { \ + if (!(res = LLVMBuild##Op(comp_ctx->builder, left, right, name))) { \ + aot_set_last_error("llvm build " #name " fail."); \ + return err_ret; \ + } \ + } while (0) + +#define ADD_BASIC_BLOCK(block, name) \ + do { \ + if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \ + func_ctx->func, name))) { \ + aot_set_last_error("llvm add basic block failed."); \ + goto fail; \ + } \ + \ + LLVMMoveBasicBlockAfter(block, LLVMGetInsertBlock(comp_ctx->builder)); \ + } while (0) + +#if LLVM_VERSION_NUMBER >= 12 +#define IS_CONST_ZERO(val) \ + (!LLVMIsUndef(val) && !LLVMIsPoison(val) && LLVMIsConstant(val) \ + && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \ || (!is_i32 && (int64)LLVMConstIntGetSExtValue(val) == 0))) - -#define CHECK_INT_OVERFLOW(type) do { \ - LLVMValueRef cmp_min_int, cmp_neg_one; \ - LLVM_BUILD_ICMP(LLVMIntEQ, left, type##_MIN, \ - cmp_min_int, "cmp_min_int"); \ - LLVM_BUILD_ICMP(LLVMIntEQ, right, type##_NEG_ONE, \ - cmp_neg_one, "cmp_neg_one"); \ - LLVM_BUILD_OP(And, cmp_min_int, cmp_neg_one, \ - overflow, "overflow", false); \ -} while (0) - -#define PUSH_INT(v) do { \ - if (is_i32) \ - PUSH_I32(v); \ - else \ - PUSH_I64(v); \ -} while (0) - -#define POP_INT(v) do { \ - if (is_i32) \ - POP_I32(v); \ - else \ - POP_I64(v); \ -} while (0) - -#define PUSH_FLOAT(v) do { \ - if (is_f32) \ - PUSH_F32(v); \ - else \ - PUSH_F64(v); \ -} while (0) - -#define POP_FLOAT(v) do { \ - if (is_f32) \ - POP_F32(v); \ - else \ - POP_F64(v); \ -} while (0) - -#define DEF_INT_UNARY_OP(op, err) do { \ - LLVMValueRef res, operand; \ - POP_INT(operand); \ - if (!(res = op)) { \ - if (err) \ - aot_set_last_error(err); \ - return false; \ - } \ - PUSH_INT(res); \ -} while (0) - -#define DEF_INT_BINARY_OP(op, err) do { \ - LLVMValueRef res, left, right; \ - POP_INT(right); \ - POP_INT(left); \ - if (!(res = op)) { \ - if (err) \ - aot_set_last_error(err); \ - return false; \ - } \ - PUSH_INT(res); \ -} while (0) - -#define DEF_FP_UNARY_OP(op, err) do { \ - LLVMValueRef res, operand; \ - POP_FLOAT(operand); \ - if (!(res = op)) { \ - if (err) \ - aot_set_last_error(err); \ - return false; \ - } \ - PUSH_FLOAT(res); \ -} while (0) - -#define DEF_FP_BINARY_OP(op, err) do { \ - LLVMValueRef res, left, right; \ - POP_FLOAT(right); \ - POP_FLOAT(left); \ - if (!(res = op)) { \ - if (err) \ - aot_set_last_error(err); \ - return false; \ - } \ - PUSH_FLOAT(res); \ -} while (0) - -#define SHIFT_COUNT_MASK do { \ - /* LLVM has undefined behavior if shift count is greater than bits count \ - * while Webassembly spec requires the shift count be wrapped. */ \ - LLVMValueRef shift_count_mask, bits_minus_one; \ - bits_minus_one = is_i32 ? I32_31 : I64_63; \ - LLVM_BUILD_OP(And, right, bits_minus_one, \ - shift_count_mask, "shift_count_mask", NULL); \ - right = shift_count_mask; \ -} while (0) - +#else +#define IS_CONST_ZERO(val) \ + (!LLVMIsUndef(val) && LLVMIsConstant(val) \ + && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \ + || (!is_i32 && (int64)LLVMConstIntGetSExtValue(val) == 0))) +#endif + +#define CHECK_INT_OVERFLOW(type) \ + do { \ + LLVMValueRef cmp_min_int, cmp_neg_one; \ + LLVM_BUILD_ICMP(LLVMIntEQ, left, type##_MIN, cmp_min_int, \ + "cmp_min_int"); \ + LLVM_BUILD_ICMP(LLVMIntEQ, right, type##_NEG_ONE, cmp_neg_one, \ + "cmp_neg_one"); \ + LLVM_BUILD_OP(And, cmp_min_int, cmp_neg_one, overflow, "overflow", \ + false); \ + } while (0) + +#define PUSH_INT(v) \ + do { \ + if (is_i32) \ + PUSH_I32(v); \ + else \ + PUSH_I64(v); \ + } while (0) + +#define POP_INT(v) \ + do { \ + if (is_i32) \ + POP_I32(v); \ + else \ + POP_I64(v); \ + } while (0) + +#define PUSH_FLOAT(v) \ + do { \ + if (is_f32) \ + PUSH_F32(v); \ + else \ + PUSH_F64(v); \ + } while (0) + +#define POP_FLOAT(v) \ + do { \ + if (is_f32) \ + POP_F32(v); \ + else \ + POP_F64(v); \ + } while (0) + +#define DEF_INT_UNARY_OP(op, err) \ + do { \ + LLVMValueRef res, operand; \ + POP_INT(operand); \ + if (!(res = op)) { \ + if (err) \ + aot_set_last_error(err); \ + return false; \ + } \ + PUSH_INT(res); \ + } while (0) + +#define DEF_INT_BINARY_OP(op, err) \ + do { \ + LLVMValueRef res, left, right; \ + POP_INT(right); \ + POP_INT(left); \ + if (!(res = op)) { \ + if (err) \ + aot_set_last_error(err); \ + return false; \ + } \ + PUSH_INT(res); \ + } while (0) + +#define DEF_FP_UNARY_OP(op, err) \ + do { \ + LLVMValueRef res, operand; \ + POP_FLOAT(operand); \ + if (!(res = op)) { \ + if (err) \ + aot_set_last_error(err); \ + return false; \ + } \ + PUSH_FLOAT(res); \ + } while (0) + +#define DEF_FP_BINARY_OP(op, err) \ + do { \ + LLVMValueRef res, left, right; \ + POP_FLOAT(right); \ + POP_FLOAT(left); \ + if (!(res = op)) { \ + if (err) \ + aot_set_last_error(err); \ + return false; \ + } \ + PUSH_FLOAT(res); \ + } while (0) + +#define SHIFT_COUNT_MASK \ + do { \ + /* LLVM has undefined behavior if shift count is greater than \ + * bits count while Webassembly spec requires the shift count \ + * be wrapped. \ + */ \ + LLVMValueRef shift_count_mask, bits_minus_one; \ + bits_minus_one = is_i32 ? I32_31 : I64_63; \ + LLVM_BUILD_OP(And, right, bits_minus_one, shift_count_mask, \ + "shift_count_mask", NULL); \ + right = shift_count_mask; \ + } while (0) /* Call llvm constrained floating-point intrinsic */ static LLVMValueRef call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_f32, - const char *intrinsic, - ...) + const char *intrinsic, ...) { va_list param_value_list; LLVMValueRef ret; LLVMTypeRef param_types[4], ret_type = is_f32 ? F32_TYPE : F64_TYPE; + int param_count = (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, intrinsic)) + ? 2 + : 4; param_types[0] = param_types[1] = ret_type; param_types[2] = param_types[3] = MD_TYPE; va_start(param_value_list, intrinsic); - ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, param_types, - 4, param_value_list); + ret = aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type, + param_types, param_count, param_value_list); va_end(param_value_list); @@ -162,9 +188,9 @@ call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx, /* Call llvm constrained libm-equivalent intrinsic */ static LLVMValueRef call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_f32, - const char *intrinsic, - ...) + const char *intrinsic, ...) { va_list param_value_list; LLVMValueRef ret; @@ -175,8 +201,8 @@ call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx, va_start(param_value_list, intrinsic); - ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, param_types, - 3, param_value_list); + ret = aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type, + param_types, 3, param_value_list); va_end(param_value_list); @@ -184,38 +210,35 @@ call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx, } static LLVMValueRef -compile_op_float_min_max(AOTCompContext *comp_ctx, - bool is_f32, - LLVMValueRef left, - LLVMValueRef right, +compile_op_float_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool is_f32, LLVMValueRef left, LLVMValueRef right, bool is_min) { LLVMTypeRef param_types[2], ret_type = is_f32 ? F32_TYPE : F64_TYPE, - int_type = is_f32 ? I32_TYPE : I64_TYPE; + int_type = is_f32 ? I32_TYPE : I64_TYPE; LLVMValueRef cmp, is_eq, is_nan, ret, left_int, right_int, tmp, - nan = LLVMConstRealOfString(ret_type, "NaN"); - char *intrinsic = is_min ? - (is_f32 ? "llvm.minnum.f32" : "llvm.minnum.f64") : - (is_f32 ? "llvm.maxnum.f32" : "llvm.maxnum.f64"); + nan = LLVMConstRealOfString(ret_type, "NaN"); + char *intrinsic = is_min ? (is_f32 ? "llvm.minnum.f32" : "llvm.minnum.f64") + : (is_f32 ? "llvm.maxnum.f32" : "llvm.maxnum.f64"); CHECK_LLVM_CONST(nan); param_types[0] = param_types[1] = ret_type; - if (!(is_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, - left, right, "is_nan")) - || !(is_eq = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOEQ, - left, right, "is_eq"))) { + if (!(is_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, left, right, + "is_nan")) + || !(is_eq = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOEQ, left, right, + "is_eq"))) { aot_set_last_error("llvm build fcmp fail."); return NULL; } /* If left and right are equal, they may be zero with different sign. - * Webassembly spec assert -0 < +0. So do a bitwise here. */ - if (!(left_int = LLVMBuildBitCast(comp_ctx->builder, left, - int_type, "left_int")) - || !(right_int = LLVMBuildBitCast(comp_ctx->builder, right, - int_type, "right_int"))) { + Webassembly spec assert -0 < +0. So do a bitwise here. */ + if (!(left_int = + LLVMBuildBitCast(comp_ctx->builder, left, int_type, "left_int")) + || !(right_int = LLVMBuildBitCast(comp_ctx->builder, right, int_type, + "right_int"))) { aot_set_last_error("llvm build bitcast fail."); return NULL; } @@ -230,23 +253,16 @@ compile_op_float_min_max(AOTCompContext *comp_ctx, return NULL; } - if (!(cmp = aot_call_llvm_intrinsic(comp_ctx, intrinsic, ret_type, + if (!(cmp = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, ret_type, param_types, 2, left, right))) return NULL; - if (!(cmp = LLVMBuildSelect(comp_ctx->builder, - is_eq, - tmp, - cmp, - "cmp"))) { + if (!(cmp = LLVMBuildSelect(comp_ctx->builder, is_eq, tmp, cmp, "cmp"))) { aot_set_last_error("llvm build select fail."); return NULL; } - if (!(ret = LLVMBuildSelect(comp_ctx->builder, - is_nan, - nan, - cmp, + if (!(ret = LLVMBuildSelect(comp_ctx->builder, is_nan, nan, cmp, is_min ? "min" : "max"))) { aot_set_last_error("llvm build select fail."); return NULL; @@ -258,21 +274,24 @@ compile_op_float_min_max(AOTCompContext *comp_ctx, } typedef enum BitCountType { - CLZ32 = 0, - CLZ64, - CTZ32, - CTZ64, - POP_CNT32, - POP_CNT64 + CLZ32 = 0, + CLZ64, + CTZ32, + CTZ64, + POP_CNT32, + POP_CNT64 } BitCountType; -static char *bit_cnt_llvm_intrinsic[] = { "llvm.ctlz.i32", - "llvm.ctlz.i64", - "llvm.cttz.i32", - "llvm.cttz.i64", - "llvm.ctpop.i32", - "llvm.ctpop.i64", - }; +/* clang-format off */ +static char *bit_cnt_llvm_intrinsic[] = { + "llvm.ctlz.i32", + "llvm.ctlz.i64", + "llvm.cttz.i32", + "llvm.cttz.i64", + "llvm.ctpop.i32", + "llvm.ctpop.i64", +}; +/* clang-format on */ static bool aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, @@ -289,21 +308,14 @@ aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Call the LLVM intrinsic function */ if (type < POP_CNT32) - DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(comp_ctx, - bit_cnt_llvm_intrinsic[type], - ret_type, - param_types, - 2, - operand, - zero_undef), + DEF_INT_UNARY_OP(aot_call_llvm_intrinsic( + comp_ctx, func_ctx, bit_cnt_llvm_intrinsic[type], + ret_type, param_types, 2, operand, zero_undef), NULL); else - DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(comp_ctx, - bit_cnt_llvm_intrinsic[type], - ret_type, - param_types, - 1, - operand), + DEF_INT_UNARY_OP(aot_call_llvm_intrinsic( + comp_ctx, func_ctx, bit_cnt_llvm_intrinsic[type], + ret_type, param_types, 1, operand), NULL); return true; @@ -314,8 +326,8 @@ aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, static bool compile_rems(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - LLVMValueRef left, LLVMValueRef right, - LLVMValueRef overflow_cond, bool is_i32) + LLVMValueRef left, LLVMValueRef right, LLVMValueRef overflow_cond, + bool is_i32) { LLVMValueRef phi, no_overflow_value, zero = is_i32 ? I32_ZERO : I64_ZERO; LLVMBasicBlockRef block_curr, no_overflow_block, rems_end_block; @@ -327,8 +339,8 @@ compile_rems(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, ADD_BASIC_BLOCK(no_overflow_block, "rems_no_overflow"); /* Create condition br */ - if (!LLVMBuildCondBr(comp_ctx->builder, overflow_cond, - rems_end_block, no_overflow_block)) { + if (!LLVMBuildCondBr(comp_ctx->builder, overflow_cond, rems_end_block, + no_overflow_block)) { aot_set_last_error("llvm build cond br failed."); return false; } @@ -349,8 +361,7 @@ compile_rems(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMPositionBuilderAtEnd(comp_ctx->builder, rems_end_block); /* Create result phi */ - if (!(phi = LLVMBuildPhi(comp_ctx->builder, - is_i32 ? I32_TYPE : I64_TYPE, + if (!(phi = LLVMBuildPhi(comp_ctx->builder, is_i32 ? I32_TYPE : I64_TYPE, "rems_result_phi"))) { aot_set_last_error("llvm build phi failed."); return false; @@ -378,25 +389,36 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef left, right, cmp_div_zero, overflow, res; LLVMBasicBlockRef check_div_zero_succ, check_overflow_succ; - bh_assert(arith_op == INT_DIV_S - || arith_op == INT_DIV_U - || arith_op == INT_REM_S - || arith_op == INT_REM_U); + bh_assert(arith_op == INT_DIV_S || arith_op == INT_DIV_U + || arith_op == INT_REM_S || arith_op == INT_REM_U); POP_INT(right); POP_INT(left); + if (LLVMIsUndef(right) || LLVMIsUndef(left) +#if LLVM_VERSION_NUMBER >= 12 + || LLVMIsPoison(right) || LLVMIsPoison(left) +#endif + ) { + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW, + false, NULL, NULL))) { + goto fail; + } + return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); + } + if (LLVMIsConstant(right)) { int64 right_val = (int64)LLVMConstIntGetSExtValue(right); switch (right_val) { case 0: /* Directly throw exception if divided by zero */ if (!(aot_emit_exception(comp_ctx, func_ctx, - EXCE_INTEGER_DIVIDE_BY_ZERO, - false, NULL, NULL))) + EXCE_INTEGER_DIVIDE_BY_ZERO, false, + NULL, NULL))) goto fail; - return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); + return aot_handle_next_reachable_block(comp_ctx, func_ctx, + p_frame_ip); case 1: if (arith_op == INT_DIV_S || arith_op == INT_DIV_U) PUSH_INT(left); @@ -405,17 +427,15 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return true; case -1: if (arith_op == INT_DIV_S) { - LLVM_BUILD_ICMP(LLVMIntEQ, left, - is_i32 ? I32_MIN : I64_MIN, + LLVM_BUILD_ICMP(LLVMIntEQ, left, is_i32 ? I32_MIN : I64_MIN, overflow, "overflow"); ADD_BASIC_BLOCK(check_overflow_succ, "check_overflow_success"); /* Throw conditional exception if overflow */ if (!(aot_emit_exception(comp_ctx, func_ctx, - EXCE_INTEGER_OVERFLOW, - true, overflow, - check_overflow_succ))) + EXCE_INTEGER_OVERFLOW, true, + overflow, check_overflow_succ))) goto fail; /* Push -(left) to stack */ @@ -434,7 +454,7 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* fall to default */ goto handle_default; } -handle_default: + handle_default: default: /* Build div */ switch (arith_op) { @@ -483,8 +503,8 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Throw conditional exception if integer overflow */ if (!(aot_emit_exception(comp_ctx, func_ctx, - EXCE_INTEGER_OVERFLOW, - true, overflow, check_overflow_succ))) + EXCE_INTEGER_OVERFLOW, true, overflow, + check_overflow_succ))) goto fail; LLVM_BUILD_OP(SDiv, left, right, res, "div_s", false); @@ -500,8 +520,7 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, CHECK_INT_OVERFLOW(I32); else CHECK_INT_OVERFLOW(I64); - return compile_rems(comp_ctx, func_ctx, - left, right, overflow, + return compile_rems(comp_ctx, func_ctx, left, right, overflow, is_i32); case INT_REM_U: LLVM_BUILD_OP(URem, left, right, res, "rem_u", false); @@ -509,7 +528,8 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return true; default: bh_assert(0); - return false;; + return false; + ; } } @@ -518,8 +538,7 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } static LLVMValueRef -compile_int_add(AOTCompContext *comp_ctx, - LLVMValueRef left, LLVMValueRef right, +compile_int_add(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right, bool is_i32) { /* If one of the operands is 0, just return the other */ @@ -533,8 +552,7 @@ compile_int_add(AOTCompContext *comp_ctx, } static LLVMValueRef -compile_int_sub(AOTCompContext *comp_ctx, - LLVMValueRef left, LLVMValueRef right, +compile_int_sub(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right, bool is_i32) { /* If the right operand is 0, just return the left */ @@ -546,8 +564,7 @@ compile_int_sub(AOTCompContext *comp_ctx, } static LLVMValueRef -compile_int_mul(AOTCompContext *comp_ctx, - LLVMValueRef left, LLVMValueRef right, +compile_int_mul(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right, bool is_i32) { /* If one of the operands is 0, just return constant 0 */ @@ -560,7 +577,8 @@ compile_int_mul(AOTCompContext *comp_ctx, static bool compile_op_int_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - IntArithmetic arith_op, bool is_i32, uint8 **p_frame_ip) + IntArithmetic arith_op, bool is_i32, + uint8 **p_frame_ip) { switch (arith_op) { case INT_ADD: @@ -579,7 +597,8 @@ compile_op_int_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, case INT_DIV_U: case INT_REM_S: case INT_REM_U: - return compile_int_div(comp_ctx, func_ctx, arith_op, is_i32, p_frame_ip); + return compile_int_div(comp_ctx, func_ctx, arith_op, is_i32, + p_frame_ip); default: bh_assert(0); return false; @@ -595,19 +614,18 @@ compile_op_int_bitwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, { switch (bitwise_op) { case INT_AND: - DEF_INT_BINARY_OP(LLVMBuildAnd(comp_ctx->builder, - left, right, "and"), - "llvm build and fail."); + DEF_INT_BINARY_OP( + LLVMBuildAnd(comp_ctx->builder, left, right, "and"), + "llvm build and fail."); return true; case INT_OR: - DEF_INT_BINARY_OP(LLVMBuildOr(comp_ctx->builder, - left, right, "or"), + DEF_INT_BINARY_OP(LLVMBuildOr(comp_ctx->builder, left, right, "or"), "llvm build or fail."); return true; case INT_XOR: - DEF_INT_BINARY_OP(LLVMBuildXor(comp_ctx->builder, - left, right, "xor"), - "llvm build xor fail."); + DEF_INT_BINARY_OP( + LLVMBuildXor(comp_ctx->builder, left, right, "xor"), + "llvm build xor fail."); return true; default: bh_assert(0); @@ -619,8 +637,7 @@ compile_op_int_bitwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } static LLVMValueRef -compile_int_shl(AOTCompContext *comp_ctx, - LLVMValueRef left, LLVMValueRef right, +compile_int_shl(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right, bool is_i32) { LLVMValueRef res; @@ -636,9 +653,8 @@ compile_int_shl(AOTCompContext *comp_ctx, } static LLVMValueRef -compile_int_shr_s(AOTCompContext *comp_ctx, - LLVMValueRef left, LLVMValueRef right, - bool is_i32) +compile_int_shr_s(AOTCompContext *comp_ctx, LLVMValueRef left, + LLVMValueRef right, bool is_i32) { LLVMValueRef res; @@ -653,9 +669,8 @@ compile_int_shr_s(AOTCompContext *comp_ctx, } static LLVMValueRef -compile_int_shr_u(AOTCompContext *comp_ctx, - LLVMValueRef left, LLVMValueRef right, - bool is_i32) +compile_int_shr_u(AOTCompContext *comp_ctx, LLVMValueRef left, + LLVMValueRef right, bool is_i32) { LLVMValueRef res; @@ -670,10 +685,8 @@ compile_int_shr_u(AOTCompContext *comp_ctx, } static LLVMValueRef -compile_int_rot(AOTCompContext *comp_ctx, - LLVMValueRef left, LLVMValueRef right, - bool is_rotl, - bool is_i32) +compile_int_rot(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right, + bool is_rotl, bool is_i32) { LLVMValueRef bits_minus_shift_count, res, tmp_l, tmp_r; char *name = is_rotl ? "rotl" : "rotr"; @@ -681,12 +694,8 @@ compile_int_rot(AOTCompContext *comp_ctx, SHIFT_COUNT_MASK; /* Calculate (bits - shif_count) */ - LLVM_BUILD_OP(Sub, - is_i32 ? I32_32 : I64_64, - right, - bits_minus_shift_count, - "bits_minus_shift_count", - NULL); + LLVM_BUILD_OP(Sub, is_i32 ? I32_32 : I64_64, right, bits_minus_shift_count, + "bits_minus_shift_count", NULL); if (is_rotl) { /* left<>(BITS-count) */ @@ -716,20 +725,18 @@ compile_op_int_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, case INT_SHR_S: DEF_INT_BINARY_OP(compile_int_shr_s(comp_ctx, left, right, is_i32), NULL); - return true; + return true; case INT_SHR_U: DEF_INT_BINARY_OP(compile_int_shr_u(comp_ctx, left, right, is_i32), NULL); return true; case INT_ROTL: - DEF_INT_BINARY_OP(compile_int_rot(comp_ctx, left, right, - true, is_i32), - NULL); + DEF_INT_BINARY_OP( + compile_int_rot(comp_ctx, left, right, true, is_i32), NULL); return true; case INT_ROTR: - DEF_INT_BINARY_OP(compile_int_rot(comp_ctx, left, right, - false, is_i32), - NULL); + DEF_INT_BINARY_OP( + compile_int_rot(comp_ctx, left, right, false, is_i32), NULL); return true; default: bh_assert(0); @@ -743,16 +750,16 @@ compile_op_int_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, static bool is_target_arm(AOTCompContext *comp_ctx) { - return !strncmp(comp_ctx->target_arch, "arm", 3) || - !strncmp(comp_ctx->target_arch, "aarch64", 7) || - !strncmp(comp_ctx->target_arch, "thumb", 5); + return !strncmp(comp_ctx->target_arch, "arm", 3) + || !strncmp(comp_ctx->target_arch, "aarch64", 7) + || !strncmp(comp_ctx->target_arch, "thumb", 5); } static bool is_target_x86(AOTCompContext *comp_ctx) { - return !strncmp(comp_ctx->target_arch, "x86_64", 6) || - !strncmp(comp_ctx->target_arch, "i386", 4); + return !strncmp(comp_ctx->target_arch, "x86_64", 6) + || !strncmp(comp_ctx->target_arch, "i386", 4); } static bool @@ -767,6 +774,12 @@ is_target_mips(AOTCompContext *comp_ctx) return !strncmp(comp_ctx->target_arch, "mips", 4); } +static bool +is_target_riscv(AOTCompContext *comp_ctx) +{ + return !strncmp(comp_ctx->target_arch, "riscv", 5); +} + static bool is_targeting_soft_float(AOTCompContext *comp_ctx, bool is_f32) { @@ -774,7 +787,7 @@ is_targeting_soft_float(AOTCompContext *comp_ctx, bool is_f32) char *feature_string; if (!(feature_string = - LLVMGetTargetMachineFeatureString(comp_ctx->target_machine))) { + LLVMGetTargetMachineFeatureString(comp_ctx->target_machine))) { aot_set_last_error("llvm get target machine feature string fail."); return false; } @@ -783,9 +796,8 @@ is_targeting_soft_float(AOTCompContext *comp_ctx, bool is_f32) * LLVM CodeGen uses FPU Coprocessor registers by default, * so user must specify '--cpu-features=+soft-float' to wamrc if the target * doesn't have or enable FPU on arm, x86 or mips. */ - if (is_target_arm(comp_ctx) || - is_target_x86(comp_ctx) || - is_target_mips(comp_ctx)) + if (is_target_arm(comp_ctx) || is_target_x86(comp_ctx) + || is_target_mips(comp_ctx)) ret = strstr(feature_string, "+soft-float") ? true : false; else if (is_target_xtensa(comp_ctx)) /* Note: @@ -794,8 +806,20 @@ is_targeting_soft_float(AOTCompContext *comp_ctx, bool is_f32) * for f64(i.e. double). * 2. LLVM CodeGen uses Floating-Point Coprocessor registers by default, * so user must specify '--cpu-features=-fp' to wamrc if the target - * doesn't have or enable Floating-Point Coprocessor Option on xtensa. */ + * doesn't have or enable Floating-Point Coprocessor Option on xtensa. + */ ret = (!is_f32 || strstr(feature_string, "-fp")) ? true : false; + else if (is_target_riscv(comp_ctx)) { + /* + * Note: Use builtin intrinsics since hardware float operation + * will cause rodata relocation, this will try to use hardware + * float unit (by return false) but handled by software finally + */ + if (comp_ctx->disable_llvm_intrinsics) + ret = false; + else + ret = !strstr(feature_string, "+d") ? true : false; + } else ret = true; @@ -810,85 +834,72 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, switch (arith_op) { case FLOAT_ADD: if (is_targeting_soft_float(comp_ctx, is_f32)) - DEF_FP_BINARY_OP(LLVMBuildFAdd(comp_ctx->builder, left, right, "fadd"), - "llvm build fadd fail."); + DEF_FP_BINARY_OP( + LLVMBuildFAdd(comp_ctx->builder, left, right, "fadd"), + "llvm build fadd fail."); else - DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic( - comp_ctx, - is_f32, - (is_f32 - ? "llvm.experimental.constrained.fadd.f32" - : "llvm.experimental.constrained.fadd.f64"), - left, - right, - comp_ctx->fp_rounding_mode, - comp_ctx->fp_exception_behavior), - NULL); + DEF_FP_BINARY_OP( + call_llvm_float_experimental_constrained_intrinsic( + comp_ctx, func_ctx, is_f32, + (is_f32 ? "llvm.experimental.constrained.fadd.f32" + : "llvm.experimental.constrained.fadd.f64"), + left, right, comp_ctx->fp_rounding_mode, + comp_ctx->fp_exception_behavior), + NULL); return true; case FLOAT_SUB: if (is_targeting_soft_float(comp_ctx, is_f32)) - DEF_FP_BINARY_OP(LLVMBuildFSub(comp_ctx->builder, left, right, "fsub"), - "llvm build fsub fail."); + DEF_FP_BINARY_OP( + LLVMBuildFSub(comp_ctx->builder, left, right, "fsub"), + "llvm build fsub fail."); else - DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic( - comp_ctx, - is_f32, - (is_f32 - ? "llvm.experimental.constrained.fsub.f32" - : "llvm.experimental.constrained.fsub.f64"), - left, - right, - comp_ctx->fp_rounding_mode, - comp_ctx->fp_exception_behavior), - NULL); + DEF_FP_BINARY_OP( + call_llvm_float_experimental_constrained_intrinsic( + comp_ctx, func_ctx, is_f32, + (is_f32 ? "llvm.experimental.constrained.fsub.f32" + : "llvm.experimental.constrained.fsub.f64"), + left, right, comp_ctx->fp_rounding_mode, + comp_ctx->fp_exception_behavior), + NULL); return true; case FLOAT_MUL: if (is_targeting_soft_float(comp_ctx, is_f32)) - DEF_FP_BINARY_OP(LLVMBuildFMul(comp_ctx->builder, left, right, "fmul"), - "llvm build fmul fail."); + DEF_FP_BINARY_OP( + LLVMBuildFMul(comp_ctx->builder, left, right, "fmul"), + "llvm build fmul fail."); else - DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic( - comp_ctx, - is_f32, - (is_f32 - ? "llvm.experimental.constrained.fmul.f32" - : "llvm.experimental.constrained.fmul.f64"), - left, - right, - comp_ctx->fp_rounding_mode, - comp_ctx->fp_exception_behavior), - NULL); + DEF_FP_BINARY_OP( + call_llvm_float_experimental_constrained_intrinsic( + comp_ctx, func_ctx, is_f32, + (is_f32 ? "llvm.experimental.constrained.fmul.f32" + : "llvm.experimental.constrained.fmul.f64"), + left, right, comp_ctx->fp_rounding_mode, + comp_ctx->fp_exception_behavior), + NULL); return true; case FLOAT_DIV: if (is_targeting_soft_float(comp_ctx, is_f32)) - DEF_FP_BINARY_OP(LLVMBuildFDiv(comp_ctx->builder, left, right, "fdiv"), - "llvm build fdiv fail."); + DEF_FP_BINARY_OP( + LLVMBuildFDiv(comp_ctx->builder, left, right, "fdiv"), + "llvm build fdiv fail."); else - DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic( - comp_ctx, - is_f32, - (is_f32 - ? "llvm.experimental.constrained.fdiv.f32" - : "llvm.experimental.constrained.fdiv.f64"), - left, - right, - comp_ctx->fp_rounding_mode, - comp_ctx->fp_exception_behavior), - NULL); + DEF_FP_BINARY_OP( + call_llvm_float_experimental_constrained_intrinsic( + comp_ctx, func_ctx, is_f32, + (is_f32 ? "llvm.experimental.constrained.fdiv.f32" + : "llvm.experimental.constrained.fdiv.f64"), + left, right, comp_ctx->fp_rounding_mode, + comp_ctx->fp_exception_behavior), + NULL); return true; case FLOAT_MIN: - DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx, - is_f32, - left, - right, - true), + DEF_FP_BINARY_OP(compile_op_float_min_max( + comp_ctx, func_ctx, is_f32, left, right, true), NULL); return true; case FLOAT_MAX: - DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx, - is_f32, - left, - right, + DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx, func_ctx, + is_f32, left, right, false), NULL); @@ -904,9 +915,8 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, static LLVMValueRef call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx, - bool is_f32, - const char *intrinsic, - ...) + AOTFuncContext *func_ctx, bool is_f32, + const char *intrinsic, ...) { va_list param_value_list; LLVMValueRef ret; @@ -916,8 +926,8 @@ call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx, va_start(param_value_list, intrinsic); - ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, ¶m_type, - 1, param_value_list); + ret = aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type, + ¶m_type, 1, param_value_list); va_end(param_value_list); @@ -930,11 +940,10 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, { switch (math_op) { case FLOAT_ABS: - DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, - is_f32, - is_f32 ? "llvm.fabs.f32" : - "llvm.fabs.f64", - operand), + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic( + comp_ctx, func_ctx, is_f32, + is_f32 ? "llvm.fabs.f32" : "llvm.fabs.f64", + operand), NULL); return true; case FLOAT_NEG: @@ -943,56 +952,50 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return true; case FLOAT_CEIL: - DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, - is_f32, - is_f32 ? "llvm.ceil.f32" : - "llvm.ceil.f64", - operand), + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic( + comp_ctx, func_ctx, is_f32, + is_f32 ? "llvm.ceil.f32" : "llvm.ceil.f64", + operand), NULL); return true; case FLOAT_FLOOR: - DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, - is_f32, - is_f32 ? "llvm.floor.f32": - "llvm.floor.f64", - operand), + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic( + comp_ctx, func_ctx, is_f32, + is_f32 ? "llvm.floor.f32" : "llvm.floor.f64", + operand), NULL); return true; case FLOAT_TRUNC: - DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, - is_f32, - is_f32 ? "llvm.trunc.f32" : - "llvm.trunc.f64", - operand), + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic( + comp_ctx, func_ctx, is_f32, + is_f32 ? "llvm.trunc.f32" : "llvm.trunc.f64", + operand), NULL); return true; case FLOAT_NEAREST: - DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, - is_f32, - is_f32 ? "llvm.rint.f32" : - "llvm.rint.f64", - operand), + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic( + comp_ctx, func_ctx, is_f32, + is_f32 ? "llvm.rint.f32" : "llvm.rint.f64", + operand), NULL); return true; case FLOAT_SQRT: - if (is_targeting_soft_float(comp_ctx, is_f32)) - DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, - is_f32, - is_f32 ? "llvm.sqrt.f32" : - "llvm.sqrt.f64", - operand), + if (is_targeting_soft_float(comp_ctx, is_f32) + || comp_ctx->disable_llvm_intrinsics) + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic( + comp_ctx, func_ctx, is_f32, + is_f32 ? "llvm.sqrt.f32" : "llvm.sqrt.f64", + operand), NULL); else - DEF_FP_UNARY_OP(call_llvm_libm_experimental_constrained_intrinsic( - comp_ctx, - is_f32, - (is_f32 - ? "llvm.experimental.constrained.sqrt.f32" - : "llvm.experimental.constrained.sqrt.f64"), - operand, - comp_ctx->fp_rounding_mode, - comp_ctx->fp_exception_behavior), - NULL); + DEF_FP_UNARY_OP( + call_llvm_libm_experimental_constrained_intrinsic( + comp_ctx, func_ctx, is_f32, + (is_f32 ? "llvm.experimental.constrained.sqrt.f32" + : "llvm.experimental.constrained.sqrt.f64"), + operand, comp_ctx->fp_rounding_mode, + comp_ctx->fp_exception_behavior), + NULL); return true; default: bh_assert(0); @@ -1013,15 +1016,11 @@ compile_float_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_types[0] = param_types[1] = ret_type = is_f32 ? F32_TYPE : F64_TYPE; - DEF_FP_BINARY_OP(aot_call_llvm_intrinsic(comp_ctx, - is_f32 ? "llvm.copysign.f32" : - "llvm.copysign.f64", - ret_type, - param_types, - 2, - left, - right), - NULL); + DEF_FP_BINARY_OP(aot_call_llvm_intrinsic( + comp_ctx, func_ctx, + is_f32 ? "llvm.copysign.f32" : "llvm.copysign.f64", + ret_type, param_types, 2, left, right), + NULL); return true; fail: @@ -1065,17 +1064,21 @@ aot_compile_op_i64_popcnt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) } bool -aot_compile_op_i32_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - IntArithmetic arith_op, uint8 **p_frame_ip) +aot_compile_op_i32_arithmetic(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, IntArithmetic arith_op, + uint8 **p_frame_ip) { - return compile_op_int_arithmetic(comp_ctx, func_ctx, arith_op, true, p_frame_ip); + return compile_op_int_arithmetic(comp_ctx, func_ctx, arith_op, true, + p_frame_ip); } bool -aot_compile_op_i64_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - IntArithmetic arith_op, uint8 **p_frame_ip) +aot_compile_op_i64_arithmetic(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, IntArithmetic arith_op, + uint8 **p_frame_ip) { - return compile_op_int_arithmetic(comp_ctx, func_ctx, arith_op, false, p_frame_ip); + return compile_op_int_arithmetic(comp_ctx, func_ctx, arith_op, false, + p_frame_ip); } bool @@ -1147,4 +1150,3 @@ aot_compile_op_f64_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { return compile_float_copysign(comp_ctx, func_ctx, false); } - diff --git a/core/iwasm/compilation/aot_emit_numberic.h b/core/iwasm/compilation/aot_emit_numberic.h index c9dd307ba8..7206315dfe 100644 --- a/core/iwasm/compilation/aot_emit_numberic.h +++ b/core/iwasm/compilation/aot_emit_numberic.h @@ -31,12 +31,14 @@ bool aot_compile_op_i64_popcnt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); bool -aot_compile_op_i32_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - IntArithmetic arith_op, uint8 **p_frame_ip); +aot_compile_op_i32_arithmetic(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, IntArithmetic arith_op, + uint8 **p_frame_ip); bool -aot_compile_op_i64_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - IntArithmetic arith_op, uint8 **p_frame_ip); +aot_compile_op_i64_arithmetic(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, IntArithmetic arith_op, + uint8 **p_frame_ip); bool aot_compile_op_i32_bitwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, @@ -63,11 +65,13 @@ aot_compile_op_f64_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, FloatMath math_op); bool -aot_compile_op_f32_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, +aot_compile_op_f32_arithmetic(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, FloatArithmetic arith_op); bool -aot_compile_op_f64_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, +aot_compile_op_f64_arithmetic(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, FloatArithmetic arith_op); bool @@ -81,4 +85,3 @@ aot_compile_op_f64_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); #endif #endif /* end of _AOT_EMIT_NUMBERIC_H_ */ - diff --git a/core/iwasm/compilation/aot_emit_parametric.c b/core/iwasm/compilation/aot_emit_parametric.c index fba89e273a..8b1a9e6da3 100644 --- a/core/iwasm/compilation/aot_emit_parametric.c +++ b/core/iwasm/compilation/aot_emit_parametric.c @@ -7,8 +7,7 @@ static bool pop_value_from_wasm_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - LLVMValueRef *p_value, - bool is_32, uint8 *p_type) + LLVMValueRef *p_value, bool is_32, uint8 *p_type) { AOTValue *aot_value; uint8 type; @@ -22,14 +21,14 @@ pop_value_from_wasm_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } - aot_value = aot_value_stack_pop - (&func_ctx->block_stack.block_list_end->value_stack); + aot_value = + aot_value_stack_pop(&func_ctx->block_stack.block_list_end->value_stack); type = aot_value->type; if (aot_value->type == VALUE_TYPE_I1) { if (!(aot_value->value = - LLVMBuildZExt(comp_ctx->builder, aot_value->value, - I32_TYPE, "val_s_ext"))) { + LLVMBuildZExt(comp_ctx->builder, aot_value->value, I32_TYPE, + "val_s_ext"))) { aot_set_last_error("llvm build sign ext failed."); return false; } @@ -55,8 +54,7 @@ pop_value_from_wasm_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* !is_32: i64, f64 */ - if (!is_32 - && !(type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)) { + if (!is_32 && !(type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)) { aot_set_last_error("invalid WASM stack data type."); return false; } @@ -64,7 +62,6 @@ pop_value_from_wasm_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return true; } - bool aot_compile_op_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool is_drop_32) @@ -84,8 +81,10 @@ aot_compile_op_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, POP_COND(cond); - if (!pop_value_from_wasm_stack(comp_ctx, func_ctx, &val2, is_select_32, &val2_type) - || !pop_value_from_wasm_stack(comp_ctx, func_ctx, &val1, is_select_32, &val1_type)) + if (!pop_value_from_wasm_stack(comp_ctx, func_ctx, &val2, is_select_32, + &val2_type) + || !pop_value_from_wasm_stack(comp_ctx, func_ctx, &val1, is_select_32, + &val1_type)) return false; if (val1_type != val2_type) { @@ -93,9 +92,8 @@ aot_compile_op_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } - if (!(selected = LLVMBuildSelect(comp_ctx->builder, - cond, val1, val2, - "select"))) { + if (!(selected = + LLVMBuildSelect(comp_ctx->builder, cond, val1, val2, "select"))) { aot_set_last_error("llvm build select failed."); return false; } @@ -107,4 +105,3 @@ aot_compile_op_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, fail: return false; } - diff --git a/core/iwasm/compilation/aot_emit_parametric.h b/core/iwasm/compilation/aot_emit_parametric.h index 9587cb17eb..68fe8f11d3 100644 --- a/core/iwasm/compilation/aot_emit_parametric.h +++ b/core/iwasm/compilation/aot_emit_parametric.h @@ -18,12 +18,10 @@ aot_compile_op_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool aot_compile_op_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - bool is_select_32); - + bool is_select_32); #ifdef __cplusplus } /* end of extern "C" */ #endif #endif /* end of _AOT_EMIT_PARAMETRIC_H_ */ - diff --git a/core/iwasm/compilation/aot_emit_table.c b/core/iwasm/compilation/aot_emit_table.c index e84cad5d46..d3598c9282 100644 --- a/core/iwasm/compilation/aot_emit_table.c +++ b/core/iwasm/compilation/aot_emit_table.c @@ -7,11 +7,9 @@ #include "aot_emit_exception.h" #include "../aot/aot_runtime.h" - uint64 get_tbl_inst_offset(const AOTCompContext *comp_ctx, - const AOTFuncContext *func_ctx, - uint32 tbl_idx) + const AOTFuncContext *func_ctx, uint32 tbl_idx) { uint64 offset = 0, i = 0; AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables; @@ -19,12 +17,13 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx, /* from the head of AOTModuleInstance */ offset = - offsetof(AOTModuleInstance, global_table_data.bytes) - + (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance) - + comp_ctx->comp_data->global_data_size; + offsetof(AOTModuleInstance, global_table_data.bytes) + + (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance) + + comp_ctx->comp_data->global_data_size; while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) { offset += offsetof(AOTTableInstance, data); + /* avoid loading from current AOTTableInstance */ offset += sizeof(uint32) * aot_get_imp_tbl_data_slots(imp_tbls + i); ++i; } @@ -37,6 +36,7 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx, i -= comp_ctx->comp_data->import_table_count; while (i < tbl_idx && i < comp_ctx->comp_data->table_count) { offset += offsetof(AOTTableInstance, data); + /* avoid loading from current AOTTableInstance */ offset += sizeof(uint32) * aot_get_tbl_data_slots(tbls + i); ++i; } @@ -47,14 +47,13 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx, #if WASM_ENABLE_REF_TYPES != 0 LLVMValueRef -aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx) { LLVMValueRef offset, tbl_inst; if (!(offset = - I64_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)))) { + I64_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)))) { HANDLE_FAILURE("LLVMConstInt"); goto fail; } @@ -71,8 +70,7 @@ aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, } bool -aot_compile_op_elem_drop(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_elem_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_seg_idx) { LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type; @@ -93,7 +91,7 @@ aot_compile_op_elem_drop(AOTCompContext *comp_ctx, /* "" means return void */ if (!(ret_value = - LLVMBuildCall(comp_ctx->builder, func, param_values, 2, ""))) { + LLVMBuildCall(comp_ctx->builder, func, param_values, 2, ""))) { HANDLE_FAILURE("LLVMBuildCall"); goto fail; } @@ -104,10 +102,8 @@ aot_compile_op_elem_drop(AOTCompContext *comp_ctx, } static bool -aot_check_table_access(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 tbl_idx, - LLVMValueRef elem_idx) +aot_check_table_access(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 tbl_idx, LLVMValueRef elem_idx) { LLVMValueRef offset, tbl_sz, cmp_elem_idx; LLVMBasicBlockRef check_elem_idx_succ; @@ -145,7 +141,7 @@ aot_check_table_access(AOTCompContext *comp_ctx, /* Throw exception if elem index >= table size */ if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext( - comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) { + comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) { aot_set_last_error("llvm add basic block failed."); goto fail; } @@ -164,8 +160,7 @@ aot_check_table_access(AOTCompContext *comp_ctx, } bool -aot_compile_op_table_get(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx) { LLVMValueRef elem_idx, offset, table_elem, func_idx; @@ -196,14 +191,14 @@ aot_compile_op_table_get(AOTCompContext *comp_ctx, } /* Load function index */ - if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx, - 1, "table_elem"))) { + if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx, 1, + "table_elem"))) { HANDLE_FAILURE("LLVMBuildNUWAdd"); goto fail; } if (!(func_idx = - LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) { + LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) { HANDLE_FAILURE("LLVMBuildLoad"); goto fail; } @@ -216,8 +211,7 @@ aot_compile_op_table_get(AOTCompContext *comp_ctx, } bool -aot_compile_op_table_set(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx) { LLVMValueRef val, elem_idx, offset, table_elem; @@ -249,8 +243,8 @@ aot_compile_op_table_set(AOTCompContext *comp_ctx, } /* Load function index */ - if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx, - 1, "table_elem"))) { + if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx, 1, + "table_elem"))) { HANDLE_FAILURE("LLVMBuildGEP"); goto fail; } @@ -266,10 +260,8 @@ aot_compile_op_table_set(AOTCompContext *comp_ctx, } bool -aot_compile_op_table_init(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 tbl_idx, - uint32 tbl_seg_idx) +aot_compile_op_table_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 tbl_idx, uint32 tbl_seg_idx) { LLVMValueRef func, param_values[6], value; @@ -316,10 +308,8 @@ aot_compile_op_table_init(AOTCompContext *comp_ctx, } bool -aot_compile_op_table_copy(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 src_tbl_idx, - uint32 dst_tbl_idx) +aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 src_tbl_idx, uint32 dst_tbl_idx) { LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type; LLVMValueRef func, param_values[6], value; @@ -365,8 +355,7 @@ aot_compile_op_table_copy(AOTCompContext *comp_ctx, } bool -aot_compile_op_table_size(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_table_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx) { LLVMValueRef offset, tbl_sz; @@ -402,8 +391,7 @@ aot_compile_op_table_size(AOTCompContext *comp_ctx, } bool -aot_compile_op_table_grow(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_table_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx) { LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type; @@ -443,8 +431,7 @@ aot_compile_op_table_grow(AOTCompContext *comp_ctx, } bool -aot_compile_op_table_fill(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_table_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx) { LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type; diff --git a/core/iwasm/compilation/aot_emit_table.h b/core/iwasm/compilation/aot_emit_table.h index 78c5b90c39..e5ab0ed48b 100644 --- a/core/iwasm/compilation/aot_emit_table.h +++ b/core/iwasm/compilation/aot_emit_table.h @@ -14,55 +14,43 @@ extern "C" { #endif bool -aot_compile_op_elem_drop(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_elem_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_seg_idx); bool -aot_compile_op_table_get(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx); bool -aot_compile_op_table_set(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx); bool -aot_compile_op_table_init(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 tbl_idx, - uint32 tbl_seg_idx); +aot_compile_op_table_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 tbl_idx, uint32 tbl_seg_idx); bool -aot_compile_op_table_copy(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 src_tbl_idx, - uint32 dst_tbl_idx); +aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 src_tbl_idx, uint32 dst_tbl_idx); bool -aot_compile_op_table_size(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_table_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx); bool -aot_compile_op_table_grow(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_table_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx); bool -aot_compile_op_table_fill(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_op_table_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx); uint64 get_tbl_inst_offset(const AOTCompContext *comp_ctx, - const AOTFuncContext *func_ctx, - uint32 tbl_idx); + const AOTFuncContext *func_ctx, uint32 tbl_idx); LLVMValueRef -aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 tbl_idx); #ifdef __cplusplus diff --git a/core/iwasm/compilation/aot_emit_variable.c b/core/iwasm/compilation/aot_emit_variable.c index c3ddc356ff..36069f3f45 100644 --- a/core/iwasm/compilation/aot_emit_variable.c +++ b/core/iwasm/compilation/aot_emit_variable.c @@ -7,13 +7,14 @@ #include "aot_emit_exception.h" #include "../aot/aot_runtime.h" -#define CHECK_LOCAL(idx) do { \ - if (idx >= func_ctx->aot_func->func_type->param_count \ - + func_ctx->aot_func->local_count) { \ - aot_set_last_error("local index out of range"); \ - return false; \ - } \ - } while (0) +#define CHECK_LOCAL(idx) \ + do { \ + if (idx >= func_ctx->aot_func->func_type->param_count \ + + func_ctx->aot_func->local_count) { \ + aot_set_last_error("local index out of range"); \ + return false; \ + } \ + } while (0) static uint8 get_local_type(AOTFuncContext *func_ctx, uint32 local_idx) @@ -21,8 +22,8 @@ get_local_type(AOTFuncContext *func_ctx, uint32 local_idx) AOTFunc *aot_func = func_ctx->aot_func; uint32 param_count = aot_func->func_type->param_count; return local_idx < param_count - ? aot_func->func_type->types[local_idx] - : aot_func->local_types[local_idx - param_count]; + ? aot_func->func_type->types[local_idx] + : aot_func->local_types[local_idx - param_count]; } bool @@ -36,8 +37,7 @@ aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, CHECK_LOCAL(local_idx); snprintf(name, sizeof(name), "%s%d%s", "local", local_idx, "#"); - if (!(value = LLVMBuildLoad(comp_ctx->builder, - func_ctx->locals[local_idx], + if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->locals[local_idx], name))) { aot_set_last_error("llvm build load fail"); return false; @@ -45,7 +45,8 @@ aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, PUSH(value, get_local_type(func_ctx, local_idx)); - aot_value = func_ctx->block_stack.block_list_end->value_stack.value_list_end; + aot_value = + func_ctx->block_stack.block_list_end->value_stack.value_list_end; aot_value->is_local = true; aot_value->local_idx = local_idx; return true; @@ -64,8 +65,7 @@ aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, POP(value, get_local_type(func_ctx, local_idx)); - if (!LLVMBuildStore(comp_ctx->builder, - value, + if (!LLVMBuildStore(comp_ctx->builder, value, func_ctx->locals[local_idx])) { aot_set_last_error("llvm build store fail"); return false; @@ -91,8 +91,7 @@ aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, POP(value, type); - if (!LLVMBuildStore(comp_ctx->builder, - value, + if (!LLVMBuildStore(comp_ctx->builder, value, func_ctx->locals[local_idx])) { aot_set_last_error("llvm build store fail"); return false; @@ -128,15 +127,16 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, global_type = comp_data->import_globals[global_idx].type; } else { - global_offset = global_base_offset + global_offset = + global_base_offset + comp_data->globals[global_idx - import_global_count].data_offset; - global_type = - comp_data->globals[global_idx - import_global_count].type; + global_type = comp_data->globals[global_idx - import_global_count].type; } offset = I32_CONST(global_offset); - if (!(global_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, - &offset, 1, "global_ptr_tmp"))) { + if (!(global_ptr = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "global_ptr_tmp"))) { aot_set_last_error("llvm build in bounds gep failed."); return false; } @@ -164,15 +164,15 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, break; } - if (!(global_ptr = LLVMBuildBitCast(comp_ctx->builder, global_ptr, - ptr_type, "global_ptr"))) { + if (!(global_ptr = LLVMBuildBitCast(comp_ctx->builder, global_ptr, ptr_type, + "global_ptr"))) { aot_set_last_error("llvm build bit cast failed."); return false; } if (!is_set) { - if (!(global = LLVMBuildLoad(comp_ctx->builder, - global_ptr, "global"))) { + if (!(global = + LLVMBuildLoad(comp_ctx->builder, global_ptr, "global"))) { aot_set_last_error("llvm build load failed."); return false; } @@ -184,61 +184,56 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, POP(global, global_type); if (is_aux_stack && comp_ctx->enable_aux_stack_check) { - LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder); + LLVMBasicBlockRef block_curr = + LLVMGetInsertBlock(comp_ctx->builder); LLVMBasicBlockRef check_overflow_succ, check_underflow_succ; LLVMValueRef cmp; /* Add basic blocks */ - if (!(check_overflow_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_overflow_succ"))) { + if (!(check_overflow_succ = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, + "check_overflow_succ"))) { aot_set_last_error("llvm add basic block failed."); return false; } LLVMMoveBasicBlockAfter(check_overflow_succ, block_curr); - if (!(check_underflow_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_underflow_succ"))) { + if (!(check_underflow_succ = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, + "check_underflow_succ"))) { aot_set_last_error("llvm add basic block failed."); return false; } LLVMMoveBasicBlockAfter(check_underflow_succ, check_overflow_succ); /* Check aux stack overflow */ - if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE, - global, func_ctx->aux_stack_bound, - "cmp"))) { + if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE, global, + func_ctx->aux_stack_bound, "cmp"))) { aot_set_last_error("llvm build icmp failed."); return false; } - if (!aot_emit_exception(comp_ctx, func_ctx, - EXCE_AUX_STACK_OVERFLOW, + if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_AUX_STACK_OVERFLOW, true, cmp, check_overflow_succ)) { return false; } /* Check aux stack underflow */ LLVMPositionBuilderAtEnd(comp_ctx->builder, check_overflow_succ); - if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, - global, func_ctx->aux_stack_bottom, - "cmp"))) { + if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, global, + func_ctx->aux_stack_bottom, "cmp"))) { aot_set_last_error("llvm build icmp failed."); return false; } if (!aot_emit_exception(comp_ctx, func_ctx, - EXCE_AUX_STACK_UNDERFLOW, - true, cmp, check_underflow_succ)) { + EXCE_AUX_STACK_UNDERFLOW, true, cmp, + check_underflow_succ)) { return false; } LLVMPositionBuilderAtEnd(comp_ctx->builder, check_underflow_succ); } - if (!(res = LLVMBuildStore(comp_ctx->builder, - global, global_ptr))) { + if (!(res = LLVMBuildStore(comp_ctx->builder, global, global_ptr))) { aot_set_last_error("llvm build store failed."); return false; } @@ -264,4 +259,3 @@ aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, { return compile_global(comp_ctx, func_ctx, global_idx, true, is_aux_stack); } - diff --git a/core/iwasm/compilation/aot_emit_variable.h b/core/iwasm/compilation/aot_emit_variable.h index e3b588352a..28c0bd0939 100644 --- a/core/iwasm/compilation/aot_emit_variable.h +++ b/core/iwasm/compilation/aot_emit_variable.h @@ -37,4 +37,3 @@ aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, #endif #endif /* end of _AOT_EMIT_VARIABLE_H_ */ - diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 7966a5477f..8a64e29703 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -7,7 +7,11 @@ #include "aot_compiler.h" #include "aot_emit_exception.h" #include "../aot/aot_runtime.h" +#include "../aot/aot_intrinsic.h" +#if WASM_ENABLE_DEBUG_AOT != 0 +#include "debug/dwarf_extractor.h" +#endif LLVMTypeRef wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type) @@ -38,7 +42,7 @@ wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type) */ static LLVMValueRef aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type, - uint32 func_index) + uint32 func_index, LLVMTypeRef *p_func_type) { LLVMValueRef func = NULL; LLVMTypeRef *param_types, ret_type, func_type; @@ -53,7 +57,7 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type, /* Extra wasm function results(except the first one)'s address are * appended to aot function parameters. */ if (aot_func_type->result_count > 1) - param_count += aot_func_type->result_count - 1; + param_count += aot_func_type->result_count - 1; /* Initialize parameter types of the LLVM function */ size = sizeof(LLVMTypeRef) * ((uint64)param_count); @@ -69,23 +73,24 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type, param_types[j++] = TO_LLVM_TYPE(aot_func_type->types[i]); /* Extra results' address */ for (i = 1; i < aot_func_type->result_count; i++, j++) { - param_types[j] = - TO_LLVM_TYPE(aot_func_type->types[aot_func_type->param_count + i]); - if (!(param_types[j] = LLVMPointerType(param_types[j], 0))) { - aot_set_last_error("llvm get pointer type failed."); - goto fail; - } + param_types[j] = + TO_LLVM_TYPE(aot_func_type->types[aot_func_type->param_count + i]); + if (!(param_types[j] = LLVMPointerType(param_types[j], 0))) { + aot_set_last_error("llvm get pointer type failed."); + goto fail; + } } /* Resolve return type of the LLVM function */ if (aot_func_type->result_count) - ret_type = TO_LLVM_TYPE(aot_func_type->types[aot_func_type->param_count]); + ret_type = + TO_LLVM_TYPE(aot_func_type->types[aot_func_type->param_count]); else ret_type = VOID_TYPE; /* Resolve function prototype */ - if (!(func_type = LLVMFunctionType(ret_type, param_types, - param_count, false))) { + if (!(func_type = + LLVMFunctionType(ret_type, param_types, param_count, false))) { aot_set_last_error("create LLVM function type failed."); goto fail; } @@ -107,6 +112,9 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type, LLVMSetValueName(local_value, ""); } + if (p_func_type) + *p_func_type = func_type; + fail: wasm_runtime_free(param_types); return func; @@ -156,13 +164,13 @@ aot_create_func_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, aot_block->param_count = param_count; memcpy(aot_block->param_types, aot_func_type->types, param_count); aot_block->result_count = result_count; - memcpy(aot_block->result_types, aot_func_type->types + param_count, result_count); + memcpy(aot_block->result_types, aot_func_type->types + param_count, + result_count); aot_block->wasm_code_end = func->code + func->code_size; /* Add function entry block */ - if (!(aot_block->llvm_entry_block = - LLVMAppendBasicBlockInContext(comp_ctx->context, func_ctx->func, - "func_begin"))) { + if (!(aot_block->llvm_entry_block = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "func_begin"))) { aot_set_last_error("add LLVM basic block failed."); goto fail; } @@ -183,8 +191,9 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, WASMModule *module = comp_ctx->comp_data->wasm_module; WASMFunction *func = module->functions[func_index]; LLVMTypeRef bound_check_type; - bool mem_space_unchanged = (!func->has_op_memory_grow && !func->has_op_func_call) - || (!module->possible_memory_grow); + bool mem_space_unchanged = + (!func->has_op_memory_grow && !func->has_op_func_call) + || (!module->possible_memory_grow); #if WASM_ENABLE_SHARED_MEMORY != 0 bool is_shared_memory; #endif @@ -198,7 +207,7 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, memory_count = 1; if (!(func_ctx->mem_info = - wasm_runtime_malloc(sizeof(AOTMemInfo) * memory_count))) { + wasm_runtime_malloc(sizeof(AOTMemInfo) * memory_count))) { return false; } memset(func_ctx->mem_info, 0, sizeof(AOTMemInfo)); @@ -206,8 +215,8 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Currently we only create memory info for memory 0 */ /* Load memory base address */ #if WASM_ENABLE_SHARED_MEMORY != 0 - is_shared_memory = comp_ctx->comp_data->memories[0].memory_flags & 0x02 - ? true : false; + is_shared_memory = + comp_ctx->comp_data->memories[0].memory_flags & 0x02 ? true : false; if (is_shared_memory) { LLVMValueRef shared_mem_addr; offset = I32_CONST(offsetof(AOTModuleInstance, memories)); @@ -218,56 +227,52 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* aot_inst->memories */ if (!(shared_mem_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, - &offset, 1, "shared_mem_addr_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "shared_mem_addr_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } if (!(shared_mem_addr = - LLVMBuildBitCast(comp_ctx->builder, - shared_mem_addr, int8_ptr_type, - "shared_mem_addr_ptr"))) { + LLVMBuildBitCast(comp_ctx->builder, shared_mem_addr, + int8_ptr_type, "shared_mem_addr_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } /* aot_inst->memories[0] */ - if (!(shared_mem_addr = - LLVMBuildLoad(comp_ctx->builder, - shared_mem_addr, "shared_mem_addr"))) { + if (!(shared_mem_addr = LLVMBuildLoad( + comp_ctx->builder, shared_mem_addr, "shared_mem_addr"))) { aot_set_last_error("llvm build load failed"); return false; } if (!(shared_mem_addr = - LLVMBuildBitCast(comp_ctx->builder, - shared_mem_addr, int8_ptr_type, - "shared_mem_addr_ptr"))) { + LLVMBuildBitCast(comp_ctx->builder, shared_mem_addr, + int8_ptr_type, "shared_mem_addr_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } - if (!(shared_mem_addr = - LLVMBuildLoad(comp_ctx->builder, - shared_mem_addr, "shared_mem_addr"))) { + if (!(shared_mem_addr = LLVMBuildLoad( + comp_ctx->builder, shared_mem_addr, "shared_mem_addr"))) { aot_set_last_error("llvm build load failed"); return false; } offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data.ptr)); if (!(func_ctx->mem_info[0].mem_base_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, shared_mem_addr, - &offset, 1, "mem_base_addr_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, shared_mem_addr, + &offset, 1, "mem_base_addr_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } offset = I32_CONST(offsetof(AOTMemoryInstance, cur_page_count)); if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, shared_mem_addr, - &offset, 1, "mem_cur_page_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, shared_mem_addr, + &offset, 1, "mem_cur_page_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data_size)); if (!(func_ctx->mem_info[0].mem_data_size_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, shared_mem_addr, - &offset, 1, "mem_data_size_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, shared_mem_addr, + &offset, 1, "mem_data_size_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } @@ -278,24 +283,24 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data) + offsetof(AOTMemoryInstance, memory_data.ptr)); if (!(func_ctx->mem_info[0].mem_base_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, - &offset, 1, "mem_base_addr_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "mem_base_addr_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data) + offsetof(AOTMemoryInstance, cur_page_count)); if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, - &offset, 1, "mem_cur_page_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "mem_cur_page_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data) + offsetof(AOTMemoryInstance, memory_data_size)); if (!(func_ctx->mem_info[0].mem_data_size_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, - &offset, 1, "mem_data_size_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "mem_data_size_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } @@ -303,46 +308,41 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Store mem info base address before cast */ mem_info_base = func_ctx->mem_info[0].mem_base_addr; - if (!(func_ctx->mem_info[0].mem_base_addr = - LLVMBuildBitCast(comp_ctx->builder, - func_ctx->mem_info[0].mem_base_addr, - int8_ptr_type, "mem_base_addr_ptr"))) { + if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_base_addr, + int8_ptr_type, "mem_base_addr_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } - if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = - LLVMBuildBitCast(comp_ctx->builder, - func_ctx->mem_info[0].mem_cur_page_count_addr, - INT32_PTR_TYPE, "mem_cur_page_ptr"))) { + if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_cur_page_count_addr, + INT32_PTR_TYPE, "mem_cur_page_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } - if (!(func_ctx->mem_info[0].mem_data_size_addr = - LLVMBuildBitCast(comp_ctx->builder, - func_ctx->mem_info[0].mem_data_size_addr, - INT32_PTR_TYPE, "mem_data_size_ptr"))) { + if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_data_size_addr, + INT32_PTR_TYPE, "mem_data_size_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } if (mem_space_unchanged) { - if (!(func_ctx->mem_info[0].mem_base_addr = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_base_addr, - "mem_base_addr"))) { + if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildLoad( + comp_ctx->builder, func_ctx->mem_info[0].mem_base_addr, + "mem_base_addr"))) { aot_set_last_error("llvm build load failed"); return false; } if (!(func_ctx->mem_info[0].mem_cur_page_count_addr = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_cur_page_count_addr, - "mem_cur_page_count"))) { + LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_info[0].mem_cur_page_count_addr, + "mem_cur_page_count"))) { aot_set_last_error("llvm build load failed"); return false; } - if (!(func_ctx->mem_info[0].mem_data_size_addr = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_data_size_addr, - "mem_data_size"))) { + if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildLoad( + comp_ctx->builder, func_ctx->mem_info[0].mem_data_size_addr, + "mem_data_size"))) { aot_set_last_error("llvm build load failed"); return false; } @@ -351,10 +351,9 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, else if (is_shared_memory) { /* The base address for shared memory will never changed, we can load the value here */ - if (!(func_ctx->mem_info[0].mem_base_addr = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_base_addr, - "mem_base_addr"))) { + if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildLoad( + comp_ctx->builder, func_ctx->mem_info[0].mem_base_addr, + "mem_base_addr"))) { aot_set_last_error("llvm build load failed"); return false; } @@ -362,29 +361,29 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, #endif bound_check_type = (comp_ctx->pointer_size == sizeof(uint64)) - ? INT64_PTR_TYPE : INT32_PTR_TYPE; + ? INT64_PTR_TYPE + : INT32_PTR_TYPE; /* Load memory bound check constants */ offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_1byte) - offsetof(AOTMemoryInstance, memory_data.ptr)); if (!(func_ctx->mem_info[0].mem_bound_check_1byte = - LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base, - &offset, 1, "bound_check_1byte_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base, &offset, 1, + "bound_check_1byte_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } - if (!(func_ctx->mem_info[0].mem_bound_check_1byte = - LLVMBuildBitCast(comp_ctx->builder, - func_ctx->mem_info[0].mem_bound_check_1byte, - bound_check_type, "bound_check_1byte_ptr"))) { + if (!(func_ctx->mem_info[0].mem_bound_check_1byte = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_1byte, + bound_check_type, "bound_check_1byte_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } if (mem_space_unchanged) { if (!(func_ctx->mem_info[0].mem_bound_check_1byte = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_bound_check_1byte, - "bound_check_1byte"))) { + LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_info[0].mem_bound_check_1byte, + "bound_check_1byte"))) { aot_set_last_error("llvm build load failed"); return false; } @@ -393,23 +392,22 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_2bytes) - offsetof(AOTMemoryInstance, memory_data.ptr)); if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = - LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base, - &offset, 1, "bound_check_2bytes_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base, &offset, 1, + "bound_check_2bytes_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } - if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = - LLVMBuildBitCast(comp_ctx->builder, - func_ctx->mem_info[0].mem_bound_check_2bytes, - bound_check_type, "bound_check_2bytes_ptr"))) { + if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_2bytes, + bound_check_type, "bound_check_2bytes_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } if (mem_space_unchanged) { if (!(func_ctx->mem_info[0].mem_bound_check_2bytes = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_bound_check_2bytes, - "bound_check_2bytes"))) { + LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_info[0].mem_bound_check_2bytes, + "bound_check_2bytes"))) { aot_set_last_error("llvm build load failed"); return false; } @@ -418,23 +416,22 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_4bytes) - offsetof(AOTMemoryInstance, memory_data.ptr)); if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = - LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base, - &offset, 1, "bound_check_4bytes_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base, &offset, 1, + "bound_check_4bytes_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } - if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = - LLVMBuildBitCast(comp_ctx->builder, - func_ctx->mem_info[0].mem_bound_check_4bytes, - bound_check_type, "bound_check_4bytes_ptr"))) { + if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_4bytes, + bound_check_type, "bound_check_4bytes_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } if (mem_space_unchanged) { if (!(func_ctx->mem_info[0].mem_bound_check_4bytes = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_bound_check_4bytes, - "bound_check_4bytes"))) { + LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_info[0].mem_bound_check_4bytes, + "bound_check_4bytes"))) { aot_set_last_error("llvm build load failed"); return false; } @@ -443,23 +440,22 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_8bytes) - offsetof(AOTMemoryInstance, memory_data.ptr)); if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = - LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base, - &offset, 1, "bound_check_8bytes_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base, &offset, 1, + "bound_check_8bytes_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } - if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = - LLVMBuildBitCast(comp_ctx->builder, - func_ctx->mem_info[0].mem_bound_check_8bytes, - bound_check_type, "bound_check_8bytes_ptr"))) { + if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_8bytes, + bound_check_type, "bound_check_8bytes_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } if (mem_space_unchanged) { if (!(func_ctx->mem_info[0].mem_bound_check_8bytes = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_bound_check_8bytes, - "bound_check_8bytes"))) { + LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_info[0].mem_bound_check_8bytes, + "bound_check_8bytes"))) { aot_set_last_error("llvm build load failed"); return false; } @@ -468,23 +464,22 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_16bytes) - offsetof(AOTMemoryInstance, memory_data.ptr)); if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = - LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base, - &offset, 1, "bound_check_16bytes_offset"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, mem_info_base, &offset, 1, + "bound_check_16bytes_offset"))) { aot_set_last_error("llvm build in bounds gep failed"); return false; } - if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = - LLVMBuildBitCast(comp_ctx->builder, - func_ctx->mem_info[0].mem_bound_check_16bytes, - bound_check_type, "bound_check_16bytes_ptr"))) { + if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildBitCast( + comp_ctx->builder, func_ctx->mem_info[0].mem_bound_check_16bytes, + bound_check_type, "bound_check_16bytes_ptr"))) { aot_set_last_error("llvm build bit cast failed"); return false; } if (mem_space_unchanged) { if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = - LLVMBuildLoad(comp_ctx->builder, - func_ctx->mem_info[0].mem_bound_check_16bytes, - "bound_check_16bytes"))) { + LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_info[0].mem_bound_check_16bytes, + "bound_check_16bytes"))) { aot_set_last_error("llvm build load failed"); return false; } @@ -499,10 +494,8 @@ create_cur_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) LLVMValueRef offset; offset = I32_CONST(offsetof(AOTModuleInstance, cur_exception)); - func_ctx->cur_exception = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->aot_inst, - &offset, 1, - "cur_execption"); + func_ctx->cur_exception = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->aot_inst, &offset, 1, "cur_execption"); if (!func_ctx->cur_exception) { aot_set_last_error("llvm build in bounds gep failed."); return false; @@ -511,17 +504,15 @@ create_cur_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) } static bool -create_func_type_indexes(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx) +create_func_type_indexes(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { LLVMValueRef offset, func_type_indexes_ptr; LLVMTypeRef int32_ptr_type; offset = I32_CONST(offsetof(AOTModuleInstance, func_type_indexes.ptr)); - func_type_indexes_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->aot_inst, - &offset, 1, - "func_type_indexes_ptr"); + func_type_indexes_ptr = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, &offset, 1, + "func_type_indexes_ptr"); if (!func_type_indexes_ptr) { aot_set_last_error("llvm build add failed."); return false; @@ -532,18 +523,16 @@ create_func_type_indexes(AOTCompContext *comp_ctx, return false; } - func_ctx->func_type_indexes = LLVMBuildBitCast(comp_ctx->builder, - func_type_indexes_ptr, - int32_ptr_type, - "func_type_indexes_tmp"); + func_ctx->func_type_indexes = + LLVMBuildBitCast(comp_ctx->builder, func_type_indexes_ptr, + int32_ptr_type, "func_type_indexes_tmp"); if (!func_ctx->func_type_indexes) { aot_set_last_error("llvm build bit cast failed."); return false; } - func_ctx->func_type_indexes = LLVMBuildLoad(comp_ctx->builder, - func_ctx->func_type_indexes, - "func_type_indexes"); + func_ctx->func_type_indexes = LLVMBuildLoad( + comp_ctx->builder, func_ctx->func_type_indexes, "func_type_indexes"); if (!func_ctx->func_type_indexes) { aot_set_last_error("llvm build load failed."); return false; @@ -557,29 +546,30 @@ create_func_ptrs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) LLVMValueRef offset; offset = I32_CONST(offsetof(AOTModuleInstance, func_ptrs)); - func_ctx->func_ptrs = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->aot_inst, - &offset, 1, "func_ptrs_offset"); + func_ctx->func_ptrs = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->aot_inst, &offset, 1, "func_ptrs_offset"); if (!func_ctx->func_ptrs) { aot_set_last_error("llvm build in bounds gep failed."); return false; } - func_ctx->func_ptrs = LLVMBuildBitCast(comp_ctx->builder, func_ctx->func_ptrs, - comp_ctx->exec_env_type, "func_ptrs_tmp"); + func_ctx->func_ptrs = + LLVMBuildBitCast(comp_ctx->builder, func_ctx->func_ptrs, + comp_ctx->exec_env_type, "func_ptrs_tmp"); if (!func_ctx->func_ptrs) { aot_set_last_error("llvm build bit cast failed."); return false; } - func_ctx->func_ptrs = LLVMBuildLoad(comp_ctx->builder, func_ctx->func_ptrs, - "func_ptrs_ptr"); + func_ctx->func_ptrs = + LLVMBuildLoad(comp_ctx->builder, func_ctx->func_ptrs, "func_ptrs_ptr"); if (!func_ctx->func_ptrs) { aot_set_last_error("llvm build load failed."); return false; } - func_ctx->func_ptrs = LLVMBuildBitCast(comp_ctx->builder, func_ctx->func_ptrs, - comp_ctx->exec_env_type, "func_ptrs"); + func_ctx->func_ptrs = + LLVMBuildBitCast(comp_ctx->builder, func_ctx->func_ptrs, + comp_ctx->exec_env_type, "func_ptrs"); if (!func_ctx->func_ptrs) { aot_set_last_error("llvm build bit cast failed."); return false; @@ -604,15 +594,16 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, LLVMValueRef stack_bound_offset = I32_FOUR, stack_bound_addr; LLVMValueRef aux_stack_bound_offset = I32_SIX, aux_stack_bound_addr; LLVMValueRef aux_stack_bottom_offset = I32_SEVEN, aux_stack_bottom_addr; + LLVMValueRef native_symbol_offset = I32_EIGHT, native_symbol_addr; char local_name[32]; uint64 size; uint32 i, j = 0; /* Allocate memory for the function context */ - size = offsetof(AOTFuncContext, locals) + sizeof(LLVMValueRef) * - ((uint64)aot_func_type->param_count + func->local_count); - if (size >= UINT32_MAX - || !(func_ctx = wasm_runtime_malloc((uint32)size))) { + size = offsetof(AOTFuncContext, locals) + + sizeof(LLVMValueRef) + * ((uint64)aot_func_type->param_count + func->local_count); + if (size >= UINT32_MAX || !(func_ctx = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); return NULL; } @@ -621,14 +612,19 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, func_ctx->aot_func = func; /* Add LLVM function */ - if (!(func_ctx->func = aot_add_llvm_func(comp_ctx, aot_func_type, func_index))) + if (!(func_ctx->func = aot_add_llvm_func(comp_ctx, aot_func_type, + func_index, &func_ctx->func_type))) goto fail; /* Create function's first AOTBlock */ - if (!(aot_block = aot_create_func_block(comp_ctx, func_ctx, - func, aot_func_type))) + if (!(aot_block = + aot_create_func_block(comp_ctx, func_ctx, func, aot_func_type))) goto fail; +#if WASM_ENABLE_DEBUG_AOT != 0 + func_ctx->debug_func = dwarf_gen_func_info(comp_ctx, func_ctx); +#endif + aot_block_stack_push(&func_ctx->block_stack, aot_block); /* Add local variables */ @@ -640,23 +636,23 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, /* Get aot inst address, the layout of exec_env is: exec_env->next, exec_env->prev, exec_env->module_inst, and argv_buf */ if (!(aot_inst_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, - &aot_inst_offset, 1, "aot_inst_addr"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, + &aot_inst_offset, 1, "aot_inst_addr"))) { aot_set_last_error("llvm build in bounds gep failed"); goto fail; } /* Load aot inst */ - if (!(func_ctx->aot_inst = LLVMBuildLoad(comp_ctx->builder, - aot_inst_addr, "aot_inst"))) { + if (!(func_ctx->aot_inst = + LLVMBuildLoad(comp_ctx->builder, aot_inst_addr, "aot_inst"))) { aot_set_last_error("llvm build load failed"); goto fail; } /* Get argv buffer address */ if (!(argv_buf_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, - &argv_buf_offset, 1, "argv_buf_addr"))) { + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, + &argv_buf_offset, 1, "argv_buf_addr"))) { aot_set_last_error("llvm build in bounds gep failed"); goto fail; } @@ -673,86 +669,97 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, goto fail; } - if (!(func_ctx->argv_buf = LLVMBuildLoad(comp_ctx->builder, - argv_buf_addr, "argv_buf"))) { + if (!(func_ctx->argv_buf = + LLVMBuildLoad(comp_ctx->builder, argv_buf_addr, "argv_buf"))) { aot_set_last_error("llvm build load failed"); goto fail; } /* Get native stack boundary address */ - if (!(stack_bound_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, - &stack_bound_offset, 1, "stack_bound_addr"))) { + if (!(stack_bound_addr = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->exec_env, &stack_bound_offset, 1, + "stack_bound_addr"))) { aot_set_last_error("llvm build in bounds gep failed"); goto fail; } - if (!(func_ctx->native_stack_bound = - LLVMBuildLoad(comp_ctx->builder, - stack_bound_addr, "native_stack_bound"))) { + if (!(func_ctx->native_stack_bound = LLVMBuildLoad( + comp_ctx->builder, stack_bound_addr, "native_stack_bound"))) { aot_set_last_error("llvm build load failed"); goto fail; } /* Get aux stack boundary address */ - if (!(aux_stack_bound_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, - &aux_stack_bound_offset, 1, - "aux_stack_bound_addr"))) { + if (!(aux_stack_bound_addr = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->exec_env, &aux_stack_bound_offset, 1, + "aux_stack_bound_addr"))) { aot_set_last_error("llvm build in bounds gep failed"); goto fail; } if (!(aux_stack_bound_addr = - LLVMBuildBitCast(comp_ctx->builder, - aux_stack_bound_addr, - INT32_PTR_TYPE, "aux_stack_bound_ptr"))) { + LLVMBuildBitCast(comp_ctx->builder, aux_stack_bound_addr, + INT32_PTR_TYPE, "aux_stack_bound_ptr"))) { aot_set_last_error("llvm build bit cast failed"); goto fail; } - if (!(func_ctx->aux_stack_bound = - LLVMBuildLoad(comp_ctx->builder, - aux_stack_bound_addr, "aux_stack_bound"))) { + if (!(func_ctx->aux_stack_bound = LLVMBuildLoad( + comp_ctx->builder, aux_stack_bound_addr, "aux_stack_bound"))) { aot_set_last_error("llvm build load failed"); goto fail; } /* Get aux stack bottom address */ - if (!(aux_stack_bottom_addr = - LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, - &aux_stack_bottom_offset, 1, - "aux_stack_bottom_addr"))) { + if (!(aux_stack_bottom_addr = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->exec_env, &aux_stack_bottom_offset, + 1, "aux_stack_bottom_addr"))) { aot_set_last_error("llvm build in bounds gep failed"); goto fail; } if (!(aux_stack_bottom_addr = - LLVMBuildBitCast(comp_ctx->builder, - aux_stack_bottom_addr, - INT32_PTR_TYPE, "aux_stack_bottom_ptr"))) { + LLVMBuildBitCast(comp_ctx->builder, aux_stack_bottom_addr, + INT32_PTR_TYPE, "aux_stack_bottom_ptr"))) { aot_set_last_error("llvm build bit cast failed"); goto fail; } - if (!(func_ctx->aux_stack_bottom = - LLVMBuildLoad(comp_ctx->builder, - aux_stack_bottom_addr, "aux_stack_bottom"))) { + if (!(func_ctx->aux_stack_bottom = LLVMBuildLoad( + comp_ctx->builder, aux_stack_bottom_addr, "aux_stack_bottom"))) { aot_set_last_error("llvm build load failed"); goto fail; } + if (!(native_symbol_addr = LLVMBuildInBoundsGEP( + comp_ctx->builder, func_ctx->exec_env, &native_symbol_offset, 1, + "native_symbol_addr"))) { + aot_set_last_error("llvm build in bounds gep failed"); + goto fail; + } + + if (!(func_ctx->native_symbol = LLVMBuildLoad( + comp_ctx->builder, native_symbol_addr, "native_symbol_tmp"))) { + aot_set_last_error("llvm build bit cast failed"); + goto fail; + } + + if (!(func_ctx->native_symbol = + LLVMBuildBitCast(comp_ctx->builder, func_ctx->native_symbol, + comp_ctx->exec_env_type, "native_symbol"))) { + aot_set_last_error("llvm build bit cast failed"); + goto fail; + } + for (i = 0; i < aot_func_type->param_count; i++, j++) { snprintf(local_name, sizeof(local_name), "l%d", i); func_ctx->locals[i] = LLVMBuildAlloca(comp_ctx->builder, - TO_LLVM_TYPE(aot_func_type->types[i]), - local_name); + TO_LLVM_TYPE(aot_func_type->types[i]), local_name); if (!func_ctx->locals[i]) { aot_set_last_error("llvm build alloca failed."); goto fail; } - if (!LLVMBuildStore(comp_ctx->builder, - LLVMGetParam(func_ctx->func, j), + if (!LLVMBuildStore(comp_ctx->builder, LLVMGetParam(func_ctx->func, j), func_ctx->locals[i])) { aot_set_last_error("llvm build store failed."); goto fail; @@ -785,7 +792,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, local_value = F64_ZERO; break; case VALUE_TYPE_V128: - local_value = V128_ZERO; + local_value = V128_i64x2_ZERO; break; case VALUE_TYPE_FUNCREF: case VALUE_TYPE_EXTERNREF: @@ -803,18 +810,19 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, } if (aot_func_type->param_count + func->local_count > 0) { - func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count - + func->local_count - 1]; + func_ctx->last_alloca = + func_ctx + ->locals[aot_func_type->param_count + func->local_count - 1]; if (!(func_ctx->last_alloca = - LLVMBuildBitCast(comp_ctx->builder, func_ctx->last_alloca, - INT8_PTR_TYPE, "stack_ptr"))) { + LLVMBuildBitCast(comp_ctx->builder, func_ctx->last_alloca, + INT8_PTR_TYPE, "stack_ptr"))) { aot_set_last_error("llvm build bit cast failed."); goto fail; } } else { - if (!(func_ctx->last_alloca = LLVMBuildAlloca(comp_ctx->builder, INT8_TYPE, - "stack_ptr"))) { + if (!(func_ctx->last_alloca = + LLVMBuildAlloca(comp_ctx->builder, INT8_TYPE, "stack_ptr"))) { aot_set_last_error("llvm build alloca failed."); goto fail; } @@ -878,7 +886,7 @@ aot_create_func_contexts(AOTCompData *comp_data, AOTCompContext *comp_ctx) uint32 i; /* Allocate memory */ - size = sizeof(AOTFuncContext*) * (uint64)comp_data->func_count; + size = sizeof(AOTFuncContext *) * (uint64)comp_data->func_count; if (size >= UINT32_MAX || !(func_ctxes = wasm_runtime_malloc((uint32)size))) { aot_set_last_error("allocate memory failed."); @@ -890,8 +898,8 @@ aot_create_func_contexts(AOTCompData *comp_data, AOTCompContext *comp_ctx) /* Create each function context */ for (i = 0; i < comp_data->func_count; i++) { AOTFunc *func = comp_data->funcs[i]; - if (!(func_ctxes[i] = aot_create_func_context(comp_data, comp_ctx, - func, i))) { + if (!(func_ctxes[i] = + aot_create_func_context(comp_data, comp_ctx, func, i))) { aot_destroy_func_contexts(func_ctxes, comp_data->func_count); return NULL; } @@ -918,14 +926,16 @@ aot_set_llvm_basic_types(AOTLLVMTypes *basic_types, LLVMContextRef context) if (basic_types->int8_ptr_type) { basic_types->int8_pptr_type = - LLVMPointerType(basic_types->int8_ptr_type, 0); + LLVMPointerType(basic_types->int8_ptr_type, 0); } basic_types->int16_ptr_type = LLVMPointerType(basic_types->int16_type, 0); basic_types->int32_ptr_type = LLVMPointerType(basic_types->int32_type, 0); basic_types->int64_ptr_type = LLVMPointerType(basic_types->int64_type, 0); - basic_types->float32_ptr_type = LLVMPointerType(basic_types->float32_type, 0); - basic_types->float64_ptr_type = LLVMPointerType(basic_types->float64_type, 0); + basic_types->float32_ptr_type = + LLVMPointerType(basic_types->float32_type, 0); + basic_types->float64_ptr_type = + LLVMPointerType(basic_types->float64_type, 0); basic_types->i8x16_vec_type = LLVMVectorType(basic_types->int8_type, 16); basic_types->i16x8_vec_type = LLVMVectorType(basic_types->int16_type, 8); @@ -937,97 +947,110 @@ aot_set_llvm_basic_types(AOTLLVMTypes *basic_types, LLVMContextRef context) basic_types->v128_type = basic_types->i64x2_vec_type; basic_types->v128_ptr_type = LLVMPointerType(basic_types->v128_type, 0); + basic_types->i1x2_vec_type = LLVMVectorType(basic_types->int1_type, 2); + basic_types->funcref_type = LLVMInt32TypeInContext(context); basic_types->externref_type = LLVMInt32TypeInContext(context); - return (basic_types->int8_ptr_type - && basic_types->int8_pptr_type - && basic_types->int16_ptr_type - && basic_types->int32_ptr_type - && basic_types->int64_ptr_type - && basic_types->float32_ptr_type - && basic_types->float64_ptr_type - && basic_types->i8x16_vec_type - && basic_types->i16x8_vec_type - && basic_types->i32x4_vec_type - && basic_types->i64x2_vec_type - && basic_types->f32x4_vec_type - && basic_types->f64x2_vec_type - && basic_types->meta_data_type - && basic_types->funcref_type - && basic_types->externref_type) ? true : false; + return (basic_types->int8_ptr_type && basic_types->int8_pptr_type + && basic_types->int16_ptr_type && basic_types->int32_ptr_type + && basic_types->int64_ptr_type && basic_types->float32_ptr_type + && basic_types->float64_ptr_type && basic_types->i8x16_vec_type + && basic_types->i16x8_vec_type && basic_types->i32x4_vec_type + && basic_types->i64x2_vec_type && basic_types->f32x4_vec_type + && basic_types->f64x2_vec_type && basic_types->i1x2_vec_type + && basic_types->meta_data_type && basic_types->funcref_type + && basic_types->externref_type) + ? true + : false; } static bool aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx) { - LLVMValueRef i64_consts[2]; - - consts->i8_zero = I8_CONST(0); - consts->i32_zero = I32_CONST(0); - consts->i64_zero = I64_CONST(0); - consts->f32_zero = F32_CONST(0); - consts->f64_zero = F64_CONST(0); - - if (consts->i64_zero) { - i64_consts[0] = i64_consts[1] = consts->i64_zero; - consts->v128_zero = consts->i64x2_vec_zero = - LLVMConstVector(i64_consts, 2); - if (consts->i64x2_vec_zero) { - consts->i8x16_vec_zero = TO_V128_i8x16(consts->i64x2_vec_zero); - consts->i16x8_vec_zero = TO_V128_i16x8(consts->i64x2_vec_zero); - consts->i32x4_vec_zero = TO_V128_i32x4(consts->i64x2_vec_zero); - consts->f32x4_vec_zero = TO_V128_f32x4(consts->i64x2_vec_zero); - consts->f64x2_vec_zero = TO_V128_f64x2(consts->i64x2_vec_zero); - } - } - - consts->i32_one = I32_CONST(1); - consts->i32_two = I32_CONST(2); - consts->i32_three = I32_CONST(3); - consts->i32_four = I32_CONST(4); - consts->i32_five = I32_CONST(5); - consts->i32_six = I32_CONST(6); - consts->i32_seven = I32_CONST(7); - consts->i32_eight = I32_CONST(8); - consts->i32_neg_one = I32_CONST((uint32)-1); - consts->i64_neg_one = I64_CONST((uint64)-1); - consts->i32_min = I32_CONST((uint32)INT32_MIN); - consts->i64_min = I64_CONST((uint64)INT64_MIN); - consts->i32_31 = I32_CONST(31); - consts->i32_32 = I32_CONST(32); - consts->i64_63 = I64_CONST(63); - consts->i64_64 = I64_CONST(64); - consts->ref_null = I32_CONST(NULL_REF); - - return (consts->i8_zero - && consts->i32_zero - && consts->i64_zero - && consts->f32_zero - && consts->f64_zero - && consts->i8x16_vec_zero - && consts->i16x8_vec_zero - && consts->i32x4_vec_zero - && consts->i64x2_vec_zero - && consts->f32x4_vec_zero - && consts->f64x2_vec_zero - && consts->i32_one - && consts->i32_two - && consts->i32_three - && consts->i32_four - && consts->i32_five - && consts->i32_six - && consts->i32_seven - && consts->i32_eight - && consts->i32_neg_one - && consts->i64_neg_one - && consts->i32_min - && consts->i64_min - && consts->i32_31 - && consts->i32_32 - && consts->i64_63 - && consts->i64_64 - && consts->ref_null) ? true : false; +#define CREATE_I1_CONST(name, value) \ + if (!(consts->i1_##name = \ + LLVMConstInt(comp_ctx->basic_types.int1_type, value, true))) \ + return false; + + CREATE_I1_CONST(zero, 0) + CREATE_I1_CONST(one, 1) +#undef CREATE_I1_CONST + + if (!(consts->i8_zero = I8_CONST(0))) + return false; + + if (!(consts->f32_zero = F32_CONST(0))) + return false; + + if (!(consts->f64_zero = F64_CONST(0))) + return false; + +#define CREATE_I32_CONST(name, value) \ + if (!(consts->i32_##name = LLVMConstInt(I32_TYPE, value, true))) \ + return false; + + CREATE_I32_CONST(min, (uint32)INT32_MIN) + CREATE_I32_CONST(neg_one, (uint32)-1) + CREATE_I32_CONST(zero, 0) + CREATE_I32_CONST(one, 1) + CREATE_I32_CONST(two, 2) + CREATE_I32_CONST(three, 3) + CREATE_I32_CONST(four, 4) + CREATE_I32_CONST(five, 5) + CREATE_I32_CONST(six, 6) + CREATE_I32_CONST(seven, 7) + CREATE_I32_CONST(eight, 8) + CREATE_I32_CONST(nine, 9) + CREATE_I32_CONST(ten, 10) + CREATE_I32_CONST(eleven, 11) + CREATE_I32_CONST(twelve, 12) + CREATE_I32_CONST(thirteen, 13) + CREATE_I32_CONST(fourteen, 14) + CREATE_I32_CONST(fifteen, 15) + CREATE_I32_CONST(31, 31) + CREATE_I32_CONST(32, 32) +#undef CREATE_I32_CONST + +#define CREATE_I64_CONST(name, value) \ + if (!(consts->i64_##name = LLVMConstInt(I64_TYPE, value, true))) \ + return false; + + CREATE_I64_CONST(min, (uint64)INT64_MIN) + CREATE_I64_CONST(neg_one, (uint64)-1) + CREATE_I64_CONST(zero, 0) + CREATE_I64_CONST(63, 63) + CREATE_I64_CONST(64, 64) +#undef CREATE_I64_CONST + +#define CREATE_V128_CONST(name, type) \ + if (!(consts->name##_vec_zero = LLVMConstNull(type))) \ + return false; \ + if (!(consts->name##_undef = LLVMGetUndef(type))) \ + return false; + + CREATE_V128_CONST(i8x16, V128_i8x16_TYPE) + CREATE_V128_CONST(i16x8, V128_i16x8_TYPE) + CREATE_V128_CONST(i32x4, V128_i32x4_TYPE) + CREATE_V128_CONST(i64x2, V128_i64x2_TYPE) + CREATE_V128_CONST(f32x4, V128_f32x4_TYPE) + CREATE_V128_CONST(f64x2, V128_f64x2_TYPE) +#undef CREATE_V128_CONST + +#define CREATE_VEC_ZERO_MASK(slot) \ + { \ + LLVMTypeRef type = LLVMVectorType(I32_TYPE, slot); \ + if (!type || !(consts->i32x##slot##_zero = LLVMConstNull(type))) \ + return false; \ + } + + CREATE_VEC_ZERO_MASK(16) + CREATE_VEC_ZERO_MASK(8) + CREATE_VEC_ZERO_MASK(4) + CREATE_VEC_ZERO_MASK(2) +#undef CREATE_VEC_ZERO_MASK + + return true; } typedef struct ArchItem { @@ -1035,10 +1058,11 @@ typedef struct ArchItem { bool support_eb; } ArchItem; +/* clang-format off */ static ArchItem valid_archs[] = { { "x86_64", false }, { "i386", false }, - { "xtensa", false}, + { "xtensa", false }, { "mips", true }, { "aarch64v8", false }, { "aarch64v8.1", false }, @@ -1046,7 +1070,7 @@ static ArchItem valid_archs[] = { { "aarch64v8.3", false }, { "aarch64v8.4", false }, { "aarch64v8.5", false }, - { "aarch64_bev8", false }, /* big endian */ + { "aarch64_bev8", false }, /* big endian */ { "aarch64_bev8.1", false }, { "aarch64_bev8.2", false }, { "aarch64_bev8.3", false }, @@ -1087,15 +1111,25 @@ static ArchItem valid_archs[] = { { "thumbv8r", true }, { "thumbv8m.base", true }, { "thumbv8m.main", true }, - { "thumbv8.1m.main", true } + { "thumbv8.1m.main", true }, + { "riscv32", true }, + { "riscv64", true }, + { "arc", true } }; static const char *valid_abis[] = { "gnu", "eabi", "gnueabihf", - "msvc" + "msvc", + "ilp32", + "ilp32f", + "ilp32d", + "lp64", + "lp64f", + "lp64d" }; +/* clang-format on */ static void print_supported_targets() @@ -1132,8 +1166,9 @@ check_target_arch(const char *target_arch) support_eb = valid_archs[i].support_eb; if (!strncmp(target_arch, arch, strlen(arch)) - && ((support_eb && (!strcmp(target_arch + strlen(arch), "eb") - || !strcmp(target_arch + strlen(arch), ""))) + && ((support_eb + && (!strcmp(target_arch + strlen(arch), "eb") + || !strcmp(target_arch + strlen(arch), ""))) || (!support_eb && !strcmp(target_arch + strlen(arch), "")))) { return true; } @@ -1152,7 +1187,6 @@ check_target_abi(const char *target_abi) return false; } - static void get_target_arch_from_triple(const char *triple, char *arch_buf, uint32 buf_size) { @@ -1167,34 +1201,195 @@ LLVMBool WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, struct LLVMMCJITCompilerOptions *Options, - size_t SizeOfOptions, - char **OutError); + size_t SizeOfOptions, char **OutError); + +void +LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); + +#if WASM_ENABLE_LAZY_JIT != 0 +void +aot_handle_llvm_errmsg(char *error_buf, uint32 error_buf_size, + const char *string, LLVMErrorRef error) +{ + char *err_msg = LLVMGetErrorMessage(error); + if (error_buf != NULL) { + snprintf(error_buf, error_buf_size, "%s: %s", string, err_msg); + } + LLVMDisposeErrorMessage(err_msg); +} + +static bool +llvm_orcjit_create(AOTCompContext *comp_ctx) +{ + char *err_msg = NULL; + char *cpu = NULL; + char *features = NULL; + char *llvm_triple = NULL; + char buf[128] = { 0 }; + + LLVMErrorRef error; + LLVMTargetRef llvm_targetref = NULL; + LLVMTargetMachineRef tm_opt = NULL; + LLVMTargetMachineRef tm_opt2 = NULL; + LLVMOrcLLLazyJITRef lazy_orcjit = NULL; + LLVMOrcJITTargetMachineBuilderRef tm_builder = NULL; + LLVMOrcLLLazyJITBuilderRef lazy_orcjit_builder = NULL; +#if LLVM_VERSION_MAJOR < 12 + LLVMOrcJITDylibDefinitionGeneratorRef main_gen = NULL; +#else + LLVMOrcDefinitionGeneratorRef main_gen = NULL; +#endif + + llvm_triple = LLVMGetDefaultTargetTriple(); + if (llvm_triple == NULL) { + snprintf(buf, sizeof(buf), "failed to get default target triple."); + goto fail; + } + + if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &err_msg) != 0) { + snprintf(buf, sizeof(buf), + "failed to get target reference from triple %s.", err_msg); + LLVMDisposeMessage(err_msg); + goto fail; + } + + if (!LLVMTargetHasJIT(llvm_targetref)) { + snprintf(buf, sizeof(buf), "unspported JIT on this platform."); + goto fail; + } + + cpu = LLVMGetHostCPUName(); + if (cpu == NULL) { + snprintf(buf, sizeof(buf), "failed to get host cpu information."); + goto fail; + } + + features = LLVMGetHostCPUFeatures(); + if (features == NULL) { + snprintf(buf, sizeof(buf), "failed to get host cpu features."); + goto fail; + } + + LOG_VERBOSE("LLVM ORCJIT detected CPU \"%s\", with features \"%s\"\n", cpu, + features); + + tm_opt = LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features, + LLVMCodeGenLevelAggressive, + LLVMRelocDefault, LLVMCodeModelJITDefault); + if (!tm_opt) { + snprintf(buf, sizeof(buf), "failed to create target machine."); + goto fail; + } + + tm_opt2 = LLVMCreateTargetMachine( + llvm_targetref, llvm_triple, cpu, features, LLVMCodeGenLevelAggressive, + LLVMRelocDefault, LLVMCodeModelJITDefault); + if (!tm_opt2) { + snprintf(buf, sizeof(buf), "failed to create target machine2."); + goto fail; + } + + /* if success, it will dispose tm_opt2 memory. */ + tm_builder = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm_opt2); + if (!tm_builder) { + snprintf(buf, sizeof(buf), "failed to create target machine builder."); + goto fail; + } + tm_opt2 = NULL; + + lazy_orcjit_builder = LLVMOrcCreateLLLazyJITBuilder(); + if (!lazy_orcjit_builder) { + snprintf(buf, sizeof(buf), "failed to create lazy jit builder."); + goto fail; + } + + LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(lazy_orcjit_builder, + tm_builder); + + /* if success, it will dispose lazy_orcjit_builder memory */ + error = LLVMOrcCreateLLLazyJIT(&lazy_orcjit, lazy_orcjit_builder); + if (error) { + aot_handle_llvm_errmsg(buf, sizeof(buf), + "failed to create llvm lazy orcjit instance", + error); + goto fail; + } + lazy_orcjit_builder = NULL; + + error = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess( + &main_gen, LLVMOrcLLLazyJITGetGlobalPrefix(lazy_orcjit), 0, NULL); + if (error) { + aot_handle_llvm_errmsg( + buf, sizeof(buf), + "failed to create dynmaic library search generator", error); + goto fail; + } + + LLVMOrcJITDylibAddGenerator(LLVMOrcLLLazyJITGetMainJITDylib(lazy_orcjit), + main_gen); + + comp_ctx->lazy_orcjit = lazy_orcjit; + comp_ctx->target_machine = tm_opt; + comp_ctx->tm_builder = tm_builder; + LLVMDisposeMessage(llvm_triple); + LLVMDisposeMessage(cpu); + LLVMDisposeMessage(features); + return true; -void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); +fail: + if (lazy_orcjit) + LLVMOrcDisposeLLLazyJIT(lazy_orcjit); + if (tm_builder) + LLVMOrcDisposeJITTargetMachineBuilder(tm_builder); + if (lazy_orcjit_builder) + LLVMOrcDisposeLLLazyJITBuilder(lazy_orcjit_builder); + if (tm_opt2) + LLVMDisposeTargetMachine(tm_opt2); + if (tm_opt) + LLVMDisposeTargetMachine(tm_opt); + if (features) + LLVMDisposeMessage(features); + if (cpu) + LLVMDisposeMessage(cpu); + if (llvm_triple) + LLVMDisposeMessage(llvm_triple); + aot_set_last_error(buf); + return false; +} +#endif /* WASM_ENABLE_LAZY_JIT != 0 */ AOTCompContext * -aot_create_comp_context(AOTCompData *comp_data, - aot_comp_option_t option) +aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) { AOTCompContext *comp_ctx, *ret = NULL; - /*LLVMTypeRef elem_types[8];*/ +#if WASM_ENABLE_LAZY_JIT == 0 struct LLVMMCJITCompilerOptions jit_options; +#endif + LLVMTargetRef target; char *triple = NULL, *triple_norm, *arch, *abi; char *cpu = NULL, *features, buf[128]; char *triple_norm_new = NULL, *cpu_new = NULL; - char *err = NULL, *fp_round= "round.tonearest", *fp_exce = "fpexcept.strict"; - char triple_buf[32] = {0}; + char *err = NULL, *fp_round = "round.tonearest", + *fp_exce = "fpexcept.strict"; + char triple_buf[32] = { 0 }, features_buf[128] = { 0 }; uint32 opt_level, size_level; LLVMCodeModel code_model; LLVMTargetDataRef target_data_ref; /* Initialize LLVM environment */ +#if WASM_ENABLE_LAZY_JIT != 0 + LLVMInitializeCore(LLVMGetGlobalPassRegistry()); + LLVMInitializeNativeTarget(); + LLVMInitializeNativeAsmPrinter(); + LLVMInitializeNativeAsmParser(); +#else LLVMInitializeAllTargetInfos(); LLVMInitializeAllTargets(); LLVMInitializeAllTargetMCs(); LLVMInitializeAllAsmPrinters(); LLVMLinkInMCJIT(); +#endif /* Allocate memory */ if (!(comp_ctx = wasm_runtime_malloc(sizeof(AOTCompContext)))) { @@ -1206,22 +1401,63 @@ aot_create_comp_context(AOTCompData *comp_data, comp_ctx->comp_data = comp_data; /* Create LLVM context, module and builder */ +#if WASM_ENABLE_LAZY_JIT != 0 + comp_ctx->ts_context = LLVMOrcCreateNewThreadSafeContext(); + if (!comp_ctx->ts_context) { + aot_set_last_error("create LLVM ThreadSafeContext failed."); + return NULL; + } + /* Get a reference to the underlying LLVMContext */ + if (!(comp_ctx->context = + LLVMOrcThreadSafeContextGetContext(comp_ctx->ts_context))) { + aot_set_last_error("get context from LLVM ThreadSafeContext failed."); + goto fail; + } +#else if (!(comp_ctx->context = LLVMContextCreate())) { aot_set_last_error("create LLVM context failed."); goto fail; } +#endif if (!(comp_ctx->builder = LLVMCreateBuilderInContext(comp_ctx->context))) { aot_set_last_error("create LLVM builder failed."); goto fail; } - if (!(comp_ctx->module = - LLVMModuleCreateWithNameInContext("WASM Module", comp_ctx->context))) { + if (!(comp_ctx->module = LLVMModuleCreateWithNameInContext( + "WASM Module", comp_ctx->context))) { aot_set_last_error("create LLVM module failed."); goto fail; } + if (BH_LIST_ERROR == bh_list_init(&comp_ctx->native_symbols)) { + goto fail; + } + +#if WASM_ENABLE_DEBUG_AOT != 0 + if (!(comp_ctx->debug_builder = LLVMCreateDIBuilder(comp_ctx->module))) { + aot_set_last_error("create LLVM Debug Infor builder failed."); + goto fail; + } + + LLVMAddModuleFlag( + comp_ctx->module, LLVMModuleFlagBehaviorWarning, "Debug Info Version", + strlen("Debug Info Version"), + LLVMValueAsMetadata(LLVMConstInt(LLVMInt32Type(), 3, false))); + + comp_ctx->debug_file = dwarf_gen_file_info(comp_ctx); + if (!comp_ctx->debug_file) { + aot_set_last_error("dwarf generate file info failed"); + goto fail; + } + comp_ctx->debug_comp_unit = dwarf_gen_comp_unit_info(comp_ctx); + if (!comp_ctx->debug_comp_unit) { + aot_set_last_error("dwarf generate compile unit info failed"); + goto fail; + } +#endif + if (option->enable_bulk_memory) comp_ctx->enable_bulk_memory = true; @@ -1240,17 +1476,32 @@ aot_create_comp_context(AOTCompData *comp_data, if (option->enable_aux_stack_check) comp_ctx->enable_aux_stack_check = true; + if (option->is_indirect_mode) + comp_ctx->is_indirect_mode = true; + + if (option->disable_llvm_intrinsics) + comp_ctx->disable_llvm_intrinsics = true; + if (option->is_jit_mode) { char *triple_jit = NULL; +#if WASM_ENABLE_LAZY_JIT != 0 + /* Create LLLazyJIT Instance */ + if (!llvm_orcjit_create(comp_ctx)) { + aot_set_last_error("create LLVM Lazy JIT Compiler failed."); + goto fail; + } + +#else /* Create LLVM execution engine */ LLVMInitializeMCJITCompilerOptions(&jit_options, sizeof(jit_options)); jit_options.OptLevel = LLVMCodeGenLevelAggressive; jit_options.EnableFastISel = true; /*jit_options.CodeModel = LLVMCodeModelSmall;*/ - if (WAMRCreateMCJITCompilerForModule - (&comp_ctx->exec_engine, comp_ctx->module, - &jit_options, sizeof(jit_options), &err) != 0) { + if (WAMRCreateMCJITCompilerForModule(&comp_ctx->exec_engine, + comp_ctx->module, &jit_options, + sizeof(jit_options), &err) + != 0) { if (err) { LLVMDisposeMessage(err); err = NULL; @@ -1258,17 +1509,30 @@ aot_create_comp_context(AOTCompData *comp_data, aot_set_last_error("create LLVM JIT compiler failed."); goto fail; } - comp_ctx->is_jit_mode = true; comp_ctx->target_machine = - LLVMGetExecutionEngineTargetMachine(comp_ctx->exec_engine); + LLVMGetExecutionEngineTargetMachine(comp_ctx->exec_engine); +#endif + comp_ctx->is_jit_mode = true; + #ifndef OS_ENABLE_HW_BOUND_CHECK comp_ctx->enable_bound_check = true; #else comp_ctx->enable_bound_check = false; #endif +#if WASM_ENABLE_LAZY_JIT != 0 + if (!(triple_jit = (char *)LLVMOrcLLLazyJITGetTripleString( + comp_ctx->lazy_orcjit))) { + aot_set_last_error("can not get triple from the target machine"); + goto fail; + } + + /* Save target arch */ + get_target_arch_from_triple(triple_jit, comp_ctx->target_arch, + sizeof(comp_ctx->target_arch)); +#else if (!(triple_jit = - LLVMGetTargetMachineTriple(comp_ctx->target_machine))) { + LLVMGetTargetMachineTriple(comp_ctx->target_machine))) { aot_set_last_error("can not get triple from the target machine"); goto fail; } @@ -1277,6 +1541,7 @@ aot_create_comp_context(AOTCompData *comp_data, get_target_arch_from_triple(triple_jit, comp_ctx->target_arch, sizeof(comp_ctx->target_arch)); LLVMDisposeMessage(triple_jit); +#endif } else { /* Create LLVM target machine */ @@ -1308,8 +1573,9 @@ aot_create_comp_context(AOTCompData *comp_data, if (!strcmp(arch, "help")) print_supported_targets(); else - aot_set_last_error("Invalid target. " - "Use --target=help to list all supported targets"); + aot_set_last_error( + "Invalid target. " + "Use --target=help to list all supported targets"); goto fail; } @@ -1318,11 +1584,20 @@ aot_create_comp_context(AOTCompData *comp_data, if (!strcmp(abi, "help")) print_supported_abis(); else - aot_set_last_error("Invalid target ABI. " - "Use --target-abi=help to list all supported ABI"); + aot_set_last_error( + "Invalid target ABI. " + "Use --target-abi=help to list all supported ABI"); goto fail; } + /* Set default abi for riscv target */ + if (arch && !strncmp(arch, "riscv", 5) && !abi) { + if (!strcmp(arch, "riscv64")) + abi = "lp64d"; + else + abi = "ilp32d"; + } + if (arch) { /* Construct target triple: --- */ const char *vendor_sys; @@ -1351,10 +1626,12 @@ aot_create_comp_context(AOTCompData *comp_data, LLVMDisposeMessage(default_triple); - bh_assert(strlen(arch) + strlen(vendor_sys) + strlen(abi) < sizeof(triple_buf)); + bh_assert(strlen(arch) + strlen(vendor_sys) + strlen(abi) + < sizeof(triple_buf)); memcpy(triple_buf, arch, strlen(arch)); memcpy(triple_buf + strlen(arch), vendor_sys, strlen(vendor_sys)); - memcpy(triple_buf + strlen(arch) + strlen(vendor_sys), abi, strlen(abi)); + memcpy(triple_buf + strlen(arch) + strlen(vendor_sys), abi, + strlen(abi)); triple = triple_buf; } @@ -1365,7 +1642,8 @@ aot_create_comp_context(AOTCompData *comp_data, if (!triple && !cpu) { /* Get a triple for the host machine */ - if (!(triple_norm = triple_norm_new = LLVMGetDefaultTargetTriple())) { + if (!(triple_norm = triple_norm_new = + LLVMGetDefaultTargetTriple())) { aot_set_last_error("llvm get default target triple failed."); goto fail; } @@ -1377,7 +1655,8 @@ aot_create_comp_context(AOTCompData *comp_data, } else if (triple) { /* Normalize a target triple */ - if (!(triple_norm = triple_norm_new = LLVMNormalizeTargetTriple(triple))) { + if (!(triple_norm = triple_norm_new = + LLVMNormalizeTargetTriple(triple))) { snprintf(buf, sizeof(buf), "llvm normlalize target triple (%s) failed.", triple); aot_set_last_error(buf); @@ -1388,12 +1667,36 @@ aot_create_comp_context(AOTCompData *comp_data, } else { /* triple is NULL, cpu isn't NULL */ - snprintf(buf, sizeof(buf), - "target isn't specified for cpu %s.", cpu); + snprintf(buf, sizeof(buf), "target isn't specified for cpu %s.", + cpu); aot_set_last_error(buf); goto fail; } + /* Add module flag and cpu feature for riscv target */ + if (arch && !strncmp(arch, "riscv", 5)) { + LLVMMetadataRef meta_target_abi; + + if (!(meta_target_abi = LLVMMDStringInContext2(comp_ctx->context, + abi, strlen(abi)))) { + aot_set_last_error("create metadata string failed."); + goto fail; + } + LLVMAddModuleFlag(comp_ctx->module, LLVMModuleFlagBehaviorError, + "target-abi", strlen("target-abi"), + meta_target_abi); + + if (!strcmp(abi, "lp64d") || !strcmp(abi, "ilp32d")) { + if (features) { + snprintf(features_buf, sizeof(features_buf), "%s%s", + features, ",+d"); + features = features_buf; + } + else + features = "+d"; + } + } + if (!features) features = ""; @@ -1421,7 +1724,8 @@ aot_create_comp_context(AOTCompData *comp_data, } else { /* Unset by user, use default value */ - if (strstr(comp_ctx->target_arch, "64") && !option->is_sgx_platform) { + if (strstr(comp_ctx->target_arch, "64") + && !option->is_sgx_platform) { comp_ctx->enable_bound_check = false; } else { @@ -1457,9 +1761,15 @@ aot_create_comp_context(AOTCompData *comp_data, goto fail; } - if (!LLVMTargetHasAsmBackend(target)) { - snprintf(buf, sizeof(buf), - "no asm backend for this target (%s).", LLVMGetTargetName(target)); + /* Report error if target isn't arc and hasn't asm backend. + For arc target, as it cannot emit to memory buffer of elf file + currently, we let it emit to assembly file instead, and then call + arc-gcc to compile + asm file to elf file, and read elf file to memory buffer. */ + if (strncmp(comp_ctx->target_arch, "arc", 3) + && !LLVMTargetHasAsmBackend(target)) { + snprintf(buf, sizeof(buf), "no asm backend for this target (%s).", + LLVMGetTargetName(target)); aot_set_last_error(buf); goto fail; } @@ -1475,17 +1785,15 @@ aot_create_comp_context(AOTCompData *comp_data, code_model = LLVMCodeModelSmall; /* Create the target machine */ - if (!(comp_ctx->target_machine = - LLVMCreateTargetMachine(target, triple_norm, cpu, features, - opt_level, LLVMRelocStatic, - code_model))) { + if (!(comp_ctx->target_machine = LLVMCreateTargetMachine( + target, triple_norm, cpu, features, opt_level, + LLVMRelocStatic, code_model))) { aot_set_last_error("create LLVM target machine failed."); goto fail; } } - if (option->enable_simd - && strcmp(comp_ctx->target_arch, "x86_64") != 0 + if (option->enable_simd && strcmp(comp_ctx->target_arch, "x86_64") != 0 && strncmp(comp_ctx->target_arch, "aarch64", 7) != 0) { /* Disable simd if it isn't supported by target arch */ option->enable_simd = false; @@ -1513,7 +1821,7 @@ aot_create_comp_context(AOTCompData *comp_data, } if (!(target_data_ref = - LLVMCreateTargetDataLayout(comp_ctx->target_machine))) { + LLVMCreateTargetDataLayout(comp_ctx->target_machine))) { aot_set_last_error("create LLVM target data layout failed."); goto fail; } @@ -1524,8 +1832,8 @@ aot_create_comp_context(AOTCompData *comp_data, if (option->output_format == AOT_LLVMIR_UNOPT_FILE) comp_ctx->optimize = false; - if (!(comp_ctx->pass_mgr = LLVMCreateFunctionPassManagerForModule - (comp_ctx->module))) { + if (!(comp_ctx->pass_mgr = + LLVMCreateFunctionPassManagerForModule(comp_ctx->module))) { aot_set_last_error("create LLVM pass manager failed."); goto fail; } @@ -1546,7 +1854,7 @@ aot_create_comp_context(AOTCompData *comp_data, LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr); if (!option->enable_thread_mgr) { /* These two passes may destroy the volatile semantics, - disable them when building as multi-thread mode */ + disable them when building as multi-thread mode */ LLVMAddGVNPass(comp_ctx->pass_mgr); LLVMAddLICMPass(comp_ctx->pass_mgr); } @@ -1557,14 +1865,10 @@ aot_create_comp_context(AOTCompData *comp_data, } /* Create metadata for llvm float experimental constrained intrinsics */ - if (!(comp_ctx->fp_rounding_mode = - LLVMMDStringInContext(comp_ctx->context, - fp_round, - (uint32)strlen(fp_round))) - || !(comp_ctx->fp_exception_behavior = - LLVMMDStringInContext(comp_ctx->context, - fp_exce, - (uint32)strlen(fp_exce)))) { + if (!(comp_ctx->fp_rounding_mode = LLVMMDStringInContext( + comp_ctx->context, fp_round, (uint32)strlen(fp_round))) + || !(comp_ctx->fp_exception_behavior = LLVMMDStringInContext( + comp_ctx->context, fp_exce, (uint32)strlen(fp_exce)))) { aot_set_last_error("create float llvm metadata failed."); goto fail; } @@ -1589,9 +1893,21 @@ aot_create_comp_context(AOTCompData *comp_data, comp_ctx->func_ctx_count = comp_data->func_count; if (comp_data->func_count > 0 && !(comp_ctx->func_ctxes = - aot_create_func_contexts(comp_data, comp_ctx))) + aot_create_func_contexts(comp_data, comp_ctx))) goto fail; + if (cpu) { + uint32 len = (uint32)strlen(cpu) + 1; + if (!(comp_ctx->target_cpu = wasm_runtime_malloc(len))) { + aot_set_last_error("allocate memory failed"); + goto fail; + } + bh_memcpy_s(comp_ctx->target_cpu, len, cpu, len); + } + + if (comp_ctx->disable_llvm_intrinsics) + aot_intrinsic_fill_capability_flags(comp_ctx); + ret = comp_ctx; fail: @@ -1613,9 +1929,29 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx) if (!comp_ctx) return; - if (comp_ctx->pass_mgr) + if (comp_ctx->pass_mgr) { + LLVMFinalizeFunctionPassManager(comp_ctx->pass_mgr); LLVMDisposePassManager(comp_ctx->pass_mgr); + } + +#if WASM_ENABLE_LAZY_JIT != 0 + if (comp_ctx->target_machine && comp_ctx->is_jit_mode) + LLVMDisposeTargetMachine(comp_ctx->target_machine); + + if (comp_ctx->builder) + LLVMDisposeBuilder(comp_ctx->builder); + + if (comp_ctx->lazy_orcjit) + LLVMOrcDisposeLLLazyJIT(comp_ctx->lazy_orcjit); + if (comp_ctx->ts_context) + LLVMOrcDisposeThreadSafeContext(comp_ctx->ts_context); + + if (comp_ctx->tm_builder) + LLVMOrcDisposeJITTargetMachineBuilder(comp_ctx->tm_builder); + + LLVMShutdown(); +#else if (comp_ctx->target_machine && !comp_ctx->is_jit_mode) LLVMDisposeTargetMachine(comp_ctx->target_machine); @@ -1632,14 +1968,71 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx) if (comp_ctx->context) LLVMContextDispose(comp_ctx->context); +#endif if (comp_ctx->func_ctxes) aot_destroy_func_contexts(comp_ctx->func_ctxes, comp_ctx->func_ctx_count); + if (bh_list_length(&comp_ctx->native_symbols) > 0) { + AOTNativeSymbol *sym = bh_list_first_elem(&comp_ctx->native_symbols); + while (sym) { + AOTNativeSymbol *t = bh_list_elem_next(sym); + bh_list_remove(&comp_ctx->native_symbols, sym); + wasm_runtime_free(sym); + sym = t; + } + } + + if (comp_ctx->target_cpu) { + wasm_runtime_free(comp_ctx->target_cpu); + } + wasm_runtime_free(comp_ctx); } +int32 +aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol) +{ + int32 idx = -1; + AOTNativeSymbol *sym = NULL; + + sym = bh_list_first_elem(&comp_ctx->native_symbols); + + /* Lookup an existing symobl record */ + + while (sym) { + if (strcmp(sym->symbol, symbol) == 0) { + idx = sym->index; + break; + } + sym = bh_list_elem_next(sym); + } + + /* Given symbol is not exist in list, then we alloc a new index for it */ + + if (idx < 0) { + sym = wasm_runtime_malloc(sizeof(AOTNativeSymbol)); + + if (!sym) { + aot_set_last_error("alloc native symbol failed."); + return idx; + } + + idx = bh_list_length(&comp_ctx->native_symbols); + sym->symbol = symbol; + sym->index = idx; + + if (BH_LIST_ERROR == bh_list_insert(&comp_ctx->native_symbols, sym)) { + wasm_runtime_free(sym); + aot_set_last_error("alloc index for native symbol failed."); + return -1; + } + } + + return idx; +} + void aot_value_stack_push(AOTValueStack *stack, AOTValue *value) { @@ -1743,8 +2136,8 @@ aot_block_destroy(AOTBlock *block) } bool -aot_checked_addr_list_add(AOTFuncContext *func_ctx, - uint32 local_idx, uint32 offset, uint32 bytes) +aot_checked_addr_list_add(AOTFuncContext *func_ctx, uint32 local_idx, + uint32 offset, uint32 bytes) { AOTCheckedAddr *node = func_ctx->checked_addr_list; @@ -1787,14 +2180,13 @@ aot_checked_addr_list_del(AOTFuncContext *func_ctx, uint32 local_idx) } bool -aot_checked_addr_list_find(AOTFuncContext *func_ctx, - uint32 local_idx, uint32 offset, uint32 bytes) +aot_checked_addr_list_find(AOTFuncContext *func_ctx, uint32 local_idx, + uint32 offset, uint32 bytes) { AOTCheckedAddr *node = func_ctx->checked_addr_list; while (node) { - if (node->local_idx == local_idx - && node->offset == offset + if (node->local_idx == local_idx && node->offset == offset && node->bytes >= bytes) { return true; } @@ -1819,7 +2211,7 @@ aot_checked_addr_list_destroy(AOTFuncContext *func_ctx) } bool -aot_build_zero_function_ret(AOTCompContext *comp_ctx, +aot_build_zero_function_ret(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, AOTFuncType *func_type) { LLVMValueRef ret = NULL; @@ -1839,7 +2231,8 @@ aot_build_zero_function_ret(AOTCompContext *comp_ctx, ret = LLVMBuildRet(comp_ctx->builder, F64_ZERO); break; case VALUE_TYPE_V128: - ret = LLVMBuildRet(comp_ctx->builder, V128_ZERO); + ret = + LLVMBuildRet(comp_ctx->builder, LLVM_CONST(i64x2_vec_zero)); break; case VALUE_TYPE_FUNCREF: case VALUE_TYPE_EXTERNREF: @@ -1857,38 +2250,84 @@ aot_build_zero_function_ret(AOTCompContext *comp_ctx, aot_set_last_error("llvm build ret failed."); return false; } +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMMetadataRef return_location = + dwarf_gen_func_ret_location(comp_ctx, func_ctx); + LLVMInstructionSetDebugLoc(ret, return_location); +#endif return true; } static LLVMValueRef __call_llvm_intrinsic(const AOTCompContext *comp_ctx, - const char *name, - LLVMTypeRef ret_type, - LLVMTypeRef *param_types, - int param_count, - LLVMValueRef *param_values) + const AOTFuncContext *func_ctx, const char *name, + LLVMTypeRef ret_type, LLVMTypeRef *param_types, + int param_count, LLVMValueRef *param_values) { LLVMValueRef func, ret; LLVMTypeRef func_type; + const char *symname; + int32 func_idx; + + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, name)) { + if (func_ctx == NULL) { + aot_set_last_error_v("invalid func_ctx for intrinsic: %s", name); + return NULL; + } - /* Declare llvm intrinsic function if necessary */ - if (!(func = LLVMGetNamedFunction(comp_ctx->module, name))) { if (!(func_type = LLVMFunctionType(ret_type, param_types, (uint32)param_count, false))) { - aot_set_last_error("create LLVM function type failed."); + aot_set_last_error("create LLVM intrinsic function type failed."); + return NULL; + } + if (!(func_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error( + "create LLVM intrinsic function pointer type failed."); return NULL; } - if (!(func = LLVMAddFunction(comp_ctx->module, name, func_type))) { - aot_set_last_error("add LLVM function failed."); + if (!(symname = aot_intrinsic_get_symbol(name))) { + aot_set_last_error_v("runtime intrinsic not implemented: %s\n", + name); return NULL; } + + func_idx = + aot_get_native_symbol_index((AOTCompContext *)comp_ctx, symname); + if (func_idx < 0) { + aot_set_last_error_v("get runtime intrinsc index failed: %s\n", + name); + return NULL; + } + + if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol, + func_type, func_idx))) { + aot_set_last_error_v("get runtime intrinsc failed: %s\n", name); + return NULL; + } + } + else { + /* Declare llvm intrinsic function if necessary */ + if (!(func = LLVMGetNamedFunction(comp_ctx->module, name))) { + if (!(func_type = LLVMFunctionType(ret_type, param_types, + (uint32)param_count, false))) { + aot_set_last_error( + "create LLVM intrinsic function type failed."); + return NULL; + } + + if (!(func = LLVMAddFunction(comp_ctx->module, name, func_type))) { + aot_set_last_error("add LLVM intrinsic function failed."); + return NULL; + } + } } /* Call the LLVM intrinsic function */ if (!(ret = LLVMBuildCall(comp_ctx->builder, func, param_values, (uint32)param_count, "call"))) { - aot_set_last_error("llvm build call failed."); + aot_set_last_error("llvm build intrinsic call failed."); return NULL; } @@ -1897,11 +2336,9 @@ __call_llvm_intrinsic(const AOTCompContext *comp_ctx, LLVMValueRef aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx, - const char *name, - LLVMTypeRef ret_type, - LLVMTypeRef *param_types, - int param_count, - ...) + const AOTFuncContext *func_ctx, const char *intrinsic, + LLVMTypeRef ret_type, LLVMTypeRef *param_types, + int param_count, ...) { LLVMValueRef *param_values, ret; va_list argptr; @@ -1922,8 +2359,8 @@ aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx, param_values[i++] = va_arg(argptr, LLVMValueRef); va_end(argptr); - ret = __call_llvm_intrinsic(comp_ctx, name, ret_type, param_types, - param_count, param_values); + ret = __call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, ret_type, + param_types, param_count, param_values); wasm_runtime_free(param_values); @@ -1932,11 +2369,9 @@ aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx, LLVMValueRef aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx, - const char *name, - LLVMTypeRef ret_type, - LLVMTypeRef *param_types, - int param_count, - va_list param_value_list) + const AOTFuncContext *func_ctx, const char *intrinsic, + LLVMTypeRef ret_type, LLVMTypeRef *param_types, + int param_count, va_list param_value_list) { LLVMValueRef *param_values, ret; uint64 total_size; @@ -1954,10 +2389,46 @@ aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx, while (i < param_count) param_values[i++] = va_arg(param_value_list, LLVMValueRef); - ret = __call_llvm_intrinsic(comp_ctx, name, ret_type, param_types, - param_count, param_values); + ret = __call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, ret_type, + param_types, param_count, param_values); wasm_runtime_free(param_values); return ret; } + +LLVMValueRef +aot_get_func_from_table(const AOTCompContext *comp_ctx, LLVMValueRef base, + LLVMTypeRef func_type, int32 index) +{ + LLVMValueRef func; + LLVMValueRef func_addr; + + if (!(func_addr = I32_CONST(index))) { + aot_set_last_error("construct function index failed."); + goto fail; + } + + if (!(func_addr = LLVMBuildInBoundsGEP(comp_ctx->builder, base, &func_addr, + 1, "func_addr"))) { + aot_set_last_error("get function addr by index failed."); + goto fail; + } + + func = LLVMBuildLoad(comp_ctx->builder, func_addr, "func_tmp"); + + if (func == NULL) { + aot_set_last_error("get function pointer failed."); + goto fail; + } + + if (!(func = + LLVMBuildBitCast(comp_ctx->builder, func, func_type, "func"))) { + aot_set_last_error("cast function fialed."); + goto fail; + } + + return func; +fail: + return NULL; +} diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 0ed1c33d52..c59f5199b8 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -18,175 +18,187 @@ #include "llvm-c/Transforms/Scalar.h" #include "llvm-c/Transforms/Vectorize.h" +#if WASM_ENABLE_LAZY_JIT != 0 +#include "aot_llvm_lazyjit.h" +#include "llvm-c/Orc.h" +#include "llvm-c/Error.h" +#include "llvm-c/Initialization.h" +#include "llvm-c/Support.h" +#endif +#if WASM_ENABLE_DEBUG_AOT != 0 +#include "llvm-c/DebugInfo.h" +#endif + #ifdef __cplusplus extern "C" { #endif - /** * Value in the WASM operation stack, each stack element * is an LLVM value */ typedef struct AOTValue { - struct AOTValue *next; - struct AOTValue *prev; - LLVMValueRef value; - /* VALUE_TYPE_I32/I64/F32/F64/VOID */ - uint8 type; - bool is_local; - uint32 local_idx; + struct AOTValue *next; + struct AOTValue *prev; + LLVMValueRef value; + /* VALUE_TYPE_I32/I64/F32/F64/VOID */ + uint8 type; + bool is_local; + uint32 local_idx; } AOTValue; /** * Value stack, represents stack elements in a WASM block */ typedef struct AOTValueStack { - AOTValue *value_list_head; - AOTValue *value_list_end; + AOTValue *value_list_head; + AOTValue *value_list_end; } AOTValueStack; typedef struct AOTBlock { - struct AOTBlock *next; - struct AOTBlock *prev; - - /* Block index */ - uint32 block_index; - /* LABEL_TYPE_BLOCK/LOOP/IF/FUNCTION */ - uint32 label_type; - /* Whether it is reachable */ - bool is_reachable; - /* Whether skip translation of wasm else branch */ - bool skip_wasm_code_else; - - /* code of else opcode of this block, if it is a IF block */ - uint8 *wasm_code_else; - /* code end of this block */ - uint8 *wasm_code_end; - - /* LLVM label points to code begin */ - LLVMBasicBlockRef llvm_entry_block; - /* LLVM label points to code else */ - LLVMBasicBlockRef llvm_else_block; - /* LLVM label points to code end */ - LLVMBasicBlockRef llvm_end_block; - - /* WASM operation stack */ - AOTValueStack value_stack; - - /* Param count/types/PHIs of this block */ - uint32 param_count; - uint8 *param_types; - LLVMValueRef *param_phis; - LLVMValueRef *else_param_phis; - - /* Result count/types/PHIs of this block */ - uint32 result_count; - uint8 *result_types; - LLVMValueRef *result_phis; + struct AOTBlock *next; + struct AOTBlock *prev; + + /* Block index */ + uint32 block_index; + /* LABEL_TYPE_BLOCK/LOOP/IF/FUNCTION */ + uint32 label_type; + /* Whether it is reachable */ + bool is_reachable; + /* Whether skip translation of wasm else branch */ + bool skip_wasm_code_else; + + /* code of else opcode of this block, if it is a IF block */ + uint8 *wasm_code_else; + /* code end of this block */ + uint8 *wasm_code_end; + + /* LLVM label points to code begin */ + LLVMBasicBlockRef llvm_entry_block; + /* LLVM label points to code else */ + LLVMBasicBlockRef llvm_else_block; + /* LLVM label points to code end */ + LLVMBasicBlockRef llvm_end_block; + + /* WASM operation stack */ + AOTValueStack value_stack; + + /* Param count/types/PHIs of this block */ + uint32 param_count; + uint8 *param_types; + LLVMValueRef *param_phis; + LLVMValueRef *else_param_phis; + + /* Result count/types/PHIs of this block */ + uint32 result_count; + uint8 *result_types; + LLVMValueRef *result_phis; } AOTBlock; /** * Block stack, represents WASM block stack elements */ typedef struct AOTBlockStack { - AOTBlock *block_list_head; - AOTBlock *block_list_end; - /* Current block index of each block type */ - uint32 block_index[3]; + AOTBlock *block_list_head; + AOTBlock *block_list_end; + /* Current block index of each block type */ + uint32 block_index[3]; } AOTBlockStack; typedef struct AOTCheckedAddr { - struct AOTCheckedAddr *next; - uint32 local_idx; - uint32 offset; - uint32 bytes; + struct AOTCheckedAddr *next; + uint32 local_idx; + uint32 offset; + uint32 bytes; } AOTCheckedAddr, *AOTCheckedAddrList; typedef struct AOTMemInfo { - LLVMValueRef mem_base_addr; - LLVMValueRef mem_data_size_addr; - LLVMValueRef mem_cur_page_count_addr; - LLVMValueRef mem_bound_check_1byte; - LLVMValueRef mem_bound_check_2bytes; - LLVMValueRef mem_bound_check_4bytes; - LLVMValueRef mem_bound_check_8bytes; - LLVMValueRef mem_bound_check_16bytes; + LLVMValueRef mem_base_addr; + LLVMValueRef mem_data_size_addr; + LLVMValueRef mem_cur_page_count_addr; + LLVMValueRef mem_bound_check_1byte; + LLVMValueRef mem_bound_check_2bytes; + LLVMValueRef mem_bound_check_4bytes; + LLVMValueRef mem_bound_check_8bytes; + LLVMValueRef mem_bound_check_16bytes; } AOTMemInfo; typedef struct AOTFuncContext { - AOTFunc *aot_func; - LLVMValueRef func; - AOTBlockStack block_stack; - - LLVMValueRef exec_env; - LLVMValueRef aot_inst; - LLVMValueRef argv_buf; - LLVMValueRef native_stack_bound; - LLVMValueRef aux_stack_bound; - LLVMValueRef aux_stack_bottom; - LLVMValueRef last_alloca; - LLVMValueRef func_ptrs; - - AOTMemInfo *mem_info; - - LLVMValueRef cur_exception; - - bool mem_space_unchanged; - AOTCheckedAddrList checked_addr_list; - - LLVMBasicBlockRef got_exception_block; - LLVMBasicBlockRef func_return_block; - LLVMValueRef exception_id_phi; - LLVMValueRef func_type_indexes; - LLVMValueRef locals[1]; + AOTFunc *aot_func; + LLVMValueRef func; + LLVMTypeRef func_type; + AOTBlockStack block_stack; + + LLVMValueRef exec_env; + LLVMValueRef aot_inst; + LLVMValueRef argv_buf; + LLVMValueRef native_stack_bound; + LLVMValueRef aux_stack_bound; + LLVMValueRef aux_stack_bottom; + LLVMValueRef native_symbol; + LLVMValueRef last_alloca; + LLVMValueRef func_ptrs; + + AOTMemInfo *mem_info; + + LLVMValueRef cur_exception; + + bool mem_space_unchanged; + AOTCheckedAddrList checked_addr_list; + + LLVMBasicBlockRef got_exception_block; + LLVMBasicBlockRef func_return_block; + LLVMValueRef exception_id_phi; + LLVMValueRef func_type_indexes; +#if WASM_ENABLE_DEBUG_AOT != 0 + LLVMMetadataRef debug_func; +#endif + LLVMValueRef locals[1]; } AOTFuncContext; typedef struct AOTLLVMTypes { - LLVMTypeRef int1_type; - LLVMTypeRef int8_type; - LLVMTypeRef int16_type; - LLVMTypeRef int32_type; - LLVMTypeRef int64_type; - LLVMTypeRef float32_type; - LLVMTypeRef float64_type; - LLVMTypeRef void_type; - - LLVMTypeRef int8_ptr_type; - LLVMTypeRef int8_pptr_type; - LLVMTypeRef int16_ptr_type; - LLVMTypeRef int32_ptr_type; - LLVMTypeRef int64_ptr_type; - LLVMTypeRef float32_ptr_type; - LLVMTypeRef float64_ptr_type; - - LLVMTypeRef v128_type; - LLVMTypeRef v128_ptr_type; - LLVMTypeRef i8x16_vec_type; - LLVMTypeRef i16x8_vec_type; - LLVMTypeRef i32x4_vec_type; - LLVMTypeRef i64x2_vec_type; - LLVMTypeRef f32x4_vec_type; - LLVMTypeRef f64x2_vec_type; - - LLVMTypeRef meta_data_type; - - LLVMTypeRef funcref_type; - LLVMTypeRef externref_type; + LLVMTypeRef int1_type; + LLVMTypeRef int8_type; + LLVMTypeRef int16_type; + LLVMTypeRef int32_type; + LLVMTypeRef int64_type; + LLVMTypeRef float32_type; + LLVMTypeRef float64_type; + LLVMTypeRef void_type; + + LLVMTypeRef int8_ptr_type; + LLVMTypeRef int8_pptr_type; + LLVMTypeRef int16_ptr_type; + LLVMTypeRef int32_ptr_type; + LLVMTypeRef int64_ptr_type; + LLVMTypeRef float32_ptr_type; + LLVMTypeRef float64_ptr_type; + + LLVMTypeRef v128_type; + LLVMTypeRef v128_ptr_type; + LLVMTypeRef i8x16_vec_type; + LLVMTypeRef i16x8_vec_type; + LLVMTypeRef i32x4_vec_type; + LLVMTypeRef i64x2_vec_type; + LLVMTypeRef f32x4_vec_type; + LLVMTypeRef f64x2_vec_type; + + LLVMTypeRef i1x2_vec_type; + + LLVMTypeRef meta_data_type; + + LLVMTypeRef funcref_type; + LLVMTypeRef externref_type; } AOTLLVMTypes; typedef struct AOTLLVMConsts { + LLVMValueRef i1_zero; + LLVMValueRef i1_one; LLVMValueRef i8_zero; LLVMValueRef i32_zero; LLVMValueRef i64_zero; LLVMValueRef f32_zero; LLVMValueRef f64_zero; - LLVMValueRef v128_zero; - LLVMValueRef i8x16_vec_zero; - LLVMValueRef i16x8_vec_zero; - LLVMValueRef i32x4_vec_zero; - LLVMValueRef i64x2_vec_zero; - LLVMValueRef f32x4_vec_zero; - LLVMValueRef f64x2_vec_zero; LLVMValueRef i32_one; LLVMValueRef i32_two; LLVMValueRef i32_three; @@ -195,6 +207,13 @@ typedef struct AOTLLVMConsts { LLVMValueRef i32_six; LLVMValueRef i32_seven; LLVMValueRef i32_eight; + LLVMValueRef i32_nine; + LLVMValueRef i32_ten; + LLVMValueRef i32_eleven; + LLVMValueRef i32_twelve; + LLVMValueRef i32_thirteen; + LLVMValueRef i32_fourteen; + LLVMValueRef i32_fifteen; LLVMValueRef i32_neg_one; LLVMValueRef i64_neg_one; LLVMValueRef i32_min; @@ -203,75 +222,111 @@ typedef struct AOTLLVMConsts { LLVMValueRef i32_32; LLVMValueRef i64_63; LLVMValueRef i64_64; - LLVMValueRef ref_null; + LLVMValueRef i8x16_vec_zero; + LLVMValueRef i16x8_vec_zero; + LLVMValueRef i32x4_vec_zero; + LLVMValueRef i64x2_vec_zero; + LLVMValueRef f32x4_vec_zero; + LLVMValueRef f64x2_vec_zero; + LLVMValueRef i8x16_undef; + LLVMValueRef i16x8_undef; + LLVMValueRef i32x4_undef; + LLVMValueRef i64x2_undef; + LLVMValueRef f32x4_undef; + LLVMValueRef f64x2_undef; + LLVMValueRef i32x16_zero; + LLVMValueRef i32x8_zero; + LLVMValueRef i32x4_zero; + LLVMValueRef i32x2_zero; } AOTLLVMConsts; /** * Compiler context */ typedef struct AOTCompContext { - AOTCompData *comp_data; + AOTCompData *comp_data; + + /* LLVM variables required to emit LLVM IR */ + LLVMContextRef context; + LLVMModuleRef module; + LLVMBuilderRef builder; +#if WASM_ENABLE_DEBUG_AOT + LLVMDIBuilderRef debug_builder; + LLVMMetadataRef debug_file; + LLVMMetadataRef debug_comp_unit; +#endif + LLVMTargetMachineRef target_machine; + char *target_cpu; + char target_arch[16]; + unsigned pointer_size; + + /* Hardware intrinsic compability flags */ + uint64 flags[8]; + + /* LLVM execution engine required by JIT */ +#if WASM_ENABLE_LAZY_JIT != 0 + LLVMOrcLLLazyJITRef lazy_orcjit; + LLVMOrcThreadSafeContextRef ts_context; + LLVMOrcJITTargetMachineBuilderRef tm_builder; +#else + LLVMExecutionEngineRef exec_engine; +#endif + bool is_jit_mode; - /* LLVM variables required to emit LLVM IR */ - LLVMContextRef context; - LLVMModuleRef module; - LLVMBuilderRef builder; - LLVMTargetMachineRef target_machine; - char *target_cpu; - char target_arch[16]; - unsigned pointer_size; + /* AOT indirect mode flag & symbol list */ + bool is_indirect_mode; + bh_list native_symbols; - /* LLVM execution engine required by JIT */ - LLVMExecutionEngineRef exec_engine; - bool is_jit_mode; + /* Bulk memory feature */ + bool enable_bulk_memory; - /* Bulk memory feature */ - bool enable_bulk_memory; + /* Bounday Check */ + bool enable_bound_check; - /* Bounday Check */ - bool enable_bound_check; + /* 128-bit SIMD */ + bool enable_simd; - /* 128-bit SIMD */ - bool enable_simd; + /* Auxiliary stack overflow/underflow check */ + bool enable_aux_stack_check; - /* Auxiliary stack overflow/underflow check */ - bool enable_aux_stack_check; + /* Generate auxiliary stack frame */ + bool enable_aux_stack_frame; - /* Generate auxiliary stack frame */ - bool enable_aux_stack_frame; + /* Thread Manager */ + bool enable_thread_mgr; - /* Thread Manager */ - bool enable_thread_mgr; + /* Tail Call */ + bool enable_tail_call; - /* Tail Call */ - bool enable_tail_call; + /* Reference Types */ + bool enable_ref_types; - /* Reference Types */ - bool enable_ref_types; + /* Disable LLVM built-in intrinsics */ + bool disable_llvm_intrinsics; - /* Whether optimize the JITed code */ - bool optimize; + /* Whether optimize the JITed code */ + bool optimize; - /* LLVM pass manager to optimize the JITed code */ - LLVMPassManagerRef pass_mgr; + /* LLVM pass manager to optimize the JITed code */ + LLVMPassManagerRef pass_mgr; - /* LLVM floating-point rounding mode metadata */ - LLVMValueRef fp_rounding_mode; + /* LLVM floating-point rounding mode metadata */ + LLVMValueRef fp_rounding_mode; - /* LLVM floating-point exception behavior metadata */ - LLVMValueRef fp_exception_behavior; + /* LLVM floating-point exception behavior metadata */ + LLVMValueRef fp_exception_behavior; - /* LLVM data types */ - AOTLLVMTypes basic_types; - LLVMTypeRef exec_env_type; - LLVMTypeRef aot_inst_type; + /* LLVM data types */ + AOTLLVMTypes basic_types; + LLVMTypeRef exec_env_type; + LLVMTypeRef aot_inst_type; - /* LLVM const values */ - AOTLLVMConsts llvm_consts; + /* LLVM const values */ + AOTLLVMConsts llvm_consts; - /* Function contexts */ - AOTFuncContext **func_ctxes; - uint32 func_ctx_count; + /* Function contexts */ + AOTFuncContext **func_ctxes; + uint32 func_ctx_count; } AOTCompContext; enum { @@ -281,12 +336,14 @@ enum { AOT_LLVMIR_OPT_FILE, }; -typedef struct AOTCompOption{ +typedef struct AOTCompOption { bool is_jit_mode; + bool is_indirect_mode; char *target_arch; char *target_abi; char *target_cpu; char *cpu_features; + bool is_sgx_platform; bool enable_bulk_memory; bool enable_thread_mgr; bool enable_tail_call; @@ -294,7 +351,7 @@ typedef struct AOTCompOption{ bool enable_ref_types; bool enable_aux_stack_check; bool enable_aux_stack_frame; - bool is_sgx_platform; + bool disable_llvm_intrinsics; uint32 opt_level; uint32 size_level; uint32 output_format; @@ -302,16 +359,18 @@ typedef struct AOTCompOption{ } AOTCompOption, *aot_comp_option_t; AOTCompContext * -aot_create_comp_context(AOTCompData *comp_data, - aot_comp_option_t option); +aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option); void aot_destroy_comp_context(AOTCompContext *comp_ctx); +int32 +aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol); + bool aot_compile_wasm(AOTCompContext *comp_ctx); -uint8* +uint8 * aot_emit_elf_file(AOTCompContext *comp_ctx, uint32 *p_elf_file_size); void @@ -342,45 +401,50 @@ LLVMTypeRef wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type); bool -aot_checked_addr_list_add(AOTFuncContext *func_ctx, - uint32 local_idx, uint32 offset, uint32 bytes); +aot_checked_addr_list_add(AOTFuncContext *func_ctx, uint32 local_idx, + uint32 offset, uint32 bytes); void aot_checked_addr_list_del(AOTFuncContext *func_ctx, uint32 local_idx); bool -aot_checked_addr_list_find(AOTFuncContext *func_ctx, - uint32 local_idx, uint32 offset, uint32 bytes); +aot_checked_addr_list_find(AOTFuncContext *func_ctx, uint32 local_idx, + uint32 offset, uint32 bytes); void aot_checked_addr_list_destroy(AOTFuncContext *func_ctx); bool -aot_build_zero_function_ret(AOTCompContext *comp_ctx, +aot_build_zero_function_ret(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, AOTFuncType *func_type); LLVMValueRef aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx, - const char *name, - LLVMTypeRef ret_type, - LLVMTypeRef *param_types, - int param_count, - ...); + const AOTFuncContext *func_ctx, const char *intrinsic, + LLVMTypeRef ret_type, LLVMTypeRef *param_types, + int param_count, ...); LLVMValueRef aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx, - const char *name, - LLVMTypeRef ret_type, - LLVMTypeRef *param_types, - int param_count, - va_list param_value_list); + const AOTFuncContext *func_ctx, const char *intrinsic, + LLVMTypeRef ret_type, LLVMTypeRef *param_types, + int param_count, va_list param_value_list); + +LLVMValueRef +aot_get_func_from_table(const AOTCompContext *comp_ctx, LLVMValueRef base, + LLVMTypeRef func_type, int32 index); bool aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str); +#if WASM_ENABLE_LAZY_JIT != 0 +void +aot_handle_llvm_errmsg(char *error_buf, uint32 error_buf_size, + const char *string, LLVMErrorRef error); +#endif + #ifdef __cplusplus } /* end of extern "C" */ #endif #endif /* end of _AOT_LLVM_H_ */ - diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index 05c097600c..8755a6d74e 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -28,8 +28,7 @@ extern "C" LLVMBool WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, LLVMMCJITCompilerOptions *PassedOptions, - size_t SizeOfPassedOptions, - char **OutError); + size_t SizeOfPassedOptions, char **OutError); extern "C" bool aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str); @@ -38,23 +37,21 @@ LLVMBool WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, LLVMMCJITCompilerOptions *PassedOptions, - size_t SizeOfPassedOptions, - char **OutError) + size_t SizeOfPassedOptions, char **OutError) { LLVMMCJITCompilerOptions options; // If the user passed a larger sized options struct, then they were compiled // against a newer LLVM. Tell them that something is wrong. if (SizeOfPassedOptions > sizeof(options)) { - *OutError = strdup( - "Refusing to use options struct that is larger than my own; assuming " - "LLVM library mismatch."); + *OutError = strdup("Refusing to use options struct that is larger than " + "my own; assuming LLVM library mismatch."); return 1; } // Defend against the user having an old version of the API by ensuring that - // any fields they didn't see are cleared. We must defend against fields being - // set to the bitwise equivalent of zero, and assume that this means "do the - // default" as if that option hadn't been available. + // any fields they didn't see are cleared. We must defend against fields + // being set to the bitwise equivalent of zero, and assume that this means + // "do the default" as if that option hadn't been available. LLVMInitializeMCJITCompilerOptions(&options, sizeof(options)); memcpy(&options, PassedOptions, SizeOfPassedOptions); @@ -68,8 +65,9 @@ WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, for (auto &F : *Mod) { auto Attrs = F.getAttributes(); StringRef Value = options.NoFramePointerElim ? "all" : "none"; - Attrs = Attrs.addAttribute(F.getContext(), AttributeList::FunctionIndex, - "frame-pointer", Value); + Attrs = + Attrs.addAttribute(F.getContext(), AttributeList::FunctionIndex, + "frame-pointer", Value); F.setAttributes(Attrs); } } @@ -88,15 +86,15 @@ WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, EngineBuilder builder(std::move(Mod)); builder.setEngineKind(EngineKind::JIT) - .setErrorStr(&Error) - .setMCPU(mcpu) - .setOptLevel((CodeGenOpt::Level)options.OptLevel) - .setTargetOptions(targetOptions); + .setErrorStr(&Error) + .setMCPU(mcpu) + .setOptLevel((CodeGenOpt::Level)options.OptLevel) + .setTargetOptions(targetOptions); if (Optional CM = unwrap(options.CodeModel, JIT)) builder.setCodeModel(*CM); if (options.MCJMM) builder.setMCJITMemoryManager( - std::unique_ptr(unwrap(options.MCJMM))); + std::unique_ptr(unwrap(options.MCJMM))); if (ExecutionEngine *JIT = builder.create()) { *OutJIT = wrap(JIT); return 0; @@ -116,16 +114,16 @@ aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str) llvm::SmallVector targetAttributes; llvm::Triple targetTriple(arch_c_str, "", ""); auto targetMachine = - std::unique_ptr(llvm::EngineBuilder().selectTarget( - targetTriple, "", std::string(cpu_c_str), targetAttributes)); + std::unique_ptr(llvm::EngineBuilder().selectTarget( + targetTriple, "", std::string(cpu_c_str), targetAttributes)); if (!targetMachine) { return false; } const llvm::Triple::ArchType targetArch = - targetMachine->getTargetTriple().getArch(); + targetMachine->getTargetTriple().getArch(); const llvm::MCSubtargetInfo *subTargetInfo = - targetMachine->getMCSubtargetInfo(); + targetMachine->getMCSubtargetInfo(); if (subTargetInfo == nullptr) { return false; } @@ -145,4 +143,3 @@ aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str) return true; #endif /* WASM_ENABLE_SIMD */ } - diff --git a/core/iwasm/compilation/aot_llvm_lazyjit.cpp b/core/iwasm/compilation/aot_llvm_lazyjit.cpp new file mode 100644 index 0000000000..858fbd2abb --- /dev/null +++ b/core/iwasm/compilation/aot_llvm_lazyjit.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_llvm_lazyjit.h" + +LLVMOrcJITTargetMachineBuilderRef +LLVMOrcJITTargetMachineBuilderFromTargetMachine(LLVMTargetMachineRef TM); + +LLVMOrcLLJITBuilderRef +LLVMOrcCreateLLJITBuilder(void); + +void +LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder); + +LLVMErrorRef +LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result, LLVMOrcLLJITBuilderRef Builder); + +LLVMErrorRef +LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J); + +LLVMOrcJITDylibRef +LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J); + +const char * +LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J); + +char +LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J); + +LLVMErrorRef +LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J, LLVMOrcJITDylibRef JD, + LLVMOrcThreadSafeModuleRef TSM); + +LLVMErrorRef +LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, LLVMOrcJITTargetAddress *Result, + const char *Name); + +const char * +LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J); + +void +LLVMOrcLLJITBuilderSetJITTargetMachineBuilder( + LLVMOrcLLJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB); + +char +LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J); + +#if LLVM_VERSION_MAJOR < 12 +LLVMOrcJITTargetMachineBuilderRef +LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM) +{ + return LLVMOrcJITTargetMachineBuilderFromTargetMachine(TM); +} +#endif + +LLVMOrcJITDylibRef +LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J) +{ + return LLVMOrcLLJITGetMainJITDylib(J); +} + +LLVMOrcLLLazyJITBuilderRef +LLVMOrcCreateLLLazyJITBuilder(void) +{ + return LLVMOrcCreateLLJITBuilder(); +} + +void +LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder) +{ + return LLVMOrcDisposeLLJITBuilder(Builder); +} + +LLVMErrorRef +LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result, + LLVMOrcLLLazyJITBuilderRef Builder) +{ + return LLVMOrcCreateLLJIT(Result, Builder); +} + +LLVMErrorRef +LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J) +{ + return LLVMOrcDisposeLLJIT(J); +} + +LLVMErrorRef +LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J, LLVMOrcJITDylibRef JD, + LLVMOrcThreadSafeModuleRef TSM) +{ + return LLVMOrcLLJITAddLLVMIRModule(J, JD, TSM); +} + +LLVMErrorRef +LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J, LLVMOrcJITTargetAddress *Result, + const char *Name) +{ + return LLVMOrcLLJITLookup(J, Result, Name); +} + +const char * +LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J) +{ + return LLVMOrcLLJITGetTripleString(J); +} + +void +LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder( + LLVMOrcLLLazyJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB) +{ + return LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(Builder, JTMB); +} + +char +LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J) +{ + return LLVMOrcLLJITGetGlobalPrefix(J); +} diff --git a/core/iwasm/compilation/aot_llvm_lazyjit.h b/core/iwasm/compilation/aot_llvm_lazyjit.h new file mode 100644 index 0000000000..adb4b02209 --- /dev/null +++ b/core/iwasm/compilation/aot_llvm_lazyjit.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef AOT_LLVM_LAZYJIT_H +#define AOT_LLVM_LAZYJIT_H + +#include "llvm-c/Error.h" +#include "llvm-c/Orc.h" +#include "llvm-c/TargetMachine.h" +#include "llvm-c/Types.h" +#if LLVM_VERSION_MAJOR >= 12 +#include "llvm-c/LLJIT.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef LLVMOrcLLJITBuilderRef LLVMOrcLLLazyJITBuilderRef; + +typedef LLVMOrcLLJITRef LLVMOrcLLLazyJITRef; + +LLVMOrcJITTargetMachineBuilderRef +LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM); + +LLVMOrcLLLazyJITBuilderRef +LLVMOrcCreateLLLazyJITBuilder(void); + +void +LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder); + +LLVMErrorRef +LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result, + LLVMOrcLLLazyJITBuilderRef Builder); + +LLVMErrorRef +LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J); + +LLVMOrcJITDylibRef +LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J); + +const char * +LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J); + +char +LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J); + +LLVMErrorRef +LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J, LLVMOrcJITDylibRef JD, + LLVMOrcThreadSafeModuleRef TSM); + +LLVMErrorRef +LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J, LLVMOrcJITTargetAddress *Result, + const char *Name); + +const char * +LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J); + +void +LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder( + LLVMOrcLLLazyJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB); + +char +LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J); + +#ifdef __cplusplus +} +#endif + +#endif /* end of AOT_LLVM_LAZYJIT_H */ diff --git a/core/iwasm/compilation/debug/dwarf_extractor.cpp b/core/iwasm/compilation/debug/dwarf_extractor.cpp new file mode 100644 index 0000000000..cb30a4f60c --- /dev/null +++ b/core/iwasm/compilation/debug/dwarf_extractor.cpp @@ -0,0 +1,523 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "lldb/API/SBBlock.h" +#include "lldb/API/SBCompileUnit.h" +#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBBreakpointLocation.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API//SBFunction.h" +#include "lldb/API//SBModule.h" +#include "lldb/API//SBProcess.h" +#include "lldb/API//SBStream.h" +#include "lldb/API//SBSymbol.h" +#include "lldb/API//SBTarget.h" +#include "lldb/API//SBThread.h" +#include "lldb/API/SBDeclaration.h" + +#include "dwarf_extractor.h" +#include "../aot_llvm.h" + +#include "bh_log.h" +#include "../../aot/aot_runtime.h" + +#include "llvm/BinaryFormat/Dwarf.h" + +using namespace lldb; + +typedef struct dwar_extractor { + SBDebugger debugger; + SBTarget target; + SBModule module; + +} dwar_extractor; + +#define TO_HANDLE(extractor) (dwar_extractor_handle_t)(extractor) + +#define TO_EXTACTOR(handle) (dwar_extractor *)(handle) + +static bool is_debugger_initialized; + +dwar_extractor_handle_t +create_dwarf_extractor(AOTCompData *comp_data, char *file_name) +{ + char *arch = NULL; + char *platform = NULL; + dwar_extractor *extractor = NULL; + + //__attribute__((constructor)) may be better? + if (!is_debugger_initialized) { + SBError error = SBDebugger::InitializeWithErrorHandling(); + if (error.Fail()) { + LOG_ERROR("Init Dwarf Debugger failed"); + return TO_HANDLE(NULL); + } + is_debugger_initialized = true; + } + + SBError error; + SBFileSpec exe_file_spec(file_name, true); + + if (!(extractor = new dwar_extractor())) { + LOG_ERROR("Create Dwarf Extractor error: failed to allocate memory"); + goto fail3; + } + + extractor->debugger = SBDebugger::Create(); + if (!extractor->debugger.IsValid()) { + LOG_ERROR("Create Dwarf Debugger failed"); + goto fail2; + } + + extractor->target = extractor->debugger.CreateTarget( + file_name, arch, platform, false, error); + + if (!error.Success()) { + LOG_ERROR("Create Dwarf target failed:%s", error.GetCString()); + goto fail1; + } + + if (!extractor->target.IsValid()) { + LOG_ERROR("Create Dwarf target not valid"); + goto fail1; + } + + extractor->module = extractor->target.FindModule(exe_file_spec); + comp_data->extractor = TO_HANDLE(extractor); + + return TO_HANDLE(extractor); + +fail1: + SBDebugger::Destroy(extractor->debugger); + +fail2: + wasm_runtime_free(extractor); + +fail3: + return TO_HANDLE(NULL); +} + +void +destroy_dwarf_extractor(dwar_extractor_handle_t handle) +{ + dwar_extractor *extractor = TO_EXTACTOR(handle); + if (!extractor) + return; + extractor->debugger.DeleteTarget(extractor->target); + SBDebugger::Destroy(extractor->debugger); + delete extractor; + SBDebugger::Terminate(); + is_debugger_initialized = false; +} + +LLVMMetadataRef +dwarf_gen_file_info(AOTCompContext *comp_ctx) +{ + dwar_extractor *extractor; + int units_number; + LLVMMetadataRef file_info = NULL; + const char *file_name; + const char *dir_name; + + if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) + return NULL; + + units_number = extractor->module.GetNumCompileUnits(); + + if (units_number > 0) { + SBCompileUnit compile_unit = extractor->module.GetCompileUnitAtIndex(0); + auto filespec = compile_unit.GetFileSpec(); + file_name = filespec.GetFilename(); + dir_name = filespec.GetDirectory(); + if (file_name || dir_name) { + file_info = LLVMDIBuilderCreateFile(comp_ctx->debug_builder, + file_name, strlen(file_name), + dir_name, strlen(dir_name)); + } + } + return file_info; +} + +#if 0 +void +dwarf_gen_mock_vm_info(AOTCompContext *comp_ctx) +{ + LLVMMetadataRef file_info = NULL; + LLVMMetadataRef comp_unit = NULL; + file_info = LLVMDIBuilderCreateFile(comp_ctx->debug_builder, + "ant_runtime_mock.c", 18, ".", 1); + + comp_unit = LLVMDIBuilderCreateCompileUnit( + comp_ctx->debug_builder, LLVMDWARFSourceLanguageC, file_info, + "ant compiler", 12, 0, NULL, 0, 1, NULL, 0, LLVMDWARFEmissionFull, 0, 0, + 0, "/", 1, "", 0); + + LLVMTypeRef ParamTys[] = { + LLVMVoidType(), + }; + + LLVMTypeRef FuncTy = LLVMFunctionType(LLVMVoidType(), ParamTys, 0, 0); + + LLVMValueRef Function = + LLVMAddFunction(comp_ctx->module, "ant_runtime_mock", FuncTy); + + LLVMMetadataRef ParamTypes[0]; + LLVMMetadataRef FunctionTy = LLVMDIBuilderCreateSubroutineType( + comp_ctx->debug_builder, file_info, ParamTypes, 0, LLVMDIFlagZero); + + /* 0x0015 is subroutine_type */ + LLVMMetadataRef ReplaceableFunctionMetadata = + LLVMDIBuilderCreateReplaceableCompositeType( + comp_ctx->debug_builder, 0x15, "ant_runtime_mock", 16, file_info, + file_info, 2, 0, 0, 0, LLVMDIFlagFwdDecl, "", 0); + + LLVMMetadataRef FunctionMetadata = LLVMDIBuilderCreateFunction( + comp_ctx->debug_builder, file_info, "ant_runtime_mock", 16, + "ant_runtime_mock", 16, file_info, 2, FunctionTy, true, true, 2, LLVMDIFlagZero, + false); + + LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata, + FunctionMetadata); + + LLVMSetSubprogram(Function, FunctionMetadata); + + comp_ctx->vm_debug_comp_unit = comp_unit; + comp_ctx->vm_debug_file = file_info; + comp_ctx->vm_debug_func = FunctionMetadata; +} +#endif + +LLVMMetadataRef +dwarf_gen_comp_unit_info(AOTCompContext *comp_ctx) +{ + dwar_extractor *extractor; + int units_number; + LLVMMetadataRef comp_unit = NULL; + + if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) + return NULL; + + units_number = extractor->module.GetNumCompileUnits(); + + if (units_number > 0) { + SBCompileUnit compile_unit = extractor->module.GetCompileUnitAtIndex(0); + auto lang_type = compile_unit.GetLanguage(); + + comp_unit = LLVMDIBuilderCreateCompileUnit( + comp_ctx->debug_builder, LLDB_TO_LLVM_LANG_TYPE(lang_type), + comp_ctx->debug_file, "ant compiler", 12, 0, NULL, 0, 1, NULL, 0, + LLVMDWARFEmissionFull, 0, 0, 0, "/", 1, "", 0); + } + return comp_unit; +} + +bool +dwarf_get_func_info(dwar_extractor_handle_t handle, uint64_t offset) +{ + dwar_extractor *extractor = TO_EXTACTOR(handle); + auto sbaddr = extractor->target.ResolveFileAddress(offset); + SBSymbolContext sc(sbaddr.GetSymbolContext(eSymbolContextFunction)); + if (sc.IsValid()) { + SBFunction function(sc.GetFunction()); + if (function.IsValid()) { + } + } +} + +static LLVMDWARFTypeEncoding +lldb_get_basic_type_encoding(BasicType basic_type) +{ + LLVMDWARFTypeEncoding encoding = 0; + switch (basic_type) { + case eBasicTypeUnsignedChar: + encoding = llvm::dwarf::DW_ATE_unsigned_char; + break; + case eBasicTypeSignedChar: + encoding = llvm::dwarf::DW_ATE_signed_char; + break; + case eBasicTypeUnsignedInt: + case eBasicTypeUnsignedLong: + case eBasicTypeUnsignedLongLong: + case eBasicTypeUnsignedWChar: + case eBasicTypeUnsignedInt128: + case eBasicTypeUnsignedShort: + encoding = llvm::dwarf::DW_ATE_unsigned; + break; + case eBasicTypeInt: + case eBasicTypeLong: + case eBasicTypeLongLong: + case eBasicTypeWChar: + case eBasicTypeInt128: + case eBasicTypeShort: + encoding = llvm::dwarf::DW_ATE_signed; + break; + case eBasicTypeBool: + encoding = llvm::dwarf::DW_ATE_boolean; + break; + case eBasicTypeHalf: + case eBasicTypeFloat: + case eBasicTypeDouble: + case eBasicTypeLongDouble: + encoding = llvm::dwarf::DW_ATE_float; + break; + default: + break; + } + return encoding; +} + +static LLVMMetadataRef +lldb_type_to_type_dbi(AOTCompContext *comp_ctx, SBType &type) +{ + LLVMMetadataRef type_info = NULL; + BasicType basic_type = type.GetBasicType(); + uint64_t bit_size = type.GetByteSize() * 8; + LLVMDIBuilderRef DIB = comp_ctx->debug_builder; + LLVMDWARFTypeEncoding encoding; + + if (basic_type != eBasicTypeInvalid) { + encoding = lldb_get_basic_type_encoding(basic_type); + type_info = LLVMDIBuilderCreateBasicType( + DIB, type.GetName(), strlen(type.GetName()), bit_size, encoding, + LLVMDIFlagZero); + } + else if (type.IsPointerType()) { + SBType pointee_type = type.GetPointeeType(); + type_info = LLVMDIBuilderCreatePointerType( + DIB, lldb_type_to_type_dbi(comp_ctx, pointee_type), bit_size, 0, 0, + "", 0); + } + + return type_info; +} + +static LLVMMetadataRef +lldb_function_to_function_dbi(AOTCompContext *comp_ctx, SBSymbolContext &sc, + AOTFuncContext *func_ctx) +{ + SBFunction function(sc.GetFunction()); + const char *function_name = function.GetName(); + const char *link_name = function.GetName(); + SBTypeList function_args = function.GetType().GetFunctionArgumentTypes(); + SBType return_type = function.GetType().GetFunctionReturnType(); + const size_t num_function_args = function_args.GetSize(); + dwar_extractor *extractor; + + if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) + return NULL; + + LLVMDIBuilderRef DIB = comp_ctx->debug_builder; + LLVMMetadataRef File = comp_ctx->debug_file; + + LLVMMetadataRef ParamTypes[num_function_args + 1]; + + ParamTypes[0] = lldb_type_to_type_dbi(comp_ctx, return_type); + + for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args; + ++function_arg_idx) { + SBType function_arg_type = + function_args.GetTypeAtIndex(function_arg_idx); + + if (function_arg_type.IsValid()) { + ParamTypes[function_arg_idx + 1] = + lldb_type_to_type_dbi(comp_ctx, function_arg_type); + } + } + + LLVMMetadataRef FunctionTy = LLVMDIBuilderCreateSubroutineType( + DIB, File, ParamTypes, num_function_args + 1, LLVMDIFlagZero); + + auto line_entry = sc.GetLineEntry(); + LLVMMetadataRef ReplaceableFunctionMetadata = + LLVMDIBuilderCreateReplaceableCompositeType( + DIB, 0x15, function_name, strlen(function_name), File, File, + line_entry.GetLine(), 0, 0, 0, LLVMDIFlagFwdDecl, "", 0); + + LLVMMetadataRef FunctionMetadata = LLVMDIBuilderCreateFunction( + DIB, File, function_name, strlen(function_name), link_name, + strlen(link_name), File, line_entry.GetLine(), FunctionTy, true, true, + line_entry.GetLine(), LLVMDIFlagZero, false); + + LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata, + FunctionMetadata); + + LLVMSetSubprogram(func_ctx->func, FunctionMetadata); + + LLVMMetadataRef ParamExpression = + LLVMDIBuilderCreateExpression(DIB, NULL, 0); + auto variable_list = + function.GetBlock().GetVariables(extractor->target, true, false, false); + if (num_function_args != variable_list.GetSize()) { + LOG_ERROR( + "function args number dismatch!:value number=%d, function args=%d", + variable_list.GetSize(), num_function_args); + } + + LLVMMetadataRef ParamLocation = LLVMDIBuilderCreateDebugLocation( + comp_ctx->context, line_entry.GetLine(), 0, FunctionMetadata, NULL); + + // TODO:change to void * or WasmExenv * ? + LLVMMetadataRef voidtype = + LLVMDIBuilderCreateBasicType(DIB, "void", 4, 0, 0, LLVMDIFlagZero); + LLVMMetadataRef voidpionter = + LLVMDIBuilderCreatePointerType(DIB, voidtype, 64, 0, 0, "void *", 6); + + LLVMMetadataRef ParamVar = LLVMDIBuilderCreateParameterVariable( + DIB, FunctionMetadata, "exenv", 5, 1, + File, // starts form 1, and 1 is exenv, + line_entry.GetLine(), voidpionter, true, LLVMDIFlagZero); + LLVMValueRef Param = LLVMGetParam(func_ctx->func, 0); + LLVMBasicBlockRef block_curr = LLVMGetEntryBasicBlock(func_ctx->func); + LLVMDIBuilderInsertDbgValueAtEnd(DIB, Param, ParamVar, ParamExpression, + ParamLocation, block_curr); + + for (uint32_t function_arg_idx = 0; + function_arg_idx < variable_list.GetSize(); ++function_arg_idx) { + SBValue variable(variable_list.GetValueAtIndex(function_arg_idx)); + if (variable.IsValid()) { + SBDeclaration dec(variable.GetDeclaration()); + auto valtype = variable.GetType(); + LLVMMetadataRef ParamLocation = LLVMDIBuilderCreateDebugLocation( + comp_ctx->context, dec.GetLine(), dec.GetColumn(), + FunctionMetadata, NULL); + LLVMMetadataRef ParamVar = LLVMDIBuilderCreateParameterVariable( + DIB, FunctionMetadata, variable.GetName(), + strlen(variable.GetName()), function_arg_idx + 1 + 1, + File, // starts form 1, and 1 is exenv, + dec.GetLine(), ParamTypes[function_arg_idx + 1], true, + LLVMDIFlagZero); + LLVMValueRef Param = + LLVMGetParam(func_ctx->func, function_arg_idx + 1); + LLVMDIBuilderInsertDbgValueAtEnd(DIB, Param, ParamVar, + ParamExpression, ParamLocation, + block_curr); + } + } + + return FunctionMetadata; +} + +LLVMMetadataRef +dwarf_gen_func_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMMetadataRef func_info = NULL; + dwar_extractor *extractor; + uint64_t vm_offset; + AOTFunc *func = func_ctx->aot_func; + + if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) + return NULL; + + // A code address in DWARF for WebAssembly is the offset of an + // instruction relative within the Code section of the WebAssembly file. + // For this reason Section::GetFileAddress() must return zero for the + // Code section. (refert to ObjectFileWasm.cpp) + vm_offset = func->code - comp_ctx->comp_data->wasm_module->buf_code; + + auto sbaddr = extractor->target.ResolveFileAddress(vm_offset); + SBSymbolContext sc(sbaddr.GetSymbolContext(eSymbolContextFunction + | eSymbolContextLineEntry)); + if (sc.IsValid()) { + SBFunction function(sc.GetFunction()); + if (function.IsValid()) { + func_info = lldb_function_to_function_dbi(comp_ctx, sc, func_ctx); + } + } + return func_info; +} + +void +dwarf_get_func_name(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + char *name, int len) +{ + LLVMMetadataRef func_info = NULL; + dwar_extractor *extractor; + uint64_t vm_offset; + AOTFunc *func = func_ctx->aot_func; + + name[0] = '\0'; + + if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) + return; + + // A code address in DWARF for WebAssembly is the offset of an + // instruction relative within the Code section of the WebAssembly file. + // For this reason Section::GetFileAddress() must return zero for the + // Code section. (refert to ObjectFileWasm.cpp) + vm_offset = func->code - comp_ctx->comp_data->wasm_module->buf_code; + + auto sbaddr = extractor->target.ResolveFileAddress(vm_offset); + SBSymbolContext sc(sbaddr.GetSymbolContext(eSymbolContextFunction + | eSymbolContextLineEntry)); + if (sc.IsValid()) { + SBFunction function(sc.GetFunction()); + if (function.IsValid()) { + bh_strcpy_s(name, len, function.GetName()); + } + } +} + +LLVMMetadataRef +dwarf_gen_location(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint64_t vm_offset) +{ + LLVMMetadataRef location_info = NULL; + dwar_extractor *extractor; + AOTFunc *func = func_ctx->aot_func; + + if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) + return NULL; + + auto sbaddr = extractor->target.ResolveFileAddress(vm_offset); + SBSymbolContext sc(sbaddr.GetSymbolContext(eSymbolContextFunction + | eSymbolContextLineEntry)); + if (sc.IsValid()) { + // TODO:need to check if the vm_offset is belong to + SBFunction function(sc.GetFunction()); + if (function.IsValid()) { + uint64_t start = func_ctx->aot_func->code + - comp_ctx->comp_data->wasm_module->buf_code; + uint64_t end = func_ctx->aot_func->code + - comp_ctx->comp_data->wasm_module->buf_code + + func_ctx->aot_func->code_size; + if (function.GetStartAddress().GetOffset() <= start + && end <= function.GetEndAddress().GetOffset()) { + auto line_entry = sc.GetLineEntry(); + location_info = LLVMDIBuilderCreateDebugLocation( + comp_ctx->context, line_entry.GetLine(), + line_entry.GetColumn(), func_ctx->debug_func, NULL); + // LOG_VERBOSE("Gen the location l:%d, c:%d at %lx", + // line_entry.GetLine(), line_entry.GetColumn(), vm_offset); + } + else + LOG_WARNING("the offset and function is not matched"); + } + } + return location_info; +} + +LLVMMetadataRef +dwarf_gen_func_ret_location(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMMetadataRef func_info = NULL; + dwar_extractor *extractor; + uint64_t vm_offset; + AOTFunc *func = func_ctx->aot_func; + LLVMMetadataRef location_info = NULL; + + if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor))) + return NULL; + + // A code address in DWARF for WebAssembly is the offset of an + // instruction relative within the Code section of the WebAssembly file. + // For this reason Section::GetFileAddress() must return zero for the + // Code section. (refert to ObjectFileWasm.cpp) + vm_offset = (func->code + func->code_size - 1) + - comp_ctx->comp_data->wasm_module->buf_code; + location_info = dwarf_gen_location(comp_ctx, func_ctx, vm_offset); + + return location_info; +} \ No newline at end of file diff --git a/core/iwasm/compilation/debug/dwarf_extractor.h b/core/iwasm/compilation/debug/dwarf_extractor.h new file mode 100644 index 0000000000..449d4d57c5 --- /dev/null +++ b/core/iwasm/compilation/debug/dwarf_extractor.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _DWARF_EXTRACTOR_H_ +#define _DWARF_EXTRACTOR_H_ + +#include "llvm-c/DebugInfo.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned int LLDBLangType; +#define LLDB_TO_LLVM_LANG_TYPE(lldb_lang_type) \ + (LLVMDWARFSourceLanguage)(((lldb_lang_type) > 0 ? (lldb_lang_type)-1 : 1)) + +struct AOTCompData; +typedef struct AOTCompData *aot_comp_data_t; +typedef void *dwar_extractor_handle_t; + +struct AOTCompContext; +typedef struct AOTCompContext AOTCompContext; + +struct AOTFuncContext; + +typedef struct AOTFuncContext AOTFuncContext; +dwar_extractor_handle_t +create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name); + +LLVMMetadataRef +dwarf_gen_file_info(AOTCompContext *comp_ctx); + +LLVMMetadataRef +dwarf_gen_comp_unit_info(AOTCompContext *comp_ctx); + +LLVMMetadataRef +dwarf_gen_func_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +LLVMMetadataRef +dwarf_gen_location(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint64_t vm_offset); + +LLVMMetadataRef +dwarf_gen_func_ret_location(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +void +dwarf_get_func_name(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + char *name, int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/core/iwasm/compilation/iwasm_compl.cmake b/core/iwasm/compilation/iwasm_compl.cmake index 09b3b9ecc7..59455de9a3 100644 --- a/core/iwasm/compilation/iwasm_compl.cmake +++ b/core/iwasm/compilation/iwasm_compl.cmake @@ -2,9 +2,17 @@ set (IWASM_COMPL_DIR ${CMAKE_CURRENT_LIST_DIR}) include_directories(${IWASM_COMPL_DIR}) -file (GLOB_RECURSE source_all - ${IWASM_COMPL_DIR}/*.c - ${IWASM_COMPL_DIR}/*.cpp) +if (WAMR_BUILD_DEBUG_AOT EQUAL 1) + file (GLOB_RECURSE source_all + ${IWASM_COMPL_DIR}/*.c + ${IWASM_COMPL_DIR}/*.cpp) +else() + file (GLOB source_all + ${IWASM_COMPL_DIR}/simd/*.c + ${IWASM_COMPL_DIR}/simd/*.cpp + ${IWASM_COMPL_DIR}/*.c + ${IWASM_COMPL_DIR}/*.cpp) +endif() set (IWASM_COMPL_SOURCE ${source_all}) diff --git a/core/iwasm/compilation/simd/simd_access_lanes.c b/core/iwasm/compilation/simd/simd_access_lanes.c index 8f1489c840..4f43c35a93 100644 --- a/core/iwasm/compilation/simd/simd_access_lanes.c +++ b/core/iwasm/compilation/simd/simd_access_lanes.c @@ -8,42 +8,8 @@ #include "../aot_emit_exception.h" #include "../../aot/aot_runtime.h" -static bool -is_target_x86(AOTCompContext *comp_ctx) -{ - return !strncmp(comp_ctx->target_arch, "x86_64", 6) || - !strncmp(comp_ctx->target_arch, "i386", 4); -} - -static LLVMValueRef -build_intx16_vector(const AOTCompContext *comp_ctx, - const LLVMTypeRef element_type, - const int *element_value) -{ - LLVMValueRef vector, elements[16]; - unsigned i; - - for (i = 0; i < 16; i++) { - if (!(elements[i] = - LLVMConstInt(element_type, element_value[i], true))) { - HANDLE_FAILURE("LLVMConstInst"); - goto fail; - } - } - - if (!(vector = LLVMConstVector(elements, 16))) { - HANDLE_FAILURE("LLVMConstVector"); - goto fail; - } - - return vector; -fail: - return NULL; -} - bool -aot_compile_simd_shuffle(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_shuffle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, const uint8 *frame_ip) { LLVMValueRef vec1, vec2, mask, result; @@ -67,7 +33,8 @@ aot_compile_simd_shuffle(AOTCompContext *comp_ctx, } /* build a vector <16 x i32> */ - if (!(mask = build_intx16_vector(comp_ctx, I32_TYPE, values))) { + if (!(mask = simd_build_const_integer_vector(comp_ctx, I32_TYPE, values, + 16))) { goto fail; } @@ -77,29 +44,19 @@ aot_compile_simd_shuffle(AOTCompContext *comp_ctx, goto fail; } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } - - PUSH_V128(result); + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); - return true; fail: return false; } +/*TODO: llvm.experimental.vector.*/ /* shufflevector is not an option, since it requires *mask as a const */ bool aot_compile_simd_swizzle_x86(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { LLVMValueRef vector, mask, max_lanes, condition, mask_lanes, result; LLVMTypeRef param_types[2]; - int max_lane_id[16] = { 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16 }, - mask_lane_id[16] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }; if (!(mask = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE, "mask"))) { @@ -112,25 +69,28 @@ aot_compile_simd_swizzle_x86(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) } /* icmp uge <16 x i8> mask, <16, 16, 16, 16, ...> */ - if (!(max_lanes = build_intx16_vector(comp_ctx, INT8_TYPE, max_lane_id))) { + if (!(max_lanes = simd_build_splat_const_integer_vector(comp_ctx, INT8_TYPE, + 16, 16))) { goto fail; } - if (!(condition = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, mask, - max_lanes, "compare_with_16"))) { - HANDLE_FAILURE("LLVMBuldICmp"); + /* if the highest bit of every i8 of mask is 1, means doesn't pick up + from vector */ + /* select <16 x i1> %condition, <16 x i8> <0x80, 0x80, ...>, + <16 x i8> %mask */ + if (!(mask_lanes = simd_build_splat_const_integer_vector( + comp_ctx, INT8_TYPE, 0x80, 16))) { goto fail; } - /* if the highest bit of every i8 of mask is 1, means doesn't pick up from vector */ - /* select <16 x i1> %condition, <16 x i8> <0x80, 0x80, ...>, <16 x i8> %mask */ - if (!(mask_lanes = - build_intx16_vector(comp_ctx, INT8_TYPE, mask_lane_id))) { + if (!(condition = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, mask, + max_lanes, "compare_with_16"))) { + HANDLE_FAILURE("LLVMBuldICmp"); goto fail; } - if (!(mask = LLVMBuildSelect(comp_ctx->builder, condition, mask_lanes, - mask, "mask"))) { + if (!(mask = LLVMBuildSelect(comp_ctx->builder, condition, mask_lanes, mask, + "mask"))) { HANDLE_FAILURE("LLVMBuildSelect"); goto fail; } @@ -138,8 +98,8 @@ aot_compile_simd_swizzle_x86(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) param_types[0] = V128_i8x16_TYPE; param_types[1] = V128_i8x16_TYPE; if (!(result = aot_call_llvm_intrinsic( - comp_ctx, "llvm.x86.ssse3.pshuf.b.128", V128_i8x16_TYPE, - param_types, 2, vector, mask))) { + comp_ctx, func_ctx, "llvm.x86.ssse3.pshuf.b.128", V128_i8x16_TYPE, + param_types, 2, vector, mask))) { HANDLE_FAILURE("LLVMBuildCall"); goto fail; } @@ -158,17 +118,13 @@ aot_compile_simd_swizzle_x86(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) } static bool -aot_compile_simd_swizzle_common(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +aot_compile_simd_swizzle_common(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) { LLVMValueRef vector, mask, default_lane_value, condition, max_lane_id, - result, idx, id, replace_with_zero, elem, elem_or_zero, undef; + result, idx, id, replace_with_zero, elem, elem_or_zero, undef; uint8 i; - int const_lane_ids[16] = { 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16 }, - const_zeors[16] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - if (!(mask = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE, "mask"))) { goto fail; @@ -185,8 +141,8 @@ aot_compile_simd_swizzle_common(AOTCompContext *comp_ctx, AOTFuncContext *func_c } /* icmp uge <16 x i8> mask, <16, 16, 16, 16, ...> */ - if (!(max_lane_id = - build_intx16_vector(comp_ctx, INT8_TYPE, const_lane_ids))) { + if (!(max_lane_id = simd_build_splat_const_integer_vector( + comp_ctx, INT8_TYPE, 16, 16))) { goto fail; } @@ -196,9 +152,9 @@ aot_compile_simd_swizzle_common(AOTCompContext *comp_ctx, AOTFuncContext *func_c goto fail; } - /* if the id is out of range (>=16), set the id as 0 */ - if (!(default_lane_value = - build_intx16_vector(comp_ctx, INT8_TYPE, const_zeors))) { + /* if the id is out of range (>=16), set the id as 0 */ + if (!(default_lane_value = simd_build_splat_const_integer_vector( + comp_ctx, INT8_TYPE, 0, 16))) { goto fail; } @@ -216,8 +172,8 @@ aot_compile_simd_swizzle_common(AOTCompContext *comp_ctx, AOTFuncContext *func_c } if (!(replace_with_zero = - LLVMBuildExtractElement(comp_ctx->builder, condition, - I8_CONST(i), "replace_with_zero"))) { + LLVMBuildExtractElement(comp_ctx->builder, condition, + I8_CONST(i), "replace_with_zero"))) { HANDLE_FAILURE("LLVMBuildExtractElement"); goto fail; } @@ -229,15 +185,15 @@ aot_compile_simd_swizzle_common(AOTCompContext *comp_ctx, AOTFuncContext *func_c } if (!(elem_or_zero = - LLVMBuildSelect(comp_ctx->builder, replace_with_zero, - I8_CONST(0), elem, "elem_or_zero"))) { + LLVMBuildSelect(comp_ctx->builder, replace_with_zero, + I8_CONST(0), elem, "elem_or_zero"))) { HANDLE_FAILURE("LLVMBuildSelect"); goto fail; } if (!(undef = - LLVMBuildInsertElement(comp_ctx->builder, undef, elem_or_zero, - I8_CONST(i), "new_vector"))) { + LLVMBuildInsertElement(comp_ctx->builder, undef, elem_or_zero, + I8_CONST(i), "new_vector"))) { HANDLE_FAILURE("LLVMBuildInsertElement"); goto fail; } @@ -268,18 +224,14 @@ aot_compile_simd_swizzle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) } static bool -aot_compile_simd_extract(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id, - bool need_extend, - bool is_signed, - LLVMTypeRef vector_type, - LLVMTypeRef result_type, +aot_compile_simd_extract(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 lane_id, bool need_extend, bool is_signed, + LLVMTypeRef vector_type, LLVMTypeRef result_type, unsigned aot_value_type) { - LLVMValueRef vector, idx, result; + LLVMValueRef vector, lane, result; - if (!(idx = I8_CONST(lane_id))) { + if (!(lane = simd_lane_id_to_llvm_value(comp_ctx, lane_id))) { HANDLE_FAILURE("LLVMConstInt"); goto fail; } @@ -291,7 +243,7 @@ aot_compile_simd_extract(AOTCompContext *comp_ctx, } /* extractelement %vector, i8 lane_id*/ - if (!(result = LLVMBuildExtractElement(comp_ctx->builder, vector, idx, + if (!(result = LLVMBuildExtractElement(comp_ctx->builder, vector, lane, "element"))) { HANDLE_FAILURE("LLVMBuildExtractElement"); goto fail; @@ -300,16 +252,16 @@ aot_compile_simd_extract(AOTCompContext *comp_ctx, if (need_extend) { if (is_signed) { /* sext %element to */ - if (!(result = LLVMBuildSExt(comp_ctx->builder, result, - result_type, "ret"))) { + if (!(result = LLVMBuildSExt(comp_ctx->builder, result, result_type, + "ret"))) { HANDLE_FAILURE("LLVMBuildSExt"); goto fail; } } else { /* sext %element to */ - if (!(result = LLVMBuildZExt(comp_ctx->builder, result, - result_type, "ret"))) { + if (!(result = LLVMBuildZExt(comp_ctx->builder, result, result_type, + "ret"))) { HANDLE_FAILURE("LLVMBuildZExt"); goto fail; } @@ -325,8 +277,7 @@ aot_compile_simd_extract(AOTCompContext *comp_ctx, bool aot_compile_simd_extract_i8x16(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id, + AOTFuncContext *func_ctx, uint8 lane_id, bool is_signed) { return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, true, @@ -336,8 +287,7 @@ aot_compile_simd_extract_i8x16(AOTCompContext *comp_ctx, bool aot_compile_simd_extract_i16x8(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id, + AOTFuncContext *func_ctx, uint8 lane_id, bool is_signed) { return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, true, @@ -347,8 +297,7 @@ aot_compile_simd_extract_i16x8(AOTCompContext *comp_ctx, bool aot_compile_simd_extract_i32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id) + AOTFuncContext *func_ctx, uint8 lane_id) { return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false, V128_i32x4_TYPE, I32_TYPE, VALUE_TYPE_I32); @@ -356,8 +305,7 @@ aot_compile_simd_extract_i32x4(AOTCompContext *comp_ctx, bool aot_compile_simd_extract_i64x2(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id) + AOTFuncContext *func_ctx, uint8 lane_id) { return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false, V128_i64x2_TYPE, I64_TYPE, VALUE_TYPE_I64); @@ -365,8 +313,7 @@ aot_compile_simd_extract_i64x2(AOTCompContext *comp_ctx, bool aot_compile_simd_extract_f32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id) + AOTFuncContext *func_ctx, uint8 lane_id) { return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false, V128_f32x4_TYPE, F32_TYPE, VALUE_TYPE_F32); @@ -374,39 +321,32 @@ aot_compile_simd_extract_f32x4(AOTCompContext *comp_ctx, bool aot_compile_simd_extract_f64x2(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id) + AOTFuncContext *func_ctx, uint8 lane_id) { return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false, V128_f64x2_TYPE, F64_TYPE, VALUE_TYPE_F64); } static bool -aot_compile_simd_replace(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id, - unsigned new_value_type, - LLVMTypeRef vector_type, - bool need_reduce, +aot_compile_simd_replace(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 lane_id, unsigned new_value_type, + LLVMTypeRef vector_type, bool need_reduce, LLVMTypeRef element_type) { - LLVMValueRef vector, new_value, idx, result; + LLVMValueRef vector, new_value, lane, result; POP(new_value, new_value_type); - if (!(idx = I8_CONST(lane_id))) { - HANDLE_FAILURE("LLVMConstInt"); + if (!(lane = simd_lane_id_to_llvm_value(comp_ctx, lane_id))) { goto fail; } - /* bitcast <2 x i64> %0 to */ - if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "vec"))) { goto fail; } - /* bitcast to */ + /* trunc to */ if (need_reduce) { if (!(new_value = LLVMBuildTrunc(comp_ctx->builder, new_value, element_type, "element"))) { @@ -415,83 +355,64 @@ aot_compile_simd_replace(AOTCompContext *comp_ctx, } } - /* insertelement %vector, %element, i8 idx */ + /* insertelement %vector, %element, + i32 lane */ if (!(result = LLVMBuildInsertElement(comp_ctx->builder, vector, new_value, - idx, "new_vector"))) { + lane, "new_vector"))) { HANDLE_FAILURE("LLVMBuildInsertElement"); goto fail; } - /* bitcast %result to <2 x i64> */ - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "reesult"); - PUSH_V128(result); - - return true; fail: return false; } bool aot_compile_simd_replace_i8x16(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id) + AOTFuncContext *func_ctx, uint8 lane_id) { - return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, - VALUE_TYPE_I32, V128_i8x16_TYPE, true, - INT8_TYPE); + return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_I32, + V128_i8x16_TYPE, true, INT8_TYPE); } bool aot_compile_simd_replace_i16x8(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id) + AOTFuncContext *func_ctx, uint8 lane_id) { - return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, - VALUE_TYPE_I32, V128_i16x8_TYPE, true, - INT16_TYPE); + return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_I32, + V128_i16x8_TYPE, true, INT16_TYPE); } bool aot_compile_simd_replace_i32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id) + AOTFuncContext *func_ctx, uint8 lane_id) { - return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, - VALUE_TYPE_I32, V128_i32x4_TYPE, false, - I32_TYPE); + return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_I32, + V128_i32x4_TYPE, false, I32_TYPE); } bool aot_compile_simd_replace_i64x2(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id) + AOTFuncContext *func_ctx, uint8 lane_id) { - return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, - VALUE_TYPE_I64, V128_i64x2_TYPE, false, - I64_TYPE); + return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_I64, + V128_i64x2_TYPE, false, I64_TYPE); } bool aot_compile_simd_replace_f32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id) + AOTFuncContext *func_ctx, uint8 lane_id) { - return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, - VALUE_TYPE_F32, V128_f32x4_TYPE, false, - F32_TYPE); + return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_F32, + V128_f32x4_TYPE, false, F32_TYPE); } bool aot_compile_simd_replace_f64x2(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id) + AOTFuncContext *func_ctx, uint8 lane_id) { - return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, - VALUE_TYPE_F64, V128_f64x2_TYPE, false, - F64_TYPE); + return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id, VALUE_TYPE_F64, + V128_f64x2_TYPE, false, F64_TYPE); } diff --git a/core/iwasm/compilation/simd/simd_access_lanes.h b/core/iwasm/compilation/simd/simd_access_lanes.h index ae90242df5..75ca71ced7 100644 --- a/core/iwasm/compilation/simd/simd_access_lanes.h +++ b/core/iwasm/compilation/simd/simd_access_lanes.h @@ -13,8 +13,7 @@ extern "C" { #endif bool -aot_compile_simd_shuffle(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_shuffle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, const uint8 *frame_ip); bool @@ -22,65 +21,69 @@ aot_compile_simd_swizzle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); bool aot_compile_simd_extract_i8x16(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id, + AOTFuncContext *func_ctx, uint8 lane_id, bool is_signed); bool aot_compile_simd_extract_i16x8(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id, + AOTFuncContext *func_ctx, uint8 lane_id, bool is_signed); bool aot_compile_simd_extract_i32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id); + AOTFuncContext *func_ctx, uint8 lane_id); bool aot_compile_simd_extract_i64x2(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id); + AOTFuncContext *func_ctx, uint8 lane_id); bool aot_compile_simd_extract_f32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id); + AOTFuncContext *func_ctx, uint8 lane_id); bool aot_compile_simd_extract_f64x2(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id); + AOTFuncContext *func_ctx, uint8 lane_id); bool aot_compile_simd_replace_i8x16(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id); + AOTFuncContext *func_ctx, uint8 lane_id); bool aot_compile_simd_replace_i16x8(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id); + AOTFuncContext *func_ctx, uint8 lane_id); bool aot_compile_simd_replace_i32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id); + AOTFuncContext *func_ctx, uint8 lane_id); bool aot_compile_simd_replace_i64x2(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id); + AOTFuncContext *func_ctx, uint8 lane_id); bool aot_compile_simd_replace_f32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id); + AOTFuncContext *func_ctx, uint8 lane_id); bool aot_compile_simd_replace_f64x2(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 lane_id); + AOTFuncContext *func_ctx, uint8 lane_id); + +bool +aot_compile_simd_load8_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 lane_id); + +bool +aot_compile_simd_load16_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 lane_id); + +bool +aot_compile_simd_load32_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 lane_id); + +bool +aot_compile_simd_load64_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 lane_id); #ifdef __cplusplus } /* end of extern "C" */ diff --git a/core/iwasm/compilation/simd/simd_bit_shifts.c b/core/iwasm/compilation/simd/simd_bit_shifts.c index 5b1ee90245..675ffbcfe0 100644 --- a/core/iwasm/compilation/simd/simd_bit_shifts.c +++ b/core/iwasm/compilation/simd/simd_bit_shifts.c @@ -8,157 +8,137 @@ #include "../aot_emit_exception.h" #include "../../aot/aot_runtime.h" +enum integer_shift { + e_shift_i8x16, + e_shift_i16x8, + e_shift_i32x4, + e_shift_i64x2, +}; + static bool -simd_shift(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - IntShift shift_op, - LLVMTypeRef vector_type, - LLVMTypeRef element_type, - unsigned lane_width) +simd_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntShift shift_op, enum integer_shift itype) { - LLVMValueRef vector, offset, width, undef, zeros, result; - LLVMTypeRef zeros_type; + LLVMValueRef vector, offset, result = NULL; + LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE, + V128_i32x4_TYPE, V128_i64x2_TYPE }; + LLVMTypeRef element_type[] = { INT8_TYPE, INT16_TYPE, I32_TYPE, I64_TYPE }; + + LLVMValueRef undef[] = { LLVM_CONST(i8x16_undef), LLVM_CONST(i16x8_undef), + LLVM_CONST(i32x4_undef), LLVM_CONST(i64x2_undef) }; + LLVMValueRef mask[] = { LLVM_CONST(i8x16_vec_zero), + LLVM_CONST(i16x8_vec_zero), + LLVM_CONST(i32x4_vec_zero), + LLVM_CONST(i64x2_vec_zero) }; + LLVMValueRef lane_bits[] = { + LLVM_CONST(i32_eight), + LLVMConstInt(I32_TYPE, 16, true), + LLVMConstInt(I32_TYPE, 32, true), + LLVMConstInt(I32_TYPE, 64, true), + }; POP_I32(offset); - if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "vec"))) { - goto fail; - } - - if (!(width = LLVMConstInt(I32_TYPE, lane_width, true))) { - HANDLE_FAILURE("LLVMConstInt"); - goto fail; + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + vector_type[itype], "vec"))) { + return false; } - if (!(offset = - LLVMBuildURem(comp_ctx->builder, offset, width, "remainder"))) { - HANDLE_FAILURE("LLVMBuildURem"); - goto fail; - } - - if (I64_TYPE == element_type) { - if (!(offset = LLVMBuildZExt(comp_ctx->builder, offset, element_type, - "offset_scalar"))) { - HANDLE_FAILURE("LLVMBuildZExt"); - goto fail; - } - } - else { - if (!(offset = LLVMBuildTruncOrBitCast( - comp_ctx->builder, offset, element_type, "offset_scalar"))) { - HANDLE_FAILURE("LLVMBuildTrunc"); - goto fail; - } + /* offset mod LaneBits */ + if (!lane_bits[itype] + || !(offset = LLVMBuildSRem(comp_ctx->builder, offset, lane_bits[itype], + "offset_fix"))) { + HANDLE_FAILURE("LLVMBuildSRem"); + return false; } - /* create a vector with offset */ - if (!(undef = LLVMGetUndef(vector_type))) { - HANDLE_FAILURE("LLVMGetUndef"); - goto fail; + /* change type */ + if (itype < e_shift_i32x4) { + offset = LLVMBuildTrunc(comp_ctx->builder, offset, element_type[itype], + "offset_trunc"); } - - if (!(zeros_type = LLVMVectorType(I32_TYPE, 128 / lane_width))) { - HANDLE_FAILURE("LVMVectorType"); - goto fail; + else if (itype == e_shift_i64x2) { + offset = LLVMBuildZExt(comp_ctx->builder, offset, element_type[itype], + "offset_ext"); } - if (!(zeros = LLVMConstNull(zeros_type))) { - HANDLE_FAILURE("LLVMConstNull"); - goto fail; + if (!offset) { + HANDLE_FAILURE("LLVMBuildZext/LLVMBuildTrunc"); + return false; } - if (!(offset = LLVMBuildInsertElement(comp_ctx->builder, undef, offset, - I32_ZERO, "base_vector"))) { + /* splat to a vector */ + if (!(offset = + LLVMBuildInsertElement(comp_ctx->builder, undef[itype], offset, + I32_ZERO, "offset_vector_base"))) { HANDLE_FAILURE("LLVMBuildInsertElement"); - goto fail; + return false; } - if (!(offset = LLVMBuildShuffleVector(comp_ctx->builder, offset, undef, - zeros, "offset_vector"))) { + if (!(offset = + LLVMBuildShuffleVector(comp_ctx->builder, offset, undef[itype], + mask[itype], "offset_vector"))) { HANDLE_FAILURE("LLVMBuildShuffleVector"); - goto fail; + return false; } switch (shift_op) { case INT_SHL: { - if (!(result = - LLVMBuildShl(comp_ctx->builder, vector, offset, "shl"))) { - HANDLE_FAILURE("LLVMBuildShl"); - goto fail; - } + result = LLVMBuildShl(comp_ctx->builder, vector, offset, "shl"); break; } case INT_SHR_S: { - if (!(result = LLVMBuildAShr(comp_ctx->builder, vector, offset, - "ashr"))) { - HANDLE_FAILURE("LLVMBuildAShr"); - goto fail; - } + result = LLVMBuildAShr(comp_ctx->builder, vector, offset, "ashr"); break; } case INT_SHR_U: { - if (!(result = LLVMBuildLShr(comp_ctx->builder, vector, offset, - "lshr"))) { - HANDLE_FAILURE("LLVMBuildLShr"); - goto fail; - } + result = LLVMBuildLShr(comp_ctx->builder, vector, offset, "lshr"); break; } default: { - bh_assert(0); - goto fail; + break; } } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "result"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); + if (!result) { + HANDLE_FAILURE("LLVMBuildShl/LLVMBuildLShr/LLVMBuildAShr"); goto fail; } - PUSH_V128(result); - return true; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); + fail: return false; } bool -aot_compile_simd_i8x16_shift(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i8x16_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, IntShift shift_op) { - return simd_shift(comp_ctx, func_ctx, shift_op, V128_i8x16_TYPE, INT8_TYPE, - 8); + return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i8x16); } bool -aot_compile_simd_i16x8_shift(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i16x8_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, IntShift shift_op) { - return simd_shift(comp_ctx, func_ctx, shift_op, V128_i16x8_TYPE, - INT16_TYPE, 16); + return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i16x8); } bool -aot_compile_simd_i32x4_shift(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i32x4_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, IntShift shift_op) { - return simd_shift(comp_ctx, func_ctx, shift_op, V128_i32x4_TYPE, I32_TYPE, - 32); + return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i32x4); } bool -aot_compile_simd_i64x2_shift(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i64x2_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, IntShift shift_op) { - return simd_shift(comp_ctx, func_ctx, shift_op, V128_i64x2_TYPE, I64_TYPE, - 64); + return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i64x2); } diff --git a/core/iwasm/compilation/simd/simd_bit_shifts.h b/core/iwasm/compilation/simd/simd_bit_shifts.h index 5034060795..06e86cad01 100644 --- a/core/iwasm/compilation/simd/simd_bit_shifts.h +++ b/core/iwasm/compilation/simd/simd_bit_shifts.h @@ -13,23 +13,19 @@ extern "C" { #endif bool -aot_compile_simd_i8x16_shift(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i8x16_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, IntShift shift_op); bool -aot_compile_simd_i16x8_shift(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i16x8_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, IntShift shift_op); bool -aot_compile_simd_i32x4_shift(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i32x4_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, IntShift shift_op); bool -aot_compile_simd_i64x2_shift(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i64x2_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, IntShift shift_op); #ifdef __cplusplus diff --git a/core/iwasm/compilation/simd/simd_bitmask_extracts.c b/core/iwasm/compilation/simd/simd_bitmask_extracts.c index 79565cfc25..67d965426f 100644 --- a/core/iwasm/compilation/simd/simd_bitmask_extracts.c +++ b/core/iwasm/compilation/simd/simd_bitmask_extracts.c @@ -8,70 +8,92 @@ #include "../aot_emit_exception.h" #include "../../aot/aot_runtime.h" +enum integer_bitmask_type { + e_bitmask_i8x16, + e_bitmask_i16x8, + e_bitmask_i32x4, + e_bitmask_i64x2, +}; + +/* TODO: should use a much clever intrinsic */ static bool simd_build_bitmask(const AOTCompContext *comp_ctx, const AOTFuncContext *func_ctx, - uint8 length, - LLVMTypeRef vector_type, - LLVMTypeRef element_type, - const char *intrinsic) + enum integer_bitmask_type itype) { - LLVMValueRef vector, zeros, mask, mask_elements[16], cond, result; - LLVMTypeRef param_types[1], vector_ext_type; - const uint32 numbers[16] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, - 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, - 0x1000, 0x2000, 0x4000, 0x8000 }; + LLVMValueRef vector, mask, result; uint8 i; - - if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "vec"))) { + LLVMTypeRef vector_ext_type; + + uint32 lanes[] = { 16, 8, 4, 2 }; + uint32 lane_bits[] = { 8, 16, 32, 64 }; + LLVMTypeRef element_type[] = { INT8_TYPE, INT16_TYPE, I32_TYPE, I64_TYPE }; + LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE, + V128_i32x4_TYPE, V128_i64x2_TYPE }; + int32 mask_element[16] = { 0 }; + const char *intrinsic[] = { + "llvm.vector.reduce.or.v16i64", + "llvm.vector.reduce.or.v8i64", + "llvm.vector.reduce.or.v4i64", + "llvm.vector.reduce.or.v2i64", + }; + + LLVMValueRef ashr_distance; + + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + vector_type[itype], "vec"))) { goto fail; } - if (!(vector_ext_type = LLVMVectorType(I32_TYPE, length))) { - HANDLE_FAILURE("LLVMVectorType"); + /* fill every bit in a lange with its sign bit */ + if (!(ashr_distance = simd_build_splat_const_integer_vector( + comp_ctx, element_type[itype], lane_bits[itype] - 1, + lanes[itype]))) { goto fail; } - if (!(vector = LLVMBuildSExt(comp_ctx->builder, vector, vector_ext_type, - "vec_ext"))) { - HANDLE_FAILURE("LLVMBuildSExt"); + if (!(vector = LLVMBuildAShr(comp_ctx->builder, vector, ashr_distance, + "vec_ashr"))) { + HANDLE_FAILURE("LLVMBuildAShr"); goto fail; } - if (!(zeros = LLVMConstNull(vector_ext_type))) { - HANDLE_FAILURE("LLVMConstNull"); + if (!(vector_ext_type = LLVMVectorType(I64_TYPE, lanes[itype]))) { + HANDLE_FAILURE("LLVMVectorType"); goto fail; } - for (i = 0; i < 16; i++) { - if (!(mask_elements[i] = LLVMConstInt(I32_TYPE, numbers[i], false))) { - HANDLE_FAILURE("LLVMConstInt"); + if (e_bitmask_i64x2 != itype) { + if (!(vector = LLVMBuildSExt(comp_ctx->builder, vector, vector_ext_type, + "zext_to_i64"))) { goto fail; } } - if (!(mask = LLVMConstVector(mask_elements, length))) { - HANDLE_FAILURE("LLVMConstVector"); + for (i = 0; i < 16; i++) { + mask_element[i] = 0x1 << i; + } + + if (!(mask = simd_build_const_integer_vector(comp_ctx, I64_TYPE, + mask_element, lanes[itype]))) { goto fail; } - if (!(cond = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, vector, zeros, - "lt_zero"))) { - HANDLE_FAILURE("LLVMBuildICmp"); + if (!(vector = + LLVMBuildAnd(comp_ctx->builder, vector, mask, "mask_bits"))) { + HANDLE_FAILURE("LLVMBuildAnd"); goto fail; } if (!(result = - LLVMBuildSelect(comp_ctx->builder, cond, mask, zeros, "select"))) { - HANDLE_FAILURE("LLVMBuildSelect"); + aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic[itype], + I64_TYPE, &vector_ext_type, 1, vector))) { goto fail; } - param_types[0] = vector_ext_type; - if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, I32_TYPE, - param_types, 1, result))) { - HANDLE_FAILURE("LLVMBuildCall"); + if (!(result = + LLVMBuildTrunc(comp_ctx->builder, result, I32_TYPE, "to_i32"))) { + HANDLE_FAILURE("LLVMBuildTrunc"); goto fail; } @@ -86,24 +108,26 @@ bool aot_compile_simd_i8x16_bitmask(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_build_bitmask(comp_ctx, func_ctx, 16, V128_i8x16_TYPE, - INT8_TYPE, - "llvm.experimental.vector.reduce.or.v16i32"); + return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i8x16); } bool aot_compile_simd_i16x8_bitmask(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_build_bitmask(comp_ctx, func_ctx, 8, V128_i16x8_TYPE, - INT16_TYPE, - "llvm.experimental.vector.reduce.or.v8i32"); + return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i16x8); } bool aot_compile_simd_i32x4_bitmask(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_build_bitmask(comp_ctx, func_ctx, 4, V128_i32x4_TYPE, I32_TYPE, - "llvm.experimental.vector.reduce.or.v4i32"); + return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i32x4); +} + +bool +aot_compile_simd_i64x2_bitmask(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i64x2); } diff --git a/core/iwasm/compilation/simd/simd_bitmask_extracts.h b/core/iwasm/compilation/simd/simd_bitmask_extracts.h index b8cd5e86fa..aac4cc2ce5 100644 --- a/core/iwasm/compilation/simd/simd_bitmask_extracts.h +++ b/core/iwasm/compilation/simd/simd_bitmask_extracts.h @@ -13,17 +13,23 @@ extern "C" { #endif bool -aot_compile_simd_i8x16_bitmask(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_simd_i8x16_bitmask(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); bool -aot_compile_simd_i16x8_bitmask(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_simd_i16x8_bitmask(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); bool -aot_compile_simd_i32x4_bitmask(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_simd_i32x4_bitmask(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_i64x2_bitmask(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); #ifdef __cplusplus } /* end of extern "C" */ #endif #endif /* end of _SIMD_BITMASK_EXTRACTS_H_ */ - diff --git a/core/iwasm/compilation/simd/simd_bitwise_ops.c b/core/iwasm/compilation/simd/simd_bitwise_ops.c index 69e82bb850..66aef3637e 100644 --- a/core/iwasm/compilation/simd/simd_bitwise_ops.c +++ b/core/iwasm/compilation/simd/simd_bitwise_ops.c @@ -8,8 +8,7 @@ #include "../../aot/aot_runtime.h" static bool -v128_bitwise_two_component(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +v128_bitwise_two_component(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, V128Bitwise bitwise_op) { LLVMValueRef vector1, vector2, result; @@ -27,7 +26,7 @@ v128_bitwise_two_component(AOTCompContext *comp_ctx, break; case V128_OR: if (!(result = - LLVMBuildOr(comp_ctx->builder, vector1, vector2, "or"))) { + LLVMBuildOr(comp_ctx->builder, vector1, vector2, "or"))) { HANDLE_FAILURE("LLVMBuildAnd"); goto fail; } @@ -86,7 +85,7 @@ v128_bitwise_not(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) /* v128.or(v128.and(v1, c), v128.and(v2, v128.not(c))) */ static bool -v128_bitwise_bit_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +v128_bitwise_bitselect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { LLVMValueRef vector1, vector2, vector3, result; @@ -95,7 +94,7 @@ v128_bitwise_bit_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) POP_V128(vector1); if (!(vector1 = - LLVMBuildAnd(comp_ctx->builder, vector1, vector3, "a_and_c"))) { + LLVMBuildAnd(comp_ctx->builder, vector1, vector3, "a_and_c"))) { HANDLE_FAILURE("LLVMBuildAdd"); goto fail; } @@ -106,13 +105,13 @@ v128_bitwise_bit_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) } if (!(vector2 = - LLVMBuildAnd(comp_ctx->builder, vector2, vector3, "b_and_c"))) { + LLVMBuildAnd(comp_ctx->builder, vector2, vector3, "b_and_c"))) { HANDLE_FAILURE("LLVMBuildAdd"); goto fail; } if (!(result = - LLVMBuildOr(comp_ctx->builder, vector1, vector2, "a_or_b"))) { + LLVMBuildOr(comp_ctx->builder, vector1, vector2, "a_or_b"))) { HANDLE_FAILURE("LLVMBuildOr"); goto fail; } @@ -126,8 +125,7 @@ v128_bitwise_bit_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) bool aot_compile_simd_v128_bitwise(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Bitwise bitwise_op) + AOTFuncContext *func_ctx, V128Bitwise bitwise_op) { switch (bitwise_op) { case V128_AND: @@ -138,7 +136,7 @@ aot_compile_simd_v128_bitwise(AOTCompContext *comp_ctx, case V128_NOT: return v128_bitwise_not(comp_ctx, func_ctx); case V128_BITSELECT: - return v128_bitwise_bit_select(comp_ctx, func_ctx); + return v128_bitwise_bitselect(comp_ctx, func_ctx); default: bh_assert(0); return false; diff --git a/core/iwasm/compilation/simd/simd_bitwise_ops.h b/core/iwasm/compilation/simd/simd_bitwise_ops.h index 4717d0158b..ddf81c0b7d 100644 --- a/core/iwasm/compilation/simd/simd_bitwise_ops.h +++ b/core/iwasm/compilation/simd/simd_bitwise_ops.h @@ -14,8 +14,7 @@ extern "C" { bool aot_compile_simd_v128_bitwise(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Bitwise bitwise_op); + AOTFuncContext *func_ctx, V128Bitwise bitwise_op); #ifdef __cplusplus } /* end of extern "C" */ diff --git a/core/iwasm/compilation/simd/simd_bool_reductions.c b/core/iwasm/compilation/simd/simd_bool_reductions.c index c2abb30271..4607d680ae 100644 --- a/core/iwasm/compilation/simd/simd_bool_reductions.c +++ b/core/iwasm/compilation/simd/simd_bool_reductions.c @@ -8,58 +8,61 @@ #include "../aot_emit_exception.h" #include "../../aot/aot_runtime.h" +enum integer_all_true { + e_int_all_true_v16i8, + e_int_all_true_v8i16, + e_int_all_true_v4i32, + e_int_all_true_v2i64, +}; + static bool -simd_any_true(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - LLVMTypeRef vector_type, - LLVMTypeRef element_type, - const char *intrinsic) +simd_all_true(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + enum integer_all_true itype) { - LLVMValueRef vector, zeros, non_zero, result; + LLVMValueRef vector, result; + LLVMTypeRef vector_i1_type; + LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE, + V128_i32x4_TYPE, V128_i64x2_TYPE }; + uint32 lanes[] = { 16, 8, 4, 2 }; + const char *intrinsic[] = { + "llvm.vector.reduce.and.v16i1", + "llvm.vector.reduce.and.v8i1", + "llvm.vector.reduce.and.v4i1", + "llvm.vector.reduce.and.v2i1", + }; + LLVMValueRef zero[] = { + LLVM_CONST(i8x16_vec_zero), + LLVM_CONST(i16x8_vec_zero), + LLVM_CONST(i32x4_vec_zero), + LLVM_CONST(i64x2_vec_zero), + }; - if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "vec"))) { + if (!(vector_i1_type = LLVMVectorType(INT1_TYPE, lanes[itype]))) { + HANDLE_FAILURE("LLVMVectorType"); goto fail; } - if (!(zeros = LLVMConstNull(vector_type))) { - HANDLE_FAILURE("LLVMConstNull"); + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + vector_type[itype], "vector"))) { goto fail; } - /* icmp eq %vector, zeroinitialize */ - if (!(non_zero = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, vector, zeros, - "non_zero"))) { + /* compare with zero */ + if (!(result = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, vector, + zero[itype], "ne_zero"))) { HANDLE_FAILURE("LLVMBuildICmp"); goto fail; } - /* zext to */ - if (!(non_zero = LLVMBuildZExt(comp_ctx->builder, non_zero, vector_type, - "non_zero_ex"))) { - HANDLE_FAILURE("LLVMBuildZExt"); - goto fail; - } - - if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, element_type, - &vector_type, 1, non_zero))) { - HANDLE_FAILURE("LLVMBuildCall"); - goto fail; - } - - if (!(zeros = LLVMConstNull(element_type))) { - HANDLE_FAILURE("LLVMConstNull"); - goto fail; - } - - if (!(result = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, result, zeros, - "gt_zero"))) { - HANDLE_FAILURE("LLVMBuildICmp"); + /* check zero */ + if (!(result = + aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic[itype], + INT1_TYPE, &vector_i1_type, 1, result))) { goto fail; } if (!(result = - LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, "ret"))) { + LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, "to_i32"))) { HANDLE_FAILURE("LLVMBuildZExt"); goto fail; } @@ -72,81 +75,57 @@ simd_any_true(AOTCompContext *comp_ctx, } bool -aot_compile_simd_i8x16_any_true(AOTCompContext *comp_ctx, +aot_compile_simd_i8x16_all_true(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_any_true(comp_ctx, func_ctx, V128_i8x16_TYPE, INT8_TYPE, - "llvm.experimental.vector.reduce.add.v16i8"); + return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v16i8); } bool -aot_compile_simd_i16x8_any_true(AOTCompContext *comp_ctx, +aot_compile_simd_i16x8_all_true(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_any_true(comp_ctx, func_ctx, V128_i16x8_TYPE, INT16_TYPE, - "llvm.experimental.vector.reduce.add.v8i16"); + return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v8i16); } bool -aot_compile_simd_i32x4_any_true(AOTCompContext *comp_ctx, +aot_compile_simd_i32x4_all_true(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_any_true(comp_ctx, func_ctx, V128_i32x4_TYPE, I32_TYPE, - "llvm.experimental.vector.reduce.add.v4i32"); + return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v4i32); } -static bool -simd_all_true(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - LLVMTypeRef vector_type, - LLVMTypeRef element_type, - const char *intrinsic) +bool +aot_compile_simd_i64x2_all_true(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) { - LLVMValueRef vector, zeros, is_zero, result; - - if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "vec"))) { - goto fail; - } - - if (!(zeros = LLVMConstNull(vector_type))) { - HANDLE_FAILURE("LLVMConstNull"); - goto fail; - } - - /* icmp eq %vector, zeroinitialize */ - if (!(is_zero = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, vector, zeros, - "is_zero"))) { - HANDLE_FAILURE("LLVMBuildICmp"); - goto fail; - } + return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v2i64); +} - /* zext to */ - if (!(is_zero = LLVMBuildZExt(comp_ctx->builder, is_zero, vector_type, - "is_zero_ex"))) { - HANDLE_FAILURE("LLVMBuildZExt"); - goto fail; - } +bool +aot_compile_simd_v128_any_true(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + LLVMTypeRef vector_type; + LLVMValueRef vector, result; - if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, element_type, - &vector_type, 1, is_zero))) { - HANDLE_FAILURE("LLVMBuildCall"); - goto fail; + if (!(vector_type = LLVMVectorType(INT1_TYPE, 128))) { + return false; } - if (!(zeros = LLVMConstNull(element_type))) { - HANDLE_FAILURE("LLVMConstNull"); + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "vector"))) { goto fail; } - if (!(result = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, result, zeros, - "none"))) { - HANDLE_FAILURE("LLVMBuildICmp"); + if (!(result = aot_call_llvm_intrinsic( + comp_ctx, func_ctx, "llvm.vector.reduce.or.v128i1", INT1_TYPE, + &vector_type, 1, vector))) { goto fail; } if (!(result = - LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, "ret"))) { + LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, "to_i32"))) { HANDLE_FAILURE("LLVMBuildZExt"); goto fail; } @@ -157,27 +136,3 @@ simd_all_true(AOTCompContext *comp_ctx, fail: return false; } - -bool -aot_compile_simd_i8x16_all_true(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx) -{ - return simd_all_true(comp_ctx, func_ctx, V128_i8x16_TYPE, INT8_TYPE, - "llvm.experimental.vector.reduce.add.v16i8"); -} - -bool -aot_compile_simd_i16x8_all_true(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx) -{ - return simd_all_true(comp_ctx, func_ctx, V128_i16x8_TYPE, INT16_TYPE, - "llvm.experimental.vector.reduce.add.v8i16"); -} - -bool -aot_compile_simd_i32x4_all_true(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx) -{ - return simd_all_true(comp_ctx, func_ctx, V128_i32x4_TYPE, I32_TYPE, - "llvm.experimental.vector.reduce.add.v4i32"); -} diff --git a/core/iwasm/compilation/simd/simd_bool_reductions.h b/core/iwasm/compilation/simd/simd_bool_reductions.h index e67f00e7ee..649d5a5e2e 100644 --- a/core/iwasm/compilation/simd/simd_bool_reductions.h +++ b/core/iwasm/compilation/simd/simd_bool_reductions.h @@ -13,28 +13,24 @@ extern "C" { #endif bool -aot_compile_simd_i8x16_any_true(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx); - -bool -aot_compile_simd_i16x8_any_true(AOTCompContext *comp_ctx, +aot_compile_simd_i8x16_all_true(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); bool -aot_compile_simd_i32x4_any_true(AOTCompContext *comp_ctx, +aot_compile_simd_i16x8_all_true(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); bool -aot_compile_simd_i8x16_all_true(AOTCompContext *comp_ctx, +aot_compile_simd_i32x4_all_true(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); bool -aot_compile_simd_i16x8_all_true(AOTCompContext *comp_ctx, +aot_compile_simd_i64x2_all_true(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); bool -aot_compile_simd_i32x4_all_true(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx); +aot_compile_simd_v128_any_true(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); #ifdef __cplusplus } /* end of extern "C" */ diff --git a/core/iwasm/compilation/simd/simd_common.c b/core/iwasm/compilation/simd/simd_common.c index 81378fa00f..95bcdfdb04 100644 --- a/core/iwasm/compilation/simd/simd_common.c +++ b/core/iwasm/compilation/simd/simd_common.c @@ -7,8 +7,7 @@ LLVMValueRef simd_pop_v128_and_bitcast(const AOTCompContext *comp_ctx, - const AOTFuncContext *func_ctx, - LLVMTypeRef vec_type, + const AOTFuncContext *func_ctx, LLVMTypeRef vec_type, const char *name) { LLVMValueRef number; @@ -16,7 +15,7 @@ simd_pop_v128_and_bitcast(const AOTCompContext *comp_ctx, POP_V128(number); if (!(number = - LLVMBuildBitCast(comp_ctx->builder, number, vec_type, name))) { + LLVMBuildBitCast(comp_ctx->builder, number, vec_type, name))) { HANDLE_FAILURE("LLVMBuildBitCast"); goto fail; } @@ -28,8 +27,7 @@ simd_pop_v128_and_bitcast(const AOTCompContext *comp_ctx, bool simd_bitcast_and_push_v128(const AOTCompContext *comp_ctx, - const AOTFuncContext *func_ctx, - LLVMValueRef vector, + const AOTFuncContext *func_ctx, LLVMValueRef vector, const char *name) { if (!(vector = LLVMBuildBitCast(comp_ctx->builder, vector, V128_i64x2_TYPE, @@ -44,4 +42,116 @@ simd_bitcast_and_push_v128(const AOTCompContext *comp_ctx, return true; fail: return false; -} \ No newline at end of file +} + +LLVMValueRef +simd_lane_id_to_llvm_value(AOTCompContext *comp_ctx, uint8 lane_id) +{ + LLVMValueRef lane_indexes[] = { + LLVM_CONST(i32_zero), LLVM_CONST(i32_one), + LLVM_CONST(i32_two), LLVM_CONST(i32_three), + LLVM_CONST(i32_four), LLVM_CONST(i32_five), + LLVM_CONST(i32_six), LLVM_CONST(i32_seven), + LLVM_CONST(i32_eight), LLVM_CONST(i32_nine), + LLVM_CONST(i32_ten), LLVM_CONST(i32_eleven), + LLVM_CONST(i32_twelve), LLVM_CONST(i32_thirteen), + LLVM_CONST(i32_fourteen), LLVM_CONST(i32_fifteen), + }; + + return lane_id < 16 ? lane_indexes[lane_id] : NULL; +} + +LLVMValueRef +simd_build_const_integer_vector(const AOTCompContext *comp_ctx, + const LLVMTypeRef element_type, + const int *element_value, uint32 length) +{ + LLVMValueRef vector = NULL; + LLVMValueRef *elements; + unsigned i; + + if (!(elements = wasm_runtime_malloc(sizeof(LLVMValueRef) * length))) { + return NULL; + } + + for (i = 0; i < length; i++) { + if (!(elements[i] = + LLVMConstInt(element_type, element_value[i], true))) { + HANDLE_FAILURE("LLVMConstInst"); + goto fail; + } + } + + if (!(vector = LLVMConstVector(elements, length))) { + HANDLE_FAILURE("LLVMConstVector"); + goto fail; + } + +fail: + wasm_runtime_free(elements); + return vector; +} + +LLVMValueRef +simd_build_splat_const_integer_vector(const AOTCompContext *comp_ctx, + const LLVMTypeRef element_type, + const int64 element_value, uint32 length) +{ + LLVMValueRef vector = NULL, element; + LLVMValueRef *elements; + unsigned i; + + if (!(elements = wasm_runtime_malloc(sizeof(LLVMValueRef) * length))) { + return NULL; + } + + if (!(element = LLVMConstInt(element_type, element_value, true))) { + HANDLE_FAILURE("LLVMConstInt"); + goto fail; + } + + for (i = 0; i < length; i++) { + elements[i] = element; + } + + if (!(vector = LLVMConstVector(elements, length))) { + HANDLE_FAILURE("LLVMConstVector"); + goto fail; + } + +fail: + wasm_runtime_free(elements); + return vector; +} + +LLVMValueRef +simd_build_splat_const_float_vector(const AOTCompContext *comp_ctx, + const LLVMTypeRef element_type, + const float element_value, uint32 length) +{ + LLVMValueRef vector = NULL, element; + LLVMValueRef *elements; + unsigned i; + + if (!(elements = wasm_runtime_malloc(sizeof(LLVMValueRef) * length))) { + return NULL; + } + + if (!(element = LLVMConstReal(element_type, element_value))) { + HANDLE_FAILURE("LLVMConstReal"); + goto fail; + } + + for (i = 0; i < length; i++) { + elements[i] = element; + } + + if (!(vector = LLVMConstVector(elements, length))) { + HANDLE_FAILURE("LLVMConstVector"); + goto fail; + } + +fail: + wasm_runtime_free(elements); + return vector; +} diff --git a/core/iwasm/compilation/simd/simd_common.h b/core/iwasm/compilation/simd/simd_common.h index 5f029b01ec..c7a08dbc73 100644 --- a/core/iwasm/compilation/simd/simd_common.h +++ b/core/iwasm/compilation/simd/simd_common.h @@ -8,16 +8,38 @@ #include "../aot_compiler.h" +static inline bool +is_target_x86(AOTCompContext *comp_ctx) +{ + return !strncmp(comp_ctx->target_arch, "x86_64", 6) + || !strncmp(comp_ctx->target_arch, "i386", 4); +} + LLVMValueRef simd_pop_v128_and_bitcast(const AOTCompContext *comp_ctx, - const AOTFuncContext *func_ctx, - LLVMTypeRef vec_type, + const AOTFuncContext *func_ctx, LLVMTypeRef vec_type, const char *name); bool simd_bitcast_and_push_v128(const AOTCompContext *comp_ctx, - const AOTFuncContext *func_ctx, - LLVMValueRef vector, + const AOTFuncContext *func_ctx, LLVMValueRef vector, const char *name); +LLVMValueRef +simd_lane_id_to_llvm_value(AOTCompContext *comp_ctx, uint8 lane_id); + +LLVMValueRef +simd_build_const_integer_vector(const AOTCompContext *comp_ctx, + const LLVMTypeRef element_type, + const int *element_value, uint32 length); + +LLVMValueRef +simd_build_splat_const_integer_vector(const AOTCompContext *comp_ctx, + const LLVMTypeRef element_type, + const int64 element_value, uint32 length); + +LLVMValueRef +simd_build_splat_const_float_vector(const AOTCompContext *comp_ctx, + const LLVMTypeRef element_type, + const float element_value, uint32 length); #endif /* _SIMD_COMMON_H_ */ \ No newline at end of file diff --git a/core/iwasm/compilation/simd/simd_comparisons.c b/core/iwasm/compilation/simd/simd_comparisons.c index 9b95a85b86..8a87ab25bc 100644 --- a/core/iwasm/compilation/simd/simd_comparisons.c +++ b/core/iwasm/compilation/simd/simd_comparisons.c @@ -86,10 +86,8 @@ int_cond_2_predicate(IntCond cond, LLVMIntPredicate *out) } static bool -interger_vector_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - IntCond cond, - LLVMTypeRef vector_type) +interger_vector_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntCond cond, LLVMTypeRef vector_type) { LLVMValueRef vec1, vec2, result; LLVMIntPredicate int_pred; @@ -110,14 +108,14 @@ interger_vector_compare(AOTCompContext *comp_ctx, } /* icmp %vec1, %vec2 */ if (!(result = - LLVMBuildICmp(comp_ctx->builder, int_pred, vec1, vec2, "cmp"))) { + LLVMBuildICmp(comp_ctx->builder, int_pred, vec1, vec2, "cmp"))) { HANDLE_FAILURE("LLVMBuildICmp"); goto fail; } /* sext %result to */ if (!(result = - LLVMBuildSExt(comp_ctx->builder, result, vector_type, "ext"))) { + LLVMBuildSExt(comp_ctx->builder, result, vector_type, "ext"))) { HANDLE_FAILURE("LLVMBuildSExt"); goto fail; } @@ -138,33 +136,35 @@ interger_vector_compare(AOTCompContext *comp_ctx, bool aot_compile_simd_i8x16_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - IntCond cond) + AOTFuncContext *func_ctx, IntCond cond) { return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i8x16_TYPE); } bool aot_compile_simd_i16x8_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - IntCond cond) + AOTFuncContext *func_ctx, IntCond cond) { return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i16x8_TYPE); } bool aot_compile_simd_i32x4_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - IntCond cond) + AOTFuncContext *func_ctx, IntCond cond) { return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i32x4_TYPE); } +bool +aot_compile_simd_i64x2_compare(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, IntCond cond) +{ + return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i64x2_TYPE); +} + static bool -float_vector_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - FloatCond cond, - LLVMTypeRef vector_type, +float_vector_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatCond cond, LLVMTypeRef vector_type, LLVMTypeRef result_type) { LLVMValueRef vec1, vec2, result; @@ -186,14 +186,14 @@ float_vector_compare(AOTCompContext *comp_ctx, } /* fcmp %vec1, %vec2 */ if (!(result = - LLVMBuildFCmp(comp_ctx->builder, real_pred, vec1, vec2, "cmp"))) { + LLVMBuildFCmp(comp_ctx->builder, real_pred, vec1, vec2, "cmp"))) { HANDLE_FAILURE("LLVMBuildFCmp"); goto fail; } /* sext %result to */ if (!(result = - LLVMBuildSExt(comp_ctx->builder, result, result_type, "ext"))) { + LLVMBuildSExt(comp_ctx->builder, result, result_type, "ext"))) { HANDLE_FAILURE("LLVMBuildSExt"); goto fail; } @@ -214,8 +214,7 @@ float_vector_compare(AOTCompContext *comp_ctx, bool aot_compile_simd_f32x4_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - FloatCond cond) + AOTFuncContext *func_ctx, FloatCond cond) { return float_vector_compare(comp_ctx, func_ctx, cond, V128_f32x4_TYPE, V128_i32x4_TYPE); @@ -223,8 +222,7 @@ aot_compile_simd_f32x4_compare(AOTCompContext *comp_ctx, bool aot_compile_simd_f64x2_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - FloatCond cond) + AOTFuncContext *func_ctx, FloatCond cond) { return float_vector_compare(comp_ctx, func_ctx, cond, V128_f64x2_TYPE, V128_i64x2_TYPE); diff --git a/core/iwasm/compilation/simd/simd_comparisons.h b/core/iwasm/compilation/simd/simd_comparisons.h index 46d8167149..322ebefb28 100644 --- a/core/iwasm/compilation/simd/simd_comparisons.h +++ b/core/iwasm/compilation/simd/simd_comparisons.h @@ -14,28 +14,27 @@ extern "C" { bool aot_compile_simd_i8x16_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - IntCond cond); + AOTFuncContext *func_ctx, IntCond cond); bool aot_compile_simd_i16x8_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - IntCond cond); + AOTFuncContext *func_ctx, IntCond cond); bool aot_compile_simd_i32x4_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - IntCond cond); + AOTFuncContext *func_ctx, IntCond cond); + +bool +aot_compile_simd_i64x2_compare(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, IntCond cond); bool aot_compile_simd_f32x4_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - FloatCond cond); + AOTFuncContext *func_ctx, FloatCond cond); bool aot_compile_simd_f64x2_compare(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - FloatCond cond); + AOTFuncContext *func_ctx, FloatCond cond); #ifdef __cplusplus } /* end of extern "C" */ diff --git a/core/iwasm/compilation/simd/simd_construct_values.c b/core/iwasm/compilation/simd/simd_construct_values.c index 1438a16393..ceb09e370f 100644 --- a/core/iwasm/compilation/simd/simd_construct_values.c +++ b/core/iwasm/compilation/simd/simd_construct_values.c @@ -3,34 +3,30 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#include "simd_common.h" #include "simd_construct_values.h" #include "../aot_emit_exception.h" #include "../interpreter/wasm_opcode.h" #include "../../aot/aot_runtime.h" bool -aot_compile_simd_v128_const(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_v128_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, const uint8 *imm_bytes) { uint64 imm1, imm2; - LLVMValueRef undef, first_long, agg1, second_long, agg2; + LLVMValueRef first_long, agg1, second_long, agg2; wasm_runtime_read_v128(imm_bytes, &imm1, &imm2); - if (!(undef = LLVMGetUndef(V128_i64x2_TYPE))) { - HANDLE_FAILURE("LLVMGetUndef"); - goto fail; - } - /* %agg1 = insertelement <2 x i64> undef, i16 0, i64 ${*imm} */ if (!(first_long = I64_CONST(imm1))) { HANDLE_FAILURE("LLVMConstInt"); goto fail; } - if (!(agg1 = LLVMBuildInsertElement(comp_ctx->builder, undef, first_long, - I32_ZERO, "agg1"))) { + if (!(agg1 = + LLVMBuildInsertElement(comp_ctx->builder, LLVM_CONST(i64x2_undef), + first_long, I32_ZERO, "agg1"))) { HANDLE_FAILURE("LLVMBuildInsertElement"); goto fail; } @@ -48,143 +44,92 @@ aot_compile_simd_v128_const(AOTCompContext *comp_ctx, } PUSH_V128(agg2); - return true; fail: return false; } bool -aot_compile_simd_splat(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 splat_opcode) +aot_compile_simd_splat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode) { - LLVMValueRef value, undef, base, mask, new_vector, result; - LLVMTypeRef all_zero_ty; - - switch (splat_opcode) { + uint32 opcode_index = opcode - SIMD_i8x16_splat; + LLVMValueRef value = NULL, base, new_vector; + LLVMValueRef undefs[] = { + LLVM_CONST(i8x16_undef), LLVM_CONST(i16x8_undef), + LLVM_CONST(i32x4_undef), LLVM_CONST(i64x2_undef), + LLVM_CONST(f32x4_undef), LLVM_CONST(f64x2_undef), + }; + LLVMValueRef masks[] = { + LLVM_CONST(i32x16_zero), LLVM_CONST(i32x8_zero), LLVM_CONST(i32x4_zero), + LLVM_CONST(i32x2_zero), LLVM_CONST(i32x4_zero), LLVM_CONST(i32x2_zero), + }; + + switch (opcode) { case SIMD_i8x16_splat: { LLVMValueRef input; POP_I32(input); - /* trunc i32 %input to i8 */ - if (!(value = LLVMBuildTrunc(comp_ctx->builder, input, INT8_TYPE, - "trunc"))) { - HANDLE_FAILURE("LLVMBuildTrunc"); - goto fail; - } - undef = LLVMGetUndef(V128_i8x16_TYPE); - if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 16))) { - HANDLE_FAILURE("LLVMVectorType"); - goto fail; - } + value = + LLVMBuildTrunc(comp_ctx->builder, input, INT8_TYPE, "trunc"); break; } case SIMD_i16x8_splat: { LLVMValueRef input; POP_I32(input); - /* trunc i32 %input to i16 */ - if (!(value = LLVMBuildTrunc(comp_ctx->builder, input, INT16_TYPE, - "trunc"))) { - HANDLE_FAILURE("LLVMBuildTrunc"); - goto fail; - } - undef = LLVMGetUndef(V128_i16x8_TYPE); - if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 8))) { - HANDLE_FAILURE("LLVMVectorType"); - goto fail; - } + value = + LLVMBuildTrunc(comp_ctx->builder, input, INT16_TYPE, "trunc"); break; } case SIMD_i32x4_splat: { POP_I32(value); - undef = LLVMGetUndef(V128_i32x4_TYPE); - - if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 4))) { - HANDLE_FAILURE("LLVMVectorType"); - goto fail; - } break; } case SIMD_i64x2_splat: { POP(value, VALUE_TYPE_I64); - undef = LLVMGetUndef(V128_i64x2_TYPE); - - if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 2))) { - HANDLE_FAILURE("LLVMVectorType"); - goto fail; - } break; } case SIMD_f32x4_splat: { POP(value, VALUE_TYPE_F32); - undef = LLVMGetUndef(V128_f32x4_TYPE); - - if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 4))) { - HANDLE_FAILURE("LLVMVectorType"); - goto fail; - } break; } case SIMD_f64x2_splat: { POP(value, VALUE_TYPE_F64); - undef = LLVMGetUndef(V128_f64x2_TYPE); - - if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 2))) { - HANDLE_FAILURE("LLVMVectorType"); - goto fail; - } break; } default: { - bh_assert(0); - goto fail; + break; } } - if (!undef) { - HANDLE_FAILURE("LVMGetUndef"); + + if (!value) { goto fail; } /* insertelement undef, ty %value, i32 0 */ - if (!(base = LLVMBuildInsertElement(comp_ctx->builder, undef, value, - I32_ZERO, "base"))) { + if (!(base = LLVMBuildInsertElement(comp_ctx->builder, undefs[opcode_index], + value, I32_ZERO, "base"))) { HANDLE_FAILURE("LLVMBuildInsertElement"); goto fail; } - /* zeroinitializer */ - if (!(mask = LLVMConstNull(all_zero_ty))) { - HANDLE_FAILURE("LLVMConstNull"); - goto fail; - } - /* shufflevector %base, undef, zeroinitializer */ - if (!(new_vector = LLVMBuildShuffleVector(comp_ctx->builder, base, undef, - mask, "new_vector"))) { + if (!(new_vector = LLVMBuildShuffleVector( + comp_ctx->builder, base, undefs[opcode_index], + masks[opcode_index], "new_vector"))) { HANDLE_FAILURE("LLVMBuildShuffleVector"); goto fail; } - /* bitcast to <2 x i64> */ - if (!(result = LLVMBuildBitCast(comp_ctx->builder, new_vector, - V128_i64x2_TYPE, "ret"))) { - HANDLE_FAILURE("LLVMBuidlCast"); - goto fail; - } - - /* push result into the stack */ - PUSH_V128(result); - - return true; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, new_vector, "result"); fail: return false; } diff --git a/core/iwasm/compilation/simd/simd_construct_values.h b/core/iwasm/compilation/simd/simd_construct_values.h index 12bc3dedf9..8cd50c88bc 100644 --- a/core/iwasm/compilation/simd/simd_construct_values.h +++ b/core/iwasm/compilation/simd/simd_construct_values.h @@ -13,13 +13,11 @@ extern "C" { #endif bool -aot_compile_simd_v128_const(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_v128_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, const uint8 *imm_bytes); bool -aot_compile_simd_splat(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_splat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint8 splat_opcode); #ifdef __cplusplus diff --git a/core/iwasm/compilation/simd/simd_conversions.c b/core/iwasm/compilation/simd/simd_conversions.c index d330c38a31..554b088d0e 100644 --- a/core/iwasm/compilation/simd/simd_conversions.c +++ b/core/iwasm/compilation/simd/simd_conversions.c @@ -10,784 +10,734 @@ #include "../../aot/aot_runtime.h" static bool -is_target_x86(AOTCompContext *comp_ctx) -{ - return !strncmp(comp_ctx->target_arch, "x86_64", 6) || - !strncmp(comp_ctx->target_arch, "i386", 4); -} - -static bool -simd_integer_narrow(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_signed, - LLVMTypeRef in_vector_type, - LLVMTypeRef out_vector_type, - const char *instrinsic) +simd_integer_narrow_x86(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMTypeRef in_vector_type, LLVMTypeRef out_vector_type, + const char *instrinsic) { LLVMValueRef vector1, vector2, result; LLVMTypeRef param_types[2] = { in_vector_type, in_vector_type }; if (!(vector2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - in_vector_type, "vec2"))) { - goto fail; + in_vector_type, "vec2")) + || !(vector1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + in_vector_type, "vec1"))) { + return false; } - if (!(vector1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - in_vector_type, "vec1"))) { - goto fail; - } - - if (!(result = - aot_call_llvm_intrinsic(comp_ctx, instrinsic, out_vector_type, - param_types, 2, vector1, vector2))) { + if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, instrinsic, + out_vector_type, param_types, 2, + vector1, vector2))) { HANDLE_FAILURE("LLVMBuildCall"); - goto fail; - } - - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; + return false; } - PUSH_V128(result); - return true; -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } +enum integer_sat_type { + e_sat_i16x8 = 0, + e_sat_i32x4, + e_sat_i64x2, + e_sat_i32x8, +}; + static LLVMValueRef -build_intx4_vector(const AOTCompContext *comp_ctx, - const LLVMTypeRef element_type, - const int *element_value) +simd_saturate(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + enum integer_sat_type itype, LLVMValueRef vector, + LLVMValueRef min, LLVMValueRef max, bool is_signed) { - LLVMValueRef vector, elements[4]; - unsigned i; - - for (i = 0; i < 4; i++) { - if (!(elements[i] = - LLVMConstInt(element_type, element_value[i], true))) { - HANDLE_FAILURE("LLVMConstInst"); - goto fail; + LLVMValueRef result; + LLVMTypeRef vector_type; + + LLVMTypeRef param_types[][2] = { + { V128_i16x8_TYPE, V128_i16x8_TYPE }, + { V128_i32x4_TYPE, V128_i32x4_TYPE }, + { V128_i64x2_TYPE, V128_i64x2_TYPE }, + { 0 }, + }; + + const char *smin_intrinsic[] = { + "llvm.smin.v8i16", + "llvm.smin.v4i32", + "llvm.smin.v2i64", + "llvm.smin.v8i32", + }; + + const char *umin_intrinsic[] = { + "llvm.umin.v8i16", + "llvm.umin.v4i32", + "llvm.umin.v2i64", + "llvm.umin.v8i32", + }; + + const char *smax_intrinsic[] = { + "llvm.smax.v8i16", + "llvm.smax.v4i32", + "llvm.smax.v2i64", + "llvm.smax.v8i32", + }; + + const char *umax_intrinsic[] = { + "llvm.umax.v8i16", + "llvm.umax.v4i32", + "llvm.umax.v2i64", + "llvm.umax.v8i32", + }; + + if (e_sat_i32x8 == itype) { + if (!(vector_type = LLVMVectorType(I32_TYPE, 8))) { + HANDLE_FAILURE("LLVMVectorType"); + return NULL; } + + param_types[itype][0] = vector_type; + param_types[itype][1] = vector_type; } - if (!(vector = LLVMConstVector(elements, 4))) { - HANDLE_FAILURE("LLVMConstVector"); - goto fail; + if (!(result = aot_call_llvm_intrinsic( + comp_ctx, func_ctx, + is_signed ? smin_intrinsic[itype] : umin_intrinsic[itype], + param_types[itype][0], param_types[itype], 2, vector, max)) + || !(result = aot_call_llvm_intrinsic( + comp_ctx, func_ctx, + is_signed ? smax_intrinsic[itype] : umax_intrinsic[itype], + param_types[itype][0], param_types[itype], 2, result, min))) { + return NULL; } - return vector; -fail: - return NULL; + + return result; } -static LLVMValueRef -build_intx8_vector(const AOTCompContext *comp_ctx, - const LLVMTypeRef element_type, - const int *element_value) +static bool +simd_integer_narrow_common(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + enum integer_sat_type itype, bool is_signed) { - LLVMValueRef vector, elements[8]; - unsigned i; - - for (i = 0; i < 8; i++) { - if (!(elements[i] = - LLVMConstInt(element_type, element_value[i], true))) { - HANDLE_FAILURE("LLVMConstInst"); - goto fail; - } + LLVMValueRef vec1, vec2, min, max, mask, result; + LLVMTypeRef in_vector_type[] = { V128_i16x8_TYPE, V128_i32x4_TYPE, + V128_i64x2_TYPE }; + LLVMTypeRef min_max_type[] = { INT16_TYPE, I32_TYPE, I64_TYPE }; + LLVMTypeRef trunc_type[3] = { 0 }; + uint8 length[] = { 8, 4, 2 }; + + int64 smin[] = { 0xff80, 0xffFF8000, 0xffFFffFF80000000 }; + int64 umin[] = { 0x0, 0x0, 0x0 }; + int64 smax[] = { 0x007f, 0x00007fff, 0x000000007fFFffFF }; + int64 umax[] = { 0x00ff, 0x0000ffff, 0x00000000ffFFffFF }; + + LLVMValueRef mask_element[] = { + LLVM_CONST(i32_zero), LLVM_CONST(i32_one), + LLVM_CONST(i32_two), LLVM_CONST(i32_three), + LLVM_CONST(i32_four), LLVM_CONST(i32_five), + LLVM_CONST(i32_six), LLVM_CONST(i32_seven), + LLVM_CONST(i32_eight), LLVM_CONST(i32_nine), + LLVM_CONST(i32_ten), LLVM_CONST(i32_eleven), + LLVM_CONST(i32_twelve), LLVM_CONST(i32_thirteen), + LLVM_CONST(i32_fourteen), LLVM_CONST(i32_fifteen), + }; + + if (!(trunc_type[0] == LLVMVectorType(INT8_TYPE, 8)) + || !(trunc_type[1] == LLVMVectorType(INT16_TYPE, 4)) + || !(trunc_type[2] == LLVMVectorType(I32_TYPE, 2))) { + HANDLE_FAILURE("LLVMVectorType"); + return false; + } + + if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + in_vector_type[itype], "vec2")) + || !(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + in_vector_type[itype], "vec1"))) { + return false; + } + + if (!(max = simd_build_splat_const_integer_vector( + comp_ctx, min_max_type[itype], + is_signed ? smax[itype] : umax[itype], length[itype])) + || !(min = simd_build_splat_const_integer_vector( + comp_ctx, min_max_type[itype], + is_signed ? smin[itype] : umin[itype], length[itype]))) { + return false; + } + + /* sat */ + if (!(vec1 = simd_saturate(comp_ctx, func_ctx, e_sat_i16x8, vec1, min, max, + is_signed)) + || !(vec2 = simd_saturate(comp_ctx, func_ctx, e_sat_i16x8, vec2, min, + max, is_signed))) { + return false; + } + + /* trunc */ + if (!(vec1 = LLVMBuildTrunc(comp_ctx->builder, vec1, trunc_type[itype], + "vec1_trunc")) + || !(vec2 = LLVMBuildTrunc(comp_ctx->builder, vec2, trunc_type[itype], + "vec2_trunc"))) { + HANDLE_FAILURE("LLVMBuildTrunc"); + return false; } - if (!(vector = LLVMConstVector(elements, 8))) { - HANDLE_FAILURE("LLVMConstVector"); - goto fail; + /* combine */ + if (!(mask = LLVMConstVector(mask_element, (length[itype] << 1)))) { + HANDLE_FAILURE("LLVMConstInt"); + return false; } - return vector; -fail: - return NULL; + if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, vec1, vec2, mask, + "vec_shuffle"))) { + HANDLE_FAILURE("LLVMBuildShuffleVector"); + return false; + } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } -static LLVMValueRef -build_intx16_vector(const AOTCompContext *comp_ctx, - const LLVMTypeRef element_type, - const int *element_value) +bool +aot_compile_simd_i8x16_narrow_i16x8(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_signed) { - LLVMValueRef vector, elements[16]; - unsigned i; - - for (i = 0; i < 16; i++) { - if (!(elements[i] = - LLVMConstInt(element_type, element_value[i], true))) { - HANDLE_FAILURE("LLVMConstInst"); - goto fail; - } + if (is_target_x86(comp_ctx)) { + return simd_integer_narrow_x86( + comp_ctx, func_ctx, V128_i16x8_TYPE, V128_i8x16_TYPE, + is_signed ? "llvm.x86.sse2.packsswb.128" + : "llvm.x86.sse2.packuswb.128"); } - - if (!(vector = LLVMConstVector(elements, 16))) { - HANDLE_FAILURE("LLVMConstVector"); - goto fail; + else { + return simd_integer_narrow_common(comp_ctx, func_ctx, e_sat_i16x8, + is_signed); } - - return vector; -fail: - return NULL; } bool -aot_compile_simd_i8x16_narrow_i16x8_x86(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_signed) +aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_signed) { - return simd_integer_narrow( - comp_ctx, func_ctx, is_signed, V128_i16x8_TYPE, V128_i8x16_TYPE, - is_signed ? "llvm.x86.sse2.packsswb.128" : "llvm.x86.sse2.packuswb.128"); + if (is_target_x86(comp_ctx)) { + return simd_integer_narrow_x86(comp_ctx, func_ctx, V128_i32x4_TYPE, + V128_i16x8_TYPE, + is_signed ? "llvm.x86.sse2.packssdw.128" + : "llvm.x86.sse41.packusdw"); + } + else { + return simd_integer_narrow_common(comp_ctx, func_ctx, e_sat_i32x4, + is_signed); + } } bool -aot_compile_simd_i16x8_narrow_i32x4_x86(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_signed) +aot_compile_simd_i32x4_narrow_i64x2(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_signed) { - return simd_integer_narrow( - comp_ctx, func_ctx, is_signed, V128_i32x4_TYPE, V128_i16x8_TYPE, - is_signed ? "llvm.x86.sse2.packssdw.128" : "llvm.x86.sse41.packusdw"); + /* TODO: x86 intrinsics */ + return simd_integer_narrow_common(comp_ctx, func_ctx, e_sat_i64x2, + is_signed); } -static bool -aot_compile_simd_i8x16_narrow_i16x8_common(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_signed) -{ - LLVMValueRef vector1, vector2, result, vector_min, vector_max, shuffle, - vector1_clamped, vector2_clamped, vector1_trunced, vector2_trunced, - shuffle_vector; - LLVMValueRef v1_gt_max, v1_lt_min, v2_gt_max, v2_lt_min; - - int min_s_array[8] = { 0xff80, 0xff80, 0xff80, 0xff80, - 0xff80, 0xff80, 0xff80, 0xff80 }; - int max_s_array[8] = { 0x007f, 0x007f, 0x007f, 0x007f, - 0x007f, 0x007f, 0x007f, 0x007f }; - - int min_u_array[8] = { 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000 }; - int max_u_array[8] = { 0x00ff, 0x00ff, 0x00ff, 0x00ff, - 0x00ff, 0x00ff, 0x00ff, 0x00ff }; +enum integer_extend_type { + e_ext_i8x16, + e_ext_i16x8, + e_ext_i32x4, +}; - int shuffle_array[16] = { 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15 }; - - if (!(vector2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_i16x8_TYPE, "vec2"))) { - goto fail; - } - - if (!(vector1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_i16x8_TYPE, "vec1"))) { - goto fail; - } - - if (!(vector_min = build_intx8_vector( - comp_ctx, INT16_TYPE, is_signed ? min_s_array : min_u_array))) { - goto fail; - } - if (!(vector_max = build_intx8_vector( - comp_ctx, INT16_TYPE, is_signed ? max_s_array : max_u_array))) { - goto fail; - } - if (!(shuffle = build_intx16_vector(comp_ctx, I32_TYPE, shuffle_array))) { - goto fail; - } - - if (!(v1_gt_max = LLVMBuildICmp(comp_ctx->builder, LLVMIntSGT, vector1, - vector_max, "v1_great_than_max"))) { - HANDLE_FAILURE("LLVMBuldICmp"); - goto fail; - } - - if (!(v2_gt_max = LLVMBuildICmp(comp_ctx->builder, LLVMIntSGT, vector2, - vector_max, "v2_great_than_max"))) { - HANDLE_FAILURE("LLVMBuldICmp"); - goto fail; - } - - if (!(v1_lt_min = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, vector1, - vector_min, "v1_less_than_min"))) { - HANDLE_FAILURE("LLVMBuldICmp"); - goto fail; - } - - if (!(v2_lt_min = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, vector2, - vector_min, "v2_less_than_min"))) { - HANDLE_FAILURE("LLVMBuldICmp"); - goto fail; +static LLVMValueRef +simd_integer_extension(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + enum integer_extend_type itype, LLVMValueRef vector, + bool lower_half, bool is_signed) +{ + LLVMValueRef mask, sub_vector, result; + LLVMValueRef bits[] = { + LLVM_CONST(i32_zero), LLVM_CONST(i32_one), + LLVM_CONST(i32_two), LLVM_CONST(i32_three), + LLVM_CONST(i32_four), LLVM_CONST(i32_five), + LLVM_CONST(i32_six), LLVM_CONST(i32_seven), + LLVM_CONST(i32_eight), LLVM_CONST(i32_nine), + LLVM_CONST(i32_ten), LLVM_CONST(i32_eleven), + LLVM_CONST(i32_twelve), LLVM_CONST(i32_thirteen), + LLVM_CONST(i32_fourteen), LLVM_CONST(i32_fifteen), + }; + LLVMTypeRef out_vector_type[] = { V128_i16x8_TYPE, V128_i32x4_TYPE, + V128_i64x2_TYPE }; + LLVMValueRef undef[] = { LLVM_CONST(i8x16_undef), LLVM_CONST(i16x8_undef), + LLVM_CONST(i32x4_undef) }; + uint32 sub_vector_length[] = { 8, 4, 2 }; + + if (!(mask = lower_half ? LLVMConstVector(bits, sub_vector_length[itype]) + : LLVMConstVector(bits + sub_vector_length[itype], + sub_vector_length[itype]))) { + HANDLE_FAILURE("LLVMConstVector"); + return false; } - if (!(vector1_clamped = - LLVMBuildSelect(comp_ctx->builder, v1_gt_max, vector_max, vector1, - "vector1_clamped_max"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; + /* retrive the low or high half */ + if (!(sub_vector = LLVMBuildShuffleVector(comp_ctx->builder, vector, + undef[itype], mask, "half"))) { + HANDLE_FAILURE("LLVMBuildShuffleVector"); + return false; } - if (!(vector1_clamped = - LLVMBuildSelect(comp_ctx->builder, v1_lt_min, vector_min, - vector1_clamped, "vector1_clamped_min"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; + if (is_signed) { + if (!(result = LLVMBuildSExt(comp_ctx->builder, sub_vector, + out_vector_type[itype], "sext"))) { + HANDLE_FAILURE("LLVMBuildSExt"); + return false; + } } - - if (!(vector2_clamped = - LLVMBuildSelect(comp_ctx->builder, v2_gt_max, vector_max, vector2, - "vector2_clamped_max"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; + else { + if (!(result = LLVMBuildZExt(comp_ctx->builder, sub_vector, + out_vector_type[itype], "zext"))) { + HANDLE_FAILURE("LLVMBuildZExt"); + return false; + } } - if (!(vector2_clamped = - LLVMBuildSelect(comp_ctx->builder, v2_lt_min, vector_min, - vector2_clamped, "vector2_clamped_min"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; - } + return result; +} - if (!(vector1_trunced = - LLVMBuildTrunc(comp_ctx->builder, vector1_clamped, - LLVMVectorType(INT8_TYPE, 8), "vector1_trunced"))) { - HANDLE_FAILURE("LLVMBuildTrunc"); - goto fail; - } +static bool +simd_integer_extension_wrapper(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + enum integer_extend_type itype, bool lower_half, + bool is_signed) +{ + LLVMValueRef vector, result; - if (!(vector2_trunced = - LLVMBuildTrunc(comp_ctx->builder, vector2_clamped, - LLVMVectorType(INT8_TYPE, 8), "vector2_trunced"))) { - HANDLE_FAILURE("LLVMBuildTrunc"); - goto fail; - } + LLVMTypeRef in_vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE, + V128_i32x4_TYPE }; - if (!(shuffle_vector = LLVMBuildShuffleVector( - comp_ctx->builder, vector1_trunced, vector2_trunced, shuffle, - "shuffle_vector"))) { - HANDLE_FAILURE("LLVMBuildShuffleVector"); - goto fail; + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + in_vector_type[itype], "vec"))) { + return false; } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, shuffle_vector, - V128_i64x2_TYPE, "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; + if (!(result = simd_integer_extension(comp_ctx, func_ctx, itype, vector, + lower_half, is_signed))) { + return false; } - PUSH_V128(result); - return true; - -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool -aot_compile_simd_i8x16_narrow_i16x8(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i16x8_extend_i8x16(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool lower_half, bool is_signed) { - if (is_target_x86(comp_ctx)) { - return aot_compile_simd_i8x16_narrow_i16x8_x86(comp_ctx, func_ctx, - is_signed); - } - else { - return aot_compile_simd_i8x16_narrow_i16x8_common(comp_ctx, func_ctx, - is_signed); - } + return simd_integer_extension_wrapper(comp_ctx, func_ctx, e_ext_i8x16, + lower_half, is_signed); } -static bool -aot_compile_simd_i16x8_narrow_i32x4_common(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_signed) +bool +aot_compile_simd_i32x4_extend_i16x8(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool lower_half, + bool is_signed) { - LLVMValueRef vector1, vector2, result, vector_min, vector_max, shuffle, - vector1_clamped, vector2_clamped, vector1_trunced, vector2_trunced, - shuffle_vector; - LLVMValueRef v1_gt_max, v1_lt_min, v2_gt_max, v2_lt_min; - - int min_s_array[4] = { 0xffff8000, 0xffff8000, 0xffff8000, 0xffff8000 }; - int32 max_s_array[4] = { 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff }; - - int min_u_array[4] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; - int max_u_array[4] = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; + return simd_integer_extension_wrapper(comp_ctx, func_ctx, e_ext_i16x8, + lower_half, is_signed); +} - int shuffle_array[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +bool +aot_compile_simd_i64x2_extend_i32x4(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool lower_half, + bool is_signed) +{ + return simd_integer_extension_wrapper(comp_ctx, func_ctx, e_ext_i32x4, + lower_half, is_signed); +} - if (!(vector2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_i32x4_TYPE, "vec2"))) { - goto fail; - } +static LLVMValueRef +simd_trunc_sat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + const char *intrinsics, LLVMTypeRef in_vector_type, + LLVMTypeRef out_vector_type) +{ + LLVMValueRef vector, result; + LLVMTypeRef param_types[] = { in_vector_type }; - if (!(vector1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_i32x4_TYPE, "vec1"))) { - goto fail; + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, in_vector_type, + "vector"))) { + return false; } - if (!(vector_min = build_intx4_vector( - comp_ctx, I32_TYPE, is_signed ? min_s_array : min_u_array))) { - goto fail; - } - if (!(vector_max = build_intx4_vector( - comp_ctx, I32_TYPE, is_signed ? max_s_array : max_u_array))) { - goto fail; - } - if (!(shuffle = build_intx8_vector(comp_ctx, I32_TYPE, shuffle_array))) { - goto fail; + if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsics, + out_vector_type, param_types, 1, + vector))) { + return false; } - if (!(v1_gt_max = LLVMBuildICmp(comp_ctx->builder, LLVMIntSGT, vector1, - vector_max, "v1_great_than_max"))) { - HANDLE_FAILURE("LLVMBuldICmp"); - goto fail; - } + return result; +} - if (!(v2_gt_max = LLVMBuildICmp(comp_ctx->builder, LLVMIntSGT, vector2, - vector_max, "v2_great_than_max"))) { - HANDLE_FAILURE("LLVMBuldICmp"); - goto fail; +bool +aot_compile_simd_i32x4_trunc_sat_f32x4(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_signed) +{ + LLVMValueRef result; + if (!(result = simd_trunc_sat(comp_ctx, func_ctx, + is_signed ? "llvm.fptosi.sat.v4i32.v4f32" + : "llvm.fptoui.sat.v4i32.v4f32", + V128_f32x4_TYPE, V128_i32x4_TYPE))) { + return false; } - if (!(v1_lt_min = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, vector1, - vector_min, "v1_less_than_min"))) { - HANDLE_FAILURE("LLVMBuldICmp"); - goto fail; - } + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); +} - if (!(v2_lt_min = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, vector2, - vector_min, "v2_less_than_min"))) { - HANDLE_FAILURE("LLVMBuldICmp"); - goto fail; - } +bool +aot_compile_simd_i32x4_trunc_sat_f64x2(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_signed) +{ + LLVMValueRef result, zero, mask; + LLVMTypeRef out_vector_type; + LLVMValueRef lanes[] = { + LLVM_CONST(i32_zero), + LLVM_CONST(i32_one), + LLVM_CONST(i32_two), + LLVM_CONST(i32_three), + }; - if (!(vector1_clamped = - LLVMBuildSelect(comp_ctx->builder, v1_gt_max, vector_max, vector1, - "vector1_clamped_max"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; + if (!(out_vector_type = LLVMVectorType(I32_TYPE, 2))) { + HANDLE_FAILURE("LLVMVectorType"); + return false; } - if (!(vector1_clamped = - LLVMBuildSelect(comp_ctx->builder, v1_lt_min, vector_min, - vector1_clamped, "vector1_clamped_min"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; + if (!(result = simd_trunc_sat(comp_ctx, func_ctx, + is_signed ? "llvm.fptosi.sat.v2i32.v2f64" + : "llvm.fptoui.sat.v2i32.v2f64", + V128_f64x2_TYPE, out_vector_type))) { + return false; } - if (!(vector2_clamped = - LLVMBuildSelect(comp_ctx->builder, v2_gt_max, vector_max, vector2, - "vector2_clamped_max"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; + if (!(zero = LLVMConstNull(out_vector_type))) { + HANDLE_FAILURE("LLVMConstNull"); + return false; } - if (!(vector2_clamped = - LLVMBuildSelect(comp_ctx->builder, v2_lt_min, vector_min, - vector2_clamped, "vector2_clamped_min"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; + /* v2i32 -> v4i32 */ + if (!(mask = LLVMConstVector(lanes, 4))) { + HANDLE_FAILURE("LLVMConstVector"); + return false; } - if (!(vector1_trunced = LLVMBuildTrunc(comp_ctx->builder, vector1_clamped, - LLVMVectorType(INT16_TYPE, 4), - "vector1_trunced"))) { - HANDLE_FAILURE("LLVMBuildTrunc"); - goto fail; + if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, result, zero, mask, + "extend"))) { + HANDLE_FAILURE("LLVMBuildShuffleVector"); + return false; } - if (!(vector2_trunced = LLVMBuildTrunc(comp_ctx->builder, vector2_clamped, - LLVMVectorType(INT16_TYPE, 4), - "vector2_trunced"))) { - HANDLE_FAILURE("LLVMBuildTrunc"); - goto fail; - } + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); +} - if (!(shuffle_vector = LLVMBuildShuffleVector( - comp_ctx->builder, vector1_trunced, vector2_trunced, shuffle, - "shuffle_vector"))) { - HANDLE_FAILURE("LLVMBuildShuffleVector"); - goto fail; - } +static LLVMValueRef +simd_integer_convert(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool is_signed, LLVMValueRef vector, + LLVMTypeRef out_vector_type) - if (!(result = LLVMBuildBitCast(comp_ctx->builder, shuffle_vector, - V128_i64x2_TYPE, "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; +{ + LLVMValueRef result; + result = is_signed ? LLVMBuildSIToFP(comp_ctx->builder, vector, + out_vector_type, "converted") + : LLVMBuildUIToFP(comp_ctx->builder, vector, + out_vector_type, "converted"); + if (!result) { + HANDLE_FAILURE("LLVMBuildSIToFP/LLVMBuildUIToFP"); } - PUSH_V128(result); - return true; - -fail: - return false; + return result; } bool -aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_signed) +aot_compile_simd_f32x4_convert_i32x4(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_signed) { - if (is_target_x86(comp_ctx)) { - return aot_compile_simd_i16x8_narrow_i32x4_x86(comp_ctx, func_ctx, - is_signed); + LLVMValueRef vector, result; + + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + V128_i32x4_TYPE, "vec"))) { + return false; } - else { - return aot_compile_simd_i16x8_narrow_i32x4_common(comp_ctx, func_ctx, - is_signed); + + if (!(result = simd_integer_convert(comp_ctx, func_ctx, is_signed, vector, + V128_f32x4_TYPE))) { + return false; } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool -aot_compile_simd_i16x8_widen_i8x16(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_low_half, - bool is_signed) +aot_compile_simd_f64x2_convert_i32x4(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_signed) { - LLVMValueRef vector, undef, mask_high[8], mask_low[8], mask, shuffled, - result; - uint8 mask_high_value[8] = { 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }, - mask_low_value[8] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 }, i; + LLVMValueRef vector, mask, result; + LLVMValueRef lanes[] = { + LLVM_CONST(i32_zero), + LLVM_CONST(i32_one), + }; + LLVMTypeRef out_vector_type; if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_i8x16_TYPE, "vec"))) { - goto fail; + V128_i32x4_TYPE, "vec"))) { + return false; } - if (!(undef = LLVMGetUndef(V128_i8x16_TYPE))) { - HANDLE_FAILURE("LLVMGetUndef"); - goto fail; + if (!(out_vector_type = LLVMVectorType(F64_TYPE, 4))) { + HANDLE_FAILURE("LLVMVectorType"); + return false; } - /* create a mask */ - for (i = 0; i < 8; i++) { - mask_high[i] = LLVMConstInt(I32_TYPE, mask_high_value[i], true); - mask_low[i] = LLVMConstInt(I32_TYPE, mask_low_value[i], true); + if (!(result = simd_integer_convert(comp_ctx, func_ctx, is_signed, vector, + out_vector_type))) { + return false; } - mask = is_low_half ? LLVMConstVector(mask_low, 8) - : LLVMConstVector(mask_high, 8); - if (!mask) { + /* v4f64 -> v2f64 */ + if (!(mask = LLVMConstVector(lanes, 2))) { HANDLE_FAILURE("LLVMConstVector"); - goto fail; + return false; } - /* retrive the low or high half */ - if (!(shuffled = LLVMBuildShuffleVector(comp_ctx->builder, vector, undef, - mask, "shuffled"))) { + if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, result, result, + mask, "trunc"))) { HANDLE_FAILURE("LLVMBuildShuffleVector"); - goto fail; + return false; } - if (is_signed) { - if (!(result = LLVMBuildSExt(comp_ctx->builder, shuffled, - V128_i16x8_TYPE, "ext"))) { - HANDLE_FAILURE("LLVMBuildSExt"); - goto fail; - } - } - else { - if (!(result = LLVMBuildZExt(comp_ctx->builder, shuffled, - V128_i16x8_TYPE, "ext"))) { - HANDLE_FAILURE("LLVMBuildZExt"); - goto fail; - } - } - - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } - - PUSH_V128(result); - return true; -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } -bool -aot_compile_simd_i32x4_widen_i16x8(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_low_half, - bool is_signed) +static bool +simd_extadd_pairwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMTypeRef in_vector_type, LLVMTypeRef out_vector_type, + bool is_signed) { - LLVMValueRef vector, undef, mask_high[4], mask_low[4], mask, shuffled, - result; - uint8 mask_high_value[4] = { 0x4, 0x5, 0x6, 0x7 }, - mask_low_value[4] = { 0x0, 0x1, 0x2, 0x3 }, i; + LLVMValueRef vector, even_mask, odd_mask, sub_vector_even, sub_vector_odd, + result; - if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_i16x8_TYPE, "vec"))) { - goto fail; - } + LLVMValueRef even_element[] = { + LLVM_CONST(i32_zero), LLVM_CONST(i32_two), LLVM_CONST(i32_four), + LLVM_CONST(i32_six), LLVM_CONST(i32_eight), LLVM_CONST(i32_ten), + LLVM_CONST(i32_twelve), LLVM_CONST(i32_fourteen), + }; - if (!(undef = LLVMGetUndef(V128_i16x8_TYPE))) { - HANDLE_FAILURE("LLVMGetUndef"); - goto fail; - } + LLVMValueRef odd_element[] = { + LLVM_CONST(i32_one), LLVM_CONST(i32_three), + LLVM_CONST(i32_five), LLVM_CONST(i32_seven), + LLVM_CONST(i32_nine), LLVM_CONST(i32_eleven), + LLVM_CONST(i32_thirteen), LLVM_CONST(i32_fifteen), + }; + + /* assumption about i16x8 from i8x16 and i32x4 from i16x8 */ + uint8 mask_length = V128_i16x8_TYPE == out_vector_type ? 8 : 4; - /* create a mask */ - for (i = 0; i < 4; i++) { - mask_high[i] = LLVMConstInt(I32_TYPE, mask_high_value[i], true); - mask_low[i] = LLVMConstInt(I32_TYPE, mask_low_value[i], true); + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, in_vector_type, + "vector"))) { + return false; } - mask = is_low_half ? LLVMConstVector(mask_low, 4) - : LLVMConstVector(mask_high, 4); - if (!mask) { + if (!(even_mask = LLVMConstVector(even_element, mask_length)) + || !(odd_mask = LLVMConstVector(odd_element, mask_length))) { HANDLE_FAILURE("LLVMConstVector"); - goto fail; + return false; } - /* retrive the low or high half */ - if (!(shuffled = LLVMBuildShuffleVector(comp_ctx->builder, vector, undef, - mask, "shuffled"))) { + /* shuffle a <16xi8> vector to two <8xi8> vectors */ + if (!(sub_vector_even = LLVMBuildShuffleVector( + comp_ctx->builder, vector, vector, even_mask, "pick_even")) + || !(sub_vector_odd = LLVMBuildShuffleVector( + comp_ctx->builder, vector, vector, odd_mask, "pick_odd"))) { HANDLE_FAILURE("LLVMBuildShuffleVector"); - goto fail; + return false; } + /* sext/zext <8xi8> to <8xi16> */ if (is_signed) { - if (!(result = LLVMBuildSExt(comp_ctx->builder, shuffled, - V128_i32x4_TYPE, "ext"))) { + if (!(sub_vector_even = + LLVMBuildSExt(comp_ctx->builder, sub_vector_even, + out_vector_type, "even_sext")) + || !(sub_vector_odd = + LLVMBuildSExt(comp_ctx->builder, sub_vector_odd, + out_vector_type, "odd_sext"))) { HANDLE_FAILURE("LLVMBuildSExt"); - goto fail; + return false; } } else { - if (!(result = LLVMBuildZExt(comp_ctx->builder, shuffled, - V128_i32x4_TYPE, "ext"))) { + if (!(sub_vector_even = + LLVMBuildZExt(comp_ctx->builder, sub_vector_even, + out_vector_type, "even_zext")) + || !(sub_vector_odd = + LLVMBuildZExt(comp_ctx->builder, sub_vector_odd, + out_vector_type, "odd_zext"))) { HANDLE_FAILURE("LLVMBuildZExt"); - goto fail; + return false; } } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; + if (!(result = LLVMBuildAdd(comp_ctx->builder, sub_vector_even, + sub_vector_odd, "sum"))) { + HANDLE_FAILURE("LLVMBuildAdd"); + return false; } - PUSH_V128(result); - return true; -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } -static LLVMValueRef -simd_build_const_f32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - float f) +bool +aot_compile_simd_i16x8_extadd_pairwise_i8x16(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + bool is_signed) { - LLVMValueRef elements[4], vector; - - if (!(elements[0] = LLVMConstReal(F32_TYPE, f))) { - HANDLE_FAILURE("LLVMConstInt"); - goto fail; - } - - elements[1] = elements[2] = elements[3] = elements[0]; - - if (!(vector = LLVMConstVector(elements, 4))) { - HANDLE_FAILURE("LLVMConstVector"); - goto fail; - } - - return vector; -fail: - return NULL; + return simd_extadd_pairwise(comp_ctx, func_ctx, V128_i8x16_TYPE, + V128_i16x8_TYPE, is_signed); } -static LLVMValueRef -simd_build_const_i32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint64 integer, - bool is_signed) +bool +aot_compile_simd_i32x4_extadd_pairwise_i16x8(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + bool is_signed) { - LLVMValueRef elements[4], vector; - - if (!(elements[0] = LLVMConstInt(I32_TYPE, integer, is_signed))) { - HANDLE_FAILURE("LLVMConstInt"); - goto fail; - } - - elements[1] = elements[2] = elements[3] = elements[0]; - - if (!(vector = LLVMConstVector(elements, 4))) { - HANDLE_FAILURE("LLVMConstVector"); - goto fail; - } - - return vector; -fail: - return NULL; + return simd_extadd_pairwise(comp_ctx, func_ctx, V128_i16x8_TYPE, + V128_i32x4_TYPE, is_signed); } bool -aot_compile_simd_i32x4_trunc_sat_f32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_signed) +aot_compile_simd_i16x8_q15mulr_sat(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) { - LLVMValueRef vector, zeros, is_nan, max_float_v, min_float_v, is_ge_max, - is_le_min, result, max_int_v, min_int_v; - uint32 max_ui = 0xFFffFFff, min_ui = 0x0; - int32 max_si = 0x7FFFffff, min_si = 0x80000000; - float max_f_ui = 4294967296.0f, min_f_ui = 0.0f, max_f_si = 2147483647.0f, - min_f_si = -2147483648.0f; + LLVMValueRef lhs, rhs, pad, offset, min, max, result; + LLVMTypeRef vector_ext_type; - if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_f32x4_TYPE, "vec"))) { - goto fail; + if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i16x8_TYPE, + "rhs")) + || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + V128_i16x8_TYPE, "lhs"))) { + return false; } - if (!(zeros = LLVMConstNull(V128_f32x4_TYPE))) { - HANDLE_FAILURE("LLVMConstNull"); - goto fail; + if (!(vector_ext_type = LLVMVectorType(I32_TYPE, 8))) { + HANDLE_FAILURE("LLVMVectorType"); + return false; } - if (is_signed) { - if (!(max_float_v = - simd_build_const_f32x4(comp_ctx, func_ctx, max_f_si))) { - goto fail; - } - - if (!(min_float_v = - simd_build_const_f32x4(comp_ctx, func_ctx, min_f_si))) { - goto fail; - } - - if (!(max_int_v = - simd_build_const_i32x4(comp_ctx, func_ctx, max_si, true))) { - goto fail; - } - - if (!(min_int_v = - simd_build_const_i32x4(comp_ctx, func_ctx, min_si, true))) { - goto fail; - } - } - else { - if (!(max_float_v = - simd_build_const_f32x4(comp_ctx, func_ctx, max_f_ui))) { - goto fail; - } - - if (!(min_float_v = - simd_build_const_f32x4(comp_ctx, func_ctx, min_f_ui))) { - goto fail; - } - - if (!(max_int_v = - simd_build_const_i32x4(comp_ctx, func_ctx, max_ui, false))) { - goto fail; - } - - if (!(min_int_v = - simd_build_const_i32x4(comp_ctx, func_ctx, min_ui, false))) { - goto fail; - } + if (!(lhs = LLVMBuildSExt(comp_ctx->builder, lhs, vector_ext_type, + "lhs_v8i32")) + || !(rhs = LLVMBuildSExt(comp_ctx->builder, rhs, vector_ext_type, + "rhs_v8i32"))) { + HANDLE_FAILURE("LLVMBuildSExt"); + return false; } - if (!(is_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealORD, vector, zeros, - "is_nan"))) { - HANDLE_FAILURE("LLVMBuildFCmp"); - goto fail; + /* 0x4000 and 15*/ + if (!(pad = simd_build_splat_const_integer_vector(comp_ctx, I32_TYPE, + 0x4000, 8)) + || !(offset = simd_build_splat_const_integer_vector(comp_ctx, I32_TYPE, + 15, 8))) { + return false; } - if (!(is_le_min = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, vector, - min_float_v, "le_min"))) { - HANDLE_FAILURE("LLVMBuildFCmp"); - goto fail; + /* TODO: looking for x86 intrinsics about integer"fused multiply-and-add" */ + /* S.SignedSaturate((x * y + 0x4000) >> 15) */ + if (!(result = LLVMBuildMul(comp_ctx->builder, lhs, rhs, "mul"))) { + HANDLE_FAILURE("LLVMBuildMul"); + return false; } - if (!(is_ge_max = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, vector, - max_float_v, "ge_max"))) { - HANDLE_FAILURE("LLVMBuildFCmp"); - goto fail; + if (!(result = LLVMBuildAdd(comp_ctx->builder, result, pad, "add"))) { + HANDLE_FAILURE("LLVMBuildAdd"); + return false; } - if (is_signed) { - if (!(result = LLVMBuildFPToSI(comp_ctx->builder, vector, - V128_i32x4_TYPE, "truncated"))) { - HANDLE_FAILURE("LLVMBuildSIToFP"); - goto fail; - } - } - else { - if (!(result = LLVMBuildFPToUI(comp_ctx->builder, vector, - V128_i32x4_TYPE, "truncated"))) { - HANDLE_FAILURE("LLVMBuildUIToFP"); - goto fail; - } + if (!(result = LLVMBuildAShr(comp_ctx->builder, result, offset, "ashr"))) { + HANDLE_FAILURE("LLVMBuildAShr"); + return false; } - if (!(result = LLVMBuildSelect(comp_ctx->builder, is_ge_max, max_int_v, - result, "sat_w_max"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; + if (!(min = simd_build_splat_const_integer_vector(comp_ctx, I32_TYPE, + 0xffff8000, 8)) + || !(max = simd_build_splat_const_integer_vector(comp_ctx, I32_TYPE, + 0x00007fff, 8))) { + return false; } - if (!(result = LLVMBuildSelect(comp_ctx->builder, is_le_min, min_int_v, - result, "sat_w_min"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; + /* sat after trunc will let *sat* part be optimized */ + if (!(result = simd_saturate(comp_ctx, func_ctx, e_sat_i32x8, result, min, + max, true))) { + return false; } - if (!(result = LLVMBuildSelect(comp_ctx->builder, is_nan, result, - V128_i32x4_ZERO, "sat_w_nan"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; + if (!(result = LLVMBuildTrunc(comp_ctx->builder, result, V128_i16x8_TYPE, + "down_to_v8i16"))) { + HANDLE_FAILURE("LLVMBuidlTrunc"); + return false; } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } - - PUSH_V128(result); - return true; -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } -bool -aot_compile_simd_f32x4_convert_i32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_signed) +enum integer_extmul_type { + e_i16x8_extmul_i8x16, + e_i32x4_extmul_i16x8, + e_i64x2_extmul_i32x4, +}; + +static bool +simd_integer_extmul(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool lower_half, bool is_signed, + enum integer_extmul_type itype) { - LLVMValueRef vector, result; + LLVMValueRef vec1, vec2, result; + enum integer_extend_type ext_type[] = { + e_ext_i8x16, + e_ext_i16x8, + e_ext_i32x4, + }; + LLVMTypeRef in_vector_type[] = { + V128_i8x16_TYPE, + V128_i16x8_TYPE, + V128_i32x4_TYPE, + }; - if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_i32x4_TYPE, "vec"))) { - goto fail; + if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + in_vector_type[itype], "vec1")) + || !(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + in_vector_type[itype], "vec2"))) { + return false; } - if (is_signed) { - if (!(result = LLVMBuildSIToFP(comp_ctx->builder, vector, - V128_f32x4_TYPE, "converted"))) { - HANDLE_FAILURE("LLVMBuildSIToFP"); - goto fail; - } - } - else { - if (!(result = LLVMBuildUIToFP(comp_ctx->builder, vector, - V128_f32x4_TYPE, "converted"))) { - HANDLE_FAILURE("LLVMBuildSIToFP"); - goto fail; - } + if (!(vec1 = simd_integer_extension(comp_ctx, func_ctx, ext_type[itype], + vec1, lower_half, is_signed)) + || !(vec2 = simd_integer_extension(comp_ctx, func_ctx, ext_type[itype], + vec2, lower_half, is_signed))) { + return false; } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; + if (!(result = LLVMBuildMul(comp_ctx->builder, vec1, vec2, "product"))) { + return false; } - PUSH_V128(result); - return true; -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } + +bool +aot_compile_simd_i16x8_extmul_i8x16(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool lower_half, + bool is_signed) +{ + return simd_integer_extmul(comp_ctx, func_ctx, lower_half, is_signed, + e_i16x8_extmul_i8x16); +} + +bool +aot_compile_simd_i32x4_extmul_i16x8(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool lower_half, + bool is_signed) +{ + return simd_integer_extmul(comp_ctx, func_ctx, lower_half, is_signed, + e_i32x4_extmul_i16x8); +} + +bool +aot_compile_simd_i64x2_extmul_i32x4(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool lower_half, + bool is_signed) +{ + return simd_integer_extmul(comp_ctx, func_ctx, lower_half, is_signed, + e_i64x2_extmul_i32x4); +} \ No newline at end of file diff --git a/core/iwasm/compilation/simd/simd_conversions.h b/core/iwasm/compilation/simd/simd_conversions.h index 823b5dc3a8..87b8bd684e 100644 --- a/core/iwasm/compilation/simd/simd_conversions.h +++ b/core/iwasm/compilation/simd/simd_conversions.h @@ -14,36 +14,75 @@ extern "C" { bool aot_compile_simd_i8x16_narrow_i16x8(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_signed); + AOTFuncContext *func_ctx, bool is_signed); bool aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, + AOTFuncContext *func_ctx, bool is_signed); + +bool +aot_compile_simd_i32x4_narrow_i64x2(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_signed); + +bool +aot_compile_simd_i16x8_extend_i8x16(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_low, bool is_signed); bool -aot_compile_simd_i16x8_widen_i8x16(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_low, - bool is_signed); +aot_compile_simd_i32x4_extend_i16x8(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_low, + bool is_signed); bool -aot_compile_simd_i32x4_widen_i16x8(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_low, - bool is_signed); +aot_compile_simd_i64x2_extend_i32x4(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool lower_half, + bool is_signed); bool aot_compile_simd_i32x4_trunc_sat_f32x4(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, bool is_signed); +bool +aot_compile_simd_i32x4_trunc_sat_f64x2(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + bool is_signed); + bool aot_compile_simd_f32x4_convert_i32x4(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - bool is_signed); + AOTFuncContext *func_ctx, bool is_signed); +bool +aot_compile_simd_f64x2_convert_i32x4(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_signed); +bool +aot_compile_simd_i16x8_extadd_pairwise_i8x16(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + bool is_signed); + +bool +aot_compile_simd_i32x4_extadd_pairwise_i16x8(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + bool is_signed); +bool +aot_compile_simd_i16x8_q15mulr_sat(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_i16x8_extmul_i8x16(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_low, + bool is_signed); + +bool +aot_compile_simd_i32x4_extmul_i16x8(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool is_low, + bool is_signed); + +bool +aot_compile_simd_i64x2_extmul_i32x4(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool lower_half, + bool is_signed); #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/compilation/simd/simd_floating_point.c b/core/iwasm/compilation/simd/simd_floating_point.c index e26b3a5187..d850fe8f75 100644 --- a/core/iwasm/compilation/simd/simd_floating_point.c +++ b/core/iwasm/compilation/simd/simd_floating_point.c @@ -9,160 +9,76 @@ #include "../aot_emit_numberic.h" #include "../../aot/aot_runtime.h" -static LLVMValueRef -simd_v128_float_cmp(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - FloatArithmetic arith_op, - LLVMValueRef lhs, - LLVMValueRef rhs) -{ - LLVMValueRef result; - LLVMRealPredicate op; - - op = FLOAT_MIN == arith_op ? LLVMRealULT : LLVMRealUGT; - - if (!(result = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) { - HANDLE_FAILURE("LLVMBuildFCmp"); - goto fail; - } - - if (!(result = - LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; - } - - return result; -fail: - return NULL; -} - static bool -simd_v128_float_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - FloatArithmetic arith_op, - LLVMTypeRef vector_type) +simd_v128_float_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatArithmetic arith_op, LLVMTypeRef vector_type) { - LLVMValueRef lhs, rhs, result; + LLVMValueRef lhs, rhs, result = NULL; - if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "rhs"))) { - goto fail; - } - - if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "lhs"))) { - goto fail; + if (!(rhs = + simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs")) + || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "lhs"))) { + return false; } switch (arith_op) { case FLOAT_ADD: - if (!(result = - LLVMBuildFAdd(comp_ctx->builder, lhs, rhs, "sum"))) { - HANDLE_FAILURE("LLVMBuildFAdd"); - goto fail; - } + result = LLVMBuildFAdd(comp_ctx->builder, lhs, rhs, "sum"); break; case FLOAT_SUB: - if (!(result = LLVMBuildFSub(comp_ctx->builder, lhs, rhs, - "difference"))) { - HANDLE_FAILURE("LLVMBuildFSub"); - goto fail; - } + result = LLVMBuildFSub(comp_ctx->builder, lhs, rhs, "difference"); break; case FLOAT_MUL: - if (!(result = - LLVMBuildFMul(comp_ctx->builder, lhs, rhs, "product"))) { - HANDLE_FAILURE("LLVMBuildFMul"); - goto fail; - } + result = LLVMBuildFMul(comp_ctx->builder, lhs, rhs, "product"); break; case FLOAT_DIV: - if (!(result = - LLVMBuildFDiv(comp_ctx->builder, lhs, rhs, "quotient"))) { - HANDLE_FAILURE("LLVMBuildFDiv"); - goto fail; - } - break; - case FLOAT_MIN: - if (!(result = simd_v128_float_cmp(comp_ctx, func_ctx, FLOAT_MIN, - lhs, rhs))) { - goto fail; - } - break; - case FLOAT_MAX: - if (!(result = simd_v128_float_cmp(comp_ctx, func_ctx, FLOAT_MAX, - lhs, rhs))) { - goto fail; - } + result = LLVMBuildFDiv(comp_ctx->builder, lhs, rhs, "quotient"); break; default: - result = NULL; - bh_assert(0); - break; + return false; } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; + if (!result) { + HANDLE_FAILURE( + "LLVMBuildFAdd/LLVMBuildFSub/LLVMBuildFMul/LLVMBuildFDiv"); + return false; } - /* push result into the stack */ - PUSH_V128(result); - - return true; -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool -aot_compile_simd_f32x4_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_f32x4_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, FloatArithmetic arith_op) { - return simd_v128_float_arith(comp_ctx, func_ctx, arith_op, - V128_f32x4_TYPE); + return simd_v128_float_arith(comp_ctx, func_ctx, arith_op, V128_f32x4_TYPE); } bool -aot_compile_simd_f64x2_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_f64x2_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, FloatArithmetic arith_op) { - return simd_v128_float_arith(comp_ctx, func_ctx, arith_op, - V128_f64x2_TYPE); + return simd_v128_float_arith(comp_ctx, func_ctx, arith_op, V128_f64x2_TYPE); } static bool -simd_v128_float_neg(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +simd_v128_float_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMTypeRef vector_type) { - LLVMValueRef number, result; + LLVMValueRef vector, result; - if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "number"))) { - goto fail; + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "vector"))) { + return false; } - if (!(result = LLVMBuildFNeg(comp_ctx->builder, number, "neg"))) { + if (!(result = LLVMBuildFNeg(comp_ctx->builder, vector, "neg"))) { HANDLE_FAILURE("LLVMBuildFNeg"); - goto fail; + return false; } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } - - /* push result into the stack */ - PUSH_V128(result); - - return true; -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool @@ -178,119 +94,295 @@ aot_compile_simd_f64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) } static bool -simd_v128_float_intrinsic(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - LLVMTypeRef vector_type, - const char *intrinsic) +simd_float_intrinsic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMTypeRef vector_type, const char *intrinsic) { - LLVMValueRef number, result; + LLVMValueRef vector, result; LLVMTypeRef param_types[1] = { vector_type }; - if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "number"))) { - goto fail; + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "vector"))) { + return false; } - if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, vector_type, - param_types, 1, number))) { + if (!(result = + aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, + vector_type, param_types, 1, vector))) { HANDLE_FAILURE("LLVMBuildCall"); - goto fail; + return false; } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } - - /* push result into the stack */ - PUSH_V128(result); - - return true; -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool aot_compile_simd_f32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, - "llvm.fabs.v4f32"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, + "llvm.fabs.v4f32"); } bool aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, - "llvm.fabs.v2f64"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, + "llvm.fabs.v2f64"); +} + +bool +aot_compile_simd_f32x4_round(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, + "llvm.round.v4f32"); +} + +bool +aot_compile_simd_f64x2_round(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, + "llvm.round.v2f64"); } bool aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, - "llvm.sqrt.v4f32"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, + "llvm.sqrt.v4f32"); } bool aot_compile_simd_f64x2_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, - "llvm.sqrt.v2f64"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, + "llvm.sqrt.v2f64"); } bool aot_compile_simd_f32x4_ceil(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, - "llvm.ceil.v4f32"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, + "llvm.ceil.v4f32"); } bool aot_compile_simd_f64x2_ceil(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, - "llvm.ceil.v2f64"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, + "llvm.ceil.v2f64"); } bool aot_compile_simd_f32x4_floor(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, - "llvm.floor.v4f32"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, + "llvm.floor.v4f32"); } bool aot_compile_simd_f64x2_floor(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, - "llvm.floor.v2f64"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, + "llvm.floor.v2f64"); } bool aot_compile_simd_f32x4_trunc(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, - "llvm.trunc.v4f32"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, + "llvm.trunc.v4f32"); } bool aot_compile_simd_f64x2_trunc(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, - "llvm.trunc.v2f64"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, + "llvm.trunc.v2f64"); } bool -aot_compile_simd_f32x4_nearest(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +aot_compile_simd_f32x4_nearest(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, - "llvm.rint.v4f32"); + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE, + "llvm.rint.v4f32"); } bool -aot_compile_simd_f64x2_nearest(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +aot_compile_simd_f64x2_nearest(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, + "llvm.rint.v2f64"); +} + +static bool +simd_float_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatArithmetic arith_op, LLVMTypeRef vector_type) { - return simd_v128_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE, - "llvm.rint.v2f64"); + LLVMValueRef lhs, rhs, result; + LLVMRealPredicate op = FLOAT_MIN == arith_op ? LLVMRealULT : LLVMRealUGT; + + if (!(rhs = + simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs")) + || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "lhs"))) { + return false; + } + + if (!(result = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) { + HANDLE_FAILURE("LLVMBuildFCmp"); + return false; + } + + if (!(result = + LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) { + HANDLE_FAILURE("LLVMBuildSelect"); + return false; + } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); +} + +/*TODO: sugggest non-IA platforms check with "llvm.minimum.*" and + * "llvm.maximum.*" firstly */ +bool +aot_compile_simd_f32x4_min_max(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool run_min) +{ + return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX, + V128_f32x4_TYPE); +} + +bool +aot_compile_simd_f64x2_min_max(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool run_min) +{ + return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX, + V128_f64x2_TYPE); +} + +static bool +simd_float_pmin_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMTypeRef vector_type, const char *intrinsic) +{ + LLVMValueRef lhs, rhs, result; + LLVMTypeRef param_types[2]; + + param_types[0] = vector_type; + param_types[1] = vector_type; + + if (!(rhs = + simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs")) + || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "lhs"))) { + return false; + } + + if (!(result = + aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, + vector_type, param_types, 2, lhs, rhs))) { + return false; + } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); +} + +bool +aot_compile_simd_f32x4_pmin_pmax(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool run_min) +{ + return simd_float_pmin_max(comp_ctx, func_ctx, V128_f32x4_TYPE, + run_min ? "llvm.minnum.v4f32" + : "llvm.maxnum.v4f32"); +} + +bool +aot_compile_simd_f64x2_pmin_pmax(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool run_min) +{ + return simd_float_pmin_max(comp_ctx, func_ctx, V128_f64x2_TYPE, + run_min ? "llvm.minnum.v2f64" + : "llvm.maxnum.v2f64"); +} + +bool +aot_compile_simd_f64x2_demote(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + LLVMValueRef vector, elem_0, elem_1, result; + + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + V128_f64x2_TYPE, "vector"))) { + return false; + } + + if (!(elem_0 = LLVMBuildExtractElement(comp_ctx->builder, vector, + LLVM_CONST(i32_zero), "elem_0")) + || !(elem_1 = LLVMBuildExtractElement(comp_ctx->builder, vector, + LLVM_CONST(i32_one), "elem_1"))) { + HANDLE_FAILURE("LLVMBuildExtractElement"); + return false; + } + + /* fptrunc elem to */ + if (!(elem_0 = LLVMBuildFPTrunc(comp_ctx->builder, elem_0, F32_TYPE, + "elem_0_trunc")) + || !(elem_1 = LLVMBuildFPTrunc(comp_ctx->builder, elem_1, F32_TYPE, + "elem_1_trunc"))) { + HANDLE_FAILURE("LLVMBuildFPTrunc"); + return false; + } + + if (!(result = LLVMBuildInsertElement(comp_ctx->builder, + LLVM_CONST(f32x4_vec_zero), elem_0, + LLVM_CONST(i32_zero), "new_vector_0")) + || !(result = + LLVMBuildInsertElement(comp_ctx->builder, result, elem_1, + LLVM_CONST(i32_one), "new_vector_1"))) { + HANDLE_FAILURE("LLVMBuildInsertElement"); + return false; + } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); +} + +bool +aot_compile_simd_f32x4_promote(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + LLVMValueRef vector, elem_0, elem_1, result; + + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + V128_f32x4_TYPE, "vector"))) { + return false; + } + + if (!(elem_0 = LLVMBuildExtractElement(comp_ctx->builder, vector, + LLVM_CONST(i32_zero), "elem_0")) + || !(elem_1 = LLVMBuildExtractElement(comp_ctx->builder, vector, + LLVM_CONST(i32_one), "elem_1"))) { + HANDLE_FAILURE("LLVMBuildExtractElement"); + return false; + } + + /* fpext elem to */ + if (!(elem_0 = + LLVMBuildFPExt(comp_ctx->builder, elem_0, F64_TYPE, "elem_0_ext")) + || !(elem_1 = LLVMBuildFPExt(comp_ctx->builder, elem_1, F64_TYPE, + "elem_1_ext"))) { + HANDLE_FAILURE("LLVMBuildFPExt"); + return false; + } + + if (!(result = LLVMBuildInsertElement(comp_ctx->builder, + LLVM_CONST(f64x2_vec_zero), elem_0, + LLVM_CONST(i32_zero), "new_vector_0")) + || !(result = + LLVMBuildInsertElement(comp_ctx->builder, result, elem_1, + LLVM_CONST(i32_one), "new_vector_1"))) { + HANDLE_FAILURE("LLVMBuildInsertElement"); + return false; + } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } diff --git a/core/iwasm/compilation/simd/simd_floating_point.h b/core/iwasm/compilation/simd/simd_floating_point.h index e95cab6ee1..213b4391f8 100644 --- a/core/iwasm/compilation/simd/simd_floating_point.h +++ b/core/iwasm/compilation/simd/simd_floating_point.h @@ -13,13 +13,11 @@ extern "C" { #endif bool -aot_compile_simd_f32x4_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_f32x4_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, FloatArithmetic arith_op); bool -aot_compile_simd_f64x2_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_f64x2_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, FloatArithmetic arith_op); bool @@ -34,6 +32,14 @@ aot_compile_simd_f32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); bool aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +bool +aot_compile_simd_f32x4_round(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_f64x2_round(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + bool aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); @@ -47,22 +53,52 @@ bool aot_compile_simd_f64x2_ceil(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); bool -aot_compile_simd_f32x4_floor(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_simd_f32x4_floor(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_f64x2_floor(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_f32x4_trunc(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_f64x2_trunc(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_f32x4_nearest(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_f64x2_nearest(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_f32x4_min_max(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool run_min); bool -aot_compile_simd_f64x2_floor(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_simd_f64x2_min_max(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool run_min); bool -aot_compile_simd_f32x4_trunc(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_simd_f32x4_pmin_pmax(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool run_min); bool -aot_compile_simd_f64x2_trunc(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_simd_f64x2_pmin_pmax(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, bool run_min); bool -aot_compile_simd_f32x4_nearest(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_simd_f64x2_demote(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); bool -aot_compile_simd_f64x2_nearest(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +aot_compile_simd_f32x4_promote(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); #ifdef __cplusplus } /* end of extern "C" */ diff --git a/core/iwasm/compilation/simd/simd_int_arith.c b/core/iwasm/compilation/simd/simd_int_arith.c index f61b67bcd7..1d0e6967b6 100644 --- a/core/iwasm/compilation/simd/simd_int_arith.c +++ b/core/iwasm/compilation/simd/simd_int_arith.c @@ -9,199 +9,398 @@ #include "../../aot/aot_runtime.h" static bool -simd_v128_integer_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - LLVMValueRef lhs, - LLVMValueRef rhs) +simd_integer_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + V128Arithmetic arith_op, LLVMTypeRef vector_type) { - LLVMValueRef result; + LLVMValueRef lhs, rhs, result = NULL; + + if (!(rhs = + simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs")) + || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "lhs"))) { + return false; + } switch (arith_op) { case V128_ADD: - if (!(result = LLVMBuildAdd(comp_ctx->builder, lhs, rhs, "sum"))) { - HANDLE_FAILURE("LLVMBuildAdd"); - goto fail; - } + result = LLVMBuildAdd(comp_ctx->builder, lhs, rhs, "sum"); break; case V128_SUB: - if (!(result = - LLVMBuildSub(comp_ctx->builder, lhs, rhs, "difference"))) { - HANDLE_FAILURE("LLVMBuildSub"); - goto fail; - } + result = LLVMBuildSub(comp_ctx->builder, lhs, rhs, "difference"); break; case V128_MUL: - if (!(result = - LLVMBuildMul(comp_ctx->builder, lhs, rhs, "product"))) { - HANDLE_FAILURE("LLVMBuildMul"); - goto fail; - } - break; - case V128_NEG: - if (!(result = LLVMBuildNeg(comp_ctx->builder, lhs, "neg"))) { - HANDLE_FAILURE("LLVMBuildNeg"); - goto fail; - } + result = LLVMBuildMul(comp_ctx->builder, lhs, rhs, "product"); break; default: - result = NULL; - bh_assert(0); + HANDLE_FAILURE("Unsupport arith_op"); break; } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; + if (!result) { + HANDLE_FAILURE("LLVMBuildAdd/LLVMBuildSub/LLVMBuildMul"); + return false; } - /* push result into the stack */ - PUSH_V128(result); + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); +} - return true; -fail: - return false; +bool +aot_compile_simd_i8x16_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + V128Arithmetic arith_op) +{ + return simd_integer_arith(comp_ctx, func_ctx, arith_op, V128_i8x16_TYPE); } bool -aot_compile_simd_i8x16_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i16x8_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, V128Arithmetic arith_op) { - LLVMValueRef lhs, rhs; + return simd_integer_arith(comp_ctx, func_ctx, arith_op, V128_i16x8_TYPE); +} - if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE, - "rhs"))) { - goto fail; +bool +aot_compile_simd_i32x4_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + V128Arithmetic arith_op) +{ + return simd_integer_arith(comp_ctx, func_ctx, arith_op, V128_i32x4_TYPE); +} + +bool +aot_compile_simd_i64x2_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + V128Arithmetic arith_op) +{ + return simd_integer_arith(comp_ctx, func_ctx, arith_op, V128_i64x2_TYPE); +} + +static bool +simd_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMTypeRef type) +{ + LLVMValueRef vector, result; + + if (!(vector = + simd_pop_v128_and_bitcast(comp_ctx, func_ctx, type, "vector"))) { + return false; } - if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE, - "lhs"))) { - goto fail; + if (!(result = LLVMBuildNeg(comp_ctx->builder, vector, "neg"))) { + HANDLE_FAILURE("LLVMBuildNeg"); + return false; } - return simd_v128_integer_arith(comp_ctx, func_ctx, arith_op, lhs, rhs); -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool -aot_compile_simd_i16x8_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Arithmetic arith_op) +aot_compile_simd_i8x16_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - LLVMValueRef lhs, rhs; + return simd_neg(comp_ctx, func_ctx, V128_i8x16_TYPE); +} + +bool +aot_compile_simd_i16x8_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return simd_neg(comp_ctx, func_ctx, V128_i16x8_TYPE); +} - if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i16x8_TYPE, - "rhs"))) { - goto fail; +bool +aot_compile_simd_i32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return simd_neg(comp_ctx, func_ctx, V128_i32x4_TYPE); +} + +bool +aot_compile_simd_i64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return simd_neg(comp_ctx, func_ctx, V128_i64x2_TYPE); +} + +bool +aot_compile_simd_i8x16_popcnt(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + LLVMValueRef vector, result; + + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + V128_i8x16_TYPE, "vector"))) { + return false; } - if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i16x8_TYPE, - "lhs"))) { - goto fail; + if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, + "llvm.ctpop.v16i8", V128_i8x16_TYPE, + &V128_i8x16_TYPE, 1, vector))) { + return false; } - return simd_v128_integer_arith(comp_ctx, func_ctx, arith_op, lhs, rhs); -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } -bool -aot_compile_simd_i32x4_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Arithmetic arith_op) +static bool +simd_v128_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMTypeRef vector_type, V128Arithmetic arith_op, bool is_signed) { - LLVMValueRef lhs, rhs; + LLVMValueRef lhs, rhs, result; + LLVMIntPredicate op; + + if (!(rhs = + simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs")) + || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "lhs"))) { + return false; + } - if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i32x4_TYPE, - "rhs"))) { - goto fail; + if (V128_MIN == arith_op) { + op = is_signed ? LLVMIntSLT : LLVMIntULT; + } + else { + op = is_signed ? LLVMIntSGT : LLVMIntUGT; } - if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i32x4_TYPE, - "lhs"))) { - goto fail; + if (!(result = LLVMBuildICmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) { + HANDLE_FAILURE("LLVMBuildICmp"); + return false; } - return simd_v128_integer_arith(comp_ctx, func_ctx, arith_op, lhs, rhs); -fail: - return false; + if (!(result = + LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) { + HANDLE_FAILURE("LLVMBuildSelect"); + return false; + } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool -aot_compile_simd_i64x2_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Arithmetic arith_op) +aot_compile_simd_i8x16_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + V128Arithmetic arith_op, bool is_signed) { - LLVMValueRef lhs, rhs; - - POP_V128(rhs); - POP_V128(lhs); + return simd_v128_cmp(comp_ctx, func_ctx, V128_i8x16_TYPE, arith_op, + is_signed); +} - return simd_v128_integer_arith(comp_ctx, func_ctx, arith_op, lhs, rhs); -fail: - return false; +bool +aot_compile_simd_i16x8_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + V128Arithmetic arith_op, bool is_signed) +{ + return simd_v128_cmp(comp_ctx, func_ctx, V128_i16x8_TYPE, arith_op, + is_signed); } bool -aot_compile_simd_i8x16_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +aot_compile_simd_i32x4_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + V128Arithmetic arith_op, bool is_signed) { - LLVMValueRef number; + return simd_v128_cmp(comp_ctx, func_ctx, V128_i32x4_TYPE, arith_op, + is_signed); +} - if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_i8x16_TYPE, "number"))) { - goto fail; +/* llvm.abs.* */ +static bool +simd_v128_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + char *intrinsic, LLVMTypeRef vector_type) +{ + LLVMValueRef vector, result; + LLVMTypeRef param_types[] = { vector_type, INT1_TYPE }; + + if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "vec"))) { + return false; } - return simd_v128_integer_arith(comp_ctx, func_ctx, V128_NEG, number, NULL); + if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, + vector_type, param_types, 2, vector, + /* is_int_min_poison */ + LLVM_CONST(i1_zero)))) { + return false; + } -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool -aot_compile_simd_i16x8_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +aot_compile_simd_i8x16_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { - LLVMValueRef number; - - if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_i16x8_TYPE, "number"))) { - goto fail; - } + return simd_v128_abs(comp_ctx, func_ctx, "llvm.abs.v16i8", V128_i8x16_TYPE); +} - return simd_v128_integer_arith(comp_ctx, func_ctx, V128_NEG, number, NULL); +bool +aot_compile_simd_i16x8_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return simd_v128_abs(comp_ctx, func_ctx, "llvm.abs.v8i16", V128_i16x8_TYPE); +} -fail: - return false; +bool +aot_compile_simd_i32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return simd_v128_abs(comp_ctx, func_ctx, "llvm.abs.v4i32", V128_i32x4_TYPE); } bool -aot_compile_simd_i32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +aot_compile_simd_i64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return simd_v128_abs(comp_ctx, func_ctx, "llvm.abs.v2i64", V128_i64x2_TYPE); +} + +enum integer_avgr_u { + e_avgr_u_i8x16, + e_avgr_u_i16x8, + e_avgr_u_i32x4, +}; + +/* TODO: try int_x86_mmx_pavg_b and int_x86_mmx_pavg_w */ +/* (v1 + v2 + 1) / 2 */ +static bool +simd_v128_avg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + enum integer_avgr_u itype) { - LLVMValueRef number; + LLVMValueRef lhs, rhs, ones, result; + LLVMTypeRef vector_ext_type; + LLVMTypeRef vector_type[] = { + V128_i8x16_TYPE, + V128_i16x8_TYPE, + V128_i32x4_TYPE, + }; + unsigned lanes[] = { 16, 8, 4 }; + + if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + vector_type[itype], "rhs")) + || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + vector_type[itype], "lhs"))) { + return false; + } + + if (!(vector_ext_type = LLVMVectorType(I64_TYPE, lanes[itype]))) { + HANDLE_FAILURE("LLVMVectorType"); + return false; + } + + if (!(lhs = LLVMBuildZExt(comp_ctx->builder, lhs, vector_ext_type, + "zext_to_i64")) + || !(rhs = LLVMBuildZExt(comp_ctx->builder, rhs, vector_ext_type, + "zext_to_i64"))) { + HANDLE_FAILURE("LLVMBuildZExt"); + return false; + } + + /* by default, add will do signed/unsigned overflow */ + if (!(result = LLVMBuildAdd(comp_ctx->builder, lhs, rhs, "l_add_r"))) { + HANDLE_FAILURE("LLVMBuildAdd"); + return false; + } + + if (!(ones = simd_build_splat_const_integer_vector(comp_ctx, I64_TYPE, 1, + lanes[itype]))) { + return false; + } + + if (!(result = LLVMBuildAdd(comp_ctx->builder, result, ones, "plus_1"))) { + HANDLE_FAILURE("LLVMBuildAdd"); + return false; + } - if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, - V128_i32x4_TYPE, "number"))) { - goto fail; + if (!(result = LLVMBuildLShr(comp_ctx->builder, result, ones, "avg"))) { + HANDLE_FAILURE("LLVMBuildLShr"); + return false; } - return simd_v128_integer_arith(comp_ctx, func_ctx, V128_NEG, number, NULL); + if (!(result = LLVMBuildTrunc(comp_ctx->builder, result, vector_type[itype], + "to_orig_type"))) { + HANDLE_FAILURE("LLVMBuildTrunc"); + return false; + } -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool -aot_compile_simd_i64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +aot_compile_simd_i8x16_avgr_u(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + return simd_v128_avg(comp_ctx, func_ctx, e_avgr_u_i8x16); +} + +bool +aot_compile_simd_i16x8_avgr_u(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + return simd_v128_avg(comp_ctx, func_ctx, e_avgr_u_i16x8); +} + +bool +aot_compile_simd_i32x4_avgr_u(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + return simd_v128_avg(comp_ctx, func_ctx, e_avgr_u_i32x4); +} + +bool +aot_compile_simd_i32x4_dot_i16x8(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) { - LLVMValueRef number; + LLVMValueRef vec1, vec2, even_mask, odd_mask, zero, result; + LLVMTypeRef vector_ext_type; + LLVMValueRef even_element[] = { + LLVM_CONST(i32_zero), + LLVM_CONST(i32_two), + LLVM_CONST(i32_four), + LLVM_CONST(i32_six), + }; + LLVMValueRef odd_element[] = { + LLVM_CONST(i32_one), + LLVM_CONST(i32_three), + LLVM_CONST(i32_five), + LLVM_CONST(i32_seven), + }; + + if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i16x8_TYPE, + "vec1")) + || !(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, + V128_i16x8_TYPE, "vec2"))) { + return false; + } + + if (!(vector_ext_type = LLVMVectorType(I32_TYPE, 8))) { + HANDLE_FAILURE("LLVMVectorType"); + return false; + } + + /* sext to */ + if (!(vec1 = LLVMBuildSExt(comp_ctx->builder, vec1, vector_ext_type, + "vec1_v8i32")) + || !(vec2 = LLVMBuildSExt(comp_ctx->builder, vec2, vector_ext_type, + "vec2_v8i32"))) { + HANDLE_FAILURE("LLVMBuildSExt"); + return false; + } + + if (!(result = LLVMBuildMul(comp_ctx->builder, vec1, vec2, "product"))) { + HANDLE_FAILURE("LLVMBuildMul"); + return false; + } + + /* pick elements with even indexes and odd indexes */ + if (!(even_mask = LLVMConstVector(even_element, 4)) + || !(odd_mask = LLVMConstVector(odd_element, 4))) { + HANDLE_FAILURE("LLVMConstVector"); + return false; + } - POP_V128(number); + if (!(zero = simd_build_splat_const_integer_vector(comp_ctx, I32_TYPE, 0, + 8))) { + return false; + } - return simd_v128_integer_arith(comp_ctx, func_ctx, V128_NEG, number, NULL); + if (!(vec1 = LLVMBuildShuffleVector(comp_ctx->builder, result, zero, + even_mask, "even_result")) + || !(vec2 = LLVMBuildShuffleVector(comp_ctx->builder, result, zero, + odd_mask, "odd_result"))) { + HANDLE_FAILURE("LLVMBuildShuffleVector"); + return false; + } + + if (!(result = LLVMBuildAdd(comp_ctx->builder, vec1, vec2, "new_vec"))) { + HANDLE_FAILURE("LLVMBuildAdd"); + return false; + } -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } diff --git a/core/iwasm/compilation/simd/simd_int_arith.h b/core/iwasm/compilation/simd/simd_int_arith.h index 5cd77899d5..a7a21170ae 100644 --- a/core/iwasm/compilation/simd/simd_int_arith.h +++ b/core/iwasm/compilation/simd/simd_int_arith.h @@ -13,23 +13,19 @@ extern "C" { #endif bool -aot_compile_simd_i8x16_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i8x16_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, V128Arithmetic cond); bool -aot_compile_simd_i16x8_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i16x8_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, V128Arithmetic cond); bool -aot_compile_simd_i32x4_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i32x4_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, V128Arithmetic cond); bool -aot_compile_simd_i64x2_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, +aot_compile_simd_i64x2_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, V128Arithmetic cond); bool @@ -44,6 +40,50 @@ aot_compile_simd_i32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); bool aot_compile_simd_i64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); +bool +aot_compile_simd_i8x16_popcnt(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_i8x16_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + V128Arithmetic arith_op, bool is_signed); + +bool +aot_compile_simd_i16x8_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + V128Arithmetic arith_op, bool is_signed); + +bool +aot_compile_simd_i32x4_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + V128Arithmetic arith_op, bool is_signed); + +bool +aot_compile_simd_i8x16_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_simd_i16x8_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_simd_i32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_simd_i64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_simd_i8x16_avgr_u(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_i16x8_avgr_u(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_i32x4_avgr_u(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_simd_i32x4_dot_i16x8(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/compilation/simd/simd_load_store.c b/core/iwasm/compilation/simd/simd_load_store.c index 6a15ff98ba..9d084efd7e 100644 --- a/core/iwasm/compilation/simd/simd_load_store.c +++ b/core/iwasm/compilation/simd/simd_load_store.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#include "simd_common.h" #include "simd_load_store.h" #include "../aot_emit_exception.h" #include "../aot_emit_memory.h" @@ -11,291 +12,311 @@ /* data_length in bytes */ static LLVMValueRef -simd_load(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 align, - uint32 offset, - uint32 data_length, - LLVMTypeRef ptr_type) +simd_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 align, + uint32 offset, uint32 data_length, LLVMTypeRef ptr_type) { LLVMValueRef maddr, data; if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, data_length))) { HANDLE_FAILURE("aot_check_memory_overflow"); - goto fail; + return NULL; } if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr, ptr_type, "data_ptr"))) { HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; + return NULL; } if (!(data = LLVMBuildLoad(comp_ctx->builder, maddr, "data"))) { HANDLE_FAILURE("LLVMBuildLoad"); - goto fail; + return NULL; } LLVMSetAlignment(data, 1); return data; +} + +bool +aot_compile_simd_v128_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset) +{ + LLVMValueRef result; + + if (!(result = simd_load(comp_ctx, func_ctx, align, offset, 16, + V128_PTR_TYPE))) { + return false; + } + + PUSH_V128(result); + + return true; fail: - return NULL; + return false; } -/* data_length in bytes */ -static LLVMValueRef -simd_splat(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - LLVMValueRef element, - LLVMTypeRef vectory_type, - unsigned lane_count) +bool +aot_compile_simd_load_extend(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode, uint32 align, uint32 offset) { - LLVMValueRef undef, zeros, vector; - LLVMTypeRef zeros_type; + LLVMValueRef sub_vector, result; + uint32 opcode_index = opcode - SIMD_v128_load8x8_s; + bool signeds[] = { true, false, true, false, true, false }; + LLVMTypeRef vector_types[] = { + V128_i16x8_TYPE, V128_i16x8_TYPE, V128_i32x4_TYPE, + V128_i32x4_TYPE, V128_i64x2_TYPE, V128_i64x2_TYPE, + }; + LLVMTypeRef sub_vector_types[] = { + LLVMVectorType(INT8_TYPE, 8), LLVMVectorType(INT8_TYPE, 8), + LLVMVectorType(INT16_TYPE, 4), LLVMVectorType(INT16_TYPE, 4), + LLVMVectorType(I32_TYPE, 2), LLVMVectorType(I32_TYPE, 2), + }; + LLVMTypeRef sub_vector_type; + + bh_assert(opcode_index < 6); + + sub_vector_type = sub_vector_types[opcode_index]; - if (!(undef = LLVMGetUndef(vectory_type))) { - HANDLE_FAILURE("LLVMGetUndef"); - goto fail; + /* to vector ptr type */ + if (!sub_vector_type + || !(sub_vector_type = LLVMPointerType(sub_vector_type, 0))) { + HANDLE_FAILURE("LLVMPointerType"); + return false; } - if (!(zeros_type = LLVMVectorType(I32_TYPE, lane_count))) { - HANDLE_FAILURE("LVMVectorType"); - goto fail; + if (!(sub_vector = simd_load(comp_ctx, func_ctx, align, offset, 8, + sub_vector_type))) { + return false; } - if (!(zeros = LLVMConstNull(zeros_type))) { - HANDLE_FAILURE("LLVMConstNull"); - goto fail; + if (signeds[opcode_index]) { + if (!(result = LLVMBuildSExt(comp_ctx->builder, sub_vector, + vector_types[opcode_index], "vector"))) { + HANDLE_FAILURE("LLVMBuildSExt"); + return false; + } + } + else { + if (!(result = LLVMBuildZExt(comp_ctx->builder, sub_vector, + vector_types[opcode_index], "vector"))) { + HANDLE_FAILURE("LLVMBuildZExt"); + return false; + } } - if (!(vector = LLVMBuildInsertElement(comp_ctx->builder, undef, element, - I32_ZERO, "base"))) { + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); +} + +bool +aot_compile_simd_load_splat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode, uint32 align, uint32 offset) +{ + uint32 opcode_index = opcode - SIMD_v128_load8_splat; + LLVMValueRef element, result; + LLVMTypeRef element_ptr_types[] = { INT8_PTR_TYPE, INT16_PTR_TYPE, + INT32_PTR_TYPE, INT64_PTR_TYPE }; + uint32 data_lengths[] = { 1, 2, 4, 8 }; + LLVMValueRef undefs[] = { + LLVM_CONST(i8x16_undef), + LLVM_CONST(i16x8_undef), + LLVM_CONST(i32x4_undef), + LLVM_CONST(i64x2_undef), + }; + LLVMValueRef masks[] = { + LLVM_CONST(i32x16_zero), + LLVM_CONST(i32x8_zero), + LLVM_CONST(i32x4_zero), + LLVM_CONST(i32x2_zero), + }; + + bh_assert(opcode_index < 4); + + if (!(element = simd_load(comp_ctx, func_ctx, align, offset, + data_lengths[opcode_index], + element_ptr_types[opcode_index]))) { + return false; + } + + if (!(result = + LLVMBuildInsertElement(comp_ctx->builder, undefs[opcode_index], + element, I32_ZERO, "base"))) { HANDLE_FAILURE("LLVMBuildInsertElement"); - goto fail; + return false; } - if (!(vector = LLVMBuildShuffleVector(comp_ctx->builder, vector, undef, - zeros, "vector"))) { + if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, result, + undefs[opcode_index], + masks[opcode_index], "vector"))) { HANDLE_FAILURE("LLVMBuildShuffleVector"); - goto fail; + return false; } - return vector; -fail: - return NULL; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool -aot_compile_simd_v128_load(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 align, - uint32 offset) +aot_compile_simd_load_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode, uint32 align, uint32 offset, + uint8 lane_id) { - LLVMValueRef result; + LLVMValueRef element, vector; + uint32 opcode_index = opcode - SIMD_v128_load8_lane; + uint32 data_lengths[] = { 1, 2, 4, 8 }; + LLVMTypeRef element_ptr_types[] = { INT8_PTR_TYPE, INT16_PTR_TYPE, + INT32_PTR_TYPE, INT64_PTR_TYPE }; + LLVMTypeRef vector_types[] = { V128_i8x16_TYPE, V128_i16x8_TYPE, + V128_i32x4_TYPE, V128_i64x2_TYPE }; + LLVMValueRef lane = simd_lane_id_to_llvm_value(comp_ctx, lane_id); + + bh_assert(opcode_index < 4); + + if (!(vector = simd_pop_v128_and_bitcast( + comp_ctx, func_ctx, vector_types[opcode_index], "src"))) { + return false; + } - if (!(result = - simd_load(comp_ctx, func_ctx, align, offset, 16, V128_PTR_TYPE))) { - goto fail; + if (!(element = simd_load(comp_ctx, func_ctx, align, offset, + data_lengths[opcode_index], + element_ptr_types[opcode_index]))) { + return false; } - PUSH_V128(result); - return true; -fail: - return false; + if (!(vector = LLVMBuildInsertElement(comp_ctx->builder, vector, element, + lane, "dst"))) { + HANDLE_FAILURE("LLVMBuildInsertElement"); + return false; + } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, vector, "result"); } bool -aot_compile_simd_v128_store(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 align, - uint32 offset) +aot_compile_simd_load_zero(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode, uint32 align, uint32 offset) { - LLVMValueRef maddr, value, result; + LLVMValueRef element, result, mask; + uint32 opcode_index = opcode - SIMD_v128_load32_zero; + uint32 data_lengths[] = { 4, 8 }; + LLVMTypeRef element_ptr_types[] = { INT32_PTR_TYPE, INT64_PTR_TYPE }; + LLVMValueRef zero[] = { + LLVM_CONST(i32x4_vec_zero), + LLVM_CONST(i64x2_vec_zero), + }; + LLVMValueRef undef[] = { + LLVM_CONST(i32x4_undef), + LLVM_CONST(i64x2_undef), + }; + uint32 mask_length[] = { 4, 2 }; + LLVMValueRef mask_element[][4] = { + { LLVM_CONST(i32_zero), LLVM_CONST(i32_four), LLVM_CONST(i32_five), + LLVM_CONST(i32_six) }, + { LLVM_CONST(i32_zero), LLVM_CONST(i32_two) }, + }; + + bh_assert(opcode_index < 2); + + if (!(element = simd_load(comp_ctx, func_ctx, align, offset, + data_lengths[opcode_index], + element_ptr_types[opcode_index]))) { + return false; + } - POP_V128(value); + if (!(result = + LLVMBuildInsertElement(comp_ctx->builder, undef[opcode_index], + element, I32_ZERO, "vector"))) { + HANDLE_FAILURE("LLVMBuildInsertElement"); + return false; + } + + /* fill in other lanes with zero */ + if (!(mask = LLVMConstVector(mask_element[opcode_index], + mask_length[opcode_index]))) { + HANDLE_FAILURE("LLConstVector"); + return false; + } - if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, 16))) + if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, result, + zero[opcode_index], mask, + "fill_in_zero"))) { + HANDLE_FAILURE("LLVMBuildShuffleVector"); + return false; + } + + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); +} + +/* data_length in bytes */ +static bool +simd_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 align, + uint32 offset, uint32 data_length, LLVMValueRef value, + LLVMTypeRef value_ptr_type) +{ + LLVMValueRef maddr, result; + + if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, + data_length))) return false; - if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr, V128_PTR_TYPE, + if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr, value_ptr_type, "data_ptr"))) { HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; + return false; } if (!(result = LLVMBuildStore(comp_ctx->builder, value, maddr))) { HANDLE_FAILURE("LLVMBuildStore"); - goto fail; + return false; } LLVMSetAlignment(result, 1); return true; -fail: - return false; } bool -aot_compile_simd_load_extend(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 load_opcode, - uint32 align, - uint32 offset) +aot_compile_simd_v128_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset) { - LLVMValueRef sub_vector, result; - LLVMTypeRef sub_vector_type, vector_type; - bool is_signed; - uint32 data_length; - - switch (load_opcode) { - case SIMD_i16x8_load8x8_s: - case SIMD_i16x8_load8x8_u: - { - data_length = 8; - vector_type = V128_i16x8_TYPE; - is_signed = (load_opcode == SIMD_i16x8_load8x8_s); - - if (!(sub_vector_type = LLVMVectorType(INT8_TYPE, 8))) { - HANDLE_FAILURE("LLVMVectorType"); - goto fail; - } - - break; - } - case SIMD_i32x4_load16x4_s: - case SIMD_i32x4_load16x4_u: - { - data_length = 8; - vector_type = V128_i32x4_TYPE; - is_signed = (load_opcode == SIMD_i32x4_load16x4_s); - - if (!(sub_vector_type = LLVMVectorType(INT16_TYPE, 4))) { - HANDLE_FAILURE("LLVMVectorType"); - goto fail; - } - - break; - } - case SIMD_i64x2_load32x2_s: - case SIMD_i64x2_load32x2_u: - { - data_length = 8; - vector_type = V128_i64x2_TYPE; - is_signed = (load_opcode == SIMD_i64x2_load32x2_s); - - if (!(sub_vector_type = LLVMVectorType(I32_TYPE, 2))) { - HANDLE_FAILURE("LLVMVectorType"); - goto fail; - } - - break; - } - default: - { - bh_assert(0); - goto fail; - } - } - - /* to vector ptr type */ - if (!(sub_vector_type = LLVMPointerType(sub_vector_type, 0))) { - HANDLE_FAILURE("LLVMPointerType"); - goto fail; - } + LLVMValueRef value; - if (!(sub_vector = simd_load(comp_ctx, func_ctx, align, offset, - data_length, sub_vector_type))) { - goto fail; - } - - if (is_signed) { - if (!(result = LLVMBuildSExt(comp_ctx->builder, sub_vector, - vector_type, "vector"))) { - HANDLE_FAILURE("LLVMBuildSExt"); - goto fail; - } - } - else { - if (!(result = LLVMBuildZExt(comp_ctx->builder, sub_vector, - vector_type, "vector"))) { - HANDLE_FAILURE("LLVMBuildZExt"); - goto fail; - } - } - - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "result"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } + POP_V128(value); - PUSH_V128(result); - return true; + return simd_store(comp_ctx, func_ctx, align, offset, 16, value, + V128_PTR_TYPE); fail: return false; } bool -aot_compile_simd_load_splat(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 load_opcode, - uint32 align, - uint32 offset) +aot_compile_simd_store_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode, uint32 align, uint32 offset, + uint8 lane_id) { - LLVMValueRef element, result; - LLVMTypeRef element_ptr_type, vector_type; - unsigned data_length, lane_count; - - switch (load_opcode) { - case SIMD_v8x16_load_splat: - data_length = 1; - lane_count = 16; - element_ptr_type = INT8_PTR_TYPE; - vector_type = V128_i8x16_TYPE; - break; - case SIMD_v16x8_load_splat: - data_length = 2; - lane_count = 8; - element_ptr_type = INT16_PTR_TYPE; - vector_type = V128_i16x8_TYPE; - break; - case SIMD_v32x4_load_splat: - data_length = 4; - lane_count = 4; - element_ptr_type = INT32_PTR_TYPE; - vector_type = V128_i32x4_TYPE; - break; - case SIMD_v64x2_load_splat: - data_length = 8; - lane_count = 2; - element_ptr_type = INT64_PTR_TYPE; - vector_type = V128_i64x2_TYPE; - break; - default: - bh_assert(0); - goto fail; - } - - if (!(element = simd_load(comp_ctx, func_ctx, align, offset, data_length, - element_ptr_type))) { - goto fail; - } - - if (!(result = simd_splat(comp_ctx, func_ctx, element, vector_type, - lane_count))) { - goto fail; + LLVMValueRef element, vector; + uint32 data_lengths[] = { 1, 2, 4, 8 }; + LLVMTypeRef element_ptr_types[] = { INT8_PTR_TYPE, INT16_PTR_TYPE, + INT32_PTR_TYPE, INT64_PTR_TYPE }; + uint32 opcode_index = opcode - SIMD_v128_store8_lane; + LLVMTypeRef vector_types[] = { V128_i8x16_TYPE, V128_i16x8_TYPE, + V128_i32x4_TYPE, V128_i64x2_TYPE }; + LLVMValueRef lane = simd_lane_id_to_llvm_value(comp_ctx, lane_id); + + bh_assert(opcode_index < 4); + + if (!(vector = simd_pop_v128_and_bitcast( + comp_ctx, func_ctx, vector_types[opcode_index], "src"))) { + return false; } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "result"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; + if (!(element = LLVMBuildExtractElement(comp_ctx->builder, vector, lane, + "element"))) { + HANDLE_FAILURE("LLVMBuildExtractElement"); + return false; } - PUSH_V128(result); - return true; -fail: - return false; + return simd_store(comp_ctx, func_ctx, align, offset, + data_lengths[opcode_index], element, + element_ptr_types[opcode_index]); } diff --git a/core/iwasm/compilation/simd/simd_load_store.h b/core/iwasm/compilation/simd/simd_load_store.h index dbf662ad1b..fd118ec1b3 100644 --- a/core/iwasm/compilation/simd/simd_load_store.h +++ b/core/iwasm/compilation/simd/simd_load_store.h @@ -13,30 +13,34 @@ extern "C" { #endif bool -aot_compile_simd_v128_load(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 align, - uint32 offset); +aot_compile_simd_v128_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset); bool -aot_compile_simd_v128_store(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint32 align, - uint32 offset); +aot_compile_simd_load_extend(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode, uint32 align, uint32 offset); bool -aot_compile_simd_load_extend(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 load_opcode, - uint32 align, - uint32 offset); +aot_compile_simd_load_splat(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode, uint32 align, uint32 offset); bool -aot_compile_simd_load_splat(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - uint8 load_opcode, - uint32 align, - uint32 offset); +aot_compile_simd_load_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode, uint32 align, uint32 offset, + uint8 lane_id); + +bool +aot_compile_simd_load_zero(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode, uint32 align, uint32 offset); + +bool +aot_compile_simd_v128_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset); + +bool +aot_compile_simd_store_lane(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 opcode, uint32 align, uint32 offset, + uint8 lane_id); #ifdef __cplusplus } /* end of extern "C" */ diff --git a/core/iwasm/compilation/simd/simd_sat_int_arith.c b/core/iwasm/compilation/simd/simd_sat_int_arith.c index d8f85da768..1de4520a70 100644 --- a/core/iwasm/compilation/simd/simd_sat_int_arith.c +++ b/core/iwasm/compilation/simd/simd_sat_int_arith.c @@ -9,359 +9,73 @@ #include "../../aot/aot_runtime.h" static bool -simd_v128_integer_arith(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - LLVMTypeRef vector_type, - char *intrinsics_s_u[2], - bool is_signed) +simd_sat_int_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMTypeRef vector_type, const char *intrinsics) { LLVMValueRef lhs, rhs, result; LLVMTypeRef param_types[2]; - if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "rhs"))) { - goto fail; - } - - if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "lhs"))) { - goto fail; + if (!(rhs = + simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs")) + || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, + "lhs"))) { + return false; } param_types[0] = vector_type; param_types[1] = vector_type; - if (!(result = aot_call_llvm_intrinsic( - comp_ctx, is_signed ? intrinsics_s_u[0] : intrinsics_s_u[1], - vector_type, param_types, 2, lhs, rhs))) { + if (!(result = + aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsics, + vector_type, param_types, 2, lhs, rhs))) { HANDLE_FAILURE("LLVMBuildCall"); - goto fail; + return false; } - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } - - /* push result into the stack */ - PUSH_V128(result); - return true; -fail: - return false; + return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result"); } bool aot_compile_simd_i8x16_saturate(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - bool is_signed) + V128Arithmetic arith_op, bool is_signed) { - char *intrinsics[2] = { 0 }; - bool result = false; - switch (arith_op) { - case V128_ADD: - intrinsics[0] = "llvm.sadd.sat.v16i8"; - intrinsics[1] = "llvm.uadd.sat.v16i8"; - result = simd_v128_integer_arith( - comp_ctx, func_ctx, V128_i8x16_TYPE, intrinsics, is_signed); - break; - case V128_SUB: - intrinsics[0] = "llvm.ssub.sat.v16i8"; - intrinsics[1] = "llvm.usub.sat.v16i8"; - result = simd_v128_integer_arith( - comp_ctx, func_ctx, V128_i8x16_TYPE, intrinsics, is_signed); - break; - default: - bh_assert(0); - break; - } - - return result; + char *intrinsics[][2] = { + { "llvm.sadd.sat.v16i8", "llvm.uadd.sat.v16i8" }, + { "llvm.ssub.sat.v16i8", "llvm.usub.sat.v16i8" }, + }; + + return simd_sat_int_arith(comp_ctx, func_ctx, V128_i8x16_TYPE, + is_signed ? intrinsics[arith_op][0] + : intrinsics[arith_op][1]); } bool aot_compile_simd_i16x8_saturate(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - bool is_signed) -{ - char *intrinsics[2] = { 0 }; - bool result = false; - switch (arith_op) { - case V128_ADD: - intrinsics[0] = "llvm.sadd.sat.v8i16"; - intrinsics[1] = "llvm.uadd.sat.v8i16"; - result = simd_v128_integer_arith( - comp_ctx, func_ctx, V128_i16x8_TYPE, intrinsics, is_signed); - break; - case V128_SUB: - intrinsics[0] = "llvm.ssub.sat.v8i16"; - intrinsics[1] = "llvm.usub.sat.v8i16"; - result = simd_v128_integer_arith( - comp_ctx, func_ctx, V128_i16x8_TYPE, intrinsics, is_signed); - break; - default: - bh_assert(0); - break; - } - - return result; -} - -static bool -simd_v128_cmp(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - LLVMTypeRef vector_type, - V128Arithmetic arith_op, - bool is_signed) -{ - LLVMValueRef lhs, rhs, result; - LLVMIntPredicate op; - - if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "rhs"))) { - goto fail; - } - - if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "lhs"))) { - goto fail; - } - - if (V128_MIN == arith_op) { - op = is_signed ? LLVMIntSLT : LLVMIntULT; - } - else { - op = is_signed ? LLVMIntSGT : LLVMIntUGT; - } - - if (!(result = LLVMBuildICmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) { - HANDLE_FAILURE("LLVMBuildICmp"); - goto fail; - } - - if (!(result = - LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; - } - - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } - - /* push result into the stack */ - PUSH_V128(result); - return true; -fail: - return false; -} - -bool -aot_compile_simd_i8x16_cmp(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - bool is_signed) -{ - return simd_v128_cmp(comp_ctx, func_ctx, V128_i8x16_TYPE, arith_op, - is_signed); -} - -bool -aot_compile_simd_i16x8_cmp(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - bool is_signed) -{ - return simd_v128_cmp(comp_ctx, func_ctx, V128_i16x8_TYPE, arith_op, - is_signed); -} - -bool -aot_compile_simd_i32x4_cmp(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - bool is_signed) -{ - return simd_v128_cmp(comp_ctx, func_ctx, V128_i32x4_TYPE, arith_op, - is_signed); -} - -static bool -simd_v128_abs(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - LLVMTypeRef vector_type) -{ - LLVMValueRef vector, negs, zeros, cond, result; - - if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "vec"))) { - goto fail; - } - - if (!(negs = LLVMBuildNeg(comp_ctx->builder, vector, "neg"))) { - HANDLE_FAILURE("LLVMBuildNeg"); - goto fail; - } - - if (!(zeros = LLVMConstNull(vector_type))) { - HANDLE_FAILURE("LLVMConstNull"); - goto fail; - } - - if (!(cond = LLVMBuildICmp(comp_ctx->builder, LLVMIntSGE, vector, zeros, - "ge_zero"))) { - HANDLE_FAILURE("LLVMBuildICmp"); - goto fail; - } - - if (!(result = LLVMBuildSelect(comp_ctx->builder, cond, vector, negs, - "select"))) { - HANDLE_FAILURE("LLVMBuildSelect"); - goto fail; - } - - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } - - /* push result into the stack */ - PUSH_V128(result); - return true; -fail: - return false; -} - -bool -aot_compile_simd_i8x16_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) + V128Arithmetic arith_op, bool is_signed) { - return simd_v128_abs(comp_ctx, func_ctx, V128_i8x16_TYPE); + char *intrinsics[][2] = { + { "llvm.sadd.sat.v8i16", "llvm.uadd.sat.v8i16" }, + { "llvm.ssub.sat.v8i16", "llvm.usub.sat.v8i16" }, + }; + + return simd_sat_int_arith(comp_ctx, func_ctx, V128_i16x8_TYPE, + is_signed ? intrinsics[arith_op][0] + : intrinsics[arith_op][1]); } bool -aot_compile_simd_i16x8_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) -{ - return simd_v128_abs(comp_ctx, func_ctx, V128_i16x8_TYPE); -} - -bool -aot_compile_simd_i32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) -{ - return simd_v128_abs(comp_ctx, func_ctx, V128_i32x4_TYPE); -} - -/* (v1 + v2 + 1) / 2 */ -static bool -simd_v128_avg(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - LLVMTypeRef vector_type, - LLVMTypeRef element_type, - unsigned lane_width) -{ - LLVMValueRef lhs, rhs, undef, zeros, ones, result; - LLVMTypeRef ext_type; - - if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "rhs"))) { - goto fail; - } - - if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, - "lhs"))) { - goto fail; - } - - if (!(ext_type = LLVMVectorType(I32_TYPE, lane_width))) { - HANDLE_FAILURE("LLVMVectorType"); - goto fail; - } - - if (!(lhs = LLVMBuildZExt(comp_ctx->builder, lhs, ext_type, "left_ext"))) { - HANDLE_FAILURE("LLVMBuildZExt"); - goto fail; - } - - if (!(rhs = - LLVMBuildZExt(comp_ctx->builder, rhs, ext_type, "right_ext"))) { - HANDLE_FAILURE("LLVMBuildZExt"); - goto fail; - } - - if (!(undef = LLVMGetUndef(ext_type))) { - HANDLE_FAILURE("LLVMGetUndef"); - goto fail; - } - - if (!(zeros = LLVMConstNull(ext_type))) { - HANDLE_FAILURE("LLVMConstNull"); - goto fail; - } - - if (!(ones = LLVMConstInt(I32_TYPE, 1, true))) { - HANDLE_FAILURE("LLVMConstInt"); - goto fail; - } - - if (!(ones = LLVMBuildInsertElement(comp_ctx->builder, undef, ones, - I32_ZERO, "base_ones"))) { - HANDLE_FAILURE("LLVMBuildInsertElement"); - goto fail; - } - - if (!(ones = LLVMBuildShuffleVector(comp_ctx->builder, ones, undef, zeros, - "ones"))) { - HANDLE_FAILURE("LLVMBuildShuffleVector"); - goto fail; - } - - if (!(result = LLVMBuildAdd(comp_ctx->builder, lhs, rhs, "a_add_b"))) { - HANDLE_FAILURE("LLVMBuildAdd"); - goto fail; - } - - if (!(result = LLVMBuildAdd(comp_ctx->builder, result, ones, "plus_1"))) { - HANDLE_FAILURE("LLVMBuildAdd"); - goto fail; - } - - if (!(result = LLVMBuildLShr(comp_ctx->builder, result, ones, "avg"))) { - HANDLE_FAILURE("LLVMBuildLShr"); - goto fail; - } - - if (!(result = LLVMBuildTrunc(comp_ctx->builder, result, vector_type, - "avg_trunc"))) { - HANDLE_FAILURE("LLVMBuildTrunc"); - goto fail; - } - - if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE, - "ret"))) { - HANDLE_FAILURE("LLVMBuildBitCast"); - goto fail; - } - - /* push result into the stack */ - PUSH_V128(result); - return true; -fail: - return false; -} -bool -aot_compile_simd_i8x16_avgr_u(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx) +aot_compile_simd_i32x4_saturate(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + V128Arithmetic arith_op, bool is_signed) { - return simd_v128_avg(comp_ctx, func_ctx, V128_i8x16_TYPE, INT8_TYPE, 16); + char *intrinsics[][2] = { + { "llvm.sadd.sat.v4i32", "llvm.uadd.sat.v4i32" }, + { "llvm.ssub.sat.v4i32", "llvm.usub.sat.v4i32" }, + }; + + return simd_sat_int_arith(comp_ctx, func_ctx, V128_i16x8_TYPE, + is_signed ? intrinsics[arith_op][0] + : intrinsics[arith_op][1]); } - -bool -aot_compile_simd_i16x8_avgr_u(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx) -{ - return simd_v128_avg(comp_ctx, func_ctx, V128_i16x8_TYPE, INT16_TYPE, 8); -} \ No newline at end of file diff --git a/core/iwasm/compilation/simd/simd_sat_int_arith.h b/core/iwasm/compilation/simd/simd_sat_int_arith.h index 57669878ef..e30acaaf44 100644 --- a/core/iwasm/compilation/simd/simd_sat_int_arith.h +++ b/core/iwasm/compilation/simd/simd_sat_int_arith.h @@ -15,50 +15,17 @@ extern "C" { bool aot_compile_simd_i8x16_saturate(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - bool is_signed); + V128Arithmetic arith_op, bool is_signed); bool aot_compile_simd_i16x8_saturate(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - bool is_signed); + V128Arithmetic arith_op, bool is_signed); bool -aot_compile_simd_i8x16_cmp(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - bool is_signed); - -bool -aot_compile_simd_i16x8_cmp(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - bool is_signed); - -bool -aot_compile_simd_i32x4_cmp(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx, - V128Arithmetic arith_op, - bool is_signed); - -bool -aot_compile_simd_i8x16_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); - -bool -aot_compile_simd_i16x8_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); - -bool -aot_compile_simd_i32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); - -bool -aot_compile_simd_i8x16_avgr_u(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx); - -bool -aot_compile_simd_i16x8_avgr_u(AOTCompContext *comp_ctx, - AOTFuncContext *func_ctx); - +aot_compile_simd_i32x4_saturate(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + V128Arithmetic arith_op, bool is_signed); #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/include/aot_export.h b/core/iwasm/include/aot_export.h index d209044cee..f323a5858e 100644 --- a/core/iwasm/include/aot_export.h +++ b/core/iwasm/include/aot_export.h @@ -9,7 +9,6 @@ #include #include - #ifdef __cplusplus extern "C" { #endif @@ -26,6 +25,12 @@ aot_create_comp_data(void *wasm_module); void aot_destroy_comp_data(aot_comp_data_t comp_data); +#if WASM_ENABLE_DEBUG_AOT != 0 +typedef void *dwar_extractor_handle_t; +dwar_extractor_handle_t +create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name); +#endif + enum { AOT_FORMAT_FILE, AOT_OBJECT_FILE, @@ -33,12 +38,14 @@ enum { AOT_LLVMIR_OPT_FILE, }; -typedef struct AOTCompOption{ +typedef struct AOTCompOption { bool is_jit_mode; + bool is_indirect_mode; char *target_arch; char *target_abi; char *target_cpu; char *cpu_features; + bool is_sgx_platform; bool enable_bulk_memory; bool enable_thread_mgr; bool enable_tail_call; @@ -46,7 +53,7 @@ typedef struct AOTCompOption{ bool enable_ref_types; bool enable_aux_stack_check; bool enable_aux_stack_frame; - bool is_sgx_platform; + bool disable_llvm_intrinsics; uint32_t opt_level; uint32_t size_level; uint32_t output_format; @@ -54,8 +61,7 @@ typedef struct AOTCompOption{ } AOTCompOption, *aot_comp_option_t; aot_comp_context_t -aot_create_comp_context(aot_comp_data_t comp_data, - aot_comp_option_t option); +aot_create_comp_context(aot_comp_data_t comp_data, aot_comp_option_t option); void aot_destroy_comp_context(aot_comp_context_t comp_ctx); @@ -70,19 +76,24 @@ bool aot_emit_object_file(aot_comp_context_t comp_ctx, const char *file_name); bool -aot_emit_aot_file(aot_comp_context_t comp_ctx, - aot_comp_data_t comp_data, +aot_emit_aot_file(aot_comp_context_t comp_ctx, aot_comp_data_t comp_data, const char *file_name); void aot_destroy_aot_file(uint8_t *aot_file); -uint8_t* +bool +aot_compile_wasm_file_init(); + +uint8_t * aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size, - uint32_t opt_level, uint32_t size_level, - uint32_t *p_aot_file_size); + uint32_t opt_level, uint32_t size_level, char *error_buf, + uint32_t error_buf_size, uint32_t *p_aot_file_size); + +void +aot_compile_wasm_file_destroy(); -char* +char * aot_get_last_error(); uint32_t diff --git a/core/iwasm/include/lib_export.h b/core/iwasm/include/lib_export.h index 3a4c02d43b..e4829e4fe4 100644 --- a/core/iwasm/include/lib_export.h +++ b/core/iwasm/include/lib_export.h @@ -21,18 +21,22 @@ typedef struct NativeSymbol { void *attachment; } NativeSymbol; -#define EXPORT_WASM_API(symbol) {#symbol, (void*)symbol, NULL, NULL} -#define EXPORT_WASM_API2(symbol) {#symbol, (void*)symbol##_wrapper, NULL, NULL} +/* clang-format off */ +#define EXPORT_WASM_API(symbol) \ + { #symbol, (void *)symbol, NULL, NULL } +#define EXPORT_WASM_API2(symbol) \ + { #symbol, (void *)symbol##_wrapper, NULL, NULL } #define EXPORT_WASM_API_WITH_SIG(symbol, signature) \ - {#symbol, (void*)symbol, signature, NULL} + { #symbol, (void *)symbol, signature, NULL } #define EXPORT_WASM_API_WITH_SIG2(symbol, signature) \ - {#symbol, (void*)symbol##_wrapper, signature, NULL} + { #symbol, (void *)symbol##_wrapper, signature, NULL } #define EXPORT_WASM_API_WITH_ATT(symbol, signature, attachment) \ - {#symbol, (void*)symbol, signature, attachment} + { #symbol, (void *)symbol, signature, attachment } #define EXPORT_WASM_API_WITH_ATT2(symbol, signature, attachment) \ - {#symbol, (void*)symbol##_wrapper, signature, attachment} + { #symbol, (void *)symbol##_wrapper, signature, attachment } +/* clang-format on */ /** * Get the exported APIs of base lib @@ -48,5 +52,4 @@ get_base_lib_export_apis(NativeSymbol **p_base_lib_apis); } #endif -#endif - +#endif /* end of _LIB_EXPORT_H_ */ diff --git a/core/iwasm/include/wasm_c_api.h b/core/iwasm/include/wasm_c_api.h index 88e514be02..6722093a4a 100644 --- a/core/iwasm/include/wasm_c_api.h +++ b/core/iwasm/include/wasm_c_api.h @@ -1,7 +1,7 @@ // WebAssembly C API -#ifndef WASM_H -#define WASM_H +#ifndef _WASM_C_API_H_ +#define _WASM_C_API_H_ #include #include @@ -11,11 +11,11 @@ #ifndef WASM_API_EXTERN #if defined(_MSC_BUILD) - #if defined(COMPILING_WASM_RUNTIME_API) - #define WASM_API_EXTERN __declspec(dllexport) - #else - #define WASM_API_EXTERN __declspec(dllimport) - #endif +#if defined(COMPILING_WASM_RUNTIME_API) +#define WASM_API_EXTERN __declspec(dllexport) +#else +#define WASM_API_EXTERN __declspec(dllimport) +#endif #else #define WASM_API_EXTERN #endif @@ -25,6 +25,8 @@ extern "C" { #endif +/* clang-format off */ + /////////////////////////////////////////////////////////////////////////////// // Auxiliaries @@ -145,6 +147,37 @@ WASM_DECLARE_OWN(engine) WASM_API_EXTERN own wasm_engine_t* wasm_engine_new(void); WASM_API_EXTERN own wasm_engine_t* wasm_engine_new_with_config(own wasm_config_t*); +#ifndef MEM_ALLOC_OPTION_DEFINED +#define MEM_ALLOC_OPTION_DEFINED +/* same definition from wasm_export.h */ +/* Memory allocator type */ +typedef enum { + /* pool mode, allocate memory from user defined heap buffer */ + Alloc_With_Pool = 0, + /* user allocator mode, allocate memory from user defined + malloc function */ + Alloc_With_Allocator, + /* system allocator mode, allocate memory from system allocator, + or, platform's os_malloc function */ + Alloc_With_System_Allocator, +} mem_alloc_type_t; + +/* Memory allocator option */ +typedef union MemAllocOption { + struct { + void *heap_buf; + uint32_t heap_size; + } pool; + struct { + void *malloc_func; + void *realloc_func; + void *free_func; + } allocator; +} MemAllocOption; +#endif + +WASM_API_EXTERN own wasm_engine_t * +wasm_engine_new_with_args(mem_alloc_type_t type, const MemAllocOption *opts); // Store @@ -436,9 +469,9 @@ WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const WASM_DECLARE_REF(func) typedef own wasm_trap_t* (*wasm_func_callback_t)( - const wasm_val_t args[], own wasm_val_t results[]); + const wasm_val_vec_t* args, own wasm_val_vec_t *results); typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)( - void* env, const wasm_val_t args[], wasm_val_t results[]); + void* env, const wasm_val_vec_t *args, wasm_val_vec_t *results); WASM_API_EXTERN own wasm_func_t* wasm_func_new( wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t); @@ -451,7 +484,7 @@ WASM_API_EXTERN size_t wasm_func_param_arity(const wasm_func_t*); WASM_API_EXTERN size_t wasm_func_result_arity(const wasm_func_t*); WASM_API_EXTERN own wasm_trap_t* wasm_func_call( - const wasm_func_t*, const wasm_val_t args[], wasm_val_t results[]); + const wasm_func_t*, const wasm_val_vec_t* args, wasm_val_vec_t* results); // Global Instances @@ -538,10 +571,16 @@ WASM_API_EXTERN const wasm_memory_t* wasm_extern_as_memory_const(const wasm_exte WASM_DECLARE_REF(instance) WASM_API_EXTERN own wasm_instance_t* wasm_instance_new( - wasm_store_t*, const wasm_module_t*, const wasm_extern_t *const imports[], + wasm_store_t*, const wasm_module_t*, const wasm_extern_vec_t *imports, own wasm_trap_t** ); +// please refer to wasm_runtime_instantiate(...) in core/iwasm/include/wasm_export.h +WASM_API_EXTERN own wasm_instance_t* wasm_instance_new_with_args( + wasm_store_t*, const wasm_module_t*, const wasm_extern_vec_t *imports, + own wasm_trap_t**, const uint32_t stack_size, const uint32_t heap_size +); + WASM_API_EXTERN void wasm_instance_exports(const wasm_instance_t*, own wasm_extern_vec_t* out); @@ -733,13 +772,16 @@ static inline void* wasm_val_ptr(const wasm_val_t* val) { #define WASM_REF_VAL(r) {.kind = WASM_ANYREF, .of = {.ref = r}} #define WASM_INIT_VAL {.kind = WASM_ANYREF, .of = {.ref = NULL}} +#define KILOBYTE(n) ((n) * 1024) /////////////////////////////////////////////////////////////////////////////// #undef own +/* clang-format on */ + #ifdef __cplusplus -} // extern "C" +} // extern "C" #endif -#endif // #ifdef WASM_H +#endif // #ifdef _WASM_C_API_H_ diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 0fe46d61cd..9b33f9f4c7 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -10,14 +10,13 @@ #include #include "lib_export.h" - #ifndef WASM_RUNTIME_API_EXTERN -#if defined(_MSC_BUILD ) - #if defined(COMPILING_WASM_RUNTIME_API) - #define WASM_RUNTIME_API_EXTERN __declspec(dllexport) - #else - #define WASM_RUNTIME_API_EXTERN __declspec(dllimport) - #endif +#if defined(_MSC_BUILD) +#if defined(COMPILING_WASM_RUNTIME_API) +#define WASM_RUNTIME_API_EXTERN __declspec(dllexport) +#else +#define WASM_RUNTIME_API_EXTERN __declspec(dllimport) +#endif #else #define WASM_RUNTIME_API_EXTERN #endif @@ -27,6 +26,8 @@ extern "C" { #endif +/* clang-format off */ + #define get_module_inst(exec_env) \ wasm_runtime_get_module_inst(exec_env) @@ -48,13 +49,12 @@ extern "C" { #define module_free(offset) \ wasm_runtime_module_free(module_inst, offset) -#define native_raw_return_type(type, args) type *raw_ret = (type*)(args) +#define native_raw_return_type(type, args) type *raw_ret = (type *)(args) -#define native_raw_get_arg(type, name, args) type name = *((type*)(args++)) +#define native_raw_get_arg(type, name, args) type name = *((type *)(args++)) #define native_raw_set_return(val) *raw_ret = (val) - #ifndef WASM_MODULE_T_DEFINED #define WASM_MODULE_T_DEFINED /* Uninstantiated WASM module loaded from WASM binary file @@ -93,6 +93,8 @@ typedef enum { Package_Type_Unknown = 0xFFFF } package_type_t; +#ifndef MEM_ALLOC_OPTION_DEFINED +#define MEM_ALLOC_OPTION_DEFINED /* Memory allocator type */ typedef enum { /* pool mode, allocate memory from user defined heap buffer */ @@ -117,6 +119,7 @@ typedef union MemAllocOption { void *free_func; } allocator; } MemAllocOption; +#endif /* WASM runtime initialize arguments */ typedef struct RuntimeInitArgs { @@ -130,6 +133,11 @@ typedef struct RuntimeInitArgs { /* maximum thread number, only used when WASM_ENABLE_THREAD_MGR is defined */ uint32_t max_thread_num; +#if WASM_ENABLE_DEBUG_INTERP != 0 + char ip_addr[128]; + int platform_port; + int instance_port; +#endif } RuntimeInitArgs; #ifndef WASM_VALKIND_T_DEFINED @@ -150,14 +158,14 @@ enum wasm_valkind_enum { struct wasm_ref_t; typedef struct wasm_val_t { - wasm_valkind_t kind; - union { - int32_t i32; - int64_t i64; - float f32; - double f64; - struct wasm_ref_t* ref; - } of; + wasm_valkind_t kind; + union { + int32_t i32; + int64_t i64; + float f32; + double f64; + struct wasm_ref_t *ref; + } of; } wasm_val_t; #endif @@ -413,13 +421,13 @@ wasm_runtime_destroy_exec_env(wasm_exec_env_t exec_env); * @return true if success, false otherwise */ WASM_RUNTIME_API_EXTERN bool -wasm_runtime_init_thread_env(); +wasm_runtime_init_thread_env(void); /** * Destroy thread environment */ WASM_RUNTIME_API_EXTERN void -wasm_runtime_destroy_thread_env(); +wasm_runtime_destroy_thread_env(void); /** * Get WASM module instance from execution environment @@ -644,10 +652,11 @@ wasm_runtime_validate_app_addr(wasm_module_inst_t module_inst, /** * Similar to wasm_runtime_validate_app_addr(), except that the size parameter - * is not provided. This function validates the app string address, check whether it - * belongs to WASM module instance's address space, or in its heap space or - * memory space. Moreover, it checks whether it is the offset of a string that - * is end with '\0'. + * is not provided. This function validates the app string address, check + * whether it belongs to WASM module instance's address space, or in its heap + * space or memory space. Moreover, it checks whether it is the offset of a + * string that is end with '\0'. + * * @param module_inst the WASM module instance * @param app_str_offset the app address of the string to validate, which is a * relative address @@ -716,12 +725,15 @@ wasm_runtime_get_app_addr_range(wasm_module_inst_t module_inst, uint32_t *p_app_end_offset); /** - * Get the native address range (absolute address) that a native address belongs to + * Get the native address range (absolute address) that a native address + * belongs to * * @param module_inst the WASM module instance * @param native_ptr the native address to retrieve - * @param p_native_start_addr buffer to output the native start address if not NULL - * @param p_native_end_addr buffer to output the native end address if not NULL + * @param p_native_start_addr buffer to output the native start address + * if not NULL + * @param p_native_end_addr buffer to output the native end address + * if not NULL * * @return true if success, false otherwise. */ @@ -732,31 +744,31 @@ wasm_runtime_get_native_addr_range(wasm_module_inst_t module_inst, uint8_t **p_native_end_addr); /** - * Register native functions with same module name - * - * @param module_name the module name of the native functions - * @param native_symbols specifies an array of NativeSymbol structures which - * contain the names, function pointers and signatures - * Note: WASM runtime will not allocate memory to clone the data, so - * user must ensure the array can be used forever - * Meanings of letters in function signature: - * 'i': the parameter is i32 type - * 'I': the parameter is i64 type - * 'f': the parameter is f32 type - * 'F': the parameter is f64 type - * '*': the parameter is a pointer (i32 in WASM), and runtime will - * auto check its boundary before calling the native function. - * If it is followed by '~', the checked length of the pointer - * is gotten from the following parameter, if not, the checked - * length of the pointer is 1. - * '~': the parameter is the pointer's length with i32 type, and must - * follow after '*' - * '$': the parameter is a string (i32 in WASM), and runtime will - * auto check its boundary before calling the native function - * @param n_native_symbols specifies the number of native symbols in the array - * - * @return true if success, false otherwise - */ + * Register native functions with same module name + * + * @param module_name the module name of the native functions + * @param native_symbols specifies an array of NativeSymbol structures which + * contain the names, function pointers and signatures + * Note: WASM runtime will not allocate memory to clone the data, so + * user must ensure the array can be used forever + * Meanings of letters in function signature: + * 'i': the parameter is i32 type + * 'I': the parameter is i64 type + * 'f': the parameter is f32 type + * 'F': the parameter is f64 type + * '*': the parameter is a pointer (i32 in WASM), and runtime will + * auto check its boundary before calling the native function. + * If it is followed by '~', the checked length of the pointer + * is gotten from the following parameter, if not, the checked + * length of the pointer is 1. + * '~': the parameter is the pointer's length with i32 type, and must + * follow after '*' + * '$': the parameter is a string (i32 in WASM), and runtime will + * auto check its boundary before calling the native function + * @param n_native_symbols specifies the number of native symbols in the array + * + * @return true if success, false otherwise + */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_register_natives(const char *module_name, NativeSymbol *native_symbols, @@ -765,7 +777,7 @@ wasm_runtime_register_natives(const char *module_name, /** * Register native functions with same module name, similar to * wasm_runtime_register_natives, the difference is that runtime passes raw - * arguments to native API, which means that the native API should be defined as: + * arguments to native API, which means that the native API should be defined as * void foo(wasm_exec_env_t exec_env, uint64 *args); * and native API should extract arguments one by one from args array with macro * native_raw_get_arg @@ -794,8 +806,7 @@ wasm_runtime_get_function_attachment(wasm_exec_env_t exec_env); * @param user_data the user data to be set */ WASM_RUNTIME_API_EXTERN void -wasm_runtime_set_user_data(wasm_exec_env_t exec_env, - void *user_data); +wasm_runtime_set_user_data(wasm_exec_env_t exec_env, void *user_data); /** * Get the user data within execution environment. * @@ -827,7 +838,7 @@ WASM_RUNTIME_API_EXTERN void wasm_runtime_dump_perf_profiling(wasm_module_inst_t module_inst); /* wasm thread callback function type */ -typedef void* (*wasm_thread_callback_t)(wasm_exec_env_t, void *); +typedef void *(*wasm_thread_callback_t)(wasm_exec_env_t, void *); /* wasm thread type */ typedef uintptr_t wasm_thread_t; @@ -930,6 +941,8 @@ wasm_externref_retain(uint32_t externref_idx); WASM_RUNTIME_API_EXTERN void wasm_runtime_dump_call_stack(wasm_exec_env_t exec_env); +/* clang-format on */ + #ifdef __cplusplus } #endif diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index fedf3dd4ed..4402b92e41 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -24,7 +24,7 @@ extern "C" { #define VALUE_TYPE_EXTERNREF 0x6F #define VALUE_TYPE_VOID 0x40 /* Used by AOT */ -#define VALUE_TYPE_I1 0x41 +#define VALUE_TYPE_I1 0x41 /* Used by loader to represent any type of i32/i64/f32/f64 */ #define VALUE_TYPE_ANY 0x42 @@ -66,8 +66,8 @@ extern "C" { #endif #define SUB_SECTION_TYPE_MODULE 0 -#define SUB_SECTION_TYPE_FUNC 1 -#define SUB_SECTION_TYPE_LOCAL 2 +#define SUB_SECTION_TYPE_FUNC 1 +#define SUB_SECTION_TYPE_LOCAL 2 #define IMPORT_KIND_FUNC 0 #define IMPORT_KIND_TABLE 1 @@ -316,6 +316,13 @@ typedef struct StringNode { char *str; } StringNode, *StringList; +#if WASM_ENABLE_DEBUG_INTERP != 0 +typedef struct WASMFastOPCodeNode { + struct WASMFastOPCodeNode *next; + uint64 offset; + uint8 orig_op; +} WASMFastOPCodeNode; +#endif struct WASMModule { /* Module type, for module loaded from WASM bytecode binary, this field is Wasm_Module_Bytecode; @@ -404,6 +411,13 @@ struct WASMModule { bh_list import_module_list_head; bh_list *import_module_list; #endif +#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_DEBUG_AOT != 0 + bh_list fast_opcode_list; + uint8 *buf_code; + uint8 *load_addr; + uint64 load_size; + uint64 buf_code_size; +#endif }; typedef struct BlockType { @@ -435,7 +449,7 @@ typedef struct WASMBranchBlock { * @return the aligned value */ inline static unsigned -align_uint (unsigned v, unsigned b) +align_uint(unsigned v, unsigned b) { unsigned m = b - 1; return (v + m) & ~m; @@ -448,7 +462,7 @@ inline static uint32 wasm_string_hash(const char *str) { unsigned h = (unsigned)strlen(str); - const uint8 *p = (uint8*)str; + const uint8 *p = (uint8 *)str; const uint8 *end = p + h; while (p != end) @@ -533,9 +547,10 @@ wasm_type_equal(const WASMType *type1, const WASMType *type2) return (type1->param_count == type2->param_count && type1->result_count == type2->result_count && memcmp(type1->types, type2->types, - (uint32)(type1->param_count - + type1->result_count)) == 0) - ? true : false; + (uint32)(type1->param_count + type1->result_count)) + == 0) + ? true + : false; } inline static uint32 @@ -552,8 +567,7 @@ wasm_get_smallest_type_idx(WASMType **types, uint32 type_count, } static inline uint32 -block_type_get_param_types(BlockType *block_type, - uint8 **p_param_types) +block_type_get_param_types(BlockType *block_type, uint8 **p_param_types) { uint32 param_count = 0; if (!block_type->is_value_type) { @@ -563,15 +577,14 @@ block_type_get_param_types(BlockType *block_type, } else { *p_param_types = NULL; - param_count = 0; + param_count = 0; } return param_count; } static inline uint32 -block_type_get_result_types(BlockType *block_type, - uint8 **p_result_types) +block_type_get_result_types(BlockType *block_type, uint8 **p_result_types) { uint32 result_count = 0; if (block_type->is_value_type) { diff --git a/core/iwasm/interpreter/wasm_interp.h b/core/iwasm/interpreter/wasm_interp.h index a0d56f3287..4ac36edae6 100644 --- a/core/iwasm/interpreter/wasm_interp.h +++ b/core/iwasm/interpreter/wasm_interp.h @@ -17,43 +17,43 @@ struct WASMFunctionInstance; struct WASMExecEnv; typedef struct WASMInterpFrame { - /* The frame of the caller that are calling the current function. */ - struct WASMInterpFrame *prev_frame; + /* The frame of the caller that are calling the current function. */ + struct WASMInterpFrame *prev_frame; - /* The current WASM function. */ - struct WASMFunctionInstance *function; + /* The current WASM function. */ + struct WASMFunctionInstance *function; - /* Instruction pointer of the bytecode array. */ - uint8 *ip; + /* Instruction pointer of the bytecode array. */ + uint8 *ip; #if WASM_ENABLE_PERF_PROFILING != 0 - uint64 time_started; + uint64 time_started; #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 */ - uint32 ret_offset; - uint32 *lp; - uint32 operand[1]; + /* Return offset of the first return value of current frame, + the callee will put return values here continuously */ + uint32 ret_offset; + uint32 *lp; + uint32 operand[1]; #else - /* Operand stack top pointer of the current frame. The bottom of - the stack is the next cell after the last local variable. */ - uint32 *sp_bottom; - uint32 *sp_boundary; - uint32 *sp; + /* Operand stack top pointer of the current frame. The bottom of + the stack is the next cell after the last local variable. */ + uint32 *sp_bottom; + uint32 *sp_boundary; + uint32 *sp; - WASMBranchBlock *csp_bottom; - WASMBranchBlock *csp_boundary; - WASMBranchBlock *csp; + WASMBranchBlock *csp_bottom; + WASMBranchBlock *csp_boundary; + WASMBranchBlock *csp; - /* Frame data, the layout is: - lp: param_cell_count + local_cell_count - sp_bottom to sp_boundary: stack of data - csp_bottom to csp_boundary: stack of block - ref to frame end: data types of local vairables and stack data - */ - uint32 lp[1]; + /* Frame data, the layout is: + lp: param_cell_count + local_cell_count + sp_bottom to sp_boundary: stack of data + csp_bottom to csp_boundary: stack of block + ref to frame end: data types of local vairables and stack data + */ + uint32 lp[1]; #endif } WASMInterpFrame; @@ -68,15 +68,15 @@ typedef struct WASMInterpFrame { static inline unsigned wasm_interp_interp_frame_size(unsigned all_cell_num) { - return align_uint((uint32)offsetof(WASMInterpFrame, lp) - + all_cell_num * 5, 4); + return align_uint((uint32)offsetof(WASMInterpFrame, lp) + all_cell_num * 5, + 4); } void wasm_interp_call_wasm(struct WASMModuleInstance *module_inst, struct WASMExecEnv *exec_env, - struct WASMFunctionInstance *function, - uint32 argc, uint32 argv[]); + struct WASMFunctionInstance *function, uint32 argc, + uint32 argv[]); #ifdef __cplusplus } diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index fdfa4b32ff..a4e48510af 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -12,6 +12,9 @@ #if WASM_ENABLE_SHARED_MEMORY != 0 #include "../common/wasm_shared_memory.h" #endif +#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 +#include "../libraries/thread-mgr/thread_manager.h" +#endif typedef int32 CellType_I32; typedef int64 CellType_I64; @@ -20,29 +23,33 @@ typedef float64 CellType_F64; #define BR_TABLE_TMP_BUF_LEN 32 -#define CHECK_MEMORY_OVERFLOW(bytes) do { \ - uint64 offset1 = (uint64)offset + (uint64)addr; \ - if (offset1 + bytes <= (uint64)linear_mem_size) \ - /* If offset1 is in valid range, maddr must also be in valid range, \ - no need to check it again. */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ - } while (0) - -#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) do { \ - uint64 offset1 = (uint32)(start); \ - if (offset1 + bytes <= (uint64)linear_mem_size) \ - /* App heap space is not valid space for bulk memory operation */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ - } while (0) - -#define CHECK_ATOMIC_MEMORY_ACCESS() do { \ - if (((uintptr_t)maddr & ((1 << align) - 1)) != 0) \ - goto unaligned_atomic; \ - } while (0) +#define CHECK_MEMORY_OVERFLOW(bytes) \ + do { \ + uint64 offset1 = (uint64)offset + (uint64)addr; \ + if (offset1 + bytes <= (uint64)linear_mem_size) \ + /* If offset1 is in valid range, maddr must also \ + be in valid range, no need to check it again. */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ + } while (0) + +#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ + do { \ + uint64 offset1 = (uint32)(start); \ + if (offset1 + bytes <= (uint64)linear_mem_size) \ + /* App heap space is not valid space for \ + bulk memory operation */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ + } while (0) + +#define CHECK_ATOMIC_MEMORY_ACCESS() \ + do { \ + if (((uintptr_t)maddr & (((uintptr_t)1 << align) - 1)) != 0) \ + goto unaligned_atomic; \ + } while (0) static inline uint32 rotl32(uint32 n, uint32 c) @@ -50,7 +57,7 @@ rotl32(uint32 n, uint32 c) const uint32 mask = (31); c = c % 32; c &= mask; - return (n<>( (-c)&mask )); + return (n << c) | (n >> ((0 - c) & mask)); } static inline uint32 @@ -59,7 +66,7 @@ rotr32(uint32 n, uint32 c) const uint32 mask = (31); c = c % 32; c &= mask; - return (n>>c) | (n<<( (-c)&mask )); + return (n >> c) | (n << ((0 - c) & mask)); } static inline uint64 @@ -68,7 +75,7 @@ rotl64(uint64 n, uint64 c) const uint64 mask = (63); c = c % 64; c &= mask; - return (n<>( (-c)&mask )); + return (n << c) | (n >> ((0 - c) & mask)); } static inline uint64 @@ -77,14 +84,14 @@ rotr64(uint64 n, uint64 c) const uint64 mask = (63); c = c % 64; c &= mask; - return (n>>c) | (n<<( (-c)&mask )); + return (n >> c) | (n << ((0 - c) & mask)); } static inline double wa_fmax(double a, double b) { double c = fmax(a, b); - if (c==0 && a==b) + if (c == 0 && a == b) return signbit(a) ? b : a; return c; } @@ -93,7 +100,7 @@ static inline double wa_fmin(double a, double b) { double c = fmin(a, b); - if (c==0 && a==b) + if (c == 0 && a == b) return signbit(a) ? a : b; return c; } @@ -189,7 +196,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) } if (sign && (shift < maxbits) && (byte & 0x40)) { /* Sign extend */ - result |= - ((uint64)1 << shift); + result |= (~((uint64)0)) << shift; } *p_offset = offset; return result; @@ -197,141 +204,155 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) #define skip_leb(p) while (*p++ & 0x80) -#define PUSH_I32(value) do { \ - *(int32*)frame_sp++ = (int32)(value); \ - } while (0) - -#define PUSH_F32(value) do { \ - *(float32*)frame_sp++ = (float32)(value); \ - } while (0) - -#define PUSH_I64(value) do { \ - PUT_I64_TO_ADDR(frame_sp, value); \ - frame_sp += 2; \ - } while (0) - -#define PUSH_F64(value) do { \ - PUT_F64_TO_ADDR(frame_sp, value); \ - frame_sp += 2; \ - } while (0) - -#define PUSH_CSP(_label_type, cell_num, _target_addr) do { \ - bh_assert(frame_csp < frame->csp_boundary); \ - /* frame_csp->label_type = _label_type; */ \ - frame_csp->cell_num = cell_num; \ - frame_csp->begin_addr = frame_ip; \ - frame_csp->target_addr = _target_addr; \ - frame_csp->frame_sp = frame_sp; \ - frame_csp++; \ - } while (0) - -#define POP_I32() (--frame_sp, *(int32*)frame_sp) - -#define POP_F32() (--frame_sp, *(float32*)frame_sp) +#define PUSH_I32(value) \ + do { \ + *(int32 *)frame_sp++ = (int32)(value); \ + } while (0) + +#define PUSH_F32(value) \ + do { \ + *(float32 *)frame_sp++ = (float32)(value); \ + } while (0) + +#define PUSH_I64(value) \ + do { \ + PUT_I64_TO_ADDR(frame_sp, value); \ + frame_sp += 2; \ + } while (0) + +#define PUSH_F64(value) \ + do { \ + PUT_F64_TO_ADDR(frame_sp, value); \ + frame_sp += 2; \ + } while (0) + +#define PUSH_CSP(_label_type, cell_num, _target_addr) \ + do { \ + bh_assert(frame_csp < frame->csp_boundary); \ + /* frame_csp->label_type = _label_type; */ \ + frame_csp->cell_num = cell_num; \ + frame_csp->begin_addr = frame_ip; \ + frame_csp->target_addr = _target_addr; \ + frame_csp->frame_sp = frame_sp; \ + frame_csp++; \ + } while (0) + +#define POP_I32() (--frame_sp, *(int32 *)frame_sp) + +#define POP_F32() (--frame_sp, *(float32 *)frame_sp) #define POP_I64() (frame_sp -= 2, GET_I64_FROM_ADDR(frame_sp)) #define POP_F64() (frame_sp -= 2, GET_F64_FROM_ADDR(frame_sp)) -#define POP_CSP_CHECK_OVERFLOW(n) do { \ - bh_assert(frame_csp - n >= frame->csp_bottom); \ - } while (0) - -#define POP_CSP() do { \ - POP_CSP_CHECK_OVERFLOW(1); \ - --frame_csp; \ - } while (0) - -#define POP_CSP_N(n) do { \ - uint32 *frame_sp_old = frame_sp; \ - uint32 cell_num = 0; \ - POP_CSP_CHECK_OVERFLOW(n + 1); \ - frame_csp -= n; \ - frame_ip = (frame_csp - 1)->target_addr; \ - /* copy arity values of block */ \ - frame_sp = (frame_csp - 1)->frame_sp; \ - cell_num = (frame_csp - 1)->cell_num; \ - word_copy(frame_sp, frame_sp_old - cell_num, cell_num); \ - frame_sp += cell_num; \ - } while (0) +#define POP_CSP_CHECK_OVERFLOW(n) \ + do { \ + bh_assert(frame_csp - n >= frame->csp_bottom); \ + } while (0) + +#define POP_CSP() \ + do { \ + POP_CSP_CHECK_OVERFLOW(1); \ + --frame_csp; \ + } while (0) + +#define POP_CSP_N(n) \ + do { \ + uint32 *frame_sp_old = frame_sp; \ + uint32 cell_num = 0; \ + POP_CSP_CHECK_OVERFLOW(n + 1); \ + frame_csp -= n; \ + frame_ip = (frame_csp - 1)->target_addr; \ + /* copy arity values of block */ \ + frame_sp = (frame_csp - 1)->frame_sp; \ + cell_num = (frame_csp - 1)->cell_num; \ + word_copy(frame_sp, frame_sp_old - cell_num, cell_num); \ + frame_sp += cell_num; \ + } while (0) /* Pop the given number of elements from the given frame's stack. */ -#define POP(N) do { \ - int n = (N); \ - frame_sp -= n; \ - } while (0) - -#define SYNC_ALL_TO_FRAME() do { \ - frame->sp = frame_sp; \ - frame->ip = frame_ip; \ - frame->csp = frame_csp; \ - } while (0) - -#define UPDATE_ALL_FROM_FRAME() do { \ - frame_sp = frame->sp; \ - frame_ip = frame->ip; \ - frame_csp = frame->csp; \ - } while (0) - -#define read_leb_int64(p, p_end, res) do { \ - uint8 _val = *p; \ - if (!(_val & 0x80)) { \ - res = (int64)_val; \ - if (_val & 0x40) \ - /* sign extend */ \ - res |= 0xFFFFFFFFFFFFFF80LL; \ - p++; \ - break; \ - } \ - uint32 _off = 0; \ - res = (int64)read_leb(p, &_off, 64, true); \ - p += _off; \ -} while (0) - -#define read_leb_uint32(p, p_end, res) do { \ - uint8 _val = *p; \ - if (!(_val & 0x80)) { \ - res = _val; \ - p++; \ - break; \ - } \ - uint32 _off = 0; \ - res = (uint32)read_leb(p, &_off, 32, false); \ - p += _off; \ -} while (0) - -#define read_leb_int32(p, p_end, res) do { \ - uint8 _val = *p; \ - if (!(_val & 0x80)) { \ - res = (int32)_val; \ - if (_val & 0x40) \ - /* sign extend */ \ - res |= 0xFFFFFF80; \ - p++; \ - break; \ - } \ - uint32 _off = 0; \ - res = (int32)read_leb(p, &_off, 32, true); \ - p += _off; \ -} while (0) +#define POP(N) \ + do { \ + int n = (N); \ + frame_sp -= n; \ + } while (0) + +#define SYNC_ALL_TO_FRAME() \ + do { \ + frame->sp = frame_sp; \ + frame->ip = frame_ip; \ + frame->csp = frame_csp; \ + } while (0) + +#define UPDATE_ALL_FROM_FRAME() \ + do { \ + frame_sp = frame->sp; \ + frame_ip = frame->ip; \ + frame_csp = frame->csp; \ + } while (0) + +#define read_leb_int64(p, p_end, res) \ + do { \ + uint8 _val = *p; \ + if (!(_val & 0x80)) { \ + res = (int64)_val; \ + if (_val & 0x40) \ + /* sign extend */ \ + res |= 0xFFFFFFFFFFFFFF80LL; \ + p++; \ + break; \ + } \ + uint32 _off = 0; \ + res = (int64)read_leb(p, &_off, 64, true); \ + p += _off; \ + } while (0) + +#define read_leb_uint32(p, p_end, res) \ + do { \ + uint8 _val = *p; \ + if (!(_val & 0x80)) { \ + res = _val; \ + p++; \ + break; \ + } \ + uint32 _off = 0; \ + res = (uint32)read_leb(p, &_off, 32, false); \ + p += _off; \ + } while (0) + +#define read_leb_int32(p, p_end, res) \ + do { \ + uint8 _val = *p; \ + if (!(_val & 0x80)) { \ + res = (int32)_val; \ + if (_val & 0x40) \ + /* sign extend */ \ + res |= 0xFFFFFF80; \ + p++; \ + break; \ + } \ + uint32 _off = 0; \ + res = (int32)read_leb(p, &_off, 32, true); \ + p += _off; \ + } while (0) #if WASM_ENABLE_LABELS_AS_VALUES == 0 -#define RECOVER_FRAME_IP_END() \ - frame_ip_end = wasm_get_func_code_end(cur_func) +#define RECOVER_FRAME_IP_END() frame_ip_end = wasm_get_func_code_end(cur_func) #else #define RECOVER_FRAME_IP_END() (void)0 #endif -#define RECOVER_CONTEXT(new_frame) do { \ - frame = (new_frame); \ - cur_func = frame->function; \ - prev_frame = frame->prev_frame; \ - frame_ip = frame->ip; \ - RECOVER_FRAME_IP_END(); \ - frame_lp = frame->lp; \ - frame_sp = frame->sp; \ - frame_csp = frame->csp; \ - } while (0) +#define RECOVER_CONTEXT(new_frame) \ + do { \ + frame = (new_frame); \ + cur_func = frame->function; \ + prev_frame = frame->prev_frame; \ + frame_ip = frame->ip; \ + RECOVER_FRAME_IP_END(); \ + frame_lp = frame->lp; \ + frame_sp = frame->sp; \ + frame_csp = frame->csp; \ + } while (0) #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define GET_OPCODE() opcode = *(frame_ip - 1); @@ -339,96 +360,105 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) #define GET_OPCODE() (void)0 #endif -#define DEF_OP_I_CONST(ctype, src_op_type) do { \ - ctype cval; \ - read_leb_##ctype(frame_ip, frame_ip_end, cval); \ - PUSH_##src_op_type(cval); \ - } while (0) - -#define DEF_OP_EQZ(src_op_type) do { \ - int32 val; \ - val = POP_##src_op_type() == 0; \ - PUSH_I32(val); \ - } while (0) - -#define DEF_OP_CMP(src_type, src_op_type, cond) do { \ - uint32 res; \ - src_type val1, val2; \ - val2 = (src_type)POP_##src_op_type(); \ - val1 = (src_type)POP_##src_op_type(); \ - res = val1 cond val2; \ - PUSH_I32(res); \ - } while (0) - -#define DEF_OP_BIT_COUNT(src_type, src_op_type, operation) do { \ - src_type val1, val2; \ - val1 = (src_type)POP_##src_op_type(); \ - val2 = (src_type)operation(val1); \ - PUSH_##src_op_type(val2); \ - } while (0) - -#define DEF_OP_NUMERIC(src_type1, src_type2, src_op_type, operation) do { \ - frame_sp -= sizeof(src_type2)/sizeof(uint32); \ - *(src_type1*)(frame_sp - sizeof(src_type1)/sizeof(uint32)) operation##= \ - *(src_type2*)(frame_sp); \ - } while (0) +#define DEF_OP_I_CONST(ctype, src_op_type) \ + do { \ + ctype cval; \ + read_leb_##ctype(frame_ip, frame_ip_end, cval); \ + PUSH_##src_op_type(cval); \ + } while (0) + +#define DEF_OP_EQZ(src_op_type) \ + do { \ + int32 val; \ + val = POP_##src_op_type() == 0; \ + PUSH_I32(val); \ + } while (0) + +#define DEF_OP_CMP(src_type, src_op_type, cond) \ + do { \ + uint32 res; \ + src_type val1, val2; \ + val2 = (src_type)POP_##src_op_type(); \ + val1 = (src_type)POP_##src_op_type(); \ + res = val1 cond val2; \ + PUSH_I32(res); \ + } while (0) + +#define DEF_OP_BIT_COUNT(src_type, src_op_type, operation) \ + do { \ + src_type val1, val2; \ + val1 = (src_type)POP_##src_op_type(); \ + val2 = (src_type)operation(val1); \ + PUSH_##src_op_type(val2); \ + } while (0) + +#define DEF_OP_NUMERIC(src_type1, src_type2, src_op_type, operation) \ + do { \ + frame_sp -= sizeof(src_type2) / sizeof(uint32); \ + *(src_type1 *)(frame_sp - sizeof(src_type1) / sizeof(uint32)) \ + operation## = *(src_type2 *)(frame_sp); \ + } while (0) #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 #define DEF_OP_NUMERIC_64 DEF_OP_NUMERIC #else -#define DEF_OP_NUMERIC_64(src_type1, src_type2, src_op_type, operation) do {\ - src_type1 val1; \ - src_type2 val2; \ - frame_sp -= 2; \ - val1 = (src_type1)GET_##src_op_type##_FROM_ADDR(frame_sp - 2); \ - val2 = (src_type2)GET_##src_op_type##_FROM_ADDR(frame_sp); \ - val1 operation##= val2; \ - PUT_##src_op_type##_TO_ADDR(frame_sp - 2, val1); \ - } while (0) +#define DEF_OP_NUMERIC_64(src_type1, src_type2, src_op_type, operation) \ + do { \ + src_type1 val1; \ + src_type2 val2; \ + frame_sp -= 2; \ + val1 = (src_type1)GET_##src_op_type##_FROM_ADDR(frame_sp - 2); \ + val2 = (src_type2)GET_##src_op_type##_FROM_ADDR(frame_sp); \ + val1 operation## = val2; \ + PUT_##src_op_type##_TO_ADDR(frame_sp - 2, val1); \ + } while (0) #endif -#define DEF_OP_NUMERIC2(src_type1, src_type2, src_op_type, operation) do { \ - frame_sp -= sizeof(src_type2)/sizeof(uint32); \ - *(src_type1*)(frame_sp - sizeof(src_type1)/sizeof(uint32)) operation##= \ - (*(src_type2*)(frame_sp) % 32); \ - } while (0) - -#define DEF_OP_NUMERIC2_64(src_type1, src_type2, src_op_type, operation) do { \ - src_type1 val1; \ - src_type2 val2; \ - frame_sp -= 2; \ - val1 = (src_type1)GET_##src_op_type##_FROM_ADDR(frame_sp - 2); \ - val2 = (src_type2)GET_##src_op_type##_FROM_ADDR(frame_sp); \ - val1 operation##= (val2 % 64); \ - PUT_##src_op_type##_TO_ADDR(frame_sp - 2, val1); \ - } while (0) - -#define DEF_OP_MATH(src_type, src_op_type, method) do { \ - src_type val; \ - val = POP_##src_op_type(); \ - PUSH_##src_op_type(method(val)); \ - } while (0) +#define DEF_OP_NUMERIC2(src_type1, src_type2, src_op_type, operation) \ + do { \ + frame_sp -= sizeof(src_type2) / sizeof(uint32); \ + *(src_type1 *)(frame_sp - sizeof(src_type1) / sizeof(uint32)) \ + operation## = (*(src_type2 *)(frame_sp) % 32); \ + } while (0) + +#define DEF_OP_NUMERIC2_64(src_type1, src_type2, src_op_type, operation) \ + do { \ + src_type1 val1; \ + src_type2 val2; \ + frame_sp -= 2; \ + val1 = (src_type1)GET_##src_op_type##_FROM_ADDR(frame_sp - 2); \ + val2 = (src_type2)GET_##src_op_type##_FROM_ADDR(frame_sp); \ + val1 operation## = (val2 % 64); \ + PUT_##src_op_type##_TO_ADDR(frame_sp - 2, val1); \ + } while (0) + +#define DEF_OP_MATH(src_type, src_op_type, method) \ + do { \ + src_type val; \ + val = POP_##src_op_type(); \ + PUSH_##src_op_type(method(val)); \ + } while (0) #define TRUNC_FUNCTION(func_name, src_type, dst_type, signed_type) \ -static dst_type \ -func_name(src_type src_value, src_type src_min, src_type src_max, \ - dst_type dst_min, dst_type dst_max, bool is_sign) \ -{ \ - dst_type dst_value = 0; \ - if (!isnan(src_value)) { \ - if (src_value <= src_min) \ - dst_value = dst_min; \ - else if (src_value >= src_max) \ - dst_value = dst_max; \ - else { \ - if (is_sign) \ - dst_value = (dst_type)(signed_type)src_value; \ - else \ - dst_value = (dst_type)src_value; \ - } \ - } \ - return dst_value; \ -} + static dst_type func_name(src_type src_value, src_type src_min, \ + src_type src_max, dst_type dst_min, \ + dst_type dst_max, bool is_sign) \ + { \ + dst_type dst_value = 0; \ + if (!isnan(src_value)) { \ + if (src_value <= src_min) \ + dst_value = dst_min; \ + else if (src_value >= src_max) \ + dst_value = dst_max; \ + else { \ + if (is_sign) \ + dst_value = (dst_type)(signed_type)src_value; \ + else \ + dst_value = (dst_type)src_value; \ + } \ + } \ + return dst_value; \ + } TRUNC_FUNCTION(trunc_f32_to_i32, float32, uint32, int32) TRUNC_FUNCTION(trunc_f32_to_i64, float32, uint64, int64) @@ -436,10 +466,8 @@ TRUNC_FUNCTION(trunc_f64_to_i32, float64, uint32, int32) TRUNC_FUNCTION(trunc_f64_to_i64, float64, uint64, int64) static bool -trunc_f32_to_int(WASMModuleInstance *module, - uint32 *frame_sp, - float32 src_min, float32 src_max, - bool saturating, bool is_i32, bool is_sign) +trunc_f32_to_int(WASMModuleInstance *module, uint32 *frame_sp, float32 src_min, + float32 src_max, bool saturating, bool is_i32, bool is_sign) { float32 src_value = POP_F32(); uint64 dst_value_i64; @@ -459,25 +487,23 @@ trunc_f32_to_int(WASMModuleInstance *module, if (is_i32) { uint32 dst_min = is_sign ? INT32_MIN : 0; uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX; - dst_value_i32 = trunc_f32_to_i32(src_value, src_min, src_max, - dst_min, dst_max, is_sign); + dst_value_i32 = trunc_f32_to_i32(src_value, src_min, src_max, dst_min, + dst_max, is_sign); PUSH_I32(dst_value_i32); } else { uint64 dst_min = is_sign ? INT64_MIN : 0; uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX; - dst_value_i64 = trunc_f32_to_i64(src_value, src_min, src_max, - dst_min, dst_max, is_sign); + dst_value_i64 = trunc_f32_to_i64(src_value, src_min, src_max, dst_min, + dst_max, is_sign); PUSH_I64(dst_value_i64); } return false; } static bool -trunc_f64_to_int(WASMModuleInstance *module, - uint32 *frame_sp, - float64 src_min, float64 src_max, - bool saturating, bool is_i32, bool is_sign) +trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min, + float64 src_max, bool saturating, bool is_i32, bool is_sign) { float64 src_value = POP_F64(); uint64 dst_value_i64; @@ -497,150 +523,155 @@ trunc_f64_to_int(WASMModuleInstance *module, if (is_i32) { uint32 dst_min = is_sign ? INT32_MIN : 0; uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX; - dst_value_i32 = trunc_f64_to_i32(src_value, src_min, src_max, - dst_min, dst_max, is_sign); + dst_value_i32 = trunc_f64_to_i32(src_value, src_min, src_max, dst_min, + dst_max, is_sign); PUSH_I32(dst_value_i32); } else { uint64 dst_min = is_sign ? INT64_MIN : 0; uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX; - dst_value_i64 = trunc_f64_to_i64(src_value, src_min, src_max, - dst_min, dst_max, is_sign); + dst_value_i64 = trunc_f64_to_i64(src_value, src_min, src_max, dst_min, + dst_max, is_sign); PUSH_I64(dst_value_i64); } return false; } -#define DEF_OP_TRUNC_F32(min, max, is_i32, is_sign) do { \ - if (trunc_f32_to_int(module, frame_sp, min, max, \ - false, is_i32, is_sign)) \ - goto got_exception; \ - } while (0) - -#define DEF_OP_TRUNC_F64(min, max, is_i32, is_sign) do { \ - if (trunc_f64_to_int(module, frame_sp, min, max, \ - false, is_i32, is_sign)) \ - goto got_exception; \ - } while (0) - -#define DEF_OP_TRUNC_SAT_F32(min, max, is_i32, is_sign) do { \ - (void)trunc_f32_to_int(module, frame_sp, min, max, \ - true, is_i32, is_sign); \ - } while (0) - -#define DEF_OP_TRUNC_SAT_F64(min, max, is_i32, is_sign) do { \ - (void)trunc_f64_to_int(module, frame_sp, min, max, \ - true, is_i32, is_sign); \ - } while (0) - -#define DEF_OP_CONVERT(dst_type, dst_op_type, \ - src_type, src_op_type) do { \ - dst_type value = (dst_type)(src_type)POP_##src_op_type(); \ - PUSH_##dst_op_type(value); \ - } while (0) - -#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() do { \ - uint32 param_count = cur_func->param_count; \ - read_leb_uint32(frame_ip, frame_ip_end, local_idx); \ - bh_assert(local_idx < param_count + cur_func->local_count); \ - local_offset = cur_func->local_offsets[local_idx]; \ - if (local_idx < param_count) \ - local_type = cur_func->param_types[local_idx]; \ - else \ - local_type = cur_func->local_types[local_idx - param_count]; \ - } while (0) - -#define DEF_ATOMIC_RMW_OPCODE(OP_NAME, op) \ - case WASM_OP_ATOMIC_RMW_I32_##OP_NAME: \ - case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U: \ - case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U: \ - { \ - uint32 readv, sval; \ - \ - sval = POP_I32(); \ - addr = POP_I32(); \ - \ - if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U) { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint32)(*(uint8*)maddr); \ - *(uint8*)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint32)LOAD_U16(maddr); \ - STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - else { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = LOAD_I32(maddr); \ - STORE_U32(maddr, readv op sval); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - PUSH_I32(readv); \ - break; \ - } \ - case WASM_OP_ATOMIC_RMW_I64_##OP_NAME: \ - case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U: \ - case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U: \ - case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U: \ - { \ - uint64 readv, sval; \ - \ - sval = (uint64)POP_I64(); \ - addr = POP_I32(); \ - \ - if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U) { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint64)(*(uint8*)maddr); \ - *(uint8*)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint64)LOAD_U16(maddr); \ - STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint64)LOAD_U32(maddr); \ - STORE_U32(maddr, (uint32)(readv op sval)); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - else { \ - uint64 op_result; \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint64)LOAD_I64(maddr); \ - op_result = readv op sval; \ - STORE_I64(maddr, op_result); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - PUSH_I64(readv); \ - break; \ - } +#define DEF_OP_TRUNC_F32(min, max, is_i32, is_sign) \ + do { \ + if (trunc_f32_to_int(module, frame_sp, min, max, false, is_i32, \ + is_sign)) \ + goto got_exception; \ + } while (0) + +#define DEF_OP_TRUNC_F64(min, max, is_i32, is_sign) \ + do { \ + if (trunc_f64_to_int(module, frame_sp, min, max, false, is_i32, \ + is_sign)) \ + goto got_exception; \ + } while (0) + +#define DEF_OP_TRUNC_SAT_F32(min, max, is_i32, is_sign) \ + do { \ + (void)trunc_f32_to_int(module, frame_sp, min, max, true, is_i32, \ + is_sign); \ + } while (0) + +#define DEF_OP_TRUNC_SAT_F64(min, max, is_i32, is_sign) \ + do { \ + (void)trunc_f64_to_int(module, frame_sp, min, max, true, is_i32, \ + is_sign); \ + } while (0) + +#define DEF_OP_CONVERT(dst_type, dst_op_type, src_type, src_op_type) \ + do { \ + dst_type value = (dst_type)(src_type)POP_##src_op_type(); \ + PUSH_##dst_op_type(value); \ + } while (0) + +#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() \ + do { \ + uint32 param_count = cur_func->param_count; \ + read_leb_uint32(frame_ip, frame_ip_end, local_idx); \ + bh_assert(local_idx < param_count + cur_func->local_count); \ + local_offset = cur_func->local_offsets[local_idx]; \ + if (local_idx < param_count) \ + local_type = cur_func->param_types[local_idx]; \ + else \ + local_type = cur_func->local_types[local_idx - param_count]; \ + } while (0) + +#define DEF_ATOMIC_RMW_OPCODE(OP_NAME, op) \ + case WASM_OP_ATOMIC_RMW_I32_##OP_NAME: \ + case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U: \ + case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U: \ + { \ + uint32 readv, sval; \ + \ + sval = POP_I32(); \ + addr = POP_I32(); \ + \ + if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U) { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint32)(*(uint8 *)maddr); \ + *(uint8 *)maddr = (uint8)(readv op sval); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint32)LOAD_U16(maddr); \ + STORE_U16(maddr, (uint16)(readv op sval)); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + else { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = LOAD_I32(maddr); \ + STORE_U32(maddr, readv op sval); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + PUSH_I32(readv); \ + break; \ + } \ + case WASM_OP_ATOMIC_RMW_I64_##OP_NAME: \ + case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U: \ + case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U: \ + case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U: \ + { \ + uint64 readv, sval; \ + \ + sval = (uint64)POP_I64(); \ + addr = POP_I32(); \ + \ + if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U) { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint64)(*(uint8 *)maddr); \ + *(uint8 *)maddr = (uint8)(readv op sval); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint64)LOAD_U16(maddr); \ + STORE_U16(maddr, (uint16)(readv op sval)); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint64)LOAD_U32(maddr); \ + STORE_U32(maddr, (uint32)(readv op sval)); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + else { \ + uint64 op_result; \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint64)LOAD_I64(maddr); \ + op_result = readv op sval; \ + STORE_I64(maddr, op_result); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + PUSH_I64(readv); \ + break; \ + } static inline int32 sign_ext_8_32(int8 val) @@ -689,7 +720,7 @@ word_copy(uint32 *dest, uint32 *src, unsigned num) *dest++ = *src++; } -static inline WASMInterpFrame* +static inline WASMInterpFrame * ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame) { WASMInterpFrame *frame = wasm_exec_env_alloc_wasm_frame(exec_env, size); @@ -701,7 +732,7 @@ ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame) #endif } else { - wasm_set_exception((WASMModuleInstance*)exec_env->module_inst, + wasm_set_exception((WASMModuleInstance *)exec_env->module_inst, "wasm operand stack overflow"); } @@ -713,8 +744,8 @@ FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame) { #if WASM_ENABLE_PERF_PROFILING != 0 if (frame->function) { - frame->function->total_exec_time += os_time_get_boot_microsecond() - - frame->time_started; + frame->function->total_exec_time += + os_time_get_boot_microsecond() - frame->time_started; frame->function->total_exec_cnt++; } #endif @@ -755,26 +786,26 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, if (func_import->call_conv_wasm_c_api) { ret = wasm_runtime_invoke_c_api_native( - (WASMModuleInstanceCommon *)module_inst, - func_import->func_ptr_linked, func_import->func_type, - cur_func->param_cell_num, frame->lp, - func_import->wasm_c_api_with_env, func_import->attachment); + (WASMModuleInstanceCommon *)module_inst, + func_import->func_ptr_linked, func_import->func_type, + cur_func->param_cell_num, frame->lp, + func_import->wasm_c_api_with_env, func_import->attachment); if (ret) { argv_ret[0] = frame->lp[0]; argv_ret[1] = frame->lp[1]; } } else if (!func_import->call_conv_raw) { - ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked, - func_import->func_type, func_import->signature, - func_import->attachment, - frame->lp, cur_func->param_cell_num, argv_ret); + ret = wasm_runtime_invoke_native( + exec_env, func_import->func_ptr_linked, func_import->func_type, + func_import->signature, func_import->attachment, frame->lp, + cur_func->param_cell_num, argv_ret); } else { - ret = wasm_runtime_invoke_native_raw(exec_env, func_import->func_ptr_linked, - func_import->func_type, func_import->signature, - func_import->attachment, - frame->lp, cur_func->param_cell_num, argv_ret); + ret = wasm_runtime_invoke_native_raw( + exec_env, func_import->func_ptr_linked, func_import->func_type, + func_import->signature, func_import->attachment, frame->lp, + cur_func->param_cell_num, argv_ret); } if (!ret) @@ -830,8 +861,8 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, exec_env->module_inst = (WASMModuleInstanceCommon *)sub_module_inst; /* call function of sub-module*/ - wasm_interp_call_func_bytecode(sub_module_inst, exec_env, - sub_func_inst, prev_frame); + wasm_interp_call_func_bytecode(sub_module_inst, exec_env, sub_func_inst, + prev_frame); /* restore ip and module_inst */ prev_frame->ip = ip; @@ -848,29 +879,86 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, #endif #if WASM_ENABLE_THREAD_MGR != 0 -#define CHECK_SUSPEND_FLAGS() do { \ - if (exec_env->suspend_flags.flags != 0) { \ - if (exec_env->suspend_flags.flags & 0x01) { \ - /* terminate current thread */ \ - return; \ - } \ - /* TODO: support suspend and breakpoint */ \ - } \ - } while (0) -#endif +#if WASM_ENABLE_DEBUG_INTERP != 0 +#define CHECK_SUSPEND_FLAGS() \ + do { \ + if (IS_WAMR_TERM_SIG(exec_env->current_status->signal_flag)) { \ + return; \ + } \ + if (IS_WAMR_STOP_SIG(exec_env->current_status->signal_flag)) { \ + SYNC_ALL_TO_FRAME(); \ + wasm_cluster_thread_stopped(exec_env); \ + wasm_cluster_thread_waiting_run(exec_env); \ + } \ + } while (0) +#else +#define CHECK_SUSPEND_FLAGS() \ + do { \ + if (exec_env->suspend_flags.flags != 0) { \ + if (exec_env->suspend_flags.flags & 0x01) { \ + /* terminate current thread */ \ + return; \ + } \ + while (exec_env->suspend_flags.flags & 0x02) { \ + /* suspend current thread */ \ + os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \ + } \ + } \ + } while (0) +#endif /* WASM_ENABLE_DEBUG_INTERP */ +#endif /* WASM_ENABLE_THREAD_MGR */ #if WASM_ENABLE_LABELS_AS_VALUES != 0 -#define HANDLE_OP(opcode) HANDLE_##opcode +#define HANDLE_OP(opcode) HANDLE_##opcode: #define FETCH_OPCODE_AND_DISPATCH() goto *handle_table[*frame_ip++] -#define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH() -#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ +#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 +#define HANDLE_OP_END() \ + do { \ + while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \ + && exec_env->current_status->step_count++ == 1) { \ + exec_env->current_status->step_count = 0; \ + SYNC_ALL_TO_FRAME(); \ + wasm_cluster_thread_stopped(exec_env); \ + wasm_cluster_thread_waiting_run(exec_env); \ + } \ + goto *handle_table[*frame_ip++]; \ + } while (0) +#else +#define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH() +#endif -#define HANDLE_OP(opcode) case opcode +#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ +#define HANDLE_OP(opcode) case opcode: +#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 +#define HANDLE_OP_END() \ + if (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \ + && exec_env->current_status->step_count++ == 2) { \ + exec_env->current_status->step_count = 0; \ + SYNC_ALL_TO_FRAME(); \ + wasm_cluster_thread_stopped(exec_env); \ + wasm_cluster_thread_waiting_run(exec_env); \ + } \ + continue +#else #define HANDLE_OP_END() continue +#endif -#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ +#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ + +static inline uint8 * +get_global_addr(uint8 *global_data, WASMGlobalInstance *global) +{ +#if WASM_ENABLE_MULTI_MODULE == 0 + return global_data + global->data_offset; +#else + return global->import_global_inst + ? global->import_module_inst->global_data + + global->import_global_inst->data_offset + : global_data + global->data_offset; +#endif +} static void wasm_interp_call_func_bytecode(WASMModuleInstance *module, @@ -878,2540 +966,2764 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { - WASMMemoryInstance *memory = module->default_memory; - uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; - uint8 *global_data = module->global_data; - uint32 linear_mem_size = memory ? num_bytes_per_page * memory->cur_page_count : 0; - WASMType **wasm_types = module->module->types; - WASMGlobalInstance *globals = module->globals, *global; - uint8 opcode_IMPDEP = WASM_OP_IMPDEP; - WASMInterpFrame *frame = NULL; - /* Points to this special opcode so as to jump to the call_method_from_entry. */ - register uint8 *frame_ip = &opcode_IMPDEP; /* cache of frame->ip */ - register uint32 *frame_lp = NULL; /* cache of frame->lp */ - register uint32 *frame_sp = NULL; /* cache of frame->sp */ - WASMBranchBlock *frame_csp = NULL; - BlockAddr *cache_items; - uint8 *frame_ip_end = frame_ip + 1; - uint8 opcode; - uint32 i, depth, cond, count, fidx, tidx, lidx, frame_size = 0; - uint64 all_cell_num = 0; - int32 val; - uint8 *else_addr, *end_addr, *maddr = NULL; - uint32 local_idx, local_offset, global_idx; - uint8 local_type, *global_addr; - uint32 cache_index, type_index, cell_num; - uint8 value_type; + WASMMemoryInstance *memory = module->default_memory; + uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; + uint8 *global_data = module->global_data; + uint32 linear_mem_size = + memory ? num_bytes_per_page * memory->cur_page_count : 0; + WASMType **wasm_types = module->module->types; + WASMGlobalInstance *globals = module->globals, *global; + uint8 opcode_IMPDEP = WASM_OP_IMPDEP; + WASMInterpFrame *frame = NULL; + /* Points to this special opcode so as to jump to the + * call_method_from_entry. */ + register uint8 *frame_ip = &opcode_IMPDEP; /* cache of frame->ip */ + register uint32 *frame_lp = NULL; /* cache of frame->lp */ + register uint32 *frame_sp = NULL; /* cache of frame->sp */ + WASMBranchBlock *frame_csp = NULL; + BlockAddr *cache_items; + uint8 *frame_ip_end = frame_ip + 1; + uint8 opcode; + uint32 i, depth, cond, count, fidx, tidx, lidx, frame_size = 0; + uint64 all_cell_num = 0; + int32 val; + uint8 *else_addr, *end_addr, *maddr = NULL; + uint32 local_idx, local_offset, global_idx; + uint8 local_type, *global_addr; + uint32 cache_index, type_index, cell_num; + uint8 value_type; #if WASM_ENABLE_LABELS_AS_VALUES != 0 - #define HANDLE_OPCODE(op) &&HANDLE_##op - DEFINE_GOTO_TABLE (const void *, handle_table); - #undef HANDLE_OPCODE +#define HANDLE_OPCODE(op) &&HANDLE_##op + DEFINE_GOTO_TABLE(const void *, handle_table); +#undef HANDLE_OPCODE #endif #if WASM_ENABLE_LABELS_AS_VALUES == 0 - while (frame_ip < frame_ip_end) { - opcode = *frame_ip++; - switch (opcode) { + while (frame_ip < frame_ip_end) { + opcode = *frame_ip++; + switch (opcode) { #else - FETCH_OPCODE_AND_DISPATCH (); + FETCH_OPCODE_AND_DISPATCH(); #endif - /* control instructions */ - HANDLE_OP (WASM_OP_UNREACHABLE): - wasm_set_exception(module, "unreachable"); - goto got_exception; + /* control instructions */ + HANDLE_OP(WASM_OP_UNREACHABLE) + { + wasm_set_exception(module, "unreachable"); + goto got_exception; + } - HANDLE_OP (WASM_OP_NOP): - HANDLE_OP_END (); - - HANDLE_OP (EXT_OP_BLOCK): - read_leb_uint32(frame_ip, frame_ip_end, type_index); - cell_num = wasm_types[type_index]->ret_cell_num; - goto handle_op_block; - - HANDLE_OP (WASM_OP_BLOCK): - value_type = *frame_ip++; - cell_num = wasm_value_type_cell_num(value_type); -handle_op_block: - 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) { - end_addr = cache_items[0].end_addr; - } - else if (cache_items[1].start_addr == frame_ip) { - end_addr = cache_items[1].end_addr; - } - else { - end_addr = NULL; - } - PUSH_CSP(LABEL_TYPE_BLOCK, cell_num, end_addr); - HANDLE_OP_END (); - - HANDLE_OP (EXT_OP_LOOP): - read_leb_uint32(frame_ip, frame_ip_end, type_index); - cell_num = wasm_types[type_index]->param_cell_num; - goto handle_op_loop; - - HANDLE_OP (WASM_OP_LOOP): - value_type = *frame_ip++; - cell_num = wasm_value_type_cell_num(value_type); -handle_op_loop: - PUSH_CSP(LABEL_TYPE_LOOP, cell_num, frame_ip); - HANDLE_OP_END (); - - HANDLE_OP (EXT_OP_IF): - read_leb_uint32(frame_ip, frame_ip_end, type_index); - cell_num = wasm_types[type_index]->ret_cell_num; - goto handle_op_if; - - HANDLE_OP (WASM_OP_IF): - value_type = *frame_ip++; - cell_num = wasm_value_type_cell_num(value_type); -handle_op_if: - 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) { - else_addr = cache_items[0].else_addr; - end_addr = cache_items[0].end_addr; - } - else if (cache_items[1].start_addr == frame_ip) { - else_addr = cache_items[1].else_addr; - end_addr = cache_items[1].end_addr; - } - else if (!wasm_loader_find_block_addr((BlockAddr*)exec_env->block_addr_cache, - frame_ip, (uint8*)-1, - LABEL_TYPE_IF, - &else_addr, &end_addr)) { - wasm_set_exception(module, "find block address failed"); - goto got_exception; - } + HANDLE_OP(WASM_OP_NOP) { HANDLE_OP_END(); } - cond = (uint32)POP_I32(); + HANDLE_OP(EXT_OP_BLOCK) + { + read_leb_uint32(frame_ip, frame_ip_end, type_index); + cell_num = wasm_types[type_index]->ret_cell_num; + goto handle_op_block; + } - if (cond) { /* if branch is met */ - PUSH_CSP(LABEL_TYPE_IF, cell_num, end_addr); - } - else { /* if branch is not met */ - /* if there is no else branch, go to the end addr */ - if (else_addr == NULL) { - frame_ip = end_addr + 1; - } - /* if there is an else branch, go to the else addr */ - else { - PUSH_CSP(LABEL_TYPE_IF, cell_num, end_addr); - frame_ip = else_addr + 1; - } - } - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_BLOCK) + { + value_type = *frame_ip++; + cell_num = wasm_value_type_cell_num(value_type); + handle_op_block: + 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) { + end_addr = cache_items[0].end_addr; + } + else if (cache_items[1].start_addr == frame_ip) { + end_addr = cache_items[1].end_addr; + } +#if WASM_ENABLE_DEBUG_INTERP != 0 + else if (!wasm_loader_find_block_addr( + exec_env, (BlockAddr *)exec_env->block_addr_cache, + frame_ip, (uint8 *)-1, LABEL_TYPE_BLOCK, + &else_addr, &end_addr)) { + wasm_set_exception(module, "find block address failed"); + goto got_exception; + } +#endif + else { + end_addr = NULL; + } + PUSH_CSP(LABEL_TYPE_BLOCK, cell_num, end_addr); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_ELSE): - /* comes from the if branch in WASM_OP_IF */ - frame_ip = (frame_csp - 1)->target_addr; - HANDLE_OP_END (); + HANDLE_OP(EXT_OP_LOOP) + { + read_leb_uint32(frame_ip, frame_ip_end, type_index); + cell_num = wasm_types[type_index]->param_cell_num; + goto handle_op_loop; + } - HANDLE_OP (WASM_OP_END): - if (frame_csp > frame->csp_bottom + 1) { - POP_CSP(); - } - else { /* end of function, treat as WASM_OP_RETURN */ - frame_sp -= cur_func->ret_cell_num; - for (i = 0; i < cur_func->ret_cell_num; i++) { - *prev_frame->sp++ = frame_sp[i]; - } - goto return_func; - } - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_LOOP) + { + value_type = *frame_ip++; + cell_num = wasm_value_type_cell_num(value_type); + handle_op_loop: + PUSH_CSP(LABEL_TYPE_LOOP, cell_num, frame_ip); + HANDLE_OP_END(); + } + + HANDLE_OP(EXT_OP_IF) + { + read_leb_uint32(frame_ip, frame_ip_end, type_index); + cell_num = wasm_types[type_index]->ret_cell_num; + goto handle_op_if; + } + + HANDLE_OP(WASM_OP_IF) + { + value_type = *frame_ip++; + cell_num = wasm_value_type_cell_num(value_type); + handle_op_if: + 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) { + else_addr = cache_items[0].else_addr; + end_addr = cache_items[0].end_addr; + } + else if (cache_items[1].start_addr == frame_ip) { + else_addr = cache_items[1].else_addr; + end_addr = cache_items[1].end_addr; + } + else if (!wasm_loader_find_block_addr( + exec_env, (BlockAddr *)exec_env->block_addr_cache, + frame_ip, (uint8 *)-1, LABEL_TYPE_IF, &else_addr, + &end_addr)) { + wasm_set_exception(module, "find block address failed"); + goto got_exception; + } + + cond = (uint32)POP_I32(); + + if (cond) { /* if branch is met */ + PUSH_CSP(LABEL_TYPE_IF, cell_num, end_addr); + } + else { /* if branch is not met */ + /* if there is no else branch, go to the end addr */ + if (else_addr == NULL) { + frame_ip = end_addr + 1; + } + /* if there is an else branch, go to the else addr */ + else { + PUSH_CSP(LABEL_TYPE_IF, cell_num, end_addr); + frame_ip = else_addr + 1; + } + } + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_BR): + HANDLE_OP(WASM_OP_ELSE) + { + /* comes from the if branch in WASM_OP_IF */ + frame_ip = (frame_csp - 1)->target_addr; + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_END) + { + if (frame_csp > frame->csp_bottom + 1) { + POP_CSP(); + } + else { /* end of function, treat as WASM_OP_RETURN */ + frame_sp -= cur_func->ret_cell_num; + for (i = 0; i < cur_func->ret_cell_num; i++) { + *prev_frame->sp++ = frame_sp[i]; + } + goto return_func; + } + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_BR) + { #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - read_leb_uint32(frame_ip, frame_ip_end, depth); -label_pop_csp_n: - POP_CSP_N(depth); - if (!frame_ip) { /* must be label pushed by WASM_OP_BLOCK */ - if (!wasm_loader_find_block_addr((BlockAddr*)exec_env->block_addr_cache, - (frame_csp - 1)->begin_addr, (uint8*)-1, - LABEL_TYPE_BLOCK, - &else_addr, &end_addr)) { - wasm_set_exception(module, "find block address failed"); - goto got_exception; - } - frame_ip = end_addr; - } - HANDLE_OP_END (); + read_leb_uint32(frame_ip, frame_ip_end, depth); + label_pop_csp_n: + POP_CSP_N(depth); + if (!frame_ip) { /* must be label pushed by WASM_OP_BLOCK */ + if (!wasm_loader_find_block_addr( + exec_env, (BlockAddr *)exec_env->block_addr_cache, + (frame_csp - 1)->begin_addr, (uint8 *)-1, + LABEL_TYPE_BLOCK, &else_addr, &end_addr)) { + wasm_set_exception(module, "find block address failed"); + goto got_exception; + } + frame_ip = end_addr; + } + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_BR_IF): + HANDLE_OP(WASM_OP_BR_IF) + { #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - read_leb_uint32(frame_ip, frame_ip_end, depth); - cond = (uint32)POP_I32(); - if (cond) - goto label_pop_csp_n; - HANDLE_OP_END (); + read_leb_uint32(frame_ip, frame_ip_end, depth); + cond = (uint32)POP_I32(); + if (cond) + goto label_pop_csp_n; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_BR_TABLE): + HANDLE_OP(WASM_OP_BR_TABLE) + { #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - read_leb_uint32(frame_ip, frame_ip_end, count); - lidx = POP_I32(); - if (lidx > count) - lidx = count; - for (i = 0; i < lidx; i++) - skip_leb(frame_ip); - read_leb_uint32(frame_ip, frame_ip_end, depth); - goto label_pop_csp_n; - - HANDLE_OP (WASM_OP_RETURN): - frame_sp -= cur_func->ret_cell_num; - for (i = 0; i < cur_func->ret_cell_num; i++) { - *prev_frame->sp++ = frame_sp[i]; - } - goto return_func; + read_leb_uint32(frame_ip, frame_ip_end, count); + lidx = POP_I32(); + if (lidx > count) + lidx = count; + for (i = 0; i < lidx; i++) + skip_leb(frame_ip); + read_leb_uint32(frame_ip, frame_ip_end, depth); + goto label_pop_csp_n; + } + + HANDLE_OP(WASM_OP_RETURN) + { + frame_sp -= cur_func->ret_cell_num; + for (i = 0; i < cur_func->ret_cell_num; i++) { + *prev_frame->sp++ = frame_sp[i]; + } + goto return_func; + } - HANDLE_OP (WASM_OP_CALL): + HANDLE_OP(WASM_OP_CALL) + { #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - read_leb_uint32(frame_ip, frame_ip_end, fidx); + read_leb_uint32(frame_ip, frame_ip_end, fidx); #if WASM_ENABLE_MULTI_MODULE != 0 - if (fidx >= module->function_count) { - wasm_set_exception(module, "unknown function"); - goto got_exception; - } + if (fidx >= module->function_count) { + wasm_set_exception(module, "unknown function"); + goto got_exception; + } #endif - cur_func = module->functions + fidx; - goto call_func_from_interp; + cur_func = module->functions + fidx; + goto call_func_from_interp; + } #if WASM_ENABLE_TAIL_CALL != 0 - HANDLE_OP (WASM_OP_RETURN_CALL): + HANDLE_OP(WASM_OP_RETURN_CALL) + { #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - read_leb_uint32(frame_ip, frame_ip_end, fidx); + read_leb_uint32(frame_ip, frame_ip_end, fidx); #if WASM_ENABLE_MULTI_MODULE != 0 - if (fidx >= module->function_count) { - wasm_set_exception(module, "unknown function"); - goto got_exception; - } + if (fidx >= module->function_count) { + wasm_set_exception(module, "unknown function"); + goto got_exception; + } #endif - cur_func = module->functions + fidx; + cur_func = module->functions + fidx; - goto call_func_from_return_call; + goto call_func_from_return_call; + } #endif /* WASM_ENABLE_TAIL_CALL */ - HANDLE_OP (WASM_OP_CALL_INDIRECT): + HANDLE_OP(WASM_OP_CALL_INDIRECT) #if WASM_ENABLE_TAIL_CALL != 0 - HANDLE_OP (WASM_OP_RETURN_CALL_INDIRECT): + HANDLE_OP(WASM_OP_RETURN_CALL_INDIRECT) #endif - { - WASMType *cur_type, *cur_func_type; - WASMTableInstance *tbl_inst; - uint32 tbl_idx; + { + WASMType *cur_type, *cur_func_type; + WASMTableInstance *tbl_inst; + uint32 tbl_idx; #if WASM_ENABLE_TAIL_CALL != 0 - opcode = *(frame_ip - 1); + opcode = *(frame_ip - 1); #endif #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - /** - * type check. compiler will make sure all like - * (call_indirect (type $x) (i32.const 1)) - * the function type has to be defined in the module also - * no matter it is used or not - */ - read_leb_uint32(frame_ip, frame_ip_end, tidx); - bh_assert(tidx < module->module->type_count); - cur_type = wasm_types[tidx]; - - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - bh_assert(tbl_idx < module->table_count); - - tbl_inst = wasm_get_table_inst(module, tbl_idx); - - val = POP_I32(); - if (val < 0 || val >= (int32)tbl_inst->cur_size) { - wasm_set_exception(module, "undefined element"); - goto got_exception; - } - - fidx = ((uint32*)tbl_inst->base_addr)[val]; - if (fidx == (uint32)-1) { - wasm_set_exception(module, "uninitialized element"); - goto got_exception; - } - - /* - * we might be using a table injected by host or - * another module. In that case, we don't validate - * the elem value while loading - */ - if (fidx >= module->function_count) { - wasm_set_exception(module, "unknown function"); - goto got_exception; - } - - /* always call module own functions */ - cur_func = module->functions + fidx; - - if (cur_func->is_import_func) - cur_func_type = cur_func->u.func_import->func_type; - else - cur_func_type = cur_func->u.func->func_type; - if (!wasm_type_equal(cur_type, cur_func_type)) { - wasm_set_exception(module, "indirect call type mismatch"); - goto got_exception; - } + /** + * type check. compiler will make sure all like + * (call_indirect (type $x) (i32.const 1)) + * the function type has to be defined in the module also + * no matter it is used or not + */ + read_leb_uint32(frame_ip, frame_ip_end, tidx); + bh_assert(tidx < module->module->type_count); + cur_type = wasm_types[tidx]; + + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + bh_assert(tbl_idx < module->table_count); + + tbl_inst = wasm_get_table_inst(module, tbl_idx); + + val = POP_I32(); + if (val < 0 || val >= (int32)tbl_inst->cur_size) { + wasm_set_exception(module, "undefined element"); + goto got_exception; + } + + fidx = ((uint32 *)tbl_inst->base_addr)[val]; + if (fidx == (uint32)-1) { + wasm_set_exception(module, "uninitialized element"); + goto got_exception; + } + + /* + * we might be using a table injected by host or + * another module. In that case, we don't validate + * the elem value while loading + */ + if (fidx >= module->function_count) { + wasm_set_exception(module, "unknown function"); + goto got_exception; + } + + /* always call module own functions */ + cur_func = module->functions + fidx; + + if (cur_func->is_import_func) + cur_func_type = cur_func->u.func_import->func_type; + else + cur_func_type = cur_func->u.func->func_type; + if (!wasm_type_equal(cur_type, cur_func_type)) { + wasm_set_exception(module, "indirect call type mismatch"); + goto got_exception; + } #if WASM_ENABLE_TAIL_CALL != 0 - if (opcode == WASM_OP_RETURN_CALL_INDIRECT) - goto call_func_from_return_call; + if (opcode == WASM_OP_RETURN_CALL_INDIRECT) + goto call_func_from_return_call; #endif - goto call_func_from_interp; - } + goto call_func_from_interp; + } - /* parametric instructions */ - HANDLE_OP (WASM_OP_DROP): - { - frame_sp--; - HANDLE_OP_END (); - } + /* parametric instructions */ + HANDLE_OP(WASM_OP_DROP) + { + frame_sp--; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_DROP_64): - { - frame_sp -= 2; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_DROP_64) + { + frame_sp -= 2; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_SELECT): - { - cond = (uint32)POP_I32(); - frame_sp--; - if (!cond) - *(frame_sp - 1) = *frame_sp; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_SELECT) + { + cond = (uint32)POP_I32(); + frame_sp--; + if (!cond) + *(frame_sp - 1) = *frame_sp; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_SELECT_64): - { - cond = (uint32)POP_I32(); - frame_sp -= 2; - if (!cond) { - *(frame_sp - 2) = *frame_sp; - *(frame_sp - 1) = *(frame_sp + 1); - } - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_SELECT_64) + { + cond = (uint32)POP_I32(); + frame_sp -= 2; + if (!cond) { + *(frame_sp - 2) = *frame_sp; + *(frame_sp - 1) = *(frame_sp + 1); + } + HANDLE_OP_END(); + } #if WASM_ENABLE_REF_TYPES != 0 - HANDLE_OP (WASM_OP_SELECT_T): - { - uint32 vec_len; - uint8 type; - - read_leb_uint32(frame_ip, frame_ip_end, vec_len); - type = *frame_ip++; - - cond = (uint32)POP_I32(); - if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) { - frame_sp -= 2; - if (!cond) { - *(frame_sp - 2) = *frame_sp; - *(frame_sp - 1) = *(frame_sp + 1); - } - } - else { - frame_sp--; - if (!cond) - *(frame_sp - 1) = *frame_sp; - } - - (void)vec_len; - HANDLE_OP_END (); - } - HANDLE_OP (WASM_OP_TABLE_GET): - { - uint32 tbl_idx, elem_idx; - WASMTableInstance *tbl_inst; + HANDLE_OP(WASM_OP_SELECT_T) + { + uint32 vec_len; + uint8 type; + + read_leb_uint32(frame_ip, frame_ip_end, vec_len); + type = *frame_ip++; + + cond = (uint32)POP_I32(); + if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) { + frame_sp -= 2; + if (!cond) { + *(frame_sp - 2) = *frame_sp; + *(frame_sp - 1) = *(frame_sp + 1); + } + } + else { + frame_sp--; + if (!cond) + *(frame_sp - 1) = *frame_sp; + } + + (void)vec_len; + HANDLE_OP_END(); + } + HANDLE_OP(WASM_OP_TABLE_GET) + { + uint32 tbl_idx, elem_idx; + WASMTableInstance *tbl_inst; - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - bh_assert(tbl_idx < module->table_count); + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + bh_assert(tbl_idx < module->table_count); - tbl_inst = wasm_get_table_inst(module, tbl_idx); + tbl_inst = wasm_get_table_inst(module, tbl_idx); - elem_idx = POP_I32(); - if (elem_idx >= tbl_inst->cur_size) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; - } + elem_idx = POP_I32(); + if (elem_idx >= tbl_inst->cur_size) { + wasm_set_exception(module, "out of bounds table access"); + goto got_exception; + } - PUSH_I32(((uint32 *)tbl_inst->base_addr)[elem_idx]); - HANDLE_OP_END (); - } + PUSH_I32(((uint32 *)tbl_inst->base_addr)[elem_idx]); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_TABLE_SET): - { - uint32 tbl_idx, elem_idx, val; - WASMTableInstance *tbl_inst; + HANDLE_OP(WASM_OP_TABLE_SET) + { + uint32 tbl_idx, elem_idx, val; + WASMTableInstance *tbl_inst; - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - bh_assert(tbl_idx < module->table_count); + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + bh_assert(tbl_idx < module->table_count); - tbl_inst = wasm_get_table_inst(module, tbl_idx); + tbl_inst = wasm_get_table_inst(module, tbl_idx); - val = POP_I32(); - elem_idx = POP_I32(); - if (elem_idx >= tbl_inst->cur_size) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; - } + val = POP_I32(); + elem_idx = POP_I32(); + if (elem_idx >= tbl_inst->cur_size) { + wasm_set_exception(module, "out of bounds table access"); + goto got_exception; + } - ((uint32 *)(tbl_inst->base_addr))[elem_idx] = val; - HANDLE_OP_END(); - } + ((uint32 *)(tbl_inst->base_addr))[elem_idx] = val; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_REF_NULL): - { - uint32 ref_type; - read_leb_uint32(frame_ip, frame_ip_end, ref_type); - PUSH_I32(NULL_REF); - (void)ref_type; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_REF_NULL) + { + uint32 ref_type; + read_leb_uint32(frame_ip, frame_ip_end, ref_type); + PUSH_I32(NULL_REF); + (void)ref_type; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_REF_IS_NULL): - { - uint32 val; - val = POP_I32(); - PUSH_I32(val == NULL_REF ? 1 : 0); - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_REF_IS_NULL) + { + uint32 val; + val = POP_I32(); + PUSH_I32(val == NULL_REF ? 1 : 0); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_REF_FUNC): - { - uint32 func_idx; - read_leb_uint32(frame_ip, frame_ip_end, func_idx); - PUSH_I32(func_idx); - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_REF_FUNC) + { + uint32 func_idx; + read_leb_uint32(frame_ip, frame_ip_end, func_idx); + PUSH_I32(func_idx); + HANDLE_OP_END(); + } #endif /* WASM_ENABLE_REF_TYPES */ - /* variable instructions */ - HANDLE_OP (WASM_OP_GET_LOCAL): - { - GET_LOCAL_INDEX_TYPE_AND_OFFSET(); + /* variable instructions */ + HANDLE_OP(WASM_OP_GET_LOCAL) + { + GET_LOCAL_INDEX_TYPE_AND_OFFSET(); - switch (local_type) { - case VALUE_TYPE_I32: - case VALUE_TYPE_F32: + switch (local_type) { + case VALUE_TYPE_I32: + case VALUE_TYPE_F32: #if WASM_ENABLE_REF_TYPES != 0 - case VALUE_TYPE_FUNCREF: - case VALUE_TYPE_EXTERNREF: + case VALUE_TYPE_FUNCREF: + case VALUE_TYPE_EXTERNREF: #endif - PUSH_I32(*(int32*)(frame_lp + local_offset)); - break; - case VALUE_TYPE_I64: - case VALUE_TYPE_F64: - PUSH_I64(GET_I64_FROM_ADDR(frame_lp + local_offset)); - break; - default: - wasm_set_exception(module, "invalid local type"); - goto got_exception; - } - - HANDLE_OP_END (); - } + PUSH_I32(*(int32 *)(frame_lp + local_offset)); + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + PUSH_I64(GET_I64_FROM_ADDR(frame_lp + local_offset)); + break; + default: + wasm_set_exception(module, "invalid local type"); + goto got_exception; + } + + HANDLE_OP_END(); + } - HANDLE_OP (EXT_OP_GET_LOCAL_FAST): - { - local_offset = *frame_ip++; - if (local_offset & 0x80) - PUSH_I64(GET_I64_FROM_ADDR(frame_lp + (local_offset & 0x7F))); - else - PUSH_I32(*(int32*)(frame_lp + local_offset)); - HANDLE_OP_END (); - } + HANDLE_OP(EXT_OP_GET_LOCAL_FAST) + { + local_offset = *frame_ip++; + if (local_offset & 0x80) + PUSH_I64( + GET_I64_FROM_ADDR(frame_lp + (local_offset & 0x7F))); + else + PUSH_I32(*(int32 *)(frame_lp + local_offset)); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_SET_LOCAL): - { - GET_LOCAL_INDEX_TYPE_AND_OFFSET(); + HANDLE_OP(WASM_OP_SET_LOCAL) + { + GET_LOCAL_INDEX_TYPE_AND_OFFSET(); - switch (local_type) { - case VALUE_TYPE_I32: - case VALUE_TYPE_F32: + switch (local_type) { + case VALUE_TYPE_I32: + case VALUE_TYPE_F32: #if WASM_ENABLE_REF_TYPES != 0 - case VALUE_TYPE_FUNCREF: - case VALUE_TYPE_EXTERNREF: + case VALUE_TYPE_FUNCREF: + case VALUE_TYPE_EXTERNREF: #endif - *(int32*)(frame_lp + local_offset) = POP_I32(); - break; - case VALUE_TYPE_I64: - case VALUE_TYPE_F64: - PUT_I64_TO_ADDR((uint32*)(frame_lp + local_offset), POP_I64()); - break; - default: - wasm_set_exception(module, "invalid local type"); - goto got_exception; - } - - HANDLE_OP_END (); - } + *(int32 *)(frame_lp + local_offset) = POP_I32(); + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset), + POP_I64()); + break; + default: + wasm_set_exception(module, "invalid local type"); + goto got_exception; + } + + HANDLE_OP_END(); + } - HANDLE_OP (EXT_OP_SET_LOCAL_FAST): - { - local_offset = *frame_ip++; - if (local_offset & 0x80) - PUT_I64_TO_ADDR((uint32*)(frame_lp + (local_offset & 0x7F)), POP_I64()); - else - *(int32*)(frame_lp + local_offset) = POP_I32(); - HANDLE_OP_END (); - } + HANDLE_OP(EXT_OP_SET_LOCAL_FAST) + { + local_offset = *frame_ip++; + if (local_offset & 0x80) + PUT_I64_TO_ADDR( + (uint32 *)(frame_lp + (local_offset & 0x7F)), + POP_I64()); + else + *(int32 *)(frame_lp + local_offset) = POP_I32(); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_TEE_LOCAL): - { - GET_LOCAL_INDEX_TYPE_AND_OFFSET(); + HANDLE_OP(WASM_OP_TEE_LOCAL) + { + GET_LOCAL_INDEX_TYPE_AND_OFFSET(); - switch (local_type) { - case VALUE_TYPE_I32: - case VALUE_TYPE_F32: + switch (local_type) { + case VALUE_TYPE_I32: + case VALUE_TYPE_F32: #if WASM_ENABLE_REF_TYPES != 0 - case VALUE_TYPE_FUNCREF: - case VALUE_TYPE_EXTERNREF: + case VALUE_TYPE_FUNCREF: + case VALUE_TYPE_EXTERNREF: #endif - *(int32*)(frame_lp + local_offset) = *(int32*)(frame_sp - 1); - break; - case VALUE_TYPE_I64: - case VALUE_TYPE_F64: - PUT_I64_TO_ADDR((uint32*)(frame_lp + local_offset), - GET_I64_FROM_ADDR(frame_sp - 2)); - break; - default: - wasm_set_exception(module, "invalid local type"); - goto got_exception; - } - - HANDLE_OP_END (); - } - - HANDLE_OP (EXT_OP_TEE_LOCAL_FAST): - { - local_offset = *frame_ip++; - if (local_offset & 0x80) - PUT_I64_TO_ADDR((uint32*)(frame_lp + (local_offset & 0x7F)), - GET_I64_FROM_ADDR(frame_sp - 2)); - else - *(int32*)(frame_lp + local_offset) = *(int32*)(frame_sp - 1); - HANDLE_OP_END (); - } + *(int32 *)(frame_lp + local_offset) = + *(int32 *)(frame_sp - 1); + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset), + GET_I64_FROM_ADDR(frame_sp - 2)); + break; + default: + wasm_set_exception(module, "invalid local type"); + goto got_exception; + } + + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_GET_GLOBAL): - { - read_leb_uint32(frame_ip, frame_ip_end, global_idx); - bh_assert(global_idx < module->global_count); - global = globals + global_idx; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_addr = global_data + global->data_offset; -#else - global_addr = global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif - PUSH_I32(*(uint32*)global_addr); - HANDLE_OP_END (); - } + HANDLE_OP(EXT_OP_TEE_LOCAL_FAST) + { + local_offset = *frame_ip++; + if (local_offset & 0x80) + PUT_I64_TO_ADDR( + (uint32 *)(frame_lp + (local_offset & 0x7F)), + GET_I64_FROM_ADDR(frame_sp - 2)); + else + *(int32 *)(frame_lp + local_offset) = + *(int32 *)(frame_sp - 1); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_GET_GLOBAL_64): - { - read_leb_uint32(frame_ip, frame_ip_end, global_idx); - bh_assert(global_idx < module->global_count); - global = globals + global_idx; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_addr = global_data + global->data_offset; -#else - global_addr = global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif - PUSH_I64(GET_I64_FROM_ADDR((uint32*)global_addr)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_GET_GLOBAL) + { + read_leb_uint32(frame_ip, frame_ip_end, global_idx); + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = get_global_addr(global_data, global); + PUSH_I32(*(uint32 *)global_addr); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_SET_GLOBAL): - { - read_leb_uint32(frame_ip, frame_ip_end, global_idx); - bh_assert(global_idx < module->global_count); - global = globals + global_idx; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_addr = global_data + global->data_offset; -#else - global_addr = global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif - *(int32*)global_addr = POP_I32(); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_GET_GLOBAL_64) + { + read_leb_uint32(frame_ip, frame_ip_end, global_idx); + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = get_global_addr(global_data, global); + PUSH_I64(GET_I64_FROM_ADDR((uint32 *)global_addr)); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_SET_GLOBAL_AUX_STACK): - { - uint32 aux_stack_top; + HANDLE_OP(WASM_OP_SET_GLOBAL) + { + read_leb_uint32(frame_ip, frame_ip_end, global_idx); + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = get_global_addr(global_data, global); + *(int32 *)global_addr = POP_I32(); + HANDLE_OP_END(); + } - read_leb_uint32(frame_ip, frame_ip_end, global_idx); - bh_assert(global_idx < module->global_count); - global = globals + global_idx; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_addr = global_data + global->data_offset; -#else - global_addr = global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif - aux_stack_top = *(uint32*)(frame_sp - 1); - if (aux_stack_top <= exec_env->aux_stack_boundary.boundary) { - wasm_set_exception(module, "wasm auxiliary stack overflow"); - goto got_exception; - } - if (aux_stack_top > exec_env->aux_stack_bottom.bottom) { - wasm_set_exception(module, "wasm auxiliary stack underflow"); - goto got_exception; - } - *(int32*)global_addr = aux_stack_top; - frame_sp--; + HANDLE_OP(WASM_OP_SET_GLOBAL_AUX_STACK) + { + uint32 aux_stack_top; + + read_leb_uint32(frame_ip, frame_ip_end, global_idx); + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = get_global_addr(global_data, global); + aux_stack_top = *(uint32 *)(frame_sp - 1); + if (aux_stack_top <= exec_env->aux_stack_boundary.boundary) { + wasm_set_exception(module, "wasm auxiliary stack overflow"); + goto got_exception; + } + if (aux_stack_top > exec_env->aux_stack_bottom.bottom) { + wasm_set_exception(module, + "wasm auxiliary stack underflow"); + goto got_exception; + } + *(int32 *)global_addr = aux_stack_top; + frame_sp--; #if WASM_ENABLE_MEMORY_PROFILING != 0 - if (module->module->aux_stack_top_global_index != (uint32)-1) { - uint32 aux_stack_used = - module->module->aux_stack_bottom - *(uint32*)global_addr; - if (aux_stack_used > module->max_aux_stack_used) - module->max_aux_stack_used = aux_stack_used; - } + if (module->module->aux_stack_top_global_index != (uint32)-1) { + uint32 aux_stack_used = module->module->aux_stack_bottom + - *(uint32 *)global_addr; + if (aux_stack_used > module->max_aux_stack_used) + module->max_aux_stack_used = aux_stack_used; + } #endif - HANDLE_OP_END (); - } + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_SET_GLOBAL_64): - { - read_leb_uint32(frame_ip, frame_ip_end, global_idx); - bh_assert(global_idx < module->global_count); - global = globals + global_idx; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_addr = global_data + global->data_offset; -#else - global_addr = global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif - PUT_I64_TO_ADDR((uint32*)global_addr, POP_I64()); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_SET_GLOBAL_64) + { + read_leb_uint32(frame_ip, frame_ip_end, global_idx); + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = get_global_addr(global_data, global); + PUT_I64_TO_ADDR((uint32 *)global_addr, POP_I64()); + HANDLE_OP_END(); + } - /* memory load instructions */ - HANDLE_OP (WASM_OP_I32_LOAD): - HANDLE_OP (WASM_OP_F32_LOAD): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(4); - PUSH_I32(LOAD_I32(maddr)); - (void)flags; - HANDLE_OP_END(); - } + /* memory load instructions */ + HANDLE_OP(WASM_OP_I32_LOAD) + HANDLE_OP(WASM_OP_F32_LOAD) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(4); + PUSH_I32(LOAD_I32(maddr)); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD): - HANDLE_OP (WASM_OP_F64_LOAD): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(8); - PUSH_I64(LOAD_I64(maddr)); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I64_LOAD) + HANDLE_OP(WASM_OP_F64_LOAD) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(8); + PUSH_I64(LOAD_I64(maddr)); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LOAD8_S): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(1); - PUSH_I32(sign_ext_8_32(*(int8*)maddr)); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I32_LOAD8_S) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(1); + PUSH_I32(sign_ext_8_32(*(int8 *)maddr)); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LOAD8_U): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(1); - PUSH_I32((uint32)(*(uint8*)maddr)); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I32_LOAD8_U) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(1); + PUSH_I32((uint32)(*(uint8 *)maddr)); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LOAD16_S): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(2); - PUSH_I32(sign_ext_16_32(LOAD_I16(maddr))); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I32_LOAD16_S) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(2); + PUSH_I32(sign_ext_16_32(LOAD_I16(maddr))); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LOAD16_U): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(2); - PUSH_I32((uint32)(LOAD_U16(maddr))); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I32_LOAD16_U) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(2); + PUSH_I32((uint32)(LOAD_U16(maddr))); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD8_S): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(1); - PUSH_I64(sign_ext_8_64(*(int8*)maddr)); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I64_LOAD8_S) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(1); + PUSH_I64(sign_ext_8_64(*(int8 *)maddr)); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD8_U): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(1); - PUSH_I64((uint64)(*(uint8*)maddr)); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I64_LOAD8_U) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(1); + PUSH_I64((uint64)(*(uint8 *)maddr)); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD16_S): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(2); - PUSH_I64(sign_ext_16_64(LOAD_I16(maddr))); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I64_LOAD16_S) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(2); + PUSH_I64(sign_ext_16_64(LOAD_I16(maddr))); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD16_U): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(2); - PUSH_I64((uint64)(LOAD_U16(maddr))); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I64_LOAD16_U) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(2); + PUSH_I64((uint64)(LOAD_U16(maddr))); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD32_S): - { - uint32 offset, flags, addr; - - opcode = *(frame_ip - 1); - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(4); - PUSH_I64(sign_ext_32_64(LOAD_I32(maddr))); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I64_LOAD32_S) + { + uint32 offset, flags, addr; + + opcode = *(frame_ip - 1); + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(4); + PUSH_I64(sign_ext_32_64(LOAD_I32(maddr))); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD32_U): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(4); - PUSH_I64((uint64)(LOAD_U32(maddr))); - (void)flags; - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_I64_LOAD32_U) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(4); + PUSH_I64((uint64)(LOAD_U32(maddr))); + (void)flags; + HANDLE_OP_END(); + } - /* memory store instructions */ - HANDLE_OP (WASM_OP_I32_STORE): - HANDLE_OP (WASM_OP_F32_STORE): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - frame_sp--; - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(4); - STORE_U32(maddr, frame_sp[1]); - (void)flags; - HANDLE_OP_END (); - } + /* memory store instructions */ + HANDLE_OP(WASM_OP_I32_STORE) + HANDLE_OP(WASM_OP_F32_STORE) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + frame_sp--; + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(4); + STORE_U32(maddr, frame_sp[1]); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_STORE): - HANDLE_OP (WASM_OP_F64_STORE): - { - uint32 offset, flags, addr; - - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - frame_sp -= 2; - addr = POP_I32(); - CHECK_MEMORY_OVERFLOW(8); - STORE_U32(maddr, frame_sp[1]); - STORE_U32(maddr + 4, frame_sp[2]); - (void)flags; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_STORE) + HANDLE_OP(WASM_OP_F64_STORE) + { + uint32 offset, flags, addr; + + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + frame_sp -= 2; + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(8); + STORE_U32(maddr, frame_sp[1]); + STORE_U32(maddr + 4, frame_sp[2]); + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_STORE8): - HANDLE_OP (WASM_OP_I32_STORE16): - { - uint32 offset, flags, addr; - uint32 sval; - - opcode = *(frame_ip - 1); - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - sval = (uint32)POP_I32(); - addr = POP_I32(); - - if (opcode == WASM_OP_I32_STORE8) { - CHECK_MEMORY_OVERFLOW(1); - *(uint8*)maddr = (uint8)sval; - } - else { - CHECK_MEMORY_OVERFLOW(2); - STORE_U16(maddr, (uint16)sval); - } - - (void)flags; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I32_STORE8) + HANDLE_OP(WASM_OP_I32_STORE16) + { + uint32 offset, flags, addr; + uint32 sval; + + opcode = *(frame_ip - 1); + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + sval = (uint32)POP_I32(); + addr = POP_I32(); + + if (opcode == WASM_OP_I32_STORE8) { + CHECK_MEMORY_OVERFLOW(1); + *(uint8 *)maddr = (uint8)sval; + } + else { + CHECK_MEMORY_OVERFLOW(2); + STORE_U16(maddr, (uint16)sval); + } + + (void)flags; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_STORE8): - HANDLE_OP (WASM_OP_I64_STORE16): - HANDLE_OP (WASM_OP_I64_STORE32): - { - uint32 offset, flags, addr; - uint64 sval; - - opcode = *(frame_ip - 1); - read_leb_uint32(frame_ip, frame_ip_end, flags); - read_leb_uint32(frame_ip, frame_ip_end, offset); - sval = (uint64)POP_I64(); - addr = POP_I32(); - - if (opcode == WASM_OP_I64_STORE8) { - CHECK_MEMORY_OVERFLOW(1); - *(uint8*)maddr = (uint8)sval; - } - else if(opcode == WASM_OP_I64_STORE16) { - CHECK_MEMORY_OVERFLOW(2); - STORE_U16(maddr, (uint16)sval); - } - else { - CHECK_MEMORY_OVERFLOW(4); - STORE_U32(maddr, (uint32)sval); - } - (void)flags; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_STORE8) + HANDLE_OP(WASM_OP_I64_STORE16) + HANDLE_OP(WASM_OP_I64_STORE32) + { + uint32 offset, flags, addr; + uint64 sval; + + opcode = *(frame_ip - 1); + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + sval = (uint64)POP_I64(); + addr = POP_I32(); + + if (opcode == WASM_OP_I64_STORE8) { + CHECK_MEMORY_OVERFLOW(1); + *(uint8 *)maddr = (uint8)sval; + } + else if (opcode == WASM_OP_I64_STORE16) { + CHECK_MEMORY_OVERFLOW(2); + STORE_U16(maddr, (uint16)sval); + } + else { + CHECK_MEMORY_OVERFLOW(4); + STORE_U32(maddr, (uint32)sval); + } + (void)flags; + HANDLE_OP_END(); + } - /* memory size and memory grow instructions */ - HANDLE_OP (WASM_OP_MEMORY_SIZE): - { - uint32 reserved; - read_leb_uint32(frame_ip, frame_ip_end, reserved); - PUSH_I32(memory->cur_page_count); - (void)reserved; - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_MEMORY_GROW): - { - uint32 reserved, delta, prev_page_count = memory->cur_page_count; - - read_leb_uint32(frame_ip, frame_ip_end, reserved); - delta = (uint32)POP_I32(); - - if (!wasm_enlarge_memory(module, delta)) { - /* failed to memory.grow, return -1 */ - PUSH_I32(-1); - } - else { - /* success, return previous page count */ - PUSH_I32(prev_page_count); - /* update memory instance ptr and memory size */ - memory = module->default_memory; - linear_mem_size = num_bytes_per_page * memory->cur_page_count; - } + /* memory size and memory grow instructions */ + HANDLE_OP(WASM_OP_MEMORY_SIZE) + { + uint32 reserved; + read_leb_uint32(frame_ip, frame_ip_end, reserved); + PUSH_I32(memory->cur_page_count); + (void)reserved; + HANDLE_OP_END(); + } - (void)reserved; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_MEMORY_GROW) + { + uint32 reserved, delta, + prev_page_count = memory->cur_page_count; + + read_leb_uint32(frame_ip, frame_ip_end, reserved); + delta = (uint32)POP_I32(); + + if (!wasm_enlarge_memory(module, delta)) { + /* failed to memory.grow, return -1 */ + PUSH_I32(-1); + } + else { + /* success, return previous page count */ + PUSH_I32(prev_page_count); + /* update memory instance ptr and memory size */ + memory = module->default_memory; + linear_mem_size = + num_bytes_per_page * memory->cur_page_count; + } + + (void)reserved; + HANDLE_OP_END(); + } - /* constant instructions */ - HANDLE_OP (WASM_OP_I32_CONST): - DEF_OP_I_CONST(int32, I32); - HANDLE_OP_END (); + /* constant instructions */ + HANDLE_OP(WASM_OP_I32_CONST) + DEF_OP_I_CONST(int32, I32); + HANDLE_OP_END(); + + HANDLE_OP(WASM_OP_I64_CONST) + DEF_OP_I_CONST(int64, I64); + HANDLE_OP_END(); + + HANDLE_OP(WASM_OP_F32_CONST) + { + uint8 *p_float = (uint8 *)frame_sp++; + for (i = 0; i < sizeof(float32); i++) + *p_float++ = *frame_ip++; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_CONST): - DEF_OP_I_CONST(int64, I64); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_F64_CONST) + { + uint8 *p_float = (uint8 *)frame_sp++; + frame_sp++; + for (i = 0; i < sizeof(float64); i++) + *p_float++ = *frame_ip++; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_F32_CONST): - { - uint8 *p_float = (uint8*)frame_sp++; - for (i = 0; i < sizeof(float32); i++) - *p_float++ = *frame_ip++; - HANDLE_OP_END (); - } + /* comparison instructions of i32 */ + HANDLE_OP(WASM_OP_I32_EQZ) + { + DEF_OP_EQZ(I32); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_F64_CONST): - { - uint8 *p_float = (uint8*)frame_sp++; - frame_sp++; - for (i = 0; i < sizeof(float64); i++) - *p_float++ = *frame_ip++; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I32_EQ) + { + DEF_OP_CMP(uint32, I32, ==); + HANDLE_OP_END(); + } - /* comparison instructions of i32 */ - HANDLE_OP (WASM_OP_I32_EQZ): - DEF_OP_EQZ(I32); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_NE) + { + DEF_OP_CMP(uint32, I32, !=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_EQ): - DEF_OP_CMP(uint32, I32, ==); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_LT_S) + { + DEF_OP_CMP(int32, I32, <); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_NE): - DEF_OP_CMP(uint32, I32, !=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_LT_U) + { + DEF_OP_CMP(uint32, I32, <); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LT_S): - DEF_OP_CMP(int32, I32, <); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_GT_S) + { + DEF_OP_CMP(int32, I32, >); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LT_U): - DEF_OP_CMP(uint32, I32, <); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_GT_U) + { + DEF_OP_CMP(uint32, I32, >); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_GT_S): - DEF_OP_CMP(int32, I32, >); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_LE_S) + { + DEF_OP_CMP(int32, I32, <=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_GT_U): - DEF_OP_CMP(uint32, I32, >); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_LE_U) + { + DEF_OP_CMP(uint32, I32, <=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LE_S): - DEF_OP_CMP(int32, I32, <=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_GE_S) + { + DEF_OP_CMP(int32, I32, >=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LE_U): - DEF_OP_CMP(uint32, I32, <=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_GE_U) + { + DEF_OP_CMP(uint32, I32, >=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_GE_S): - DEF_OP_CMP(int32, I32, >=); - HANDLE_OP_END (); + /* comparison instructions of i64 */ + HANDLE_OP(WASM_OP_I64_EQZ) + { + DEF_OP_EQZ(I64); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_GE_U): - DEF_OP_CMP(uint32, I32, >=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_EQ) + { + DEF_OP_CMP(uint64, I64, ==); + HANDLE_OP_END(); + } - /* comparison instructions of i64 */ - HANDLE_OP (WASM_OP_I64_EQZ): - DEF_OP_EQZ(I64); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_NE) + { + DEF_OP_CMP(uint64, I64, !=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_EQ): - DEF_OP_CMP(uint64, I64, ==); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_LT_S) + { + DEF_OP_CMP(int64, I64, <); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_NE): - DEF_OP_CMP(uint64, I64, !=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_LT_U) + { + DEF_OP_CMP(uint64, I64, <); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LT_S): - DEF_OP_CMP(int64, I64, <); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_GT_S) + { + DEF_OP_CMP(int64, I64, >); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LT_U): - DEF_OP_CMP(uint64, I64, <); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_GT_U) + { + DEF_OP_CMP(uint64, I64, >); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_GT_S): - DEF_OP_CMP(int64, I64, >); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_LE_S) + { + DEF_OP_CMP(int64, I64, <=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_GT_U): - DEF_OP_CMP(uint64, I64, >); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_LE_S): - DEF_OP_CMP(int64, I64, <=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_LE_U): - DEF_OP_CMP(uint64, I64, <=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_GE_S): - DEF_OP_CMP(int64, I64, >=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_GE_U): - DEF_OP_CMP(uint64, I64, >=); - HANDLE_OP_END (); - - /* comparison instructions of f32 */ - HANDLE_OP (WASM_OP_F32_EQ): - DEF_OP_CMP(float32, F32, ==); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_NE): - DEF_OP_CMP(float32, F32, !=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_LT): - DEF_OP_CMP(float32, F32, <); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_GT): - DEF_OP_CMP(float32, F32, >); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_LE): - DEF_OP_CMP(float32, F32, <=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_GE): - DEF_OP_CMP(float32, F32, >=); - HANDLE_OP_END (); - - /* comparison instructions of f64 */ - HANDLE_OP (WASM_OP_F64_EQ): - DEF_OP_CMP(float64, F64, ==); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_NE): - DEF_OP_CMP(float64, F64, !=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_LT): - DEF_OP_CMP(float64, F64, <); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_GT): - DEF_OP_CMP(float64, F64, >); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_LE): - DEF_OP_CMP(float64, F64, <=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_GE): - DEF_OP_CMP(float64, F64, >=); - HANDLE_OP_END (); - - /* numberic instructions of i32 */ - HANDLE_OP (WASM_OP_I32_CLZ): - DEF_OP_BIT_COUNT(uint32, I32, clz32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_CTZ): - DEF_OP_BIT_COUNT(uint32, I32, ctz32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_POPCNT): - DEF_OP_BIT_COUNT(uint32, I32, popcount32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_ADD): - DEF_OP_NUMERIC(uint32, uint32, I32, +); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_SUB): - DEF_OP_NUMERIC(uint32, uint32, I32, -); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_MUL): - DEF_OP_NUMERIC(uint32, uint32, I32, *); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_DIV_S): - { - int32 a, b; - - b = POP_I32(); - a = POP_I32(); - if (a == (int32)0x80000000 && b == -1) { - wasm_set_exception(module, "integer overflow"); - goto got_exception; - } - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUSH_I32(a / b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_DIV_U): - { - uint32 a, b; - - b = (uint32)POP_I32(); - a = (uint32)POP_I32(); - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUSH_I32(a / b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_REM_S): - { - int32 a, b; - - b = POP_I32(); - a = POP_I32(); - if (a == (int32)0x80000000 && b == -1) { - PUSH_I32(0); - HANDLE_OP_END (); - } - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUSH_I32(a % b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_REM_U): - { - uint32 a, b; - - b = (uint32)POP_I32(); - a = (uint32)POP_I32(); - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUSH_I32(a % b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_AND): - DEF_OP_NUMERIC(uint32, uint32, I32, &); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_OR): - DEF_OP_NUMERIC(uint32, uint32, I32, |); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_XOR): - DEF_OP_NUMERIC(uint32, uint32, I32, ^); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_SHL): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC(uint32, uint32, I32, <<); -#else - DEF_OP_NUMERIC2(uint32, uint32, I32, <<); -#endif - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_LE_U) + { + DEF_OP_CMP(uint64, I64, <=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_SHR_S): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC(int32, uint32, I32, >>); -#else - DEF_OP_NUMERIC2(int32, uint32, I32, >>); -#endif - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_GE_S) + { + DEF_OP_CMP(int64, I64, >=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_SHR_U): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC(uint32, uint32, I32, >>); -#else - DEF_OP_NUMERIC2(uint32, uint32, I32, >>); -#endif - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_ROTL): - { - uint32 a, b; - - b = (uint32)POP_I32(); - a = (uint32)POP_I32(); - PUSH_I32(rotl32(a, b)); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_ROTR): - { - uint32 a, b; - - b = (uint32)POP_I32(); - a = (uint32)POP_I32(); - PUSH_I32(rotr32(a, b)); - HANDLE_OP_END (); - } - - /* numberic instructions of i64 */ - HANDLE_OP (WASM_OP_I64_CLZ): - DEF_OP_BIT_COUNT(uint64, I64, clz64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_CTZ): - DEF_OP_BIT_COUNT(uint64, I64, ctz64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_POPCNT): - DEF_OP_BIT_COUNT(uint64, I64, popcount64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_ADD): - DEF_OP_NUMERIC_64(uint64, uint64, I64, +); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_SUB): - DEF_OP_NUMERIC_64(uint64, uint64, I64, -); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_MUL): - DEF_OP_NUMERIC_64(uint64, uint64, I64, *); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_DIV_S): - { - int64 a, b; - - b = POP_I64(); - a = POP_I64(); - if (a == (int64)0x8000000000000000LL && b == -1) { - wasm_set_exception(module, "integer overflow"); - goto got_exception; - } - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUSH_I64(a / b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_DIV_U): - { - uint64 a, b; - - b = (uint64)POP_I64(); - a = (uint64)POP_I64(); - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUSH_I64(a / b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_REM_S): - { - int64 a, b; - - b = POP_I64(); - a = POP_I64(); - if (a == (int64)0x8000000000000000LL && b == -1) { - PUSH_I64(0); - HANDLE_OP_END (); - } - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUSH_I64(a % b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_REM_U): - { - uint64 a, b; - - b = (uint64)POP_I64(); - a = (uint64)POP_I64(); - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUSH_I64(a % b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_AND): - DEF_OP_NUMERIC_64(uint64, uint64, I64, &); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_OR): - DEF_OP_NUMERIC_64(uint64, uint64, I64, |); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_XOR): - DEF_OP_NUMERIC_64(uint64, uint64, I64, ^); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_SHL): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC_64(uint64, uint64, I64, <<); -#else - DEF_OP_NUMERIC2_64(uint64, uint64, I64, <<); -#endif - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_GE_U) + { + DEF_OP_CMP(uint64, I64, >=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_SHR_S): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC_64(int64, uint64, I64, >>); -#else - DEF_OP_NUMERIC2_64(int64, uint64, I64, >>); -#endif - HANDLE_OP_END (); - } + /* comparison instructions of f32 */ + HANDLE_OP(WASM_OP_F32_EQ) + { + DEF_OP_CMP(float32, F32, ==); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_SHR_U): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC_64(uint64, uint64, I64, >>); -#else - DEF_OP_NUMERIC2_64(uint64, uint64, I64, >>); -#endif - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_ROTL): - { - uint64 a, b; - - b = (uint64)POP_I64(); - a = (uint64)POP_I64(); - PUSH_I64(rotl64(a, b)); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_ROTR): - { - uint64 a, b; - - b = (uint64)POP_I64(); - a = (uint64)POP_I64(); - PUSH_I64(rotr64(a, b)); - HANDLE_OP_END (); - } - - /* numberic instructions of f32 */ - HANDLE_OP (WASM_OP_F32_ABS): - DEF_OP_MATH(float32, F32, fabs); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_NEG): - { - int32 i32 = (int32)frame_sp[-1]; - int32 sign_bit = i32 & (1 << 31); - if (sign_bit) - frame_sp[-1] = i32 & ~(1 << 31); - else - frame_sp[-1] = (uint32)(i32 | (1 << 31)); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_F32_CEIL): - DEF_OP_MATH(float32, F32, ceil); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_FLOOR): - DEF_OP_MATH(float32, F32, floor); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_TRUNC): - DEF_OP_MATH(float32, F32, trunc); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_NEAREST): - DEF_OP_MATH(float32, F32, rint); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_SQRT): - DEF_OP_MATH(float32, F32, sqrt); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_ADD): - DEF_OP_NUMERIC(float32, float32, F32, +); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_SUB): - DEF_OP_NUMERIC(float32, float32, F32, -); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_MUL): - DEF_OP_NUMERIC(float32, float32, F32, *); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_DIV): - DEF_OP_NUMERIC(float32, float32, F32, /); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_MIN): - { - float32 a, b; - - b = POP_F32(); - a = POP_F32(); - - if (isnan(a)) - PUSH_F32(a); - else if (isnan(b)) - PUSH_F32(b); - else - PUSH_F32(wa_fmin(a, b)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_F32_NE) + { + DEF_OP_CMP(float32, F32, !=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_F32_MAX): - { - float32 a, b; + HANDLE_OP(WASM_OP_F32_LT) + { + DEF_OP_CMP(float32, F32, <); + HANDLE_OP_END(); + } - b = POP_F32(); - a = POP_F32(); + HANDLE_OP(WASM_OP_F32_GT) + { + DEF_OP_CMP(float32, F32, >); + HANDLE_OP_END(); + } - if (isnan(a)) - PUSH_F32(a); - else if (isnan(b)) - PUSH_F32(b); - else - PUSH_F32(wa_fmax(a, b)); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_F32_COPYSIGN): - { - float32 a, b; - - b = POP_F32(); - a = POP_F32(); - PUSH_F32(signbit(b) ? -fabs(a) : fabs(a)); - HANDLE_OP_END (); - } - - /* numberic instructions of f64 */ - HANDLE_OP (WASM_OP_F64_ABS): - DEF_OP_MATH(float64, F64, fabs); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_NEG): - { - int64 i64 = GET_I64_FROM_ADDR(frame_sp - 2); - int64 sign_bit = i64 & (((int64)1) << 63); - if (sign_bit) - PUT_I64_TO_ADDR(frame_sp - 2, ((uint64)i64 & ~(((uint64)1) << 63))); - else - PUT_I64_TO_ADDR(frame_sp - 2, ((uint64)i64 | (((uint64)1) << 63))); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_F64_CEIL): - DEF_OP_MATH(float64, F64, ceil); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_FLOOR): - DEF_OP_MATH(float64, F64, floor); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_TRUNC): - DEF_OP_MATH(float64, F64, trunc); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_NEAREST): - DEF_OP_MATH(float64, F64, rint); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_SQRT): - DEF_OP_MATH(float64, F64, sqrt); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_ADD): - DEF_OP_NUMERIC_64(float64, float64, F64, +); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_SUB): - DEF_OP_NUMERIC_64(float64, float64, F64, -); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_MUL): - DEF_OP_NUMERIC_64(float64, float64, F64, *); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_DIV): - DEF_OP_NUMERIC_64(float64, float64, F64, /); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_MIN): - { - float64 a, b; - - b = POP_F64(); - a = POP_F64(); - - if (isnan(a)) - PUSH_F64(a); - else if (isnan(b)) - PUSH_F64(b); - else - PUSH_F64(wa_fmin(a, b)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_F32_LE) + { + DEF_OP_CMP(float32, F32, <=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_F64_MAX): - { - float64 a, b; + HANDLE_OP(WASM_OP_F32_GE) + { + DEF_OP_CMP(float32, F32, >=); + HANDLE_OP_END(); + } - b = POP_F64(); - a = POP_F64(); + /* comparison instructions of f64 */ + HANDLE_OP(WASM_OP_F64_EQ) + { + DEF_OP_CMP(float64, F64, ==); + HANDLE_OP_END(); + } - if (isnan(a)) - PUSH_F64(a); - else if (isnan(b)) - PUSH_F64(b); - else - PUSH_F64(wa_fmax(a, b)); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_F64_COPYSIGN): - { - float64 a, b; - - b = POP_F64(); - a = POP_F64(); - PUSH_F64(signbit(b) ? -fabs(a) : fabs(a)); - HANDLE_OP_END (); - } - - /* conversions of i32 */ - HANDLE_OP (WASM_OP_I32_WRAP_I64): - { - int32 value = (int32)(POP_I64() & 0xFFFFFFFFLL); - PUSH_I32(value); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_F64_NE) + { + DEF_OP_CMP(float64, F64, !=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_TRUNC_S_F32): - /* We don't use INT32_MIN/INT32_MAX/UINT32_MIN/UINT32_MAX, - since float/double values of ieee754 cannot precisely represent - all int32/uint32/int64/uint64 values, e.g.: - UINT32_MAX is 4294967295, but (float32)4294967295 is 4294967296.0f, - but not 4294967295.0f. */ - DEF_OP_TRUNC_F32(-2147483904.0f, 2147483648.0f, true, true); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_TRUNC_U_F32): - DEF_OP_TRUNC_F32(-1.0f, 4294967296.0f, true, false); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_TRUNC_S_F64): - DEF_OP_TRUNC_F64(-2147483649.0, 2147483648.0, true, true); - /* frame_sp can't be moved in trunc function, we need to manually adjust - it if src and dst op's cell num is different */ - frame_sp--; - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_TRUNC_U_F64): - DEF_OP_TRUNC_F64(-1.0, 4294967296.0, true, false); - frame_sp--; - HANDLE_OP_END (); - - /* conversions of i64 */ - HANDLE_OP (WASM_OP_I64_EXTEND_S_I32): - DEF_OP_CONVERT(int64, I64, int32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_EXTEND_U_I32): - DEF_OP_CONVERT(int64, I64, uint32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_TRUNC_S_F32): - DEF_OP_TRUNC_F32(-9223373136366403584.0f, 9223372036854775808.0f, - false, true); - frame_sp++; - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_TRUNC_U_F32): - DEF_OP_TRUNC_F32(-1.0f, 18446744073709551616.0f, - false, false); - frame_sp++; - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_TRUNC_S_F64): - DEF_OP_TRUNC_F64(-9223372036854777856.0, 9223372036854775808.0, - false, true); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_TRUNC_U_F64): - DEF_OP_TRUNC_F64(-1.0, 18446744073709551616.0, - false, false); - HANDLE_OP_END (); - - /* conversions of f32 */ - HANDLE_OP (WASM_OP_F32_CONVERT_S_I32): - DEF_OP_CONVERT(float32, F32, int32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_CONVERT_U_I32): - DEF_OP_CONVERT(float32, F32, uint32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_CONVERT_S_I64): - DEF_OP_CONVERT(float32, F32, int64, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_CONVERT_U_I64): - DEF_OP_CONVERT(float32, F32, uint64, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_DEMOTE_F64): - DEF_OP_CONVERT(float32, F32, float64, F64); - HANDLE_OP_END (); - - /* conversions of f64 */ - HANDLE_OP (WASM_OP_F64_CONVERT_S_I32): - DEF_OP_CONVERT(float64, F64, int32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_CONVERT_U_I32): - DEF_OP_CONVERT(float64, F64, uint32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_CONVERT_S_I64): - DEF_OP_CONVERT(float64, F64, int64, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_CONVERT_U_I64): - DEF_OP_CONVERT(float64, F64, uint64, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_PROMOTE_F32): - DEF_OP_CONVERT(float64, F64, float32, F32); - HANDLE_OP_END (); - - /* reinterpretations */ - HANDLE_OP (WASM_OP_I32_REINTERPRET_F32): - HANDLE_OP (WASM_OP_I64_REINTERPRET_F64): - HANDLE_OP (WASM_OP_F32_REINTERPRET_I32): - HANDLE_OP (WASM_OP_F64_REINTERPRET_I64): - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_EXTEND8_S): - DEF_OP_CONVERT(int32, I32, int8, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_EXTEND16_S): - DEF_OP_CONVERT(int32, I32, int16, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_EXTEND8_S): - DEF_OP_CONVERT(int64, I64, int8, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_EXTEND16_S): - DEF_OP_CONVERT(int64, I64, int16, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_EXTEND32_S): - DEF_OP_CONVERT(int64, I64, int32, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_MISC_PREFIX): - { - uint32 opcode1; - - read_leb_uint32(frame_ip, frame_ip_end, opcode1); - opcode = (uint8)opcode1; + HANDLE_OP(WASM_OP_F64_LT) + { + DEF_OP_CMP(float64, F64, <); + HANDLE_OP_END(); + } - switch (opcode) { - case WASM_OP_I32_TRUNC_SAT_S_F32: - DEF_OP_TRUNC_SAT_F32(-2147483904.0f, 2147483648.0f, - true, true); - break; - case WASM_OP_I32_TRUNC_SAT_U_F32: - DEF_OP_TRUNC_SAT_F32(-1.0f, 4294967296.0f, - true, false); - break; - case WASM_OP_I32_TRUNC_SAT_S_F64: - DEF_OP_TRUNC_SAT_F64(-2147483649.0, 2147483648.0, - true, true); - frame_sp--; - break; - case WASM_OP_I32_TRUNC_SAT_U_F64: - DEF_OP_TRUNC_SAT_F64(-1.0, 4294967296.0, - true, false); - frame_sp--; - break; - case WASM_OP_I64_TRUNC_SAT_S_F32: - DEF_OP_TRUNC_SAT_F32(-9223373136366403584.0f, 9223372036854775808.0f, - false, true); - frame_sp++; - break; - case WASM_OP_I64_TRUNC_SAT_U_F32: - DEF_OP_TRUNC_SAT_F32(-1.0f, 18446744073709551616.0f, - false, false); - frame_sp++; - break; - case WASM_OP_I64_TRUNC_SAT_S_F64: - DEF_OP_TRUNC_SAT_F64(-9223372036854777856.0, 9223372036854775808.0, - false, true); - break; - case WASM_OP_I64_TRUNC_SAT_U_F64: - DEF_OP_TRUNC_SAT_F64(-1.0f, 18446744073709551616.0, - false, false); - break; -#if WASM_ENABLE_BULK_MEMORY != 0 - case WASM_OP_MEMORY_INIT: - { - uint32 addr, segment; - uint64 bytes, offset, seg_len; - uint8* data; + HANDLE_OP(WASM_OP_F64_GT) + { + DEF_OP_CMP(float64, F64, >); + HANDLE_OP_END(); + } - read_leb_uint32(frame_ip, frame_ip_end, segment); - /* skip memory index */ - frame_ip++; + HANDLE_OP(WASM_OP_F64_LE) + { + DEF_OP_CMP(float64, F64, <=); + HANDLE_OP_END(); + } - bytes = (uint64)(uint32)POP_I32(); - offset = (uint64)(uint32)POP_I32(); - addr = (uint32)POP_I32(); + HANDLE_OP(WASM_OP_F64_GE) + { + DEF_OP_CMP(float64, F64, >=); + HANDLE_OP_END(); + } - CHECK_BULK_MEMORY_OVERFLOW(addr, bytes, maddr); + /* numberic instructions of i32 */ + HANDLE_OP(WASM_OP_I32_CLZ) + { + DEF_OP_BIT_COUNT(uint32, I32, clz32); + HANDLE_OP_END(); + } - seg_len = (uint64)module->module->data_segments[segment]->data_length; - data = module->module->data_segments[segment]->data; - if (offset + bytes > seg_len) - goto out_of_bounds; + HANDLE_OP(WASM_OP_I32_CTZ) + { + DEF_OP_BIT_COUNT(uint32, I32, ctz32); + HANDLE_OP_END(); + } - bh_memcpy_s(maddr, linear_mem_size - addr, - data + offset, bytes); - break; - } - case WASM_OP_DATA_DROP: - { - uint32 segment; + HANDLE_OP(WASM_OP_I32_POPCNT) + { + DEF_OP_BIT_COUNT(uint32, I32, popcount32); + HANDLE_OP_END(); + } - read_leb_uint32(frame_ip, frame_ip_end, segment); - module->module->data_segments[segment]->data_length = 0; + HANDLE_OP(WASM_OP_I32_ADD) + { + DEF_OP_NUMERIC(uint32, uint32, I32, +); + HANDLE_OP_END(); + } - break; - } - case WASM_OP_MEMORY_COPY: - { - uint32 dst, src, len; - uint8 *mdst, *msrc; + HANDLE_OP(WASM_OP_I32_SUB) + { + DEF_OP_NUMERIC(uint32, uint32, I32, -); + HANDLE_OP_END(); + } - frame_ip += 2; + HANDLE_OP(WASM_OP_I32_MUL) + { + DEF_OP_NUMERIC(uint32, uint32, I32, *); + HANDLE_OP_END(); + } - len = POP_I32(); - src = POP_I32(); - dst = POP_I32(); + HANDLE_OP(WASM_OP_I32_DIV_S) + { + int32 a, b; + + b = POP_I32(); + a = POP_I32(); + if (a == (int32)0x80000000 && b == -1) { + wasm_set_exception(module, "integer overflow"); + goto got_exception; + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUSH_I32(a / b); + HANDLE_OP_END(); + } - CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc); - CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); + HANDLE_OP(WASM_OP_I32_DIV_U) + { + uint32 a, b; + + b = (uint32)POP_I32(); + a = (uint32)POP_I32(); + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUSH_I32(a / b); + HANDLE_OP_END(); + } - /* allowing the destination and source to overlap */ - bh_memmove_s(mdst, linear_mem_size - dst, - msrc, len); + HANDLE_OP(WASM_OP_I32_REM_S) + { + int32 a, b; + + b = POP_I32(); + a = POP_I32(); + if (a == (int32)0x80000000 && b == -1) { + PUSH_I32(0); + HANDLE_OP_END(); + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUSH_I32(a % b); + HANDLE_OP_END(); + } - break; - } - case WASM_OP_MEMORY_FILL: - { - uint32 dst, len; - uint8 val, *mdst; - frame_ip++; + HANDLE_OP(WASM_OP_I32_REM_U) + { + uint32 a, b; + + b = (uint32)POP_I32(); + a = (uint32)POP_I32(); + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUSH_I32(a % b); + HANDLE_OP_END(); + } - len = POP_I32(); - val = POP_I32(); - dst = POP_I32(); + HANDLE_OP(WASM_OP_I32_AND) + { + DEF_OP_NUMERIC(uint32, uint32, I32, &); + HANDLE_OP_END(); + } - CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); + HANDLE_OP(WASM_OP_I32_OR) + { + DEF_OP_NUMERIC(uint32, uint32, I32, |); + HANDLE_OP_END(); + } - memset(mdst, val, len); + HANDLE_OP(WASM_OP_I32_XOR) + { + DEF_OP_NUMERIC(uint32, uint32, I32, ^); + HANDLE_OP_END(); + } - break; - } -#endif /* WASM_ENABLE_BULK_MEMORY */ -#if WASM_ENABLE_REF_TYPES != 0 - case WASM_OP_TABLE_INIT: - { - uint32 tbl_idx, elem_idx; - uint64 n, s, d; - WASMTableInstance *tbl_inst; + HANDLE_OP(WASM_OP_I32_SHL) + { + DEF_OP_NUMERIC2(uint32, uint32, I32, <<); + HANDLE_OP_END(); + } - read_leb_uint32(frame_ip, frame_ip_end, elem_idx); - bh_assert(elem_idx < module->module->table_seg_count); + HANDLE_OP(WASM_OP_I32_SHR_S) + { + DEF_OP_NUMERIC2(int32, uint32, I32, >>); + HANDLE_OP_END(); + } - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - bh_assert(tbl_idx < module->module->table_count); + HANDLE_OP(WASM_OP_I32_SHR_U) + { + DEF_OP_NUMERIC2(uint32, uint32, I32, >>); + HANDLE_OP_END(); + } - tbl_inst = wasm_get_table_inst(module, tbl_idx); + HANDLE_OP(WASM_OP_I32_ROTL) + { + uint32 a, b; - n = (uint32)POP_I32(); - s = (uint32)POP_I32(); - d = (uint32)POP_I32(); + b = (uint32)POP_I32(); + a = (uint32)POP_I32(); + PUSH_I32(rotl32(a, b)); + HANDLE_OP_END(); + } - /* TODO: what if the element is not passive? */ + HANDLE_OP(WASM_OP_I32_ROTR) + { + uint32 a, b; - if (!n) { - break; - } + b = (uint32)POP_I32(); + a = (uint32)POP_I32(); + PUSH_I32(rotr32(a, b)); + HANDLE_OP_END(); + } - if (n + s > module->module->table_segments[elem_idx].function_count - || d + n > tbl_inst->cur_size) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; - } + /* numberic instructions of i64 */ + HANDLE_OP(WASM_OP_I64_CLZ) + { + DEF_OP_BIT_COUNT(uint64, I64, clz64); + HANDLE_OP_END(); + } - if (module->module->table_segments[elem_idx].is_dropped) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; - } - - if (!wasm_elem_is_passive( - module->module->table_segments[elem_idx].mode)) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; - } - - bh_memcpy_s( - (uint8 *)(tbl_inst) - + offsetof(WASMTableInstance, base_addr) + d * sizeof(uint32), - (tbl_inst->cur_size - d) * sizeof(uint32), - module->module->table_segments[elem_idx].func_indexes + s, - n * sizeof(uint32)); - - break; - } - case WASM_OP_ELEM_DROP: - { - uint32 elem_idx; - read_leb_uint32(frame_ip, frame_ip_end, elem_idx); - bh_assert(elem_idx < module->module->table_seg_count); + HANDLE_OP(WASM_OP_I64_CTZ) + { + DEF_OP_BIT_COUNT(uint64, I64, ctz64); + HANDLE_OP_END(); + } - module->module->table_segments[elem_idx].is_dropped = true; - break; - } - case WASM_OP_TABLE_COPY: - { - uint32 src_tbl_idx, dst_tbl_idx; - uint64 n, s, d; - WASMTableInstance *src_tbl_inst, *dst_tbl_inst; - - read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx); - bh_assert(dst_tbl_idx < module->table_count); - - dst_tbl_inst = wasm_get_table_inst(module, dst_tbl_idx); - - read_leb_uint32(frame_ip, frame_ip_end, src_tbl_idx); - bh_assert(src_tbl_idx < module->table_count); - - src_tbl_inst = wasm_get_table_inst(module, src_tbl_idx); - - n = (uint32)POP_I32(); - s = (uint32)POP_I32(); - d = (uint32)POP_I32(); - - if (s + n > dst_tbl_inst->cur_size - || d + n > src_tbl_inst->cur_size) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; - } - - /* if s >= d, copy from front to back */ - /* if s < d, copy from back to front */ - /* merge all together */ - bh_memcpy_s( - (uint8 *)(dst_tbl_inst) + offsetof(WASMTableInstance, base_addr) - + d * sizeof(uint32), - (dst_tbl_inst->cur_size - d) * sizeof(uint32), - (uint8 *)(src_tbl_inst) + offsetof(WASMTableInstance, base_addr) - + s * sizeof(uint32), - n * sizeof(uint32)); - break; - } - case WASM_OP_TABLE_GROW: - { - uint32 tbl_idx, n, init_val, orig_tbl_sz; - WASMTableInstance *tbl_inst; + HANDLE_OP(WASM_OP_I64_POPCNT) + { + DEF_OP_BIT_COUNT(uint64, I64, popcount64); + HANDLE_OP_END(); + } - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - bh_assert(tbl_idx < module->table_count); + HANDLE_OP(WASM_OP_I64_ADD) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, +); + HANDLE_OP_END(); + } - tbl_inst = wasm_get_table_inst(module, tbl_idx); + HANDLE_OP(WASM_OP_I64_SUB) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, -); + HANDLE_OP_END(); + } - orig_tbl_sz = tbl_inst->cur_size; + HANDLE_OP(WASM_OP_I64_MUL) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, *); + HANDLE_OP_END(); + } - n = POP_I32(); - init_val = POP_I32(); + HANDLE_OP(WASM_OP_I64_DIV_S) + { + int64 a, b; + + b = POP_I64(); + a = POP_I64(); + if (a == (int64)0x8000000000000000LL && b == -1) { + wasm_set_exception(module, "integer overflow"); + goto got_exception; + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUSH_I64(a / b); + HANDLE_OP_END(); + } - if (!wasm_enlarge_table(module, tbl_idx, n, init_val)) { - PUSH_I32(-1); - } - else { - PUSH_I32(orig_tbl_sz); - } - break; - } - case WASM_OP_TABLE_SIZE: - { - uint32 tbl_idx; - WASMTableInstance *tbl_inst; + HANDLE_OP(WASM_OP_I64_DIV_U) + { + uint64 a, b; + + b = (uint64)POP_I64(); + a = (uint64)POP_I64(); + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUSH_I64(a / b); + HANDLE_OP_END(); + } - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - bh_assert(tbl_idx < module->table_count); + HANDLE_OP(WASM_OP_I64_REM_S) + { + int64 a, b; + + b = POP_I64(); + a = POP_I64(); + if (a == (int64)0x8000000000000000LL && b == -1) { + PUSH_I64(0); + HANDLE_OP_END(); + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUSH_I64(a % b); + HANDLE_OP_END(); + } - tbl_inst = wasm_get_table_inst(module, tbl_idx); + HANDLE_OP(WASM_OP_I64_REM_U) + { + uint64 a, b; + + b = (uint64)POP_I64(); + a = (uint64)POP_I64(); + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUSH_I64(a % b); + HANDLE_OP_END(); + } - PUSH_I32(tbl_inst->cur_size); - break; - } - case WASM_OP_TABLE_FILL: - { - uint32 tbl_idx, n, val, i; - WASMTableInstance *tbl_inst; + HANDLE_OP(WASM_OP_I64_AND) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, &); + HANDLE_OP_END(); + } - read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); - bh_assert(tbl_idx < module->table_count); + HANDLE_OP(WASM_OP_I64_OR) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, |); + HANDLE_OP_END(); + } - tbl_inst = wasm_get_table_inst(module, tbl_idx); + HANDLE_OP(WASM_OP_I64_XOR) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, ^); + HANDLE_OP_END(); + } - n = POP_I32(); - val = POP_I32(); - i = POP_I32(); + HANDLE_OP(WASM_OP_I64_SHL) + { + DEF_OP_NUMERIC2_64(uint64, uint64, I64, <<); + HANDLE_OP_END(); + } - /* TODO: what if the element is not passive? */ - /* TODO: what if the element is dropped? */ + HANDLE_OP(WASM_OP_I64_SHR_S) + { + DEF_OP_NUMERIC2_64(int64, uint64, I64, >>); + HANDLE_OP_END(); + } - if (i + n > tbl_inst->cur_size) { - /* TODO: verify warning content */ - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; - } + HANDLE_OP(WASM_OP_I64_SHR_U) + { + DEF_OP_NUMERIC2_64(uint64, uint64, I64, >>); + HANDLE_OP_END(); + } - for (; n != 0; i++, n--) { - ((uint32 *)(tbl_inst->base_addr))[i] = val; - } + HANDLE_OP(WASM_OP_I64_ROTL) + { + uint64 a, b; - break; - } -#endif /* WASM_ENABLE_REF_TYPES */ - default: - wasm_set_exception(module, "unsupported opcode"); - goto got_exception; - } - HANDLE_OP_END (); - } + b = (uint64)POP_I64(); + a = (uint64)POP_I64(); + PUSH_I64(rotl64(a, b)); + HANDLE_OP_END(); + } -#if WASM_ENABLE_SHARED_MEMORY != 0 - HANDLE_OP (WASM_OP_ATOMIC_PREFIX): - { - uint32 offset, align, addr; + HANDLE_OP(WASM_OP_I64_ROTR) + { + uint64 a, b; - opcode = *frame_ip++; + b = (uint64)POP_I64(); + a = (uint64)POP_I64(); + PUSH_I64(rotr64(a, b)); + HANDLE_OP_END(); + } - read_leb_uint32(frame_ip, frame_ip_end, align); - read_leb_uint32(frame_ip, frame_ip_end, offset); - switch (opcode) { - case WASM_OP_ATOMIC_NOTIFY: - { - uint32 count, ret; + /* numberic instructions of f32 */ + HANDLE_OP(WASM_OP_F32_ABS) + { + DEF_OP_MATH(float32, F32, fabs); + HANDLE_OP_END(); + } - count = POP_I32(); - addr = POP_I32(); - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); + HANDLE_OP(WASM_OP_F32_NEG) + { + uint32 u32 = frame_sp[-1]; + uint32 sign_bit = u32 & ((uint32)1 << 31); + if (sign_bit) + frame_sp[-1] = u32 & ~((uint32)1 << 31); + else + frame_sp[-1] = u32 | ((uint32)1 << 31); + HANDLE_OP_END(); + } - ret = wasm_runtime_atomic_notify((WASMModuleInstanceCommon*)module, - maddr, count); - bh_assert((int32)ret >= 0); + HANDLE_OP(WASM_OP_F32_CEIL) + { + DEF_OP_MATH(float32, F32, ceil); + HANDLE_OP_END(); + } - PUSH_I32(ret); - break; - } - case WASM_OP_ATOMIC_WAIT32: - { - uint64 timeout; - uint32 expect, addr, ret; - - timeout = POP_I64(); - expect = POP_I32(); - addr = POP_I32(); - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - - ret = wasm_runtime_atomic_wait((WASMModuleInstanceCommon*)module, maddr, - (uint64)expect, timeout, false); - if (ret == (uint32)-1) - goto got_exception; - - PUSH_I32(ret); - break; - } - case WASM_OP_ATOMIC_WAIT64: - { - uint64 timeout, expect; - uint32 ret; - - timeout = POP_I64(); - expect = POP_I64(); - addr = POP_I32(); - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - - ret = wasm_runtime_atomic_wait((WASMModuleInstanceCommon*)module, - maddr, expect, timeout, true); - if (ret == (uint32)-1) - goto got_exception; - - PUSH_I32(ret); - break; - } - - case WASM_OP_ATOMIC_I32_LOAD: - case WASM_OP_ATOMIC_I32_LOAD8_U: - case WASM_OP_ATOMIC_I32_LOAD16_U: - { - uint32 readv; - - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - readv = (uint32)(*(uint8*)maddr); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - readv = (uint32)LOAD_U16(maddr); - os_mutex_unlock(&memory->mem_lock); - } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - readv = LOAD_I32(maddr); - os_mutex_unlock(&memory->mem_lock); - } - - PUSH_I32(readv); - break; - } - - case WASM_OP_ATOMIC_I64_LOAD: - case WASM_OP_ATOMIC_I64_LOAD8_U: - case WASM_OP_ATOMIC_I64_LOAD16_U: - case WASM_OP_ATOMIC_I64_LOAD32_U: - { - uint64 readv; - - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - readv = (uint64)(*(uint8*)maddr); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - readv = (uint64)LOAD_U16(maddr); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - readv = (uint64)LOAD_U32(maddr); - os_mutex_unlock(&memory->mem_lock); - } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - readv = LOAD_I64(maddr); - os_mutex_unlock(&memory->mem_lock); - } - - PUSH_I64(readv); - break; - } - - case WASM_OP_ATOMIC_I32_STORE: - case WASM_OP_ATOMIC_I32_STORE8: - case WASM_OP_ATOMIC_I32_STORE16: - { - uint32 sval; - - sval = (uint32)POP_I32(); - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_I32_STORE8) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - *(uint8*)maddr = (uint8)sval; - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&memory->mem_lock); - } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - STORE_U32(maddr, frame_sp[1]); - os_mutex_unlock(&memory->mem_lock); + HANDLE_OP(WASM_OP_F32_FLOOR) + { + DEF_OP_MATH(float32, F32, floor); + HANDLE_OP_END(); } - break; - } - - case WASM_OP_ATOMIC_I64_STORE: - case WASM_OP_ATOMIC_I64_STORE8: - case WASM_OP_ATOMIC_I64_STORE16: - case WASM_OP_ATOMIC_I64_STORE32: - { - uint64 sval; - - sval = (uint64)POP_I64(); - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_I64_STORE8) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - *(uint8*)maddr = (uint8)sval; - os_mutex_unlock(&memory->mem_lock); - } - else if(opcode == WASM_OP_ATOMIC_I64_STORE16) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - STORE_U32(maddr, (uint32)sval); - os_mutex_unlock(&memory->mem_lock); - } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&memory->mem_lock); - STORE_U32(maddr, frame_sp[1]); - STORE_U32(maddr + 4, frame_sp[2]); - os_mutex_unlock(&memory->mem_lock); + + HANDLE_OP(WASM_OP_F32_TRUNC) + { + DEF_OP_MATH(float32, F32, trunc); + HANDLE_OP_END(); } - break; - } - - case WASM_OP_ATOMIC_RMW_I32_CMPXCHG: - case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U: - case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U: - { - uint32 readv, sval, expect; - - sval = POP_I32(); - expect = POP_I32(); - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - - os_mutex_lock(&memory->mem_lock); - readv = (uint32)(*(uint8*)maddr); - if (readv == expect) - *(uint8*)maddr = (uint8)(sval); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - - os_mutex_lock(&memory->mem_lock); - readv = (uint32)LOAD_U16(maddr); - if (readv == expect) - STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&memory->mem_lock); - } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - - os_mutex_lock(&memory->mem_lock); - readv = LOAD_I32(maddr); - if (readv == expect) - STORE_U32(maddr, sval); - os_mutex_unlock(&memory->mem_lock); - } - PUSH_I32(readv); - break; - } - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG: - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U: - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U: - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U: - { - uint64 readv, sval, expect; - - sval = (uint64)POP_I64(); - expect = (uint64)POP_I64(); - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - - os_mutex_lock(&memory->mem_lock); - readv = (uint64)(*(uint8*)maddr); - if (readv == expect) - *(uint8*)maddr = (uint8)(sval); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - - os_mutex_lock(&memory->mem_lock); - readv = (uint64)LOAD_U16(maddr); - if (readv == expect) - STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - - os_mutex_lock(&memory->mem_lock); - readv = (uint64)LOAD_U32(maddr); - if (readv == expect) - STORE_U32(maddr, (uint32)(sval)); - os_mutex_unlock(&memory->mem_lock); - } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(); - - os_mutex_lock(&memory->mem_lock); - readv = (uint64)LOAD_I64(maddr); - if (readv == expect) { - STORE_I64(maddr, sval); - } - os_mutex_unlock(&memory->mem_lock); - } - PUSH_I64(readv); - break; - } - - DEF_ATOMIC_RMW_OPCODE(ADD, +); - DEF_ATOMIC_RMW_OPCODE(SUB, -); - DEF_ATOMIC_RMW_OPCODE(AND, &); - DEF_ATOMIC_RMW_OPCODE(OR, |); - DEF_ATOMIC_RMW_OPCODE(XOR, ^); - /* xchg, ignore the read value, and store the given value: - readv * 0 + sval */ - DEF_ATOMIC_RMW_OPCODE(XCHG, *0 +); - } - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_F32_NEAREST) + { + DEF_OP_MATH(float32, F32, rint); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_SQRT) + { + DEF_OP_MATH(float32, F32, sqrt); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_ADD) + { + DEF_OP_NUMERIC(float32, float32, F32, +); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_SUB) + { + DEF_OP_NUMERIC(float32, float32, F32, -); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_MUL) + { + DEF_OP_NUMERIC(float32, float32, F32, *); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_DIV) + { + DEF_OP_NUMERIC(float32, float32, F32, /); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_MIN) + { + float32 a, b; + + b = POP_F32(); + a = POP_F32(); + + if (isnan(a)) + PUSH_F32(a); + else if (isnan(b)) + PUSH_F32(b); + else + PUSH_F32(wa_fmin(a, b)); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_MAX) + { + float32 a, b; + + b = POP_F32(); + a = POP_F32(); + + if (isnan(a)) + PUSH_F32(a); + else if (isnan(b)) + PUSH_F32(b); + else + PUSH_F32(wa_fmax(a, b)); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_COPYSIGN) + { + float32 a, b; + + b = POP_F32(); + a = POP_F32(); + PUSH_F32(signbit(b) ? -fabs(a) : fabs(a)); + HANDLE_OP_END(); + } + + /* numberic instructions of f64 */ + HANDLE_OP(WASM_OP_F64_ABS) + { + DEF_OP_MATH(float64, F64, fabs); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_NEG) + { + uint64 u64 = GET_I64_FROM_ADDR(frame_sp - 2); + uint64 sign_bit = u64 & (((uint64)1) << 63); + if (sign_bit) + PUT_I64_TO_ADDR(frame_sp - 2, (u64 & ~(((uint64)1) << 63))); + else + PUT_I64_TO_ADDR(frame_sp - 2, (u64 | (((uint64)1) << 63))); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_CEIL) + { + DEF_OP_MATH(float64, F64, ceil); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_FLOOR) + { + DEF_OP_MATH(float64, F64, floor); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_TRUNC) + { + DEF_OP_MATH(float64, F64, trunc); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_NEAREST) + { + DEF_OP_MATH(float64, F64, rint); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_SQRT) + { + DEF_OP_MATH(float64, F64, sqrt); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_ADD) + { + DEF_OP_NUMERIC_64(float64, float64, F64, +); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_SUB) + { + DEF_OP_NUMERIC_64(float64, float64, F64, -); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_MUL) + { + DEF_OP_NUMERIC_64(float64, float64, F64, *); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_DIV) + { + DEF_OP_NUMERIC_64(float64, float64, F64, /); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_MIN) + { + float64 a, b; + + b = POP_F64(); + a = POP_F64(); + + if (isnan(a)) + PUSH_F64(a); + else if (isnan(b)) + PUSH_F64(b); + else + PUSH_F64(wa_fmin(a, b)); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_MAX) + { + float64 a, b; + + b = POP_F64(); + a = POP_F64(); + + if (isnan(a)) + PUSH_F64(a); + else if (isnan(b)) + PUSH_F64(b); + else + PUSH_F64(wa_fmax(a, b)); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_COPYSIGN) + { + float64 a, b; + + b = POP_F64(); + a = POP_F64(); + PUSH_F64(signbit(b) ? -fabs(a) : fabs(a)); + HANDLE_OP_END(); + } + + /* conversions of i32 */ + HANDLE_OP(WASM_OP_I32_WRAP_I64) + { + int32 value = (int32)(POP_I64() & 0xFFFFFFFFLL); + PUSH_I32(value); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_TRUNC_S_F32) + { + /* We don't use INT32_MIN/INT32_MAX/UINT32_MIN/UINT32_MAX, + since float/double values of ieee754 cannot precisely + represent all int32/uint32/int64/uint64 values, e.g. + UINT32_MAX is 4294967295, but (float32)4294967295 is + 4294967296.0f, but not 4294967295.0f. */ + DEF_OP_TRUNC_F32(-2147483904.0f, 2147483648.0f, true, true); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_TRUNC_U_F32) + { + DEF_OP_TRUNC_F32(-1.0f, 4294967296.0f, true, false); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_TRUNC_S_F64) + { + DEF_OP_TRUNC_F64(-2147483649.0, 2147483648.0, true, true); + /* frame_sp can't be moved in trunc function, we need to + manually adjust it if src and dst op's cell num is + different */ + frame_sp--; + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_TRUNC_U_F64) + { + DEF_OP_TRUNC_F64(-1.0, 4294967296.0, true, false); + frame_sp--; + HANDLE_OP_END(); + } + + /* conversions of i64 */ + HANDLE_OP(WASM_OP_I64_EXTEND_S_I32) + { + DEF_OP_CONVERT(int64, I64, int32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_EXTEND_U_I32) + { + DEF_OP_CONVERT(int64, I64, uint32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_TRUNC_S_F32) + { + DEF_OP_TRUNC_F32(-9223373136366403584.0f, + 9223372036854775808.0f, false, true); + frame_sp++; + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_TRUNC_U_F32) + { + DEF_OP_TRUNC_F32(-1.0f, 18446744073709551616.0f, false, false); + frame_sp++; + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_TRUNC_S_F64) + { + DEF_OP_TRUNC_F64(-9223372036854777856.0, 9223372036854775808.0, + false, true); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_TRUNC_U_F64) + { + DEF_OP_TRUNC_F64(-1.0, 18446744073709551616.0, false, false); + HANDLE_OP_END(); + } + + /* conversions of f32 */ + HANDLE_OP(WASM_OP_F32_CONVERT_S_I32) + { + DEF_OP_CONVERT(float32, F32, int32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_CONVERT_U_I32) + { + DEF_OP_CONVERT(float32, F32, uint32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_CONVERT_S_I64) + { + DEF_OP_CONVERT(float32, F32, int64, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_CONVERT_U_I64) + { + DEF_OP_CONVERT(float32, F32, uint64, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_DEMOTE_F64) + { + DEF_OP_CONVERT(float32, F32, float64, F64); + HANDLE_OP_END(); + } + + /* conversions of f64 */ + HANDLE_OP(WASM_OP_F64_CONVERT_S_I32) + { + DEF_OP_CONVERT(float64, F64, int32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_CONVERT_U_I32) + { + DEF_OP_CONVERT(float64, F64, uint32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_CONVERT_S_I64) + { + DEF_OP_CONVERT(float64, F64, int64, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_CONVERT_U_I64) + { + DEF_OP_CONVERT(float64, F64, uint64, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_PROMOTE_F32) + { + DEF_OP_CONVERT(float64, F64, float32, F32); + HANDLE_OP_END(); + } + + /* reinterpretations */ + HANDLE_OP(WASM_OP_I32_REINTERPRET_F32) + HANDLE_OP(WASM_OP_I64_REINTERPRET_F64) + HANDLE_OP(WASM_OP_F32_REINTERPRET_I32) + HANDLE_OP(WASM_OP_F64_REINTERPRET_I64) { HANDLE_OP_END(); } + + HANDLE_OP(WASM_OP_I32_EXTEND8_S) + { + DEF_OP_CONVERT(int32, I32, int8, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_EXTEND16_S) + { + DEF_OP_CONVERT(int32, I32, int16, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_EXTEND8_S) + { + DEF_OP_CONVERT(int64, I64, int8, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_EXTEND16_S) + { + DEF_OP_CONVERT(int64, I64, int16, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_EXTEND32_S) + { + DEF_OP_CONVERT(int64, I64, int32, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_MISC_PREFIX) + { + uint32 opcode1; + + read_leb_uint32(frame_ip, frame_ip_end, opcode1); + opcode = (uint8)opcode1; + + switch (opcode) { + case WASM_OP_I32_TRUNC_SAT_S_F32: + DEF_OP_TRUNC_SAT_F32(-2147483904.0f, 2147483648.0f, + true, true); + break; + case WASM_OP_I32_TRUNC_SAT_U_F32: + DEF_OP_TRUNC_SAT_F32(-1.0f, 4294967296.0f, true, false); + break; + case WASM_OP_I32_TRUNC_SAT_S_F64: + DEF_OP_TRUNC_SAT_F64(-2147483649.0, 2147483648.0, true, + true); + frame_sp--; + break; + case WASM_OP_I32_TRUNC_SAT_U_F64: + DEF_OP_TRUNC_SAT_F64(-1.0, 4294967296.0, true, false); + frame_sp--; + break; + case WASM_OP_I64_TRUNC_SAT_S_F32: + DEF_OP_TRUNC_SAT_F32(-9223373136366403584.0f, + 9223372036854775808.0f, false, + true); + frame_sp++; + break; + case WASM_OP_I64_TRUNC_SAT_U_F32: + DEF_OP_TRUNC_SAT_F32(-1.0f, 18446744073709551616.0f, + false, false); + frame_sp++; + break; + case WASM_OP_I64_TRUNC_SAT_S_F64: + DEF_OP_TRUNC_SAT_F64(-9223372036854777856.0, + 9223372036854775808.0, false, + true); + break; + case WASM_OP_I64_TRUNC_SAT_U_F64: + DEF_OP_TRUNC_SAT_F64(-1.0f, 18446744073709551616.0, + false, false); + break; +#if WASM_ENABLE_BULK_MEMORY != 0 + case WASM_OP_MEMORY_INIT: + { + uint32 addr, segment; + uint64 bytes, offset, seg_len; + uint8 *data; + + read_leb_uint32(frame_ip, frame_ip_end, segment); + /* skip memory index */ + frame_ip++; + + bytes = (uint64)(uint32)POP_I32(); + offset = (uint64)(uint32)POP_I32(); + addr = (uint32)POP_I32(); + + CHECK_BULK_MEMORY_OVERFLOW(addr, bytes, maddr); + + seg_len = (uint64)module->module->data_segments[segment] + ->data_length; + data = module->module->data_segments[segment]->data; + if (offset + bytes > seg_len) + goto out_of_bounds; + + bh_memcpy_s(maddr, linear_mem_size - addr, + data + offset, (uint32)bytes); + break; + } + case WASM_OP_DATA_DROP: + { + uint32 segment; + + read_leb_uint32(frame_ip, frame_ip_end, segment); + module->module->data_segments[segment]->data_length = 0; + + break; + } + case WASM_OP_MEMORY_COPY: + { + uint32 dst, src, len; + uint8 *mdst, *msrc; + + frame_ip += 2; + + len = POP_I32(); + src = POP_I32(); + dst = POP_I32(); + + CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc); + CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); + + /* allowing the destination and source to overlap */ + bh_memmove_s(mdst, linear_mem_size - dst, msrc, len); + + break; + } + case WASM_OP_MEMORY_FILL: + { + uint32 dst, len; + uint8 val, *mdst; + frame_ip++; + + len = POP_I32(); + val = POP_I32(); + dst = POP_I32(); + + CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); + + memset(mdst, val, len); + + break; + } +#endif /* WASM_ENABLE_BULK_MEMORY */ +#if WASM_ENABLE_REF_TYPES != 0 + case WASM_OP_TABLE_INIT: + { + uint32 tbl_idx, elem_idx; + uint64 n, s, d; + WASMTableInstance *tbl_inst; + + read_leb_uint32(frame_ip, frame_ip_end, elem_idx); + bh_assert(elem_idx < module->module->table_seg_count); + + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + bh_assert(tbl_idx < module->module->table_count); + + tbl_inst = wasm_get_table_inst(module, tbl_idx); + + n = (uint32)POP_I32(); + s = (uint32)POP_I32(); + d = (uint32)POP_I32(); + + /* TODO: what if the element is not passive? */ + + if (!n) { + break; + } + + if (n + s > module->module->table_segments[elem_idx] + .function_count + || d + n > tbl_inst->cur_size) { + wasm_set_exception(module, + "out of bounds table access"); + goto got_exception; + } + + if (module->module->table_segments[elem_idx] + .is_dropped) { + wasm_set_exception(module, + "out of bounds table access"); + goto got_exception; + } + + if (!wasm_elem_is_passive( + module->module->table_segments[elem_idx] + .mode)) { + wasm_set_exception(module, + "out of bounds table access"); + goto got_exception; + } + + bh_memcpy_s( + (uint8 *)(tbl_inst) + + offsetof(WASMTableInstance, base_addr) + + d * sizeof(uint32), + (uint32)((tbl_inst->cur_size - d) * sizeof(uint32)), + module->module->table_segments[elem_idx] + .func_indexes + + s, + (uint32)(n * sizeof(uint32))); + + break; + } + case WASM_OP_ELEM_DROP: + { + uint32 elem_idx; + read_leb_uint32(frame_ip, frame_ip_end, elem_idx); + bh_assert(elem_idx < module->module->table_seg_count); + + module->module->table_segments[elem_idx].is_dropped = + true; + break; + } + case WASM_OP_TABLE_COPY: + { + uint32 src_tbl_idx, dst_tbl_idx; + uint64 n, s, d; + WASMTableInstance *src_tbl_inst, *dst_tbl_inst; + + read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx); + bh_assert(dst_tbl_idx < module->table_count); + + dst_tbl_inst = wasm_get_table_inst(module, dst_tbl_idx); + + read_leb_uint32(frame_ip, frame_ip_end, src_tbl_idx); + bh_assert(src_tbl_idx < module->table_count); + + src_tbl_inst = wasm_get_table_inst(module, src_tbl_idx); + + n = (uint32)POP_I32(); + s = (uint32)POP_I32(); + d = (uint32)POP_I32(); + + if (s + n > dst_tbl_inst->cur_size + || d + n > src_tbl_inst->cur_size) { + wasm_set_exception(module, + "out of bounds table access"); + goto got_exception; + } + + /* if s >= d, copy from front to back */ + /* if s < d, copy from back to front */ + /* merge all together */ + bh_memmove_s( + (uint8 *)(dst_tbl_inst) + + offsetof(WASMTableInstance, base_addr) + + d * sizeof(uint32), + (uint32)((dst_tbl_inst->cur_size - d) + * sizeof(uint32)), + (uint8 *)(src_tbl_inst) + + offsetof(WASMTableInstance, base_addr) + + s * sizeof(uint32), + (uint32)(n * sizeof(uint32))); + break; + } + case WASM_OP_TABLE_GROW: + { + uint32 tbl_idx, n, init_val, orig_tbl_sz; + WASMTableInstance *tbl_inst; + + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + bh_assert(tbl_idx < module->table_count); + + tbl_inst = wasm_get_table_inst(module, tbl_idx); + + orig_tbl_sz = tbl_inst->cur_size; + + n = POP_I32(); + init_val = POP_I32(); + + if (!wasm_enlarge_table(module, tbl_idx, n, init_val)) { + PUSH_I32(-1); + } + else { + PUSH_I32(orig_tbl_sz); + } + break; + } + case WASM_OP_TABLE_SIZE: + { + uint32 tbl_idx; + WASMTableInstance *tbl_inst; + + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + bh_assert(tbl_idx < module->table_count); + + tbl_inst = wasm_get_table_inst(module, tbl_idx); + + PUSH_I32(tbl_inst->cur_size); + break; + } + case WASM_OP_TABLE_FILL: + { + uint32 tbl_idx, n, val, i; + WASMTableInstance *tbl_inst; + + read_leb_uint32(frame_ip, frame_ip_end, tbl_idx); + bh_assert(tbl_idx < module->table_count); + + tbl_inst = wasm_get_table_inst(module, tbl_idx); + + n = POP_I32(); + val = POP_I32(); + i = POP_I32(); + + /* TODO: what if the element is not passive? */ + /* TODO: what if the element is dropped? */ + + if (i + n > tbl_inst->cur_size) { + /* TODO: verify warning content */ + wasm_set_exception(module, + "out of bounds table access"); + goto got_exception; + } + + for (; n != 0; i++, n--) { + ((uint32 *)(tbl_inst->base_addr))[i] = val; + } + + break; + } +#endif /* WASM_ENABLE_REF_TYPES */ + default: + wasm_set_exception(module, "unsupported opcode"); + goto got_exception; + } + HANDLE_OP_END(); + } + +#if WASM_ENABLE_SHARED_MEMORY != 0 + HANDLE_OP(WASM_OP_ATOMIC_PREFIX) + { + uint32 offset, align, addr; + + opcode = *frame_ip++; + + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + switch (opcode) { + case WASM_OP_ATOMIC_NOTIFY: + { + uint32 count, ret; + + count = POP_I32(); + addr = POP_I32(); + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + + ret = wasm_runtime_atomic_notify( + (WASMModuleInstanceCommon *)module, maddr, count); + bh_assert((int32)ret >= 0); + + PUSH_I32(ret); + break; + } + case WASM_OP_ATOMIC_WAIT32: + { + uint64 timeout; + uint32 expect, addr, ret; + + timeout = POP_I64(); + expect = POP_I32(); + addr = POP_I32(); + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + + ret = wasm_runtime_atomic_wait( + (WASMModuleInstanceCommon *)module, maddr, + (uint64)expect, timeout, false); + if (ret == (uint32)-1) + goto got_exception; + + PUSH_I32(ret); + break; + } + case WASM_OP_ATOMIC_WAIT64: + { + uint64 timeout, expect; + uint32 ret; + + timeout = POP_I64(); + expect = POP_I64(); + addr = POP_I32(); + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + + ret = wasm_runtime_atomic_wait( + (WASMModuleInstanceCommon *)module, maddr, expect, + timeout, true); + if (ret == (uint32)-1) + goto got_exception; + + PUSH_I32(ret); + break; + } + + case WASM_OP_ATOMIC_I32_LOAD: + case WASM_OP_ATOMIC_I32_LOAD8_U: + case WASM_OP_ATOMIC_I32_LOAD16_U: + { + uint32 readv; + + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + readv = (uint32)(*(uint8 *)maddr); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + readv = (uint32)LOAD_U16(maddr); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + readv = LOAD_I32(maddr); + os_mutex_unlock(&memory->mem_lock); + } + + PUSH_I32(readv); + break; + } + + case WASM_OP_ATOMIC_I64_LOAD: + case WASM_OP_ATOMIC_I64_LOAD8_U: + case WASM_OP_ATOMIC_I64_LOAD16_U: + case WASM_OP_ATOMIC_I64_LOAD32_U: + { + uint64 readv; + + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + readv = (uint64)(*(uint8 *)maddr); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + readv = (uint64)LOAD_U16(maddr); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + readv = (uint64)LOAD_U32(maddr); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + readv = LOAD_I64(maddr); + os_mutex_unlock(&memory->mem_lock); + } + + PUSH_I64(readv); + break; + } + + case WASM_OP_ATOMIC_I32_STORE: + case WASM_OP_ATOMIC_I32_STORE8: + case WASM_OP_ATOMIC_I32_STORE16: + { + uint32 sval; + + sval = (uint32)POP_I32(); + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_I32_STORE8) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + *(uint8 *)maddr = (uint8)sval; + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + STORE_U16(maddr, (uint16)sval); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + STORE_U32(maddr, frame_sp[1]); + os_mutex_unlock(&memory->mem_lock); + } + break; + } + + case WASM_OP_ATOMIC_I64_STORE: + case WASM_OP_ATOMIC_I64_STORE8: + case WASM_OP_ATOMIC_I64_STORE16: + case WASM_OP_ATOMIC_I64_STORE32: + { + uint64 sval; + + sval = (uint64)POP_I64(); + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_I64_STORE8) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + *(uint8 *)maddr = (uint8)sval; + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I64_STORE16) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + STORE_U16(maddr, (uint16)sval); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + STORE_U32(maddr, (uint32)sval); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + os_mutex_lock(&memory->mem_lock); + STORE_U32(maddr, frame_sp[1]); + STORE_U32(maddr + 4, frame_sp[2]); + os_mutex_unlock(&memory->mem_lock); + } + break; + } + + case WASM_OP_ATOMIC_RMW_I32_CMPXCHG: + case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U: + case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U: + { + uint32 readv, sval, expect; + + sval = POP_I32(); + expect = POP_I32(); + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + + os_mutex_lock(&memory->mem_lock); + readv = (uint32)(*(uint8 *)maddr); + if (readv == expect) + *(uint8 *)maddr = (uint8)(sval); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + + os_mutex_lock(&memory->mem_lock); + readv = (uint32)LOAD_U16(maddr); + if (readv == expect) + STORE_U16(maddr, (uint16)(sval)); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + + os_mutex_lock(&memory->mem_lock); + readv = LOAD_I32(maddr); + if (readv == expect) + STORE_U32(maddr, sval); + os_mutex_unlock(&memory->mem_lock); + } + PUSH_I32(readv); + break; + } + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG: + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U: + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U: + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U: + { + uint64 readv, sval, expect; + + sval = (uint64)POP_I64(); + expect = (uint64)POP_I64(); + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + + os_mutex_lock(&memory->mem_lock); + readv = (uint64)(*(uint8 *)maddr); + if (readv == expect) + *(uint8 *)maddr = (uint8)(sval); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + + os_mutex_lock(&memory->mem_lock); + readv = (uint64)LOAD_U16(maddr); + if (readv == expect) + STORE_U16(maddr, (uint16)(sval)); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + + os_mutex_lock(&memory->mem_lock); + readv = (uint64)LOAD_U32(maddr); + if (readv == expect) + STORE_U32(maddr, (uint32)(sval)); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(); + + os_mutex_lock(&memory->mem_lock); + readv = (uint64)LOAD_I64(maddr); + if (readv == expect) { + STORE_I64(maddr, sval); + } + os_mutex_unlock(&memory->mem_lock); + } + PUSH_I64(readv); + break; + } + + DEF_ATOMIC_RMW_OPCODE(ADD, +); + DEF_ATOMIC_RMW_OPCODE(SUB, -); + DEF_ATOMIC_RMW_OPCODE(AND, &); + DEF_ATOMIC_RMW_OPCODE(OR, |); + DEF_ATOMIC_RMW_OPCODE(XOR, ^); + /* xchg, ignore the read value, and store the given + value: readv * 0 + sval */ + DEF_ATOMIC_RMW_OPCODE(XCHG, *0 +); + } + + HANDLE_OP_END(); + } #endif - HANDLE_OP (WASM_OP_IMPDEP): - frame = prev_frame; - frame_ip = frame->ip; - frame_sp = frame->sp; - frame_csp = frame->csp; - goto call_func_from_entry; + HANDLE_OP(WASM_OP_IMPDEP) + { + frame = prev_frame; + frame_ip = frame->ip; + frame_sp = frame->sp; + frame_csp = frame->csp; + goto call_func_from_entry; + } +#if WASM_ENABLE_DEBUG_INTERP != 0 + HANDLE_OP(DEBUG_OP_BREAK) + { + wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP); + exec_env->suspend_flags.flags |= 2; + frame_ip--; + SYNC_ALL_TO_FRAME(); + CHECK_SUSPEND_FLAGS(); + HANDLE_OP_END(); + } +#endif #if WASM_ENABLE_LABELS_AS_VALUES == 0 - default: - wasm_set_exception(module, "unsupported opcode"); - goto got_exception; - } + default: + wasm_set_exception(module, "unsupported opcode"); + goto got_exception; + } #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): + 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): - HANDLE_OP (WASM_OP_RETURN_CALL_INDIRECT): + HANDLE_OP(WASM_OP_RETURN_CALL) + HANDLE_OP(WASM_OP_RETURN_CALL_INDIRECT) #endif #if WASM_ENABLE_SHARED_MEMORY == 0 - HANDLE_OP (WASM_OP_ATOMIC_PREFIX): + HANDLE_OP(WASM_OP_ATOMIC_PREFIX) #endif #if WASM_ENABLE_REF_TYPES == 0 - HANDLE_OP (WASM_OP_SELECT_T): - HANDLE_OP (WASM_OP_TABLE_GET): - HANDLE_OP (WASM_OP_TABLE_SET): - HANDLE_OP (WASM_OP_REF_NULL): - HANDLE_OP (WASM_OP_REF_IS_NULL): - HANDLE_OP (WASM_OP_REF_FUNC): + HANDLE_OP(WASM_OP_SELECT_T) + HANDLE_OP(WASM_OP_TABLE_GET) + HANDLE_OP(WASM_OP_TABLE_SET) + HANDLE_OP(WASM_OP_REF_NULL) + HANDLE_OP(WASM_OP_REF_IS_NULL) + HANDLE_OP(WASM_OP_REF_FUNC) #endif - HANDLE_OP (WASM_OP_UNUSED_0x14): - 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): - HANDLE_OP (EXT_OP_TEE_LOCAL_FAST_I64): - HANDLE_OP (EXT_OP_COPY_STACK_TOP): - HANDLE_OP (EXT_OP_COPY_STACK_TOP_I64): - HANDLE_OP (EXT_OP_COPY_STACK_VALUES): - { - wasm_set_exception(module, "unsupported opcode"); - goto got_exception; - } + HANDLE_OP(WASM_OP_UNUSED_0x14) + 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) + HANDLE_OP(EXT_OP_TEE_LOCAL_FAST_I64) + HANDLE_OP(EXT_OP_COPY_STACK_TOP) + HANDLE_OP(EXT_OP_COPY_STACK_TOP_I64) + HANDLE_OP(EXT_OP_COPY_STACK_VALUES) + { + wasm_set_exception(module, "unsupported opcode"); + goto got_exception; + } #endif #if WASM_ENABLE_LABELS_AS_VALUES == 0 - continue; + continue; #else - FETCH_OPCODE_AND_DISPATCH (); + FETCH_OPCODE_AND_DISPATCH(); #endif #if WASM_ENABLE_TAIL_CALL != 0 - call_func_from_return_call: - POP(cur_func->param_cell_num); - word_copy(frame->lp, frame_sp, cur_func->param_cell_num); - FREE_FRAME(exec_env, frame); - wasm_exec_env_set_cur_frame(exec_env, - (WASMRuntimeFrame *)prev_frame); - goto call_func_from_entry; + call_func_from_return_call: + { + POP(cur_func->param_cell_num); + word_copy(frame->lp, frame_sp, cur_func->param_cell_num); + FREE_FRAME(exec_env, frame); + wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame); + goto call_func_from_entry; + } #endif - call_func_from_interp: - /* Only do the copy when it's called from interpreter. */ + call_func_from_interp: { - WASMInterpFrame *outs_area = wasm_exec_env_wasm_stack_top(exec_env); - POP(cur_func->param_cell_num); - SYNC_ALL_TO_FRAME(); - word_copy(outs_area->lp, frame_sp, cur_func->param_cell_num); - prev_frame = frame; + /* Only do the copy when it's called from interpreter. */ + WASMInterpFrame *outs_area = wasm_exec_env_wasm_stack_top(exec_env); + POP(cur_func->param_cell_num); + SYNC_ALL_TO_FRAME(); + word_copy(outs_area->lp, frame_sp, cur_func->param_cell_num); + prev_frame = frame; } - call_func_from_entry: + call_func_from_entry: { - if (cur_func->is_import_func) { + if (cur_func->is_import_func) { #if WASM_ENABLE_MULTI_MODULE != 0 - if (cur_func->import_func_inst) { - wasm_interp_call_func_import(module, exec_env, cur_func, - prev_frame); - } - else + if (cur_func->import_func_inst) { + wasm_interp_call_func_import(module, exec_env, cur_func, + prev_frame); + } + else #endif - { - wasm_interp_call_func_native(module, exec_env, cur_func, - prev_frame); - } - - prev_frame = frame->prev_frame; - cur_func = frame->function; - UPDATE_ALL_FROM_FRAME(); - - /* update memory instance ptr and memory size */ - memory = module->default_memory; - if (memory) - linear_mem_size = num_bytes_per_page * memory->cur_page_count; - if (wasm_get_exception(module)) - goto got_exception; - } - else { - WASMFunction *cur_wasm_func = cur_func->u.func; - WASMType *func_type; - - func_type = cur_wasm_func->func_type; - - all_cell_num = (uint64)cur_func->param_cell_num - + (uint64)cur_func->local_cell_num - + (uint64)cur_wasm_func->max_stack_cell_num - + ((uint64)cur_wasm_func->max_block_num) * sizeof(WASMBranchBlock) / 4; - if (all_cell_num >= UINT32_MAX) { - wasm_set_exception(module, "wasm operand stack overflow"); - goto got_exception; - } + { + wasm_interp_call_func_native(module, exec_env, cur_func, + prev_frame); + } + + prev_frame = frame->prev_frame; + cur_func = frame->function; + UPDATE_ALL_FROM_FRAME(); - frame_size = wasm_interp_interp_frame_size((uint32)all_cell_num); - if (!(frame = ALLOC_FRAME(exec_env, frame_size, prev_frame))) { - frame = prev_frame; - goto got_exception; + /* update memory instance ptr and memory size */ + memory = module->default_memory; + if (memory) + linear_mem_size = num_bytes_per_page * memory->cur_page_count; + if (wasm_get_exception(module)) + goto got_exception; } + else { + WASMFunction *cur_wasm_func = cur_func->u.func; + WASMType *func_type; + + func_type = cur_wasm_func->func_type; + + all_cell_num = (uint64)cur_func->param_cell_num + + (uint64)cur_func->local_cell_num + + (uint64)cur_wasm_func->max_stack_cell_num + + ((uint64)cur_wasm_func->max_block_num) + * sizeof(WASMBranchBlock) / 4; + if (all_cell_num >= UINT32_MAX) { + wasm_set_exception(module, "wasm operand stack overflow"); + goto got_exception; + } + + frame_size = wasm_interp_interp_frame_size((uint32)all_cell_num); + if (!(frame = ALLOC_FRAME(exec_env, frame_size, prev_frame))) { + frame = prev_frame; + goto got_exception; + } - /* Initialize the interpreter context. */ - frame->function = cur_func; - frame_ip = wasm_get_func_code(cur_func); - frame_ip_end = wasm_get_func_code_end(cur_func); - frame_lp = frame->lp; + /* Initialize the interpreter context. */ + frame->function = cur_func; + frame_ip = wasm_get_func_code(cur_func); + frame_ip_end = wasm_get_func_code_end(cur_func); + frame_lp = frame->lp; - frame_sp = frame->sp_bottom = frame_lp + cur_func->param_cell_num - + cur_func->local_cell_num; - frame->sp_boundary = frame->sp_bottom + cur_wasm_func->max_stack_cell_num; + frame_sp = frame->sp_bottom = + frame_lp + cur_func->param_cell_num + cur_func->local_cell_num; + frame->sp_boundary = + frame->sp_bottom + cur_wasm_func->max_stack_cell_num; - frame_csp = frame->csp_bottom = (WASMBranchBlock*)frame->sp_boundary; - frame->csp_boundary = frame->csp_bottom + cur_wasm_func->max_block_num; + frame_csp = frame->csp_bottom = + (WASMBranchBlock *)frame->sp_boundary; + frame->csp_boundary = + frame->csp_bottom + cur_wasm_func->max_block_num; - /* Initialize the local varialbes */ - memset(frame_lp + cur_func->param_cell_num, 0, - (uint32)(cur_func->local_cell_num * 4)); + /* Initialize the local varialbes */ + memset(frame_lp + cur_func->param_cell_num, 0, + (uint32)(cur_func->local_cell_num * 4)); - /* Push function block as first block */ - cell_num = func_type->ret_cell_num; - PUSH_CSP(LABEL_TYPE_FUNCTION, cell_num, frame_ip_end - 1); + /* Push function block as first block */ + cell_num = func_type->ret_cell_num; + PUSH_CSP(LABEL_TYPE_FUNCTION, cell_num, frame_ip_end - 1); - wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)frame); - } - HANDLE_OP_END (); + wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)frame); +#if WASM_ENABLE_THREAD_MGR != 0 + CHECK_SUSPEND_FLAGS(); +#endif + } + HANDLE_OP_END(); } - return_func: + return_func: { - FREE_FRAME(exec_env, frame); - wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)prev_frame); + FREE_FRAME(exec_env, frame); + wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame); - if (!prev_frame->ip) - /* Called from native. */ - return; + if (!prev_frame->ip) + /* Called from native. */ + return; - RECOVER_CONTEXT(prev_frame); - HANDLE_OP_END (); + RECOVER_CONTEXT(prev_frame); + HANDLE_OP_END(); } #if WASM_ENABLE_SHARED_MEMORY != 0 - unaligned_atomic: - wasm_set_exception(module, "unaligned atomic"); - goto got_exception; + unaligned_atomic: + wasm_set_exception(module, "unaligned atomic"); + goto got_exception; #endif - out_of_bounds: - wasm_set_exception(module, "out of bounds memory access"); + out_of_bounds: + wasm_set_exception(module, "out of bounds memory access"); - got_exception: - return; + got_exception: + SYNC_ALL_TO_FRAME(); + return; #if WASM_ENABLE_LABELS_AS_VALUES == 0 - } + } #else - FETCH_OPCODE_AND_DISPATCH (); + FETCH_OPCODE_AND_DISPATCH(); #endif } void -wasm_interp_call_wasm(WASMModuleInstance *module_inst, - WASMExecEnv *exec_env, - WASMFunctionInstance *function, - uint32 argc, uint32 argv[]) +wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, + WASMFunctionInstance *function, uint32 argc, + uint32 argv[]) { WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env); WASMInterpFrame *frame, *outs_area; /* Allocate sufficient cells for all kinds of return values. */ - unsigned all_cell_num = function->ret_cell_num > 2 ? - function->ret_cell_num : 2, i; + unsigned all_cell_num = + function->ret_cell_num > 2 ? function->ret_cell_num : 2, + i; /* This frame won't be used by JITed code, so only allocate interp frame here. */ unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num); if (argc != function->param_cell_num) { char buf[128]; - snprintf(buf, sizeof(buf), - "invalid argument count %d, expected %d", + snprintf(buf, sizeof(buf), "invalid argument count %d, expected %d", argc, function->param_cell_num); wasm_set_exception(module_inst, buf); return; } - if ((uint8*)&prev_frame < exec_env->native_stack_boundary) { - wasm_set_exception((WASMModuleInstance*)exec_env->module_inst, + if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) { + wasm_set_exception((WASMModuleInstance *)exec_env->module_inst, "native stack overflow"); return; } - if (!(frame = ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame*)prev_frame))) + if (!(frame = + ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame *)prev_frame))) return; outs_area = wasm_exec_env_wasm_stack_top(exec_env); @@ -3428,15 +3740,15 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, if (function->is_import_func) { #if WASM_ENABLE_MULTI_MODULE != 0 if (function->import_module_inst) { - wasm_interp_call_func_import(module_inst, exec_env, - function, frame); + wasm_interp_call_func_import(module_inst, exec_env, function, + frame); } else #endif { /* it is a native function */ - wasm_interp_call_func_native(module_inst, exec_env, - function, frame); + wasm_interp_call_func_native(module_inst, exec_env, function, + frame); } } else { diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 7c714ee96a..b0e29e4564 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -18,29 +18,33 @@ typedef int64 CellType_I64; typedef float32 CellType_F32; typedef float64 CellType_F64; -#define CHECK_MEMORY_OVERFLOW(bytes) do { \ - uint64 offset1 = (uint64)offset + (uint64)addr; \ - if (offset1 + bytes <= (uint64)linear_mem_size) \ - /* If offset1 is in valid range, maddr must also be in valid range,\ - no need to check it again. */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ - } while (0) - -#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) do { \ - uint64 offset1 = (uint32)(start); \ - if (offset1 + bytes <= linear_mem_size) \ - /* App heap space is not valid space for bulk memory operation */ \ - maddr = memory->memory_data + offset1; \ - else \ - goto out_of_bounds; \ - } while (0) - -#define CHECK_ATOMIC_MEMORY_ACCESS(align) do { \ - if (((uintptr_t)maddr & (align - 1)) != 0) \ - goto unaligned_atomic; \ - } while (0) +#define CHECK_MEMORY_OVERFLOW(bytes) \ + do { \ + uint64 offset1 = (uint64)offset + (uint64)addr; \ + if (offset1 + bytes <= (uint64)linear_mem_size) \ + /* If offset1 is in valid range, maddr must also \ + be in valid range, no need to check it again. */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ + } while (0) + +#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \ + do { \ + uint64 offset1 = (uint32)(start); \ + if (offset1 + bytes <= linear_mem_size) \ + /* App heap space is not valid space for \ + bulk memory operation */ \ + maddr = memory->memory_data + offset1; \ + else \ + goto out_of_bounds; \ + } while (0) + +#define CHECK_ATOMIC_MEMORY_ACCESS(align) \ + do { \ + if (((uintptr_t)maddr & (align - 1)) != 0) \ + goto unaligned_atomic; \ + } while (0) static inline uint32 rotl32(uint32 n, uint32 c) @@ -48,7 +52,7 @@ rotl32(uint32 n, uint32 c) const uint32 mask = (31); c = c % 32; c &= mask; - return (n<>( (-c)&mask )); + return (n << c) | (n >> ((0 - c) & mask)); } static inline uint32 @@ -57,7 +61,7 @@ rotr32(uint32 n, uint32 c) const uint32 mask = (31); c = c % 32; c &= mask; - return (n>>c) | (n<<( (-c)&mask )); + return (n >> c) | (n << ((0 - c) & mask)); } static inline uint64 @@ -66,7 +70,7 @@ rotl64(uint64 n, uint64 c) const uint64 mask = (63); c = c % 64; c &= mask; - return (n<>( (-c)&mask )); + return (n << c) | (n >> ((0 - c) & mask)); } static inline uint64 @@ -75,14 +79,14 @@ rotr64(uint64 n, uint64 c) const uint64 mask = (63); c = c % 64; c &= mask; - return (n>>c) | (n<<( (-c)&mask )); + return (n >> c) | (n << ((0 - c) & mask)); } static inline double wa_fmax(double a, double b) { double c = fmax(a, b); - if (c==0 && a==b) + if (c == 0 && a == b) return signbit(a) ? b : a; return c; } @@ -91,7 +95,7 @@ static inline double wa_fmin(double a, double b) { double c = fmin(a, b); - if (c==0 && a==b) + if (c == 0 && a == b) return signbit(a) ? a : b; return c; } @@ -171,41 +175,48 @@ popcount64(uint64 u) } #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 -#define LOAD_U32_WITH_2U16S(addr) (*(uint32*)(addr)) -#define LOAD_PTR(addr) (*(void**)(addr)) +#define LOAD_U32_WITH_2U16S(addr) (*(uint32 *)(addr)) +#define LOAD_PTR(addr) (*(void **)(addr)) #else /* else of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ static inline uint32 LOAD_U32_WITH_2U16S(void *addr) { - union { uint32 val; uint16 u16[2]; } u; + union { + uint32 val; + uint16 u16[2]; + } u; bh_assert(((uintptr_t)addr & 1) == 0); - u.u16[0] = ((uint16*)addr)[0]; - u.u16[1] = ((uint16*)addr)[1]; + u.u16[0] = ((uint16 *)addr)[0]; + u.u16[1] = ((uint16 *)addr)[1]; return u.val; } #if UINTPTR_MAX == UINT32_MAX -#define LOAD_PTR(addr) ((void*)LOAD_U32_WITH_2U16S(addr)) +#define LOAD_PTR(addr) ((void *)LOAD_U32_WITH_2U16S(addr)) #elif UINTPTR_MAX == UINT64_MAX static inline void * LOAD_PTR(void *addr) { uintptr_t addr1 = (uintptr_t)addr; - union { void *val; uint32 u32[2]; uint16 u16[4]; } u; + union { + void *val; + uint32 u32[2]; + uint16 u16[4]; + } u; bh_assert(((uintptr_t)addr & 1) == 0); if ((addr1 & (uintptr_t)7) == 0) - return *(void**)addr; + return *(void **)addr; if ((addr1 & (uintptr_t)3) == 0) { - u.u32[0] = ((uint32*)addr)[0]; - u.u32[1] = ((uint32*)addr)[1]; + u.u32[0] = ((uint32 *)addr)[0]; + u.u32[1] = ((uint32 *)addr)[1]; } else { - u.u16[0] = ((uint16*)addr)[0]; - u.u16[1] = ((uint16*)addr)[1]; - u.u16[2] = ((uint16*)addr)[2]; - u.u16[3] = ((uint16*)addr)[3]; + u.u16[0] = ((uint16 *)addr)[0]; + u.u16[1] = ((uint16 *)addr)[1]; + u.u16[2] = ((uint16 *)addr)[2]; + u.u16[3] = ((uint16 *)addr)[3]; } return u.val; } @@ -215,270 +226,289 @@ LOAD_PTR(void *addr) #define read_uint32(p) \ (p += sizeof(uint32), LOAD_U32_WITH_2U16S(p - sizeof(uint32))) -#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() do { \ - uint32 param_count = cur_func->param_count; \ - local_idx = read_uint32(frame_ip); \ - bh_assert(local_idx < param_count + cur_func->local_count); \ - local_offset = cur_func->local_offsets[local_idx]; \ - if (local_idx < param_count) \ - local_type = cur_func->param_types[local_idx]; \ - else \ - local_type = cur_func->local_types[local_idx - param_count]; \ - } while (0) - -#define GET_OFFSET() (frame_ip += 2, *(int16*)(frame_ip - 2)) - -#define SET_OPERAND_I32(off, value) do { \ - *(uint32*)(frame_lp + *(int16*)(frame_ip + off)) = value; \ - } while (0) -#define SET_OPERAND_F32(off, value) do { \ - *(float32*)(frame_lp + *(int16*)(frame_ip + off)) = value; \ - } while (0) -#define SET_OPERAND_I64(off, value) do { \ - uint32 *addr_tmp = frame_lp + *(int16*)(frame_ip + off); \ - PUT_I64_TO_ADDR(addr_tmp, value); \ - } while (0) -#define SET_OPERAND_F64(off, value) do { \ - uint32 *addr_tmp = frame_lp + *(int16*)(frame_ip + off); \ - PUT_F64_TO_ADDR(addr_tmp, value); \ - } while (0) +#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() \ + do { \ + uint32 param_count = cur_func->param_count; \ + local_idx = read_uint32(frame_ip); \ + bh_assert(local_idx < param_count + cur_func->local_count); \ + local_offset = cur_func->local_offsets[local_idx]; \ + if (local_idx < param_count) \ + local_type = cur_func->param_types[local_idx]; \ + else \ + local_type = cur_func->local_types[local_idx - param_count]; \ + } while (0) + +#define GET_OFFSET() (frame_ip += 2, *(int16 *)(frame_ip - 2)) + +#define SET_OPERAND_I32(off, value) \ + do { \ + *(uint32 *)(frame_lp + *(int16 *)(frame_ip + off)) = value; \ + } while (0) +#define SET_OPERAND_F32(off, value) \ + do { \ + *(float32 *)(frame_lp + *(int16 *)(frame_ip + off)) = value; \ + } while (0) +#define SET_OPERAND_I64(off, value) \ + do { \ + uint32 *addr_tmp = frame_lp + *(int16 *)(frame_ip + off); \ + PUT_I64_TO_ADDR(addr_tmp, value); \ + } while (0) +#define SET_OPERAND_F64(off, value) \ + do { \ + uint32 *addr_tmp = frame_lp + *(int16 *)(frame_ip + off); \ + PUT_F64_TO_ADDR(addr_tmp, value); \ + } while (0) #define SET_OPERAND(op_type, off, value) SET_OPERAND_##op_type(off, value) -#define GET_OPERAND_I32(type, off) \ - *(type*)(frame_lp + *(int16*)(frame_ip + off)) -#define GET_OPERAND_F32(type, off) \ - *(type*)(frame_lp + *(int16*)(frame_ip + off)) -#define GET_OPERAND_I64(type, off) \ - (type)GET_I64_FROM_ADDR(frame_lp + *(int16*)(frame_ip + off)) -#define GET_OPERAND_F64(type, off) \ - (type)GET_F64_FROM_ADDR(frame_lp + *(int16*)(frame_ip + off)) +#define GET_OPERAND_I32(type, off) \ + *(type *)(frame_lp + *(int16 *)(frame_ip + off)) +#define GET_OPERAND_F32(type, off) \ + *(type *)(frame_lp + *(int16 *)(frame_ip + off)) +#define GET_OPERAND_I64(type, off) \ + (type) GET_I64_FROM_ADDR(frame_lp + *(int16 *)(frame_ip + off)) +#define GET_OPERAND_F64(type, off) \ + (type) GET_F64_FROM_ADDR(frame_lp + *(int16 *)(frame_ip + off)) #define GET_OPERAND(type, op_type, off) GET_OPERAND_##op_type(type, off) -#define PUSH_I32(value) do { \ - *(int32*)(frame_lp + GET_OFFSET()) = value; \ - } while (0) +#define PUSH_I32(value) \ + do { \ + *(int32 *)(frame_lp + GET_OFFSET()) = value; \ + } while (0) -#define PUSH_F32(value) do { \ - *(float32*)(frame_lp + GET_OFFSET()) = value; \ - } while (0) +#define PUSH_F32(value) \ + do { \ + *(float32 *)(frame_lp + GET_OFFSET()) = value; \ + } while (0) -#define PUSH_I64(value) do { \ - uint32 *addr_tmp = frame_lp + GET_OFFSET(); \ - PUT_I64_TO_ADDR(addr_tmp, value); \ - } while (0) +#define PUSH_I64(value) \ + do { \ + uint32 *addr_tmp = frame_lp + GET_OFFSET(); \ + PUT_I64_TO_ADDR(addr_tmp, value); \ + } while (0) -#define PUSH_F64(value) do { \ - uint32 *addr_tmp = frame_lp + GET_OFFSET(); \ - PUT_F64_TO_ADDR(addr_tmp, value); \ - } while (0) +#define PUSH_F64(value) \ + do { \ + uint32 *addr_tmp = frame_lp + GET_OFFSET(); \ + PUT_F64_TO_ADDR(addr_tmp, value); \ + } while (0) -#define POP_I32() (*(int32*)(frame_lp + GET_OFFSET())) +#define POP_I32() (*(int32 *)(frame_lp + GET_OFFSET())) -#define POP_F32() (*(float32*)(frame_lp + GET_OFFSET())) +#define POP_F32() (*(float32 *)(frame_lp + GET_OFFSET())) #define POP_I64() (GET_I64_FROM_ADDR(frame_lp + GET_OFFSET())) #define POP_F64() (GET_F64_FROM_ADDR(frame_lp + GET_OFFSET())) -#define SYNC_ALL_TO_FRAME() do { \ - frame->ip = frame_ip; \ - } while (0) +#define SYNC_ALL_TO_FRAME() \ + do { \ + frame->ip = frame_ip; \ + } while (0) -#define UPDATE_ALL_FROM_FRAME() do { \ - frame_ip = frame->ip; \ - } while (0) +#define UPDATE_ALL_FROM_FRAME() \ + do { \ + frame_ip = frame->ip; \ + } while (0) #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define UPDATE_FRAME_IP_END() (void)0 #else -#define UPDATE_FRAME_IP_END() \ - frame_ip_end = wasm_get_func_code_end(cur_func) +#define UPDATE_FRAME_IP_END() frame_ip_end = wasm_get_func_code_end(cur_func) #endif -#define RECOVER_CONTEXT(new_frame) do { \ - frame = (new_frame); \ - cur_func = frame->function; \ - prev_frame = frame->prev_frame; \ - frame_ip = frame->ip; \ - UPDATE_FRAME_IP_END(); \ - frame_lp = frame->lp; \ - } while (0) +#define RECOVER_CONTEXT(new_frame) \ + do { \ + frame = (new_frame); \ + cur_func = frame->function; \ + prev_frame = frame->prev_frame; \ + frame_ip = frame->ip; \ + UPDATE_FRAME_IP_END(); \ + frame_lp = frame->lp; \ + } while (0) #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 #define GET_OPCODE() opcode = *frame_ip++; #else -#define GET_OPCODE() opcode = *frame_ip; frame_ip += 2; +#define GET_OPCODE() \ + opcode = *frame_ip; \ + frame_ip += 2; #endif -#define DEF_OP_EQZ(ctype, src_op_type) do { \ - SET_OPERAND(I32, 2, (GET_OPERAND(ctype, src_op_type, 0) == 0)); \ - frame_ip += 4; \ - } while (0) - -#define DEF_OP_CMP(src_type, src_op_type, cond) do { \ - SET_OPERAND(I32, 4, GET_OPERAND(src_type, src_op_type, 2) cond \ - GET_OPERAND(src_type, src_op_type, 0)); \ - frame_ip += 6; \ - } while (0) - -#define DEF_OP_BIT_COUNT(src_type, src_op_type, operation) do { \ - SET_OPERAND(src_op_type, 2, (src_type)operation( \ - GET_OPERAND(src_type, src_op_type, 0))); \ - frame_ip += 4; \ - } while (0) - -#define DEF_OP_NUMERIC(src_type1, src_type2, \ - src_op_type, operation) do { \ - SET_OPERAND(src_op_type, 4, \ - GET_OPERAND(src_type1, src_op_type, 2) operation \ - GET_OPERAND(src_type2, src_op_type, 0)); \ - frame_ip += 6; \ - } while (0) - -#define DEF_OP_REINTERPRET(src_type, src_op_type) do { \ - SET_OPERAND(src_op_type, 2, \ - GET_OPERAND(src_type, src_op_type, 0)); \ - frame_ip += 4; \ - } while (0) +#define DEF_OP_EQZ(ctype, src_op_type) \ + do { \ + SET_OPERAND(I32, 2, (GET_OPERAND(ctype, src_op_type, 0) == 0)); \ + frame_ip += 4; \ + } while (0) + +#define DEF_OP_CMP(src_type, src_op_type, cond) \ + do { \ + SET_OPERAND(I32, 4, \ + GET_OPERAND(src_type, src_op_type, 2) \ + cond GET_OPERAND(src_type, src_op_type, 0)); \ + frame_ip += 6; \ + } while (0) + +#define DEF_OP_BIT_COUNT(src_type, src_op_type, operation) \ + do { \ + SET_OPERAND( \ + src_op_type, 2, \ + (src_type)operation(GET_OPERAND(src_type, src_op_type, 0))); \ + frame_ip += 4; \ + } while (0) + +#define DEF_OP_NUMERIC(src_type1, src_type2, src_op_type, operation) \ + do { \ + SET_OPERAND(src_op_type, 4, \ + GET_OPERAND(src_type1, src_op_type, 2) \ + operation GET_OPERAND(src_type2, src_op_type, 0)); \ + frame_ip += 6; \ + } while (0) + +#define DEF_OP_REINTERPRET(src_type, src_op_type) \ + do { \ + SET_OPERAND(src_op_type, 2, GET_OPERAND(src_type, src_op_type, 0)); \ + frame_ip += 4; \ + } while (0) #define DEF_OP_NUMERIC_64 DEF_OP_NUMERIC -#define DEF_OP_NUMERIC2(src_type1, src_type2, \ - src_op_type, operation) do { \ - SET_OPERAND(src_op_type, 4, \ - GET_OPERAND(src_type1, src_op_type, 2) operation \ - (GET_OPERAND(src_type2, src_op_type, 0) % 32)); \ - frame_ip += 6; \ - } while (0) - -#define DEF_OP_NUMERIC2_64(src_type1, src_type2, \ - src_op_type, operation) do { \ - SET_OPERAND(src_op_type, 4, \ - GET_OPERAND(src_type1, src_op_type, 2) operation \ - (GET_OPERAND(src_type2, src_op_type, 0) % 64)); \ - frame_ip += 6; \ - } while (0) - -#define DEF_ATOMIC_RMW_OPCODE(OP_NAME, op) \ - case WASM_OP_ATOMIC_RMW_I32_##OP_NAME: \ - case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U: \ - case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U: \ - { \ - uint32 readv, sval; \ - \ - sval = POP_I32(); \ - addr = POP_I32(); \ - \ - if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U) { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(1); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint32)(*(uint8*)maddr); \ - *(uint8*)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(2); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint32)LOAD_U16(maddr); \ - STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - else { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(4); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = LOAD_I32(maddr); \ - STORE_U32(maddr, readv op sval); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - PUSH_I32(readv); \ - break; \ - } \ - case WASM_OP_ATOMIC_RMW_I64_##OP_NAME: \ - case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U: \ - case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U: \ - case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U: \ - { \ - uint64 readv, sval; \ - \ - sval = (uint64)POP_I64(); \ - addr = POP_I32(); \ - \ - if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U) { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(1); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint64)(*(uint8*)maddr); \ - *(uint8*)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(2); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint64)LOAD_U16(maddr); \ - STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(4); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint64)LOAD_U32(maddr); \ - STORE_U32(maddr, (uint32)(readv op sval)); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - else { \ - uint64 op_result; \ - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ - CHECK_ATOMIC_MEMORY_ACCESS(8); \ - \ - os_mutex_lock(&memory->mem_lock); \ - readv = (uint64)LOAD_I64(maddr); \ - op_result = readv op sval; \ - STORE_I64(maddr, op_result); \ - os_mutex_unlock(&memory->mem_lock); \ - } \ - PUSH_I64(readv); \ - break; \ - } - -#define DEF_OP_MATH(src_type, src_op_type, method) do { \ - SET_OPERAND(src_op_type, 2, \ - method(GET_OPERAND(src_type, src_op_type, 0))); \ - frame_ip += 4; \ - } while (0) +#define DEF_OP_NUMERIC2(src_type1, src_type2, src_op_type, operation) \ + do { \ + SET_OPERAND(src_op_type, 4, \ + GET_OPERAND(src_type1, src_op_type, 2) operation( \ + GET_OPERAND(src_type2, src_op_type, 0) % 32)); \ + frame_ip += 6; \ + } while (0) + +#define DEF_OP_NUMERIC2_64(src_type1, src_type2, src_op_type, operation) \ + do { \ + SET_OPERAND(src_op_type, 4, \ + GET_OPERAND(src_type1, src_op_type, 2) operation( \ + GET_OPERAND(src_type2, src_op_type, 0) % 64)); \ + frame_ip += 6; \ + } while (0) + +#define DEF_ATOMIC_RMW_OPCODE(OP_NAME, op) \ + case WASM_OP_ATOMIC_RMW_I32_##OP_NAME: \ + case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U: \ + case WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U: \ + { \ + uint32 readv, sval; \ + \ + sval = POP_I32(); \ + addr = POP_I32(); \ + \ + if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U) { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(1); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint32)(*(uint8 *)maddr); \ + *(uint8 *)maddr = (uint8)(readv op sval); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(2); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint32)LOAD_U16(maddr); \ + STORE_U16(maddr, (uint16)(readv op sval)); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + else { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(4); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = LOAD_I32(maddr); \ + STORE_U32(maddr, readv op sval); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + PUSH_I32(readv); \ + break; \ + } \ + case WASM_OP_ATOMIC_RMW_I64_##OP_NAME: \ + case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U: \ + case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U: \ + case WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U: \ + { \ + uint64 readv, sval; \ + \ + sval = (uint64)POP_I64(); \ + addr = POP_I32(); \ + \ + if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U) { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(1); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint64)(*(uint8 *)maddr); \ + *(uint8 *)maddr = (uint8)(readv op sval); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(2); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint64)LOAD_U16(maddr); \ + STORE_U16(maddr, (uint16)(readv op sval)); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(4); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint64)LOAD_U32(maddr); \ + STORE_U32(maddr, (uint32)(readv op sval)); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + else { \ + uint64 op_result; \ + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ + CHECK_ATOMIC_MEMORY_ACCESS(8); \ + \ + os_mutex_lock(&memory->mem_lock); \ + readv = (uint64)LOAD_I64(maddr); \ + op_result = readv op sval; \ + STORE_I64(maddr, op_result); \ + os_mutex_unlock(&memory->mem_lock); \ + } \ + PUSH_I64(readv); \ + break; \ + } + +#define DEF_OP_MATH(src_type, src_op_type, method) \ + do { \ + SET_OPERAND(src_op_type, 2, \ + (src_type)method(GET_OPERAND(src_type, src_op_type, 0))); \ + frame_ip += 4; \ + } while (0) #define TRUNC_FUNCTION(func_name, src_type, dst_type, signed_type) \ -static dst_type \ -func_name(src_type src_value, src_type src_min, src_type src_max, \ - dst_type dst_min, dst_type dst_max, bool is_sign) \ -{ \ - dst_type dst_value = 0; \ - if (!isnan(src_value)) { \ - if (src_value <= src_min) \ - dst_value = dst_min; \ - else if (src_value >= src_max) \ - dst_value = dst_max; \ - else { \ - if (is_sign) \ - dst_value = (dst_type)(signed_type)src_value; \ - else \ - dst_value = (dst_type)src_value; \ - } \ - } \ - return dst_value; \ -} + static dst_type func_name(src_type src_value, src_type src_min, \ + src_type src_max, dst_type dst_min, \ + dst_type dst_max, bool is_sign) \ + { \ + dst_type dst_value = 0; \ + if (!isnan(src_value)) { \ + if (src_value <= src_min) \ + dst_value = dst_min; \ + else if (src_value >= src_max) \ + dst_value = dst_max; \ + else { \ + if (is_sign) \ + dst_value = (dst_type)(signed_type)src_value; \ + else \ + dst_value = (dst_type)src_value; \ + } \ + } \ + return dst_value; \ + } TRUNC_FUNCTION(trunc_f32_to_i32, float32, uint32, int32) TRUNC_FUNCTION(trunc_f32_to_i64, float32, uint64, int64) @@ -486,10 +516,9 @@ TRUNC_FUNCTION(trunc_f64_to_i32, float64, uint32, int32) TRUNC_FUNCTION(trunc_f64_to_i64, float64, uint64, int64) static bool -trunc_f32_to_int(WASMModuleInstance *module, - uint8 *frame_ip, uint32 *frame_lp, - float32 src_min, float32 src_max, - bool saturating, bool is_i32, bool is_sign) +trunc_f32_to_int(WASMModuleInstance *module, uint8 *frame_ip, uint32 *frame_lp, + float32 src_min, float32 src_max, bool saturating, bool is_i32, + bool is_sign) { float32 src_value = GET_OPERAND(float32, F32, 0); uint64 dst_value_i64; @@ -509,25 +538,24 @@ trunc_f32_to_int(WASMModuleInstance *module, if (is_i32) { uint32 dst_min = is_sign ? INT32_MIN : 0; uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX; - dst_value_i32 = trunc_f32_to_i32(src_value, src_min, src_max, - dst_min, dst_max, is_sign); + dst_value_i32 = trunc_f32_to_i32(src_value, src_min, src_max, dst_min, + dst_max, is_sign); SET_OPERAND(I32, 2, dst_value_i32); } else { uint64 dst_min = is_sign ? INT64_MIN : 0; uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX; - dst_value_i64 = trunc_f32_to_i64(src_value, src_min, src_max, - dst_min, dst_max, is_sign); + dst_value_i64 = trunc_f32_to_i64(src_value, src_min, src_max, dst_min, + dst_max, is_sign); SET_OPERAND(I64, 2, dst_value_i64); } return false; } static bool -trunc_f64_to_int(WASMModuleInstance *module, - uint8 *frame_ip, uint32 *frame_lp, - float64 src_min, float64 src_max, - bool saturating, bool is_i32, bool is_sign) +trunc_f64_to_int(WASMModuleInstance *module, uint8 *frame_ip, uint32 *frame_lp, + float64 src_min, float64 src_max, bool saturating, bool is_i32, + bool is_sign) { float64 src_value = GET_OPERAND(float64, F64, 0); uint64 dst_value_i64; @@ -547,51 +575,55 @@ trunc_f64_to_int(WASMModuleInstance *module, if (is_i32) { uint32 dst_min = is_sign ? INT32_MIN : 0; uint32 dst_max = is_sign ? INT32_MAX : UINT32_MAX; - dst_value_i32 = trunc_f64_to_i32(src_value, src_min, src_max, - dst_min, dst_max, is_sign); + dst_value_i32 = trunc_f64_to_i32(src_value, src_min, src_max, dst_min, + dst_max, is_sign); SET_OPERAND(I32, 2, dst_value_i32); } else { uint64 dst_min = is_sign ? INT64_MIN : 0; uint64 dst_max = is_sign ? INT64_MAX : UINT64_MAX; - dst_value_i64 = trunc_f64_to_i64(src_value, src_min, src_max, - dst_min, dst_max, is_sign); + dst_value_i64 = trunc_f64_to_i64(src_value, src_min, src_max, dst_min, + dst_max, is_sign); SET_OPERAND(I64, 2, dst_value_i64); } return false; } -#define DEF_OP_TRUNC_F32(min, max, is_i32, is_sign) do { \ - if (trunc_f32_to_int(module, frame_ip, frame_lp, min, max, \ - false, is_i32, is_sign)) \ - goto got_exception; \ - frame_ip += 4; \ - } while (0) - -#define DEF_OP_TRUNC_F64(min, max, is_i32, is_sign) do { \ - if (trunc_f64_to_int(module, frame_ip, frame_lp, min, max, \ - false, is_i32, is_sign)) \ - goto got_exception; \ - frame_ip += 4; \ - } while (0) - -#define DEF_OP_TRUNC_SAT_F32(min, max, is_i32, is_sign) do { \ - (void)trunc_f32_to_int(module, frame_ip, frame_lp, min, max, \ - true, is_i32, is_sign); \ - frame_ip += 4; \ - } while (0) - -#define DEF_OP_TRUNC_SAT_F64(min, max, is_i32, is_sign) do { \ - (void)trunc_f64_to_int(module, frame_ip, frame_lp, min, max, \ - true, is_i32, is_sign); \ - frame_ip += 4; \ - } while (0) - -#define DEF_OP_CONVERT(dst_type, dst_op_type, \ - src_type, src_op_type) do { \ - dst_type value = (dst_type)(src_type)POP_##src_op_type(); \ - PUSH_##dst_op_type(value); \ - } while (0) +#define DEF_OP_TRUNC_F32(min, max, is_i32, is_sign) \ + do { \ + if (trunc_f32_to_int(module, frame_ip, frame_lp, min, max, false, \ + is_i32, is_sign)) \ + goto got_exception; \ + frame_ip += 4; \ + } while (0) + +#define DEF_OP_TRUNC_F64(min, max, is_i32, is_sign) \ + do { \ + if (trunc_f64_to_int(module, frame_ip, frame_lp, min, max, false, \ + is_i32, is_sign)) \ + goto got_exception; \ + frame_ip += 4; \ + } while (0) + +#define DEF_OP_TRUNC_SAT_F32(min, max, is_i32, is_sign) \ + do { \ + (void)trunc_f32_to_int(module, frame_ip, frame_lp, min, max, true, \ + is_i32, is_sign); \ + frame_ip += 4; \ + } while (0) + +#define DEF_OP_TRUNC_SAT_F64(min, max, is_i32, is_sign) \ + do { \ + (void)trunc_f64_to_int(module, frame_ip, frame_lp, min, max, true, \ + is_i32, is_sign); \ + frame_ip += 4; \ + } while (0) + +#define DEF_OP_CONVERT(dst_type, dst_op_type, src_type, src_op_type) \ + do { \ + dst_type value = (dst_type)(src_type)POP_##src_op_type(); \ + PUSH_##dst_op_type(value); \ + } while (0) #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 #define CELL_SIZE sizeof(uint8) @@ -600,120 +632,117 @@ trunc_f64_to_int(WASMModuleInstance *module, #endif static bool -copy_stack_values(WASMModuleInstance *module, uint32 *frame_lp, - uint32 arity, uint32 total_cell_num, const uint8 *cells, +copy_stack_values(WASMModuleInstance *module, uint32 *frame_lp, uint32 arity, + uint32 total_cell_num, const uint8 *cells, const int16 *src_offsets, const uint16 *dst_offsets) { - /* To avoid the overlap issue between src offsets and dst offset, - * we use 2 steps to do the copy. First step, copy the src values - * to a tmp buf. Second step, copy the values from tmp buf to dst. - */ - uint32 buf[16] = {0}, i; - uint32 *tmp_buf = buf; - uint8 cell; - int16 src, buf_index = 0; - uint16 dst; - - /* Allocate memory if the buf is not large enough */ - if (total_cell_num > sizeof(buf)/sizeof(uint32)) { - uint64 total_size = sizeof(uint32) * (uint64)total_cell_num; - if (total_size >= UINT32_MAX - || !(tmp_buf = wasm_runtime_malloc((uint32)total_size))) { - wasm_set_exception(module, "allocate memory failed"); - return false; + /* To avoid the overlap issue between src offsets and dst offset, + * we use 2 steps to do the copy. First step, copy the src values + * to a tmp buf. Second step, copy the values from tmp buf to dst. + */ + uint32 buf[16] = { 0 }, i; + uint32 *tmp_buf = buf; + uint8 cell; + int16 src, buf_index = 0; + uint16 dst; + + /* Allocate memory if the buf is not large enough */ + if (total_cell_num > sizeof(buf) / sizeof(uint32)) { + uint64 total_size = sizeof(uint32) * (uint64)total_cell_num; + if (total_size >= UINT32_MAX + || !(tmp_buf = wasm_runtime_malloc((uint32)total_size))) { + wasm_set_exception(module, "allocate memory failed"); + return false; + } } - } - - /* 1) Copy values from src to tmp buf */ - for (i = 0; i < arity; i++) { - cell = cells[i * CELL_SIZE]; - src = src_offsets[i]; - if (cell == 1) - tmp_buf[buf_index] = frame_lp[src]; - else { - tmp_buf[buf_index] = frame_lp[src]; - tmp_buf[buf_index + 1] = frame_lp[src + 1]; + + /* 1) Copy values from src to tmp buf */ + for (i = 0; i < arity; i++) { + cell = cells[i * CELL_SIZE]; + src = src_offsets[i]; + if (cell == 1) + tmp_buf[buf_index] = frame_lp[src]; + else { + tmp_buf[buf_index] = frame_lp[src]; + tmp_buf[buf_index + 1] = frame_lp[src + 1]; + } + buf_index += cell; } - buf_index += cell; - } - - /* 2) Copy values from tmp buf to dest */ - buf_index = 0; - for (i = 0; i < arity; i++) { - cell = cells[i * CELL_SIZE]; - dst = dst_offsets[i]; - if (cell == 1) - frame_lp[dst] = tmp_buf[buf_index]; - else { - frame_lp[dst] = tmp_buf[buf_index]; - frame_lp[dst + 1] = tmp_buf[buf_index + 1]; + + /* 2) Copy values from tmp buf to dest */ + buf_index = 0; + for (i = 0; i < arity; i++) { + cell = cells[i * CELL_SIZE]; + dst = dst_offsets[i]; + if (cell == 1) + frame_lp[dst] = tmp_buf[buf_index]; + else { + frame_lp[dst] = tmp_buf[buf_index]; + frame_lp[dst + 1] = tmp_buf[buf_index + 1]; + } + buf_index += cell; } - buf_index += cell; - } - if (tmp_buf != buf) { - wasm_runtime_free(tmp_buf); - } + if (tmp_buf != buf) { + wasm_runtime_free(tmp_buf); + } - return true; + return true; } -#define RECOVER_BR_INFO() do { \ - uint32 arity; \ - /* read arity */ \ - arity = read_uint32(frame_ip); \ - if (arity) { \ - uint32 total_cell; \ - uint16 *dst_offsets = NULL; \ - uint8 *cells; \ - int16 *src_offsets = NULL; \ - /* read total cell num */ \ - total_cell = read_uint32(frame_ip); \ - /* cells */ \ - cells = (uint8 *)frame_ip; \ - frame_ip += arity * CELL_SIZE; \ - /* src offsets */ \ - src_offsets = (int16 *)frame_ip; \ - frame_ip += arity * sizeof(int16); \ - /* dst offsets */ \ - dst_offsets = (uint16*)frame_ip; \ - frame_ip += arity * sizeof(uint16); \ - if (arity == 1) { \ - if (cells[0] == 1) \ - frame_lp[dst_offsets[0]] = \ - frame_lp[src_offsets[0]]; \ - else if (cells[0] == 2) { \ - frame_lp[dst_offsets[0]] = \ - frame_lp[src_offsets[0]]; \ - frame_lp[dst_offsets[0] + 1] = \ - frame_lp[src_offsets[0] + 1]; \ - } \ - } \ - else { \ - if (!copy_stack_values(module, frame_lp, \ - arity, total_cell, \ - cells, src_offsets, \ - dst_offsets)) \ - goto got_exception; \ - } \ - } \ - frame_ip = (uint8*)LOAD_PTR(frame_ip); \ - } while (0) - -#define SKIP_BR_INFO() do { \ - uint32 arity; \ - /* read and skip arity */ \ - arity = read_uint32(frame_ip); \ - if (arity) { \ - /* skip total cell num */ \ - frame_ip += sizeof(uint32); \ - /* skip cells, src offsets and dst offsets */ \ - frame_ip += (CELL_SIZE + sizeof(int16) \ - + sizeof(uint16)) * arity; \ - } \ - /* skip target address */ \ - frame_ip += sizeof(uint8*); \ - } while (0) +#define RECOVER_BR_INFO() \ + do { \ + uint32 arity; \ + /* read arity */ \ + arity = read_uint32(frame_ip); \ + if (arity) { \ + uint32 total_cell; \ + uint16 *dst_offsets = NULL; \ + uint8 *cells; \ + int16 *src_offsets = NULL; \ + /* read total cell num */ \ + total_cell = read_uint32(frame_ip); \ + /* cells */ \ + cells = (uint8 *)frame_ip; \ + frame_ip += arity * CELL_SIZE; \ + /* src offsets */ \ + src_offsets = (int16 *)frame_ip; \ + frame_ip += arity * sizeof(int16); \ + /* dst offsets */ \ + dst_offsets = (uint16 *)frame_ip; \ + frame_ip += arity * sizeof(uint16); \ + if (arity == 1) { \ + if (cells[0] == 1) \ + frame_lp[dst_offsets[0]] = frame_lp[src_offsets[0]]; \ + else if (cells[0] == 2) { \ + frame_lp[dst_offsets[0]] = frame_lp[src_offsets[0]]; \ + frame_lp[dst_offsets[0] + 1] = \ + frame_lp[src_offsets[0] + 1]; \ + } \ + } \ + else { \ + if (!copy_stack_values(module, frame_lp, arity, total_cell, \ + cells, src_offsets, dst_offsets)) \ + goto got_exception; \ + } \ + } \ + frame_ip = (uint8 *)LOAD_PTR(frame_ip); \ + } while (0) + +#define SKIP_BR_INFO() \ + do { \ + uint32 arity; \ + /* read and skip arity */ \ + arity = read_uint32(frame_ip); \ + if (arity) { \ + /* skip total cell num */ \ + frame_ip += sizeof(uint32); \ + /* skip cells, src offsets and dst offsets */ \ + frame_ip += (CELL_SIZE + sizeof(int16) + sizeof(uint16)) * arity; \ + } \ + /* skip target address */ \ + frame_ip += sizeof(uint8 *); \ + } while (0) static inline int32 sign_ext_8_32(int8 val) @@ -762,7 +791,7 @@ word_copy(uint32 *dest, uint32 *src, unsigned num) *dest++ = *src++; } -static inline WASMInterpFrame* +static inline WASMInterpFrame * ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame) { WASMInterpFrame *frame = wasm_exec_env_alloc_wasm_frame(exec_env, size); @@ -774,7 +803,7 @@ ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame) #endif } else { - wasm_set_exception((WASMModuleInstance*)exec_env->module_inst, + wasm_set_exception((WASMModuleInstance *)exec_env->module_inst, "wasm operand stack overflow"); } @@ -786,8 +815,8 @@ FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame) { #if WASM_ENABLE_PERF_PROFILING != 0 if (frame->function) { - frame->function->total_exec_time += os_time_get_boot_microsecond() - - frame->time_started; + frame->function->total_exec_time += + os_time_get_boot_microsecond() - frame->time_started; frame->function->total_exec_cnt++; } #endif @@ -822,32 +851,32 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst, snprintf(buf, sizeof(buf), "failed to call unlinked import function (%s, %s)", func_import->module_name, func_import->field_name); - wasm_set_exception((WASMModuleInstance*)module_inst, buf); + wasm_set_exception((WASMModuleInstance *)module_inst, buf); return; } if (func_import->call_conv_wasm_c_api) { ret = wasm_runtime_invoke_c_api_native( - (WASMModuleInstanceCommon *)module_inst, - func_import->func_ptr_linked, func_import->func_type, - cur_func->param_cell_num, frame->lp, - func_import->wasm_c_api_with_env, func_import->attachment); + (WASMModuleInstanceCommon *)module_inst, + func_import->func_ptr_linked, func_import->func_type, + cur_func->param_cell_num, frame->lp, + func_import->wasm_c_api_with_env, func_import->attachment); if (ret) { argv_ret[0] = frame->lp[0]; argv_ret[1] = frame->lp[1]; } } else if (!func_import->call_conv_raw) { - ret = wasm_runtime_invoke_native(exec_env, func_import->func_ptr_linked, - func_import->func_type, func_import->signature, - func_import->attachment, - frame->lp, cur_func->param_cell_num, argv_ret); + ret = wasm_runtime_invoke_native( + exec_env, func_import->func_ptr_linked, func_import->func_type, + func_import->signature, func_import->attachment, frame->lp, + cur_func->param_cell_num, argv_ret); } else { - ret = wasm_runtime_invoke_native_raw(exec_env, func_import->func_ptr_linked, - func_import->func_type, func_import->signature, - func_import->attachment, - frame->lp, cur_func->param_cell_num, argv_ret); + ret = wasm_runtime_invoke_native_raw( + exec_env, func_import->func_ptr_linked, func_import->func_type, + func_import->signature, func_import->attachment, frame->lp, + cur_func->param_cell_num, argv_ret); } if (!ret) @@ -878,7 +907,7 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { - WASMModuleInstance *sub_module_inst = cur_func->import_module_inst; + WASMModuleInstance *sub_module_inst = cur_func->import_module_inst; WASMFunctionInstance *sub_func_inst = cur_func->import_func_inst; WASMFunctionImport *func_import = cur_func->u.func_import; uint8 *ip = prev_frame->ip; @@ -901,8 +930,8 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, exec_env->module_inst = (WASMModuleInstanceCommon *)sub_module_inst; /* call function of sub-module*/ - wasm_interp_call_func_bytecode(sub_module_inst, exec_env, - sub_func_inst, prev_frame); + wasm_interp_call_func_bytecode(sub_module_inst, exec_env, sub_func_inst, + prev_frame); /* restore ip and module_inst */ prev_frame->ip = ip; @@ -919,15 +948,16 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, #endif #if WASM_ENABLE_THREAD_MGR != 0 -#define CHECK_SUSPEND_FLAGS() do { \ - if (exec_env->suspend_flags.flags != 0) { \ - if (exec_env->suspend_flags.flags & 0x01) { \ - /* terminate current thread */ \ - return; \ +#define CHECK_SUSPEND_FLAGS() \ + do { \ + if (exec_env->suspend_flags.flags != 0) { \ + if (exec_env->suspend_flags.flags & 0x01) { \ + /* terminate current thread */ \ + return; \ + } \ + /* TODO: support suspend and breakpoint */ \ } \ - /* TODO: support suspend and breakpoint */ \ - } \ - } while (0) + } while (0) #endif #if WASM_ENABLE_OPCODE_COUNTER != 0 @@ -936,9 +966,14 @@ typedef struct OpcodeInfo { uint64 count; } OpcodeInfo; -#define HANDLE_OPCODE(op) { #op, 0 } -DEFINE_GOTO_TABLE (OpcodeInfo, opcode_table); +/* clang-format off */ +#define HANDLE_OPCODE(op) \ + { \ + #op, 0 \ + } +DEFINE_GOTO_TABLE(OpcodeInfo, opcode_table); #undef HANDLE_OPCODE +/* clang-format on */ static void wasm_interp_dump_op_count() @@ -951,2489 +986,2719 @@ wasm_interp_dump_op_count() printf("total opcode count: %ld\n", total_count); for (i = 0; i < WASM_OP_IMPDEP; i++) if (opcode_table[i].count > 0) - printf("\t\t%s count:\t\t%ld,\t\t%.2f%%\n", - opcode_table[i].name, opcode_table[i].count, + printf("\t\t%s count:\t\t%ld,\t\t%.2f%%\n", opcode_table[i].name, + opcode_table[i].count, opcode_table[i].count * 100.0f / total_count); } #endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 -/* #define HANDLE_OP(opcode) HANDLE_##opcode:printf(#opcode"\n");h_##opcode */ +/* #define HANDLE_OP(opcode) HANDLE_##opcode:printf(#opcode"\n"); */ #if WASM_ENABLE_OPCODE_COUNTER != 0 -#define HANDLE_OP(opcode) HANDLE_##opcode:opcode_table[opcode].count++;h_##opcode +#define HANDLE_OP(opcode) HANDLE_##opcode : opcode_table[opcode].count++; #else -#define HANDLE_OP(opcode) HANDLE_##opcode +#define HANDLE_OP(opcode) HANDLE_##opcode: #endif #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 -#define FETCH_OPCODE_AND_DISPATCH() do { \ - const void *p_label_addr = *(void**)frame_ip; \ - frame_ip += sizeof(void*); \ - goto *p_label_addr; \ - } while (0) +#define FETCH_OPCODE_AND_DISPATCH() \ + do { \ + const void *p_label_addr = *(void **)frame_ip; \ + frame_ip += sizeof(void *); \ + goto *p_label_addr; \ + } while (0) #else -#define FETCH_OPCODE_AND_DISPATCH() do { \ - const void *p_label_addr = label_base \ - + *(int16*)frame_ip; \ - frame_ip += sizeof(int16); \ - goto *p_label_addr; \ - } while (0) +#define FETCH_OPCODE_AND_DISPATCH() \ + do { \ + const void *p_label_addr = label_base + *(int16 *)frame_ip; \ + frame_ip += sizeof(int16); \ + goto *p_label_addr; \ + } while (0) #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ #define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH() -#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ +#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ -#define HANDLE_OP(opcode) case opcode +#define HANDLE_OP(opcode) case opcode: #define HANDLE_OP_END() continue -#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ +#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ #if WASM_ENABLE_LABELS_AS_VALUES != 0 static void **global_handle_table; #endif +static inline uint8 * +get_global_addr(uint8 *global_data, WASMGlobalInstance *global) +{ +#if WASM_ENABLE_MULTI_MODULE == 0 + return global_data + global->data_offset; +#else + return global->import_global_inst + ? global->import_module_inst->global_data + + global->import_global_inst->data_offset + : global_data + global->data_offset; +#endif +} + static void wasm_interp_call_func_bytecode(WASMModuleInstance *module, WASMExecEnv *exec_env, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { - WASMMemoryInstance *memory = module->default_memory; - uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; - uint8 *global_data = module->global_data; - uint32 linear_mem_size = memory ? num_bytes_per_page * memory->cur_page_count : 0; - WASMGlobalInstance *globals = module->globals, *global; - uint8 opcode_IMPDEP = WASM_OP_IMPDEP; - WASMInterpFrame *frame = NULL; - /* Points to this special opcode so as to jump to the call_method_from_entry. */ - register uint8 *frame_ip = &opcode_IMPDEP; /* cache of frame->ip */ - register uint32 *frame_lp = NULL; /* cache of frame->lp */ + WASMMemoryInstance *memory = module->default_memory; + uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; + uint8 *global_data = module->global_data; + uint32 linear_mem_size = + memory ? num_bytes_per_page * memory->cur_page_count : 0; + WASMGlobalInstance *globals = module->globals, *global; + uint8 opcode_IMPDEP = WASM_OP_IMPDEP; + WASMInterpFrame *frame = NULL; + /* Points to this special opcode so as to jump to the + * call_method_from_entry. */ + register uint8 *frame_ip = &opcode_IMPDEP; /* cache of frame->ip */ + register uint32 *frame_lp = NULL; /* cache of frame->lp */ #if WASM_ENABLE_LABELS_AS_VALUES != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 - /* cache of label base addr */ - register uint8 *label_base = &&HANDLE_WASM_OP_UNREACHABLE; + /* cache of label base addr */ + register uint8 *label_base = &&HANDLE_WASM_OP_UNREACHABLE; #endif #endif - uint8 *frame_ip_end = frame_ip + 1; - uint32 cond, count, fidx, tidx, frame_size = 0; - uint64 all_cell_num = 0; - int16 addr1, addr2, addr_ret = 0; - int32 didx, val; - uint8 *maddr = NULL; - uint32 local_idx, local_offset, global_idx; - uint8 opcode, local_type, *global_addr; + uint8 *frame_ip_end = frame_ip + 1; + uint32 cond, count, fidx, tidx, frame_size = 0; + uint64 all_cell_num = 0; + int16 addr1, addr2, addr_ret = 0; + int32 didx, val; + uint8 *maddr = NULL; + uint32 local_idx, local_offset, global_idx; + uint8 opcode, local_type, *global_addr; #if WASM_ENABLE_LABELS_AS_VALUES != 0 - #define HANDLE_OPCODE(op) &&HANDLE_##op - DEFINE_GOTO_TABLE (const void*, handle_table); - #undef HANDLE_OPCODE - if (exec_env == NULL) { - global_handle_table = (void **)handle_table; - return; - } +#define HANDLE_OPCODE(op) &&HANDLE_##op + DEFINE_GOTO_TABLE(const void *, handle_table); +#undef HANDLE_OPCODE + if (exec_env == NULL) { + global_handle_table = (void **)handle_table; + return; + } #endif #if WASM_ENABLE_LABELS_AS_VALUES == 0 - while (frame_ip < frame_ip_end) { - opcode = *frame_ip++; + while (frame_ip < frame_ip_end) { + opcode = *frame_ip++; #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 - frame_ip++; + frame_ip++; #endif - switch (opcode) { + switch (opcode) { #else - goto *handle_table[WASM_OP_IMPDEP]; + goto *handle_table[WASM_OP_IMPDEP]; #endif - /* control instructions */ - HANDLE_OP (WASM_OP_UNREACHABLE): - wasm_set_exception(module, "unreachable"); - goto got_exception; + /* control instructions */ + HANDLE_OP(WASM_OP_UNREACHABLE) + { + wasm_set_exception(module, "unreachable"); + goto got_exception; + } - HANDLE_OP (WASM_OP_IF): - cond = (uint32)POP_I32(); - - if (cond == 0) { - uint8 *else_addr = (uint8*)LOAD_PTR(frame_ip); - if (else_addr == NULL) { - frame_ip = (uint8*)LOAD_PTR(frame_ip + sizeof(uint8*)); - } - else { - frame_ip = else_addr; - } - } - else { - frame_ip += sizeof(uint8*) * 2; - } - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_IF) + { + cond = (uint32)POP_I32(); + + if (cond == 0) { + uint8 *else_addr = (uint8 *)LOAD_PTR(frame_ip); + if (else_addr == NULL) { + frame_ip = + (uint8 *)LOAD_PTR(frame_ip + sizeof(uint8 *)); + } + else { + frame_ip = else_addr; + } + } + else { + frame_ip += sizeof(uint8 *) * 2; + } + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_ELSE): - frame_ip = (uint8*)LOAD_PTR(frame_ip); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_ELSE) + { + frame_ip = (uint8 *)LOAD_PTR(frame_ip); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_BR): + HANDLE_OP(WASM_OP_BR) + { #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif -recover_br_info: - RECOVER_BR_INFO(); - HANDLE_OP_END (); + recover_br_info: + RECOVER_BR_INFO(); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_BR_IF): + HANDLE_OP(WASM_OP_BR_IF) + { #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - cond = frame_lp[GET_OFFSET()]; + cond = frame_lp[GET_OFFSET()]; - if (cond) - goto recover_br_info; - else - SKIP_BR_INFO(); + if (cond) + goto recover_br_info; + else + SKIP_BR_INFO(); - HANDLE_OP_END (); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_BR_TABLE): - { - uint32 arity, br_item_size; + HANDLE_OP(WASM_OP_BR_TABLE) + { + uint32 arity, br_item_size; #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - count = read_uint32(frame_ip); - didx = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - - if (!(didx >= 0 && (uint32)didx < count)) - didx = count; - - /* all br items must have the same arity and item size, - so we only calculate the first item size */ - arity = LOAD_U32_WITH_2U16S(frame_ip); - br_item_size = sizeof(uint32); /* arity */ - if (arity) { - /* total cell num */ - br_item_size += sizeof(uint32); - /* cells, src offsets and dst offsets */ - br_item_size += (CELL_SIZE + sizeof(int16) + sizeof(uint16)) - * arity; - } - /* target address */ - br_item_size += sizeof(uint8*); - - frame_ip += br_item_size * didx; - goto recover_br_info; - } - - HANDLE_OP (WASM_OP_RETURN): - { - uint32 ret_idx; - WASMType *func_type; - uint32 off, ret_offset; - uint8 *ret_types; - if (cur_func->is_import_func) - func_type = cur_func->u.func_import->func_type; - else - func_type = cur_func->u.func->func_type; - - /* types of each return value */ - ret_types = func_type->types + func_type->param_count; - ret_offset = prev_frame->ret_offset; - - for (ret_idx = 0, off = sizeof(int16) * (func_type->result_count - 1); - ret_idx < func_type->result_count; - ret_idx++, off -= sizeof(int16)) { - if (ret_types[ret_idx] == VALUE_TYPE_I64 - || ret_types[ret_idx] == VALUE_TYPE_F64) { - PUT_I64_TO_ADDR(prev_frame->lp + ret_offset, - GET_OPERAND(uint64, I64, off)); - ret_offset += 2; + count = read_uint32(frame_ip); + didx = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + + if (!(didx >= 0 && (uint32)didx < count)) + didx = count; + + /* all br items must have the same arity and item size, + so we only calculate the first item size */ + arity = LOAD_U32_WITH_2U16S(frame_ip); + br_item_size = sizeof(uint32); /* arity */ + if (arity) { + /* total cell num */ + br_item_size += sizeof(uint32); + /* cells, src offsets and dst offsets */ + br_item_size += + (CELL_SIZE + sizeof(int16) + sizeof(uint16)) * arity; + } + /* target address */ + br_item_size += sizeof(uint8 *); + + frame_ip += br_item_size * didx; + goto recover_br_info; } - else { - prev_frame->lp[ret_offset] = GET_OPERAND(uint32, I32, off); - ret_offset++; + + HANDLE_OP(WASM_OP_RETURN) + { + uint32 ret_idx; + WASMType *func_type; + uint32 off, ret_offset; + uint8 *ret_types; + if (cur_func->is_import_func) + func_type = cur_func->u.func_import->func_type; + else + func_type = cur_func->u.func->func_type; + + /* types of each return value */ + ret_types = func_type->types + func_type->param_count; + ret_offset = prev_frame->ret_offset; + + for (ret_idx = 0, + off = sizeof(int16) * (func_type->result_count - 1); + ret_idx < func_type->result_count; + ret_idx++, off -= sizeof(int16)) { + if (ret_types[ret_idx] == VALUE_TYPE_I64 + || ret_types[ret_idx] == VALUE_TYPE_F64) { + PUT_I64_TO_ADDR(prev_frame->lp + ret_offset, + GET_OPERAND(uint64, I64, off)); + ret_offset += 2; + } + else { + prev_frame->lp[ret_offset] = + GET_OPERAND(uint32, I32, off); + ret_offset++; + } + } + goto return_func; } - } - } - goto return_func; - HANDLE_OP (WASM_OP_CALL_INDIRECT): + HANDLE_OP(WASM_OP_CALL_INDIRECT) #if WASM_ENABLE_TAIL_CALL != 0 - HANDLE_OP (WASM_OP_RETURN_CALL_INDIRECT): + HANDLE_OP(WASM_OP_RETURN_CALL_INDIRECT) #endif - { - WASMType *cur_type, *cur_func_type; - WASMTableInstance *tbl_inst; - uint32 tbl_idx; + { + WASMType *cur_type, *cur_func_type; + WASMTableInstance *tbl_inst; + uint32 tbl_idx; #if WASM_ENABLE_TAIL_CALL != 0 - GET_OPCODE(); + GET_OPCODE(); #endif #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - tidx = read_uint32(frame_ip); - cur_type = module->module->types[tidx]; - - tbl_idx = read_uint32(frame_ip); - bh_assert(tbl_idx < module->table_count); - - tbl_inst = wasm_get_table_inst(module, tbl_idx); - - val = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - - if (val < 0 || val >= (int32)tbl_inst->cur_size) { - wasm_set_exception(module, "undefined element"); - goto got_exception; - } - - fidx = ((uint32*)tbl_inst->base_addr)[val]; - if (fidx == (uint32)-1) { - wasm_set_exception(module, "uninitialized element"); - goto got_exception; - } - - /* - * we might be using a table injected by host or - * another module. in that case, we don't validate - * the elem value while loading - */ - if (fidx >= module->function_count) { - wasm_set_exception(module, "unknown function"); - goto got_exception; - } - - /* always call module own functions */ - cur_func = module->functions + fidx; - - if (cur_func->is_import_func) - cur_func_type = cur_func->u.func_import->func_type; - else - cur_func_type = cur_func->u.func->func_type; - if (!wasm_type_equal(cur_type, cur_func_type)) { - wasm_set_exception(module, "indirect call type mismatch"); - goto got_exception; - } + tidx = read_uint32(frame_ip); + cur_type = module->module->types[tidx]; + + tbl_idx = read_uint32(frame_ip); + bh_assert(tbl_idx < module->table_count); + + tbl_inst = wasm_get_table_inst(module, tbl_idx); + + val = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + + if (val < 0 || val >= (int32)tbl_inst->cur_size) { + wasm_set_exception(module, "undefined element"); + goto got_exception; + } + + fidx = ((uint32 *)tbl_inst->base_addr)[val]; + if (fidx == (uint32)-1) { + wasm_set_exception(module, "uninitialized element"); + goto got_exception; + } + + /* + * we might be using a table injected by host or + * another module. in that case, we don't validate + * the elem value while loading + */ + if (fidx >= module->function_count) { + wasm_set_exception(module, "unknown function"); + goto got_exception; + } + + /* always call module own functions */ + cur_func = module->functions + fidx; + + if (cur_func->is_import_func) + cur_func_type = cur_func->u.func_import->func_type; + else + cur_func_type = cur_func->u.func->func_type; + if (!wasm_type_equal(cur_type, cur_func_type)) { + wasm_set_exception(module, "indirect call type mismatch"); + goto got_exception; + } #if WASM_ENABLE_TAIL_CALL != 0 - if (opcode == WASM_OP_RETURN_CALL_INDIRECT) - goto call_func_from_return_call; + if (opcode == WASM_OP_RETURN_CALL_INDIRECT) + goto call_func_from_return_call; #endif - goto call_func_from_interp; - } + goto call_func_from_interp; + } - /* parametric instructions */ - HANDLE_OP (WASM_OP_SELECT): - { - cond = frame_lp[GET_OFFSET()]; - addr1 = GET_OFFSET(); - addr2 = GET_OFFSET(); - addr_ret = GET_OFFSET(); - - if (!cond) { - if (addr_ret != addr1) - frame_lp[addr_ret] = frame_lp[addr1]; - } - else { - if (addr_ret != addr2) - frame_lp[addr_ret] = frame_lp[addr2]; - } - HANDLE_OP_END (); - } + /* parametric instructions */ + HANDLE_OP(WASM_OP_SELECT) + { + cond = frame_lp[GET_OFFSET()]; + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + + if (!cond) { + if (addr_ret != addr1) + frame_lp[addr_ret] = frame_lp[addr1]; + } + else { + if (addr_ret != addr2) + frame_lp[addr_ret] = frame_lp[addr2]; + } + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_SELECT_64): - { - cond = frame_lp[GET_OFFSET()]; - addr1 = GET_OFFSET(); - addr2 = GET_OFFSET(); - addr_ret = GET_OFFSET(); - - if (!cond) { - if (addr_ret != addr1) - PUT_I64_TO_ADDR(frame_lp + addr_ret, - GET_I64_FROM_ADDR(frame_lp + addr1)); - } - else { - if (addr_ret != addr2) - PUT_I64_TO_ADDR(frame_lp + addr_ret, - GET_I64_FROM_ADDR(frame_lp + addr2)); - } - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_SELECT_64) + { + cond = frame_lp[GET_OFFSET()]; + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + + if (!cond) { + if (addr_ret != addr1) + PUT_I64_TO_ADDR(frame_lp + addr_ret, + GET_I64_FROM_ADDR(frame_lp + addr1)); + } + else { + if (addr_ret != addr2) + PUT_I64_TO_ADDR(frame_lp + addr_ret, + GET_I64_FROM_ADDR(frame_lp + addr2)); + } + HANDLE_OP_END(); + } #if WASM_ENABLE_REF_TYPES != 0 - HANDLE_OP (WASM_OP_TABLE_GET): - { - uint32 tbl_idx, elem_idx; - WASMTableInstance *tbl_inst; + HANDLE_OP(WASM_OP_TABLE_GET) + { + uint32 tbl_idx, elem_idx; + WASMTableInstance *tbl_inst; - tbl_idx = read_uint32(frame_ip); - bh_assert(tbl_idx < module->table_count); + tbl_idx = read_uint32(frame_ip); + bh_assert(tbl_idx < module->table_count); - tbl_inst = wasm_get_table_inst(module, tbl_idx); + tbl_inst = wasm_get_table_inst(module, tbl_idx); - elem_idx = POP_I32(); - if (elem_idx >= tbl_inst->cur_size) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; + elem_idx = POP_I32(); + if (elem_idx >= tbl_inst->cur_size) { + wasm_set_exception(module, "out of bounds table access"); + goto got_exception; + } + + PUSH_I32(((uint32 *)tbl_inst->base_addr)[elem_idx]); + HANDLE_OP_END(); } - PUSH_I32(((uint32 *)tbl_inst->base_addr)[elem_idx]); - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_TABLE_SET) + { + uint32 tbl_idx, elem_idx, val; + WASMTableInstance *tbl_inst; - HANDLE_OP (WASM_OP_TABLE_SET): - { - uint32 tbl_idx, elem_idx, val; - WASMTableInstance *tbl_inst; + tbl_idx = read_uint32(frame_ip); + bh_assert(tbl_idx < module->table_count); - tbl_idx = read_uint32(frame_ip); - bh_assert(tbl_idx < module->table_count); + tbl_inst = wasm_get_table_inst(module, tbl_idx); - tbl_inst = wasm_get_table_inst(module, tbl_idx); + val = POP_I32(); + elem_idx = POP_I32(); + if (elem_idx >= tbl_inst->cur_size) { + wasm_set_exception(module, "out of bounds table access"); + goto got_exception; + } - val = POP_I32(); - elem_idx = POP_I32(); - if (elem_idx >= tbl_inst->cur_size) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; + ((uint32 *)tbl_inst->base_addr)[elem_idx] = val; + HANDLE_OP_END(); } - ((uint32 *)tbl_inst->base_addr)[elem_idx] = val; - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_REF_NULL): - { - PUSH_I32(NULL_REF); - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_REF_NULL) + { + PUSH_I32(NULL_REF); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_REF_IS_NULL): - { - uint32 val; - val = POP_I32(); - PUSH_I32(val == NULL_REF ? 1 : 0); - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_REF_IS_NULL) + { + uint32 val; + val = POP_I32(); + PUSH_I32(val == NULL_REF ? 1 : 0); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_REF_FUNC): - { - uint32 func_idx = read_uint32(frame_ip); - PUSH_I32(func_idx); - HANDLE_OP_END(); - } + HANDLE_OP(WASM_OP_REF_FUNC) + { + uint32 func_idx = read_uint32(frame_ip); + PUSH_I32(func_idx); + HANDLE_OP_END(); + } #endif /* WASM_ENABLE_REF_TYPES */ - /* variable instructions */ - HANDLE_OP (EXT_OP_SET_LOCAL_FAST): - HANDLE_OP (EXT_OP_TEE_LOCAL_FAST): - { + /* variable instructions */ + HANDLE_OP(EXT_OP_SET_LOCAL_FAST) + HANDLE_OP(EXT_OP_TEE_LOCAL_FAST) + { #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 - local_offset = *frame_ip++; + local_offset = *frame_ip++; #else - local_offset = *frame_ip; - frame_ip += 2; + /* clang-format off */ + local_offset = *frame_ip; + frame_ip += 2; + /* clang-format on */ #endif - *(uint32*)(frame_lp + local_offset) = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - HANDLE_OP_END (); - } + *(uint32 *)(frame_lp + local_offset) = + GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + HANDLE_OP_END(); + } - HANDLE_OP (EXT_OP_SET_LOCAL_FAST_I64): - HANDLE_OP (EXT_OP_TEE_LOCAL_FAST_I64): - { + HANDLE_OP(EXT_OP_SET_LOCAL_FAST_I64) + HANDLE_OP(EXT_OP_TEE_LOCAL_FAST_I64) + { #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 - local_offset = *frame_ip++; -#else - local_offset = *frame_ip; - frame_ip += 2; -#endif - PUT_I64_TO_ADDR((uint32*)(frame_lp + local_offset), - GET_OPERAND(uint64, I64, 0)); - frame_ip += 2; - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_GET_GLOBAL): - { - global_idx = read_uint32(frame_ip); - bh_assert(global_idx < module->global_count); - global = globals + global_idx; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_addr = global_data + global->data_offset; + local_offset = *frame_ip++; #else - global_addr = global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; + /* clang-format off */ + local_offset = *frame_ip; + frame_ip += 2; + /* clang-format on */ #endif - addr_ret = GET_OFFSET(); - frame_lp[addr_ret] = *(uint32*)global_addr; - HANDLE_OP_END (); - } + PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset), + GET_OPERAND(uint64, I64, 0)); + frame_ip += 2; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_GET_GLOBAL_64): - { - global_idx = read_uint32(frame_ip); - bh_assert(global_idx < module->global_count); - global = globals + global_idx; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_addr = global_data + global->data_offset; -#else - global_addr = global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif - addr_ret = GET_OFFSET(); - PUT_I64_TO_ADDR(frame_lp + addr_ret, - GET_I64_FROM_ADDR((uint32*)global_addr)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_GET_GLOBAL) + { + global_idx = read_uint32(frame_ip); + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = get_global_addr(global_data, global); + addr_ret = GET_OFFSET(); + frame_lp[addr_ret] = *(uint32 *)global_addr; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_SET_GLOBAL): - { - global_idx = read_uint32(frame_ip); - bh_assert(global_idx < module->global_count); - global = globals + global_idx; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_addr = global_data + global->data_offset; -#else - global_addr = global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif - addr1 = GET_OFFSET(); - *(int32*)global_addr = frame_lp[addr1]; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_GET_GLOBAL_64) + { + global_idx = read_uint32(frame_ip); + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = get_global_addr(global_data, global); + addr_ret = GET_OFFSET(); + PUT_I64_TO_ADDR(frame_lp + addr_ret, + GET_I64_FROM_ADDR((uint32 *)global_addr)); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_SET_GLOBAL_AUX_STACK): - { - uint32 aux_stack_top; + HANDLE_OP(WASM_OP_SET_GLOBAL) + { + global_idx = read_uint32(frame_ip); + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = get_global_addr(global_data, global); + addr1 = GET_OFFSET(); + *(int32 *)global_addr = frame_lp[addr1]; + HANDLE_OP_END(); + } - global_idx = read_uint32(frame_ip); - bh_assert(global_idx < module->global_count); - global = globals + global_idx; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_addr = global_data + global->data_offset; -#else - global_addr = global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif - aux_stack_top = frame_lp[GET_OFFSET()]; - if (aux_stack_top <= exec_env->aux_stack_boundary.boundary) { - wasm_set_exception(module, "wasm auxiliary stack overflow"); - goto got_exception; - } - if (aux_stack_top > exec_env->aux_stack_bottom.bottom) { - wasm_set_exception(module, "wasm auxiliary stack underflow"); - goto got_exception; - } - *(int32*)global_addr = aux_stack_top; + HANDLE_OP(WASM_OP_SET_GLOBAL_AUX_STACK) + { + uint32 aux_stack_top; + + global_idx = read_uint32(frame_ip); + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = get_global_addr(global_data, global); + aux_stack_top = frame_lp[GET_OFFSET()]; + if (aux_stack_top <= exec_env->aux_stack_boundary.boundary) { + wasm_set_exception(module, "wasm auxiliary stack overflow"); + goto got_exception; + } + if (aux_stack_top > exec_env->aux_stack_bottom.bottom) { + wasm_set_exception(module, + "wasm auxiliary stack underflow"); + goto got_exception; + } + *(int32 *)global_addr = aux_stack_top; #if WASM_ENABLE_MEMORY_PROFILING != 0 - if (module->module->aux_stack_top_global_index != (uint32)-1) { - uint32 aux_stack_used = - module->module->aux_stack_bottom - *(uint32*)global_addr; - if (aux_stack_used > module->max_aux_stack_used) - module->max_aux_stack_used = aux_stack_used; - } + if (module->module->aux_stack_top_global_index != (uint32)-1) { + uint32 aux_stack_used = module->module->aux_stack_bottom + - *(uint32 *)global_addr; + if (aux_stack_used > module->max_aux_stack_used) + module->max_aux_stack_used = aux_stack_used; + } #endif - HANDLE_OP_END (); - } + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_SET_GLOBAL_64): - { - global_idx = read_uint32(frame_ip); - bh_assert(global_idx < module->global_count); - global = globals + global_idx; -#if WASM_ENABLE_MULTI_MODULE == 0 - global_addr = global_data + global->data_offset; -#else - global_addr = global->import_global_inst - ? global->import_module_inst->global_data - + global->import_global_inst->data_offset - : global_data + global->data_offset; -#endif - addr1 = GET_OFFSET(); - PUT_I64_TO_ADDR((uint32*)global_addr, - GET_I64_FROM_ADDR(frame_lp + addr1)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_SET_GLOBAL_64) + { + global_idx = read_uint32(frame_ip); + bh_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = get_global_addr(global_data, global); + addr1 = GET_OFFSET(); + PUT_I64_TO_ADDR((uint32 *)global_addr, + GET_I64_FROM_ADDR(frame_lp + addr1)); + HANDLE_OP_END(); + } - /* memory load instructions */ - HANDLE_OP (WASM_OP_I32_LOAD): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(4); - frame_lp[addr_ret] = LOAD_I32(maddr); - HANDLE_OP_END (); - } + /* memory load instructions */ + HANDLE_OP(WASM_OP_I32_LOAD) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(4); + frame_lp[addr_ret] = LOAD_I32(maddr); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(8); - PUT_I64_TO_ADDR(frame_lp + addr_ret, LOAD_I64(maddr)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_LOAD) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(8); + PUT_I64_TO_ADDR(frame_lp + addr_ret, LOAD_I64(maddr)); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LOAD8_S): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(1); - frame_lp[addr_ret] = sign_ext_8_32(*(int8*)maddr); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I32_LOAD8_S) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(1); + frame_lp[addr_ret] = sign_ext_8_32(*(int8 *)maddr); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LOAD8_U): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(1); - frame_lp[addr_ret] = (uint32)(*(uint8*)maddr); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I32_LOAD8_U) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(1); + frame_lp[addr_ret] = (uint32)(*(uint8 *)maddr); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LOAD16_S): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(2); - frame_lp[addr_ret] = sign_ext_16_32(LOAD_I16(maddr)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I32_LOAD16_S) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(2); + frame_lp[addr_ret] = sign_ext_16_32(LOAD_I16(maddr)); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LOAD16_U): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(2); - frame_lp[addr_ret] = (uint32)(LOAD_U16(maddr)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I32_LOAD16_U) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(2); + frame_lp[addr_ret] = (uint32)(LOAD_U16(maddr)); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD8_S): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(1); - PUT_I64_TO_ADDR(frame_lp + addr_ret, sign_ext_8_64(*(int8*)maddr)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_LOAD8_S) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(1); + PUT_I64_TO_ADDR(frame_lp + addr_ret, + sign_ext_8_64(*(int8 *)maddr)); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD8_U): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(1); - PUT_I64_TO_ADDR(frame_lp + addr_ret, (uint64)(*(uint8*)maddr)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_LOAD8_U) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(1); + PUT_I64_TO_ADDR(frame_lp + addr_ret, (uint64)(*(uint8 *)maddr)); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD16_S): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(2); - PUT_I64_TO_ADDR(frame_lp + addr_ret, sign_ext_16_64(LOAD_I16(maddr))); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_LOAD16_S) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(2); + PUT_I64_TO_ADDR(frame_lp + addr_ret, + sign_ext_16_64(LOAD_I16(maddr))); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD16_U): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(2); - PUT_I64_TO_ADDR(frame_lp + addr_ret, (uint64)(LOAD_U16(maddr))); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_LOAD16_U) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(2); + PUT_I64_TO_ADDR(frame_lp + addr_ret, (uint64)(LOAD_U16(maddr))); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD32_S): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(4); - PUT_I64_TO_ADDR(frame_lp + addr_ret, sign_ext_32_64(LOAD_I32(maddr))); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_LOAD32_S) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(4); + PUT_I64_TO_ADDR(frame_lp + addr_ret, + sign_ext_32_64(LOAD_I32(maddr))); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LOAD32_U): - { - uint32 offset, addr; - offset = read_uint32(frame_ip); - addr = GET_OPERAND(uint32, I32, 0); - frame_ip += 2; - addr_ret = GET_OFFSET(); - CHECK_MEMORY_OVERFLOW(4); - PUT_I64_TO_ADDR(frame_lp + addr_ret, (uint64)(LOAD_U32(maddr))); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_LOAD32_U) + { + uint32 offset, addr; + offset = read_uint32(frame_ip); + addr = GET_OPERAND(uint32, I32, 0); + frame_ip += 2; + addr_ret = GET_OFFSET(); + CHECK_MEMORY_OVERFLOW(4); + PUT_I64_TO_ADDR(frame_lp + addr_ret, (uint64)(LOAD_U32(maddr))); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_STORE): - { - uint32 offset, addr; - uint32 sval; - offset = read_uint32(frame_ip); - sval = GET_OPERAND(uint32, I32, 0); - addr = GET_OPERAND(uint32, I32, 2); - frame_ip += 4; - CHECK_MEMORY_OVERFLOW(4); - STORE_U32(maddr, sval); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I32_STORE) + { + uint32 offset, addr; + uint32 sval; + offset = read_uint32(frame_ip); + sval = GET_OPERAND(uint32, I32, 0); + addr = GET_OPERAND(uint32, I32, 2); + frame_ip += 4; + CHECK_MEMORY_OVERFLOW(4); + STORE_U32(maddr, sval); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_STORE8): - { - uint32 offset, addr; - uint32 sval; - offset = read_uint32(frame_ip); - sval = GET_OPERAND(uint32, I32, 0); - addr = GET_OPERAND(uint32, I32, 2); - frame_ip += 4; - CHECK_MEMORY_OVERFLOW(1); - *(uint8*)maddr = (uint8)sval; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I32_STORE8) + { + uint32 offset, addr; + uint32 sval; + offset = read_uint32(frame_ip); + sval = GET_OPERAND(uint32, I32, 0); + addr = GET_OPERAND(uint32, I32, 2); + frame_ip += 4; + CHECK_MEMORY_OVERFLOW(1); + *(uint8 *)maddr = (uint8)sval; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_STORE16): - { - uint32 offset, addr; - uint32 sval; - offset = read_uint32(frame_ip); - sval = GET_OPERAND(uint32, I32, 0); - addr = GET_OPERAND(uint32, I32, 2); - frame_ip += 4; - CHECK_MEMORY_OVERFLOW(2); - STORE_U16(maddr, (uint16)sval); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I32_STORE16) + { + uint32 offset, addr; + uint32 sval; + offset = read_uint32(frame_ip); + sval = GET_OPERAND(uint32, I32, 0); + addr = GET_OPERAND(uint32, I32, 2); + frame_ip += 4; + CHECK_MEMORY_OVERFLOW(2); + STORE_U16(maddr, (uint16)sval); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_STORE): - { - uint32 offset, addr; - uint64 sval; - offset = read_uint32(frame_ip); - sval = GET_OPERAND(uint64, I64, 0); - addr = GET_OPERAND(uint32, I32, 2); - frame_ip += 4; - CHECK_MEMORY_OVERFLOW(8); - STORE_I64(maddr, sval); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_STORE) + { + uint32 offset, addr; + uint64 sval; + offset = read_uint32(frame_ip); + sval = GET_OPERAND(uint64, I64, 0); + addr = GET_OPERAND(uint32, I32, 2); + frame_ip += 4; + CHECK_MEMORY_OVERFLOW(8); + STORE_I64(maddr, sval); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_STORE8): - { - uint32 offset, addr; - uint64 sval; - offset = read_uint32(frame_ip); - sval = GET_OPERAND(uint64, I64, 0); - addr = GET_OPERAND(uint32, I32, 2); - frame_ip += 4; - CHECK_MEMORY_OVERFLOW(1); - *(uint8*)maddr = (uint8)sval; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_STORE8) + { + uint32 offset, addr; + uint64 sval; + offset = read_uint32(frame_ip); + sval = GET_OPERAND(uint64, I64, 0); + addr = GET_OPERAND(uint32, I32, 2); + frame_ip += 4; + CHECK_MEMORY_OVERFLOW(1); + *(uint8 *)maddr = (uint8)sval; + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_STORE16): - { - uint32 offset, addr; - uint64 sval; - offset = read_uint32(frame_ip); - sval = GET_OPERAND(uint64, I64, 0); - addr = GET_OPERAND(uint32, I32, 2); - frame_ip += 4; - CHECK_MEMORY_OVERFLOW(2); - STORE_U16(maddr, (uint16)sval); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_STORE16) + { + uint32 offset, addr; + uint64 sval; + offset = read_uint32(frame_ip); + sval = GET_OPERAND(uint64, I64, 0); + addr = GET_OPERAND(uint32, I32, 2); + frame_ip += 4; + CHECK_MEMORY_OVERFLOW(2); + STORE_U16(maddr, (uint16)sval); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_STORE32): - { - uint32 offset, addr; - uint64 sval; - offset = read_uint32(frame_ip); - sval = GET_OPERAND(uint64, I64, 0); - addr = GET_OPERAND(uint32, I32, 2); - frame_ip += 4; - CHECK_MEMORY_OVERFLOW(4); - STORE_U32(maddr, (uint32)sval); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_STORE32) + { + uint32 offset, addr; + uint64 sval; + offset = read_uint32(frame_ip); + sval = GET_OPERAND(uint64, I64, 0); + addr = GET_OPERAND(uint32, I32, 2); + frame_ip += 4; + CHECK_MEMORY_OVERFLOW(4); + STORE_U32(maddr, (uint32)sval); + HANDLE_OP_END(); + } - /* memory size and memory grow instructions */ - HANDLE_OP (WASM_OP_MEMORY_SIZE): - { - uint32 reserved; - addr_ret = GET_OFFSET(); - frame_lp[addr_ret] = memory->cur_page_count; - (void)reserved; - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_MEMORY_GROW): - { - uint32 reserved, delta, prev_page_count = memory->cur_page_count; - - addr1 = GET_OFFSET(); - addr_ret = GET_OFFSET(); - delta = (uint32)frame_lp[addr1]; - - if (!wasm_enlarge_memory(module, delta)) { - /* failed to memory.grow, return -1 */ - frame_lp[addr_ret] = -1; - } - else { - /* success, return previous page count */ - frame_lp[addr_ret] = prev_page_count; - /* update memory instance ptr and memory size */ - memory = module->default_memory; - linear_mem_size = num_bytes_per_page * memory->cur_page_count; - } + /* memory size and memory grow instructions */ + HANDLE_OP(WASM_OP_MEMORY_SIZE) + { + uint32 reserved; + addr_ret = GET_OFFSET(); + frame_lp[addr_ret] = memory->cur_page_count; + (void)reserved; + HANDLE_OP_END(); + } - (void)reserved; - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_MEMORY_GROW) + { + uint32 reserved, delta, + prev_page_count = memory->cur_page_count; + + addr1 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + delta = (uint32)frame_lp[addr1]; + + if (!wasm_enlarge_memory(module, delta)) { + /* failed to memory.grow, return -1 */ + frame_lp[addr_ret] = -1; + } + else { + /* success, return previous page count */ + frame_lp[addr_ret] = prev_page_count; + /* update memory instance ptr and memory size */ + memory = module->default_memory; + linear_mem_size = + num_bytes_per_page * memory->cur_page_count; + } + + (void)reserved; + HANDLE_OP_END(); + } - /* comparison instructions of i32 */ - HANDLE_OP (WASM_OP_I32_EQZ): - DEF_OP_EQZ(int32, I32); - HANDLE_OP_END (); + /* comparison instructions of i32 */ + HANDLE_OP(WASM_OP_I32_EQZ) + { + DEF_OP_EQZ(int32, I32); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_EQ): - DEF_OP_CMP(uint32, I32, ==); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_EQ) + { + DEF_OP_CMP(uint32, I32, ==); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_NE): - DEF_OP_CMP(uint32, I32, !=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_NE) + { + DEF_OP_CMP(uint32, I32, !=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LT_S): - DEF_OP_CMP(int32, I32, <); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_LT_S) + { + DEF_OP_CMP(int32, I32, <); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LT_U): - DEF_OP_CMP(uint32, I32, <); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_LT_U) + { + DEF_OP_CMP(uint32, I32, <); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_GT_S): - DEF_OP_CMP(int32, I32, >); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_GT_S) + { + DEF_OP_CMP(int32, I32, >); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_GT_U): - DEF_OP_CMP(uint32, I32, >); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_GT_U) + { + DEF_OP_CMP(uint32, I32, >); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LE_S): - DEF_OP_CMP(int32, I32, <=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_LE_S) + { + DEF_OP_CMP(int32, I32, <=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_LE_U): - DEF_OP_CMP(uint32, I32, <=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_LE_U) + { + DEF_OP_CMP(uint32, I32, <=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_GE_S): - DEF_OP_CMP(int32, I32, >=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_GE_S) + { + DEF_OP_CMP(int32, I32, >=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_GE_U): - DEF_OP_CMP(uint32, I32, >=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I32_GE_U) + { + DEF_OP_CMP(uint32, I32, >=); + HANDLE_OP_END(); + } - /* comparison instructions of i64 */ - HANDLE_OP (WASM_OP_I64_EQZ): - DEF_OP_EQZ(int64, I64); - HANDLE_OP_END (); + /* comparison instructions of i64 */ + HANDLE_OP(WASM_OP_I64_EQZ) + { + DEF_OP_EQZ(int64, I64); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_EQ): - DEF_OP_CMP(uint64, I64, ==); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_EQ) + { + DEF_OP_CMP(uint64, I64, ==); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_NE): - DEF_OP_CMP(uint64, I64, !=); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_NE) + { + DEF_OP_CMP(uint64, I64, !=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LT_S): - DEF_OP_CMP(int64, I64, <); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_LT_S) + { + DEF_OP_CMP(int64, I64, <); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_LT_U): - DEF_OP_CMP(uint64, I64, <); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_LT_U) + { + DEF_OP_CMP(uint64, I64, <); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_GT_S): - DEF_OP_CMP(int64, I64, >); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_I64_GT_S) + { + DEF_OP_CMP(int64, I64, >); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_GT_U): - DEF_OP_CMP(uint64, I64, >); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_LE_S): - DEF_OP_CMP(int64, I64, <=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_LE_U): - DEF_OP_CMP(uint64, I64, <=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_GE_S): - DEF_OP_CMP(int64, I64, >=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_GE_U): - DEF_OP_CMP(uint64, I64, >=); - HANDLE_OP_END (); - - /* comparison instructions of f32 */ - HANDLE_OP (WASM_OP_F32_EQ): - DEF_OP_CMP(float32, F32, ==); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_NE): - DEF_OP_CMP(float32, F32, !=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_LT): - DEF_OP_CMP(float32, F32, <); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_GT): - DEF_OP_CMP(float32, F32, >); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_LE): - DEF_OP_CMP(float32, F32, <=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_GE): - DEF_OP_CMP(float32, F32, >=); - HANDLE_OP_END (); - - /* comparison instructions of f64 */ - HANDLE_OP (WASM_OP_F64_EQ): - DEF_OP_CMP(float64, F64, ==); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_NE): - DEF_OP_CMP(float64, F64, !=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_LT): - DEF_OP_CMP(float64, F64, <); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_GT): - DEF_OP_CMP(float64, F64, >); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_LE): - DEF_OP_CMP(float64, F64, <=); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_GE): - DEF_OP_CMP(float64, F64, >=); - HANDLE_OP_END (); - - /* numberic instructions of i32 */ - HANDLE_OP (WASM_OP_I32_CLZ): - DEF_OP_BIT_COUNT(uint32, I32, clz32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_CTZ): - DEF_OP_BIT_COUNT(uint32, I32, ctz32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_POPCNT): - DEF_OP_BIT_COUNT(uint32, I32, popcount32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_ADD): - DEF_OP_NUMERIC(uint32, uint32, I32, +); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_SUB): - DEF_OP_NUMERIC(uint32, uint32, I32, -); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_MUL): - DEF_OP_NUMERIC(uint32, uint32, I32, *); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_DIV_S): - { - int32 a, b; - - b = frame_lp[GET_OFFSET()]; - a = frame_lp[GET_OFFSET()]; - addr_ret = GET_OFFSET(); - if (a == (int32)0x80000000 && b == -1) { - wasm_set_exception(module, "integer overflow"); - goto got_exception; - } - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - frame_lp[addr_ret] = (a / b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_DIV_U): - { - uint32 a, b; - - addr1 = GET_OFFSET(); - addr2 = GET_OFFSET(); - addr_ret = GET_OFFSET(); - - b = (uint32)frame_lp[addr1]; - a = (uint32)frame_lp[addr2]; - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - frame_lp[addr_ret] = (a / b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_REM_S): - { - int32 a, b; - - addr1 = GET_OFFSET(); - addr2 = GET_OFFSET(); - addr_ret = GET_OFFSET(); - - b = frame_lp[addr1]; - a = frame_lp[addr2]; - if (a == (int32)0x80000000 && b == -1) { - frame_lp[addr_ret] = 0; - HANDLE_OP_END (); - } - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - frame_lp[addr_ret] = (a % b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_REM_U): - { - uint32 a, b; - - addr1 = GET_OFFSET(); - addr2 = GET_OFFSET(); - addr_ret = GET_OFFSET(); - - b = (uint32)frame_lp[addr1]; - a = (uint32)frame_lp[addr2]; - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - frame_lp[addr_ret] = (a % b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_AND): - DEF_OP_NUMERIC(uint32, uint32, I32, &); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_OR): - DEF_OP_NUMERIC(uint32, uint32, I32, |); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_XOR): - DEF_OP_NUMERIC(uint32, uint32, I32, ^); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_SHL): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC(uint32, uint32, I32, <<); -#else - DEF_OP_NUMERIC2(uint32, uint32, I32, <<); -#endif - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_GT_U) + { + DEF_OP_CMP(uint64, I64, >); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_SHR_S): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC(int32, uint32, I32, >>); -#else - DEF_OP_NUMERIC2(int32, uint32, I32, >>); -#endif - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_LE_S) + { + DEF_OP_CMP(int64, I64, <=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_SHR_U): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC(uint32, uint32, I32, >>); -#else - DEF_OP_NUMERIC2(uint32, uint32, I32, >>); -#endif - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_ROTL): - { - uint32 a, b; - - b = (uint32)frame_lp[GET_OFFSET()]; - a = (uint32)frame_lp[GET_OFFSET()]; - frame_lp[GET_OFFSET()] = rotl32(a, b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I32_ROTR): - { - uint32 a, b; - - b = (uint32)frame_lp[GET_OFFSET()]; - a = (uint32)frame_lp[GET_OFFSET()]; - frame_lp[GET_OFFSET()] = rotr32(a, b); - HANDLE_OP_END (); - } - - /* numberic instructions of i64 */ - HANDLE_OP (WASM_OP_I64_CLZ): - DEF_OP_BIT_COUNT(uint64, I64, clz64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_CTZ): - DEF_OP_BIT_COUNT(uint64, I64, ctz64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_POPCNT): - DEF_OP_BIT_COUNT(uint64, I64, popcount64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_ADD): - DEF_OP_NUMERIC_64(uint64, uint64, I64, +); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_SUB): - DEF_OP_NUMERIC_64(uint64, uint64, I64, -); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_MUL): - DEF_OP_NUMERIC_64(uint64, uint64, I64, *); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_DIV_S): - { - int64 a, b; - - b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - if (a == (int64)0x8000000000000000LL && b == -1) { - wasm_set_exception(module, "integer overflow"); - goto got_exception; - } - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a / b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_DIV_U): - { - uint64 a, b; - - b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a / b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_REM_S): - { - int64 a, b; - - b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - if (a == (int64)0x8000000000000000LL && b == -1) { - *(int64*)(frame_lp + GET_OFFSET()) = 0; - HANDLE_OP_END (); - } - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a % b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_REM_U): - { - uint64 a, b; - - b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - if (b == 0) { - wasm_set_exception(module, "integer divide by zero"); - goto got_exception; - } - PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a % b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_AND): - DEF_OP_NUMERIC_64(uint64, uint64, I64, &); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_OR): - DEF_OP_NUMERIC_64(uint64, uint64, I64, |); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_XOR): - DEF_OP_NUMERIC_64(uint64, uint64, I64, ^); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_SHL): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC_64(uint64, uint64, I64, <<); -#else - DEF_OP_NUMERIC2_64(uint64, uint64, I64, <<); -#endif - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_LE_U) + { + DEF_OP_CMP(uint64, I64, <=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_SHR_S): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC_64(int64, uint64, I64, >>); -#else - DEF_OP_NUMERIC2_64(int64, uint64, I64, >>); -#endif - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_GE_S) + { + DEF_OP_CMP(int64, I64, >=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_SHR_U): - { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) - DEF_OP_NUMERIC_64(uint64, uint64, I64, >>); -#else - DEF_OP_NUMERIC2_64(uint64, uint64, I64, >>); -#endif - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_ROTL): - { - uint64 a, b; - - b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), rotl64(a, b)); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_I64_ROTR): - { - uint64 a, b; - - b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), rotr64(a, b)); - HANDLE_OP_END (); - } - - /* numberic instructions of f32 */ - HANDLE_OP (WASM_OP_F32_ABS): - DEF_OP_MATH(float32, F32, fabs); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_NEG): - { - int32 i32 = (int32)frame_lp[GET_OFFSET()]; - addr_ret = GET_OFFSET(); - int32 sign_bit = i32 & (1 << 31); - if (sign_bit) - frame_lp[addr_ret] = i32 & ~(1 << 31); - else - frame_lp[addr_ret] = (uint32)(i32 | (1 << 31)); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_F32_CEIL): - DEF_OP_MATH(float32, F32, ceil); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_FLOOR): - DEF_OP_MATH(float32, F32, floor); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_TRUNC): - DEF_OP_MATH(float32, F32, trunc); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_NEAREST): - DEF_OP_MATH(float32, F32, rint); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_SQRT): - DEF_OP_MATH(float32, F32, sqrt); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_ADD): - DEF_OP_NUMERIC(float32, float32, F32, +); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_SUB): - DEF_OP_NUMERIC(float32, float32, F32, -); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_MUL): - DEF_OP_NUMERIC(float32, float32, F32, *); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_DIV): - DEF_OP_NUMERIC(float32, float32, F32, /); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_MIN): - { - float32 a, b; - - b = *(float32*)(frame_lp + GET_OFFSET()); - a = *(float32*)(frame_lp + GET_OFFSET()); - - if (isnan(a)) - *(float32*)(frame_lp + GET_OFFSET()) = a; - else if (isnan(b)) - *(float32*)(frame_lp + GET_OFFSET()) = b; - else - *(float32*)(frame_lp + GET_OFFSET()) = wa_fmin(a, b); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_GE_U) + { + DEF_OP_CMP(uint64, I64, >=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_F32_MAX): - { - float32 a, b; + /* comparison instructions of f32 */ + HANDLE_OP(WASM_OP_F32_EQ) + { + DEF_OP_CMP(float32, F32, ==); + HANDLE_OP_END(); + } - b = *(float32*)(frame_lp + GET_OFFSET()); - a = *(float32*)(frame_lp + GET_OFFSET()); + HANDLE_OP(WASM_OP_F32_NE) + { + DEF_OP_CMP(float32, F32, !=); + HANDLE_OP_END(); + } - if (isnan(a)) - *(float32*)(frame_lp + GET_OFFSET()) = a; - else if (isnan(b)) - *(float32*)(frame_lp + GET_OFFSET()) = b; - else - *(float32*)(frame_lp + GET_OFFSET()) = wa_fmax(a, b); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_F32_COPYSIGN): - { - float32 a, b; - - b = *(float32*)(frame_lp + GET_OFFSET()); - a = *(float32*)(frame_lp + GET_OFFSET()); - *(float32*)(frame_lp + GET_OFFSET()) = (signbit(b) ? -fabs(a) : fabs(a)); - HANDLE_OP_END (); - } - - /* numberic instructions of f64 */ - HANDLE_OP (WASM_OP_F64_ABS): - DEF_OP_MATH(float64, F64, fabs); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_NEG): - { - int64 i64 = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); - int64 sign_bit = i64 & (((int64)1) << 63); - if (sign_bit) - PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), - ((uint64)i64 & ~(((uint64)1) << 63))); - else - PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), - ((uint64)i64 | (((uint64)1) << 63))); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_F64_CEIL): - DEF_OP_MATH(float64, F64, ceil); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_FLOOR): - DEF_OP_MATH(float64, F64, floor); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_TRUNC): - DEF_OP_MATH(float64, F64, trunc); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_NEAREST): - DEF_OP_MATH(float64, F64, rint); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_SQRT): - DEF_OP_MATH(float64, F64, sqrt); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_ADD): - DEF_OP_NUMERIC_64(float64, float64, F64, +); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_SUB): - DEF_OP_NUMERIC_64(float64, float64, F64, -); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_MUL): - DEF_OP_NUMERIC_64(float64, float64, F64, *); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_DIV): - DEF_OP_NUMERIC_64(float64, float64, F64, /); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_MIN): - { - float64 a, b; - - b = POP_F64(); - a = POP_F64(); - - if (isnan(a)) - PUSH_F64(a); - else if (isnan(b)) - PUSH_F64(b); - else - PUSH_F64(wa_fmin(a, b)); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_F32_LT) + { + DEF_OP_CMP(float32, F32, <); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_F64_MAX): - { - float64 a, b; + HANDLE_OP(WASM_OP_F32_GT) + { + DEF_OP_CMP(float32, F32, >); + HANDLE_OP_END(); + } - b = POP_F64(); - a = POP_F64(); + HANDLE_OP(WASM_OP_F32_LE) + { + DEF_OP_CMP(float32, F32, <=); + HANDLE_OP_END(); + } - if (isnan(a)) - PUSH_F64(a); - else if (isnan(b)) - PUSH_F64(b); - else - PUSH_F64(wa_fmax(a, b)); - HANDLE_OP_END (); - } - - HANDLE_OP (WASM_OP_F64_COPYSIGN): - { - float64 a, b; - - b = POP_F64(); - a = POP_F64(); - PUSH_F64(signbit(b) ? -fabs(a) : fabs(a)); - HANDLE_OP_END (); - } - - /* conversions of i32 */ - HANDLE_OP (WASM_OP_I32_WRAP_I64): - { - int32 value = (int32)(POP_I64() & 0xFFFFFFFFLL); - PUSH_I32(value); - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_F32_GE) + { + DEF_OP_CMP(float32, F32, >=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_TRUNC_S_F32): - /* We don't use INT32_MIN/INT32_MAX/UINT32_MIN/UINT32_MAX, - since float/double values of ieee754 cannot precisely represent - all int32/uint32/int64/uint64 values, e.g.: - UINT32_MAX is 4294967295, but (float32)4294967295 is 4294967296.0f, - but not 4294967295.0f. */ - DEF_OP_TRUNC_F32(-2147483904.0f, 2147483648.0f, true, true); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_TRUNC_U_F32): - DEF_OP_TRUNC_F32(-1.0f, 4294967296.0f, true, false); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_TRUNC_S_F64): - DEF_OP_TRUNC_F64(-2147483649.0, 2147483648.0, true, true); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I32_TRUNC_U_F64): - DEF_OP_TRUNC_F64(-1.0, 4294967296.0, true, false); - HANDLE_OP_END (); - - /* conversions of i64 */ - HANDLE_OP (WASM_OP_I64_EXTEND_S_I32): - DEF_OP_CONVERT(int64, I64, int32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_EXTEND_U_I32): - DEF_OP_CONVERT(int64, I64, uint32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_TRUNC_S_F32): - DEF_OP_TRUNC_F32(-9223373136366403584.0f, - 9223372036854775808.0f, false, true); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_TRUNC_U_F32): - DEF_OP_TRUNC_F32(-1.0f, 18446744073709551616.0f, - false, false); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_TRUNC_S_F64): - DEF_OP_TRUNC_F64(-9223372036854777856.0, - 9223372036854775808.0, false, true); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_TRUNC_U_F64): - DEF_OP_TRUNC_F64(-1.0, 18446744073709551616.0, - false, false); - HANDLE_OP_END (); - - /* conversions of f32 */ - HANDLE_OP (WASM_OP_F32_CONVERT_S_I32): - DEF_OP_CONVERT(float32, F32, int32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_CONVERT_U_I32): - DEF_OP_CONVERT(float32, F32, uint32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_CONVERT_S_I64): - DEF_OP_CONVERT(float32, F32, int64, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_CONVERT_U_I64): - DEF_OP_CONVERT(float32, F32, uint64, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F32_DEMOTE_F64): - DEF_OP_CONVERT(float32, F32, float64, F64); - HANDLE_OP_END (); - - /* conversions of f64 */ - HANDLE_OP (WASM_OP_F64_CONVERT_S_I32): - DEF_OP_CONVERT(float64, F64, int32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_CONVERT_U_I32): - DEF_OP_CONVERT(float64, F64, uint32, I32); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_CONVERT_S_I64): - DEF_OP_CONVERT(float64, F64, int64, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_CONVERT_U_I64): - DEF_OP_CONVERT(float64, F64, uint64, I64); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_F64_PROMOTE_F32): - DEF_OP_CONVERT(float64, F64, float32, F32); - HANDLE_OP_END (); - - /* reinterpretations */ - HANDLE_OP (WASM_OP_I32_REINTERPRET_F32): - HANDLE_OP (WASM_OP_F32_REINTERPRET_I32): - DEF_OP_REINTERPRET(uint32, I32); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I64_REINTERPRET_F64): - HANDLE_OP (WASM_OP_F64_REINTERPRET_I64): - DEF_OP_REINTERPRET(int64, I64); - HANDLE_OP_END (); - - HANDLE_OP (EXT_OP_COPY_STACK_TOP): - addr1 = GET_OFFSET(); - addr2 = GET_OFFSET(); - frame_lp[addr2] = frame_lp[addr1]; - HANDLE_OP_END (); - - HANDLE_OP (EXT_OP_COPY_STACK_TOP_I64): - addr1 = GET_OFFSET(); - addr2 = GET_OFFSET(); - frame_lp[addr2] = frame_lp[addr1]; - frame_lp[addr2 + 1] = frame_lp[addr1 + 1]; - HANDLE_OP_END (); - - HANDLE_OP (EXT_OP_COPY_STACK_VALUES): - { - uint32 values_count, total_cell; - uint8 *cells; - int16 *src_offsets = NULL; - uint16 *dst_offsets = NULL; - - /* read values_count */ - values_count = read_uint32(frame_ip); - /* read total cell num */ - total_cell = read_uint32(frame_ip); - /* cells */ - cells = (uint8 *)frame_ip; - frame_ip += values_count * CELL_SIZE; - /* src offsets */ - src_offsets = (int16 *)frame_ip; - frame_ip += values_count * sizeof(int16); - /* dst offsets */ - dst_offsets = (uint16*)frame_ip; - frame_ip += values_count * sizeof(uint16); - - if (!copy_stack_values(module, frame_lp, values_count, - total_cell, cells, - src_offsets, dst_offsets)) - goto got_exception; - - HANDLE_OP_END (); - } - HANDLE_OP (WASM_OP_SET_LOCAL): - HANDLE_OP (WASM_OP_TEE_LOCAL): - { - GET_LOCAL_INDEX_TYPE_AND_OFFSET(); - addr1 = GET_OFFSET(); - - if (local_type == VALUE_TYPE_I32 - || local_type == VALUE_TYPE_F32) { - *(int32*)(frame_lp + local_offset) = frame_lp[addr1]; - } - else if (local_type == VALUE_TYPE_I64 - || local_type == VALUE_TYPE_F64) { - PUT_I64_TO_ADDR((uint32*)(frame_lp + local_offset), - GET_I64_FROM_ADDR(frame_lp + addr1)); - } - else { - wasm_set_exception(module, "invalid local type"); - goto got_exception; - } + /* comparison instructions of f64 */ + HANDLE_OP(WASM_OP_F64_EQ) + { + DEF_OP_CMP(float64, F64, ==); + HANDLE_OP_END(); + } - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_F64_NE) + { + DEF_OP_CMP(float64, F64, !=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_EXTEND8_S): - DEF_OP_CONVERT(int32, I32, int8, I32); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_F64_LT) + { + DEF_OP_CMP(float64, F64, <); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I32_EXTEND16_S): - DEF_OP_CONVERT(int32, I32, int16, I32); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_F64_GT) + { + DEF_OP_CMP(float64, F64, >); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_EXTEND8_S): - DEF_OP_CONVERT(int64, I64, int8, I64); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_F64_LE) + { + DEF_OP_CMP(float64, F64, <=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_EXTEND16_S): - DEF_OP_CONVERT(int64, I64, int16, I64); - HANDLE_OP_END (); + HANDLE_OP(WASM_OP_F64_GE) + { + DEF_OP_CMP(float64, F64, >=); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_I64_EXTEND32_S): - DEF_OP_CONVERT(int64, I64, int32, I64); - HANDLE_OP_END (); + /* numberic instructions of i32 */ + HANDLE_OP(WASM_OP_I32_CLZ) + { + DEF_OP_BIT_COUNT(uint32, I32, clz32); + HANDLE_OP_END(); + } - HANDLE_OP (WASM_OP_MISC_PREFIX): - { - GET_OPCODE(); - switch (opcode) - { - case WASM_OP_I32_TRUNC_SAT_S_F32: - DEF_OP_TRUNC_SAT_F32(-2147483904.0f, 2147483648.0f, - true, true); - break; - case WASM_OP_I32_TRUNC_SAT_U_F32: - DEF_OP_TRUNC_SAT_F32(-1.0f, 4294967296.0f, - true, false); - break; - case WASM_OP_I32_TRUNC_SAT_S_F64: - DEF_OP_TRUNC_SAT_F64(-2147483649.0, 2147483648.0, - true, true); - break; - case WASM_OP_I32_TRUNC_SAT_U_F64: - DEF_OP_TRUNC_SAT_F64(-1.0, 4294967296.0, - true, false); - break; - case WASM_OP_I64_TRUNC_SAT_S_F32: - DEF_OP_TRUNC_SAT_F32(-9223373136366403584.0f, 9223372036854775808.0f, - false, true); - break; - case WASM_OP_I64_TRUNC_SAT_U_F32: - DEF_OP_TRUNC_SAT_F32(-1.0f, 18446744073709551616.0f, - false, false); - break; - case WASM_OP_I64_TRUNC_SAT_S_F64: - DEF_OP_TRUNC_SAT_F64(-9223372036854777856.0, 9223372036854775808.0, - false, true); - break; - case WASM_OP_I64_TRUNC_SAT_U_F64: - DEF_OP_TRUNC_SAT_F64(-1.0, 18446744073709551616.0, - false, false); - break; -#if WASM_ENABLE_BULK_MEMORY != 0 - case WASM_OP_MEMORY_INIT: - { - uint32 addr, segment; - uint64 bytes, offset, seg_len; - uint8* data; + HANDLE_OP(WASM_OP_I32_CTZ) + { + DEF_OP_BIT_COUNT(uint32, I32, ctz32); + HANDLE_OP_END(); + } - segment = read_uint32(frame_ip); + HANDLE_OP(WASM_OP_I32_POPCNT) + { + DEF_OP_BIT_COUNT(uint32, I32, popcount32); + HANDLE_OP_END(); + } - bytes = (uint64)POP_I32(); - offset = (uint64)POP_I32(); - addr = POP_I32(); + HANDLE_OP(WASM_OP_I32_ADD) + { + DEF_OP_NUMERIC(uint32, uint32, I32, +); + HANDLE_OP_END(); + } - CHECK_BULK_MEMORY_OVERFLOW(addr, bytes, maddr); + HANDLE_OP(WASM_OP_I32_SUB) + { + DEF_OP_NUMERIC(uint32, uint32, I32, -); + HANDLE_OP_END(); + } - seg_len = (uint64)module->module->data_segments[segment]->data_length; - data = module->module->data_segments[segment]->data; - if (offset + bytes > seg_len) - goto out_of_bounds; + HANDLE_OP(WASM_OP_I32_MUL) + { + DEF_OP_NUMERIC(uint32, uint32, I32, *); + HANDLE_OP_END(); + } - bh_memcpy_s(maddr, linear_mem_size - addr, data + offset, bytes); - break; - } - case WASM_OP_DATA_DROP: - { - uint32 segment; + HANDLE_OP(WASM_OP_I32_DIV_S) + { + int32 a, b; + + b = frame_lp[GET_OFFSET()]; + a = frame_lp[GET_OFFSET()]; + addr_ret = GET_OFFSET(); + if (a == (int32)0x80000000 && b == -1) { + wasm_set_exception(module, "integer overflow"); + goto got_exception; + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + frame_lp[addr_ret] = (a / b); + HANDLE_OP_END(); + } - segment = read_uint32(frame_ip); + HANDLE_OP(WASM_OP_I32_DIV_U) + { + uint32 a, b; + + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + + b = (uint32)frame_lp[addr1]; + a = (uint32)frame_lp[addr2]; + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + frame_lp[addr_ret] = (a / b); + HANDLE_OP_END(); + } - module->module->data_segments[segment]->data_length = 0; + HANDLE_OP(WASM_OP_I32_REM_S) + { + int32 a, b; + + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + + b = frame_lp[addr1]; + a = frame_lp[addr2]; + if (a == (int32)0x80000000 && b == -1) { + frame_lp[addr_ret] = 0; + HANDLE_OP_END(); + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + frame_lp[addr_ret] = (a % b); + HANDLE_OP_END(); + } - break; - } - case WASM_OP_MEMORY_COPY: - { - uint32 dst, src, len; - uint8 *mdst, *msrc; + HANDLE_OP(WASM_OP_I32_REM_U) + { + uint32 a, b; + + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + addr_ret = GET_OFFSET(); + + b = (uint32)frame_lp[addr1]; + a = (uint32)frame_lp[addr2]; + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + frame_lp[addr_ret] = (a % b); + HANDLE_OP_END(); + } - len = POP_I32(); - src = POP_I32(); - dst = POP_I32(); + HANDLE_OP(WASM_OP_I32_AND) + { + DEF_OP_NUMERIC(uint32, uint32, I32, &); + HANDLE_OP_END(); + } - CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc); - CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); + HANDLE_OP(WASM_OP_I32_OR) + { + DEF_OP_NUMERIC(uint32, uint32, I32, |); + HANDLE_OP_END(); + } - /* allowing the destination and source to overlap */ - bh_memmove_s(mdst, linear_mem_size - dst, msrc, len); + HANDLE_OP(WASM_OP_I32_XOR) + { + DEF_OP_NUMERIC(uint32, uint32, I32, ^); + HANDLE_OP_END(); + } - break; - } - case WASM_OP_MEMORY_FILL: - { - uint32 dst, len; - uint8 val, *mdst; + HANDLE_OP(WASM_OP_I32_SHL) + { + DEF_OP_NUMERIC2(uint32, uint32, I32, <<); + HANDLE_OP_END(); + } - len = POP_I32(); - val = POP_I32(); - dst = POP_I32(); + HANDLE_OP(WASM_OP_I32_SHR_S) + { + DEF_OP_NUMERIC2(int32, uint32, I32, >>); + HANDLE_OP_END(); + } - CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); + HANDLE_OP(WASM_OP_I32_SHR_U) + { + DEF_OP_NUMERIC2(uint32, uint32, I32, >>); + HANDLE_OP_END(); + } - memset(mdst, val, len); + HANDLE_OP(WASM_OP_I32_ROTL) + { + uint32 a, b; - break; - } -#endif /* WASM_ENABLE_BULK_MEMORY */ -#if WASM_ENABLE_REF_TYPES != 0 - case WASM_OP_TABLE_INIT: - { - uint32 tbl_idx, elem_idx; - uint64 n, s, d; - WASMTableInstance *tbl_inst; + b = (uint32)frame_lp[GET_OFFSET()]; + a = (uint32)frame_lp[GET_OFFSET()]; + frame_lp[GET_OFFSET()] = rotl32(a, b); + HANDLE_OP_END(); + } - elem_idx = read_uint32(frame_ip); - bh_assert(elem_idx < module->module->table_seg_count); + HANDLE_OP(WASM_OP_I32_ROTR) + { + uint32 a, b; - tbl_idx = read_uint32(frame_ip); - bh_assert(tbl_idx < module->module->table_count); + b = (uint32)frame_lp[GET_OFFSET()]; + a = (uint32)frame_lp[GET_OFFSET()]; + frame_lp[GET_OFFSET()] = rotr32(a, b); + HANDLE_OP_END(); + } - tbl_inst = wasm_get_table_inst(module, tbl_idx); + /* numberic instructions of i64 */ + HANDLE_OP(WASM_OP_I64_CLZ) + { + DEF_OP_BIT_COUNT(uint64, I64, clz64); + HANDLE_OP_END(); + } - n = (uint32)POP_I32(); - s = (uint32)POP_I32(); - d = (uint32)POP_I32(); + HANDLE_OP(WASM_OP_I64_CTZ) + { + DEF_OP_BIT_COUNT(uint64, I64, ctz64); + HANDLE_OP_END(); + } - if (!n) { - break; + HANDLE_OP(WASM_OP_I64_POPCNT) + { + DEF_OP_BIT_COUNT(uint64, I64, popcount64); + HANDLE_OP_END(); } - if (n + s > module->module->table_segments[elem_idx].function_count - || d + n > tbl_inst->cur_size) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; + HANDLE_OP(WASM_OP_I64_ADD) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, +); + HANDLE_OP_END(); } - if (module->module->table_segments[elem_idx].is_dropped) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; + HANDLE_OP(WASM_OP_I64_SUB) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, -); + HANDLE_OP_END(); } - if (!wasm_elem_is_passive( - module->module->table_segments[elem_idx].mode)) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; + HANDLE_OP(WASM_OP_I64_MUL) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, *); + HANDLE_OP_END(); } - bh_memcpy_s( - (uint8 *)tbl_inst + offsetof(WASMTableInstance, base_addr) - + d * sizeof(uint32), - (tbl_inst->cur_size - d) * sizeof(uint32), - module->module->table_segments[elem_idx].func_indexes + s, - n * sizeof(uint32)); - break; - } - case WASM_OP_ELEM_DROP: - { - uint32 elem_idx = read_uint32(frame_ip); - bh_assert(elem_idx < module->module->table_seg_count); + HANDLE_OP(WASM_OP_I64_DIV_S) + { + int64 a, b; + + b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + if (a == (int64)0x8000000000000000LL && b == -1) { + wasm_set_exception(module, "integer overflow"); + goto got_exception; + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a / b); + HANDLE_OP_END(); + } - module->module->table_segments[elem_idx].is_dropped = true; - break; - } - case WASM_OP_TABLE_COPY: - { - uint32 src_tbl_idx, dst_tbl_idx; - uint64 n, s, d; - WASMTableInstance *src_tbl_inst, *dst_tbl_inst; + HANDLE_OP(WASM_OP_I64_DIV_U) + { + uint64 a, b; + + b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a / b); + HANDLE_OP_END(); + } - dst_tbl_idx = read_uint32(frame_ip); - bh_assert(dst_tbl_idx < module->table_count); + HANDLE_OP(WASM_OP_I64_REM_S) + { + int64 a, b; + + b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + if (a == (int64)0x8000000000000000LL && b == -1) { + *(int64 *)(frame_lp + GET_OFFSET()) = 0; + HANDLE_OP_END(); + } + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a % b); + HANDLE_OP_END(); + } - dst_tbl_inst = wasm_get_table_inst(module, dst_tbl_idx); + HANDLE_OP(WASM_OP_I64_REM_U) + { + uint64 a, b; + + b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + if (b == 0) { + wasm_set_exception(module, "integer divide by zero"); + goto got_exception; + } + PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), a % b); + HANDLE_OP_END(); + } - src_tbl_idx = read_uint32(frame_ip); - bh_assert(src_tbl_idx < module->table_count); + HANDLE_OP(WASM_OP_I64_AND) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, &); + HANDLE_OP_END(); + } - src_tbl_inst = wasm_get_table_inst(module, src_tbl_idx); + HANDLE_OP(WASM_OP_I64_OR) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, |); + HANDLE_OP_END(); + } - n = (uint32)POP_I32(); - s = (uint32)POP_I32(); - d = (uint32)POP_I32(); + HANDLE_OP(WASM_OP_I64_XOR) + { + DEF_OP_NUMERIC_64(uint64, uint64, I64, ^); + HANDLE_OP_END(); + } - if (s + n > dst_tbl_inst->cur_size - || d + n > src_tbl_inst->cur_size) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; + HANDLE_OP(WASM_OP_I64_SHL) + { + DEF_OP_NUMERIC2_64(uint64, uint64, I64, <<); + HANDLE_OP_END(); } - /* if s >= d, copy from front to back */ - /* if s < d, copy from back to front */ - /* merge all together */ - bh_memcpy_s( - (uint8 *)dst_tbl_inst + offsetof(WASMTableInstance, base_addr) - + d * sizeof(uint32), - (dst_tbl_inst->cur_size - d) * sizeof(uint32), - (uint8 *)src_tbl_inst - + offsetof(WASMTableInstance, base_addr) + s * sizeof(uint32), - n * sizeof(uint32)); - break; - } - case WASM_OP_TABLE_GROW: - { - uint32 tbl_idx, n, init_val, orig_tbl_sz; - WASMTableInstance *tbl_inst; + HANDLE_OP(WASM_OP_I64_SHR_S) + { + DEF_OP_NUMERIC2_64(int64, uint64, I64, >>); + HANDLE_OP_END(); + } - tbl_idx = read_uint32(frame_ip); - bh_assert(tbl_idx < module->table_count); + HANDLE_OP(WASM_OP_I64_SHR_U) + { + DEF_OP_NUMERIC2_64(uint64, uint64, I64, >>); + HANDLE_OP_END(); + } - tbl_inst = wasm_get_table_inst(module, tbl_idx); + HANDLE_OP(WASM_OP_I64_ROTL) + { + uint64 a, b; - orig_tbl_sz = tbl_inst->cur_size; + b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), rotl64(a, b)); + HANDLE_OP_END(); + } - n = POP_I32(); - init_val = POP_I32(); + HANDLE_OP(WASM_OP_I64_ROTR) + { + uint64 a, b; - if (!wasm_enlarge_table(module, tbl_idx, n, init_val)) { - PUSH_I32(-1); - } else { - PUSH_I32(orig_tbl_sz); + b = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + a = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), rotr64(a, b)); + HANDLE_OP_END(); } - break; - } - case WASM_OP_TABLE_SIZE: - { - uint32 tbl_idx; - WASMTableInstance *tbl_inst; + /* numberic instructions of f32 */ + HANDLE_OP(WASM_OP_F32_ABS) + { + DEF_OP_MATH(float32, F32, fabs); + HANDLE_OP_END(); + } - tbl_idx = read_uint32(frame_ip); - bh_assert(tbl_idx < module->table_count); + HANDLE_OP(WASM_OP_F32_NEG) + { + uint32 u32 = frame_lp[GET_OFFSET()]; + uint32 sign_bit = u32 & ((uint32)1 << 31); + addr_ret = GET_OFFSET(); + if (sign_bit) + frame_lp[addr_ret] = u32 & ~((uint32)1 << 31); + else + frame_lp[addr_ret] = u32 | ((uint32)1 << 31); + HANDLE_OP_END(); + } - tbl_inst = wasm_get_table_inst(module, tbl_idx); + HANDLE_OP(WASM_OP_F32_CEIL) + { + DEF_OP_MATH(float32, F32, ceil); + HANDLE_OP_END(); + } - PUSH_I32(tbl_inst->cur_size); - break; - } - case WASM_OP_TABLE_FILL: - { - uint32 tbl_idx, n, val, i; - WASMTableInstance *tbl_inst; + HANDLE_OP(WASM_OP_F32_FLOOR) + { + DEF_OP_MATH(float32, F32, floor); + HANDLE_OP_END(); + } - tbl_idx = read_uint32(frame_ip); - bh_assert(tbl_idx < module->table_count); + HANDLE_OP(WASM_OP_F32_TRUNC) + { + DEF_OP_MATH(float32, F32, trunc); + HANDLE_OP_END(); + } - tbl_inst = wasm_get_table_inst(module, tbl_idx); + HANDLE_OP(WASM_OP_F32_NEAREST) + { + DEF_OP_MATH(float32, F32, rint); + HANDLE_OP_END(); + } - n = POP_I32(); - val = POP_I32(); - i = POP_I32(); + HANDLE_OP(WASM_OP_F32_SQRT) + { + DEF_OP_MATH(float32, F32, sqrt); + HANDLE_OP_END(); + } - if (i + n > tbl_inst->cur_size) { - wasm_set_exception(module, "out of bounds table access"); - goto got_exception; + HANDLE_OP(WASM_OP_F32_ADD) + { + DEF_OP_NUMERIC(float32, float32, F32, +); + HANDLE_OP_END(); } - for (; n != 0; i++, n--) { - ((uint32 *)(tbl_inst->base_addr))[i] = val; + HANDLE_OP(WASM_OP_F32_SUB) + { + DEF_OP_NUMERIC(float32, float32, F32, -); + HANDLE_OP_END(); } - break; - } -#endif /* WASM_ENABLE_REF_TYPES */ - default: - wasm_set_exception(module, "unsupported opcode"); - goto got_exception; - } - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_F32_MUL) + { + DEF_OP_NUMERIC(float32, float32, F32, *); + HANDLE_OP_END(); + } -#if WASM_ENABLE_SHARED_MEMORY != 0 - HANDLE_OP (WASM_OP_ATOMIC_PREFIX): - { - uint32 offset, addr; + HANDLE_OP(WASM_OP_F32_DIV) + { + DEF_OP_NUMERIC(float32, float32, F32, /); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_MIN) + { + float32 a, b; + + b = *(float32 *)(frame_lp + GET_OFFSET()); + a = *(float32 *)(frame_lp + GET_OFFSET()); + + if (isnan(a)) + *(float32 *)(frame_lp + GET_OFFSET()) = a; + else if (isnan(b)) + *(float32 *)(frame_lp + GET_OFFSET()) = b; + else + *(float32 *)(frame_lp + GET_OFFSET()) = + (float32)wa_fmin(a, b); + HANDLE_OP_END(); + } - GET_OPCODE(); + HANDLE_OP(WASM_OP_F32_MAX) + { + float32 a, b; + + b = *(float32 *)(frame_lp + GET_OFFSET()); + a = *(float32 *)(frame_lp + GET_OFFSET()); + + if (isnan(a)) + *(float32 *)(frame_lp + GET_OFFSET()) = a; + else if (isnan(b)) + *(float32 *)(frame_lp + GET_OFFSET()) = b; + else + *(float32 *)(frame_lp + GET_OFFSET()) = + (float32)wa_fmax(a, b); + HANDLE_OP_END(); + } - offset = read_uint32(frame_ip); + HANDLE_OP(WASM_OP_F32_COPYSIGN) + { + float32 a, b; - switch (opcode) { - case WASM_OP_ATOMIC_NOTIFY: - { - uint32 count, ret; - - count = POP_I32(); - addr = POP_I32(); - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(4); - - ret = wasm_runtime_atomic_notify((WASMModuleInstanceCommon*)module, - maddr, count); - bh_assert((int32)ret >= 0); - - PUSH_I32(ret); - break; - } - case WASM_OP_ATOMIC_WAIT32: - { - uint64 timeout; - uint32 expect, addr, ret; - - timeout = POP_I64(); - expect = POP_I32(); - addr = POP_I32(); - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(4); - - ret = wasm_runtime_atomic_wait((WASMModuleInstanceCommon*)module, maddr, - (uint64)expect, timeout, false); - if (ret == (uint32)-1) - goto got_exception; - - PUSH_I32(ret); - break; - } - case WASM_OP_ATOMIC_WAIT64: - { - uint64 timeout, expect; - uint32 ret; - - timeout = POP_I64(); - expect = POP_I64(); - addr = POP_I32(); - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(8); - - ret = wasm_runtime_atomic_wait((WASMModuleInstanceCommon*)module, - maddr, expect, timeout, true); - if (ret == (uint32)-1) - goto got_exception; - - PUSH_I32(ret); - break; - } - - case WASM_OP_ATOMIC_I32_LOAD: - case WASM_OP_ATOMIC_I32_LOAD8_U: - case WASM_OP_ATOMIC_I32_LOAD16_U: - { - uint32 readv; - - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&memory->mem_lock); - readv = (uint32)(*(uint8*)maddr); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&memory->mem_lock); - readv = (uint32)LOAD_U16(maddr); - os_mutex_unlock(&memory->mem_lock); + b = *(float32 *)(frame_lp + GET_OFFSET()); + a = *(float32 *)(frame_lp + GET_OFFSET()); + *(float32 *)(frame_lp + GET_OFFSET()) = + (float32)(signbit(b) ? -fabs(a) : fabs(a)); + HANDLE_OP_END(); } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&memory->mem_lock); - readv = LOAD_I32(maddr); - os_mutex_unlock(&memory->mem_lock); - } - - PUSH_I32(readv); - break; - } - - case WASM_OP_ATOMIC_I64_LOAD: - case WASM_OP_ATOMIC_I64_LOAD8_U: - case WASM_OP_ATOMIC_I64_LOAD16_U: - case WASM_OP_ATOMIC_I64_LOAD32_U: - { - uint64 readv; - - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&memory->mem_lock); - readv = (uint64)(*(uint8*)maddr); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&memory->mem_lock); - readv = (uint64)LOAD_U16(maddr); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&memory->mem_lock); - readv = (uint64)LOAD_U32(maddr); - os_mutex_unlock(&memory->mem_lock); + + /* numberic instructions of f64 */ + HANDLE_OP(WASM_OP_F64_ABS) + { + DEF_OP_MATH(float64, F64, fabs); + HANDLE_OP_END(); } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&memory->mem_lock); - readv = LOAD_I64(maddr); - os_mutex_unlock(&memory->mem_lock); - } - - PUSH_I64(readv); - break; - } - case WASM_OP_ATOMIC_I32_STORE: - case WASM_OP_ATOMIC_I32_STORE8: - case WASM_OP_ATOMIC_I32_STORE16: - { - uint32 sval; - - sval = (uint32)POP_I32(); - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_I32_STORE8) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&memory->mem_lock); - *(uint8*)maddr = (uint8)sval; - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&memory->mem_lock); - STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&memory->mem_lock); + + HANDLE_OP(WASM_OP_F64_NEG) + { + uint64 u64 = GET_I64_FROM_ADDR(frame_lp + GET_OFFSET()); + uint64 sign_bit = u64 & (((uint64)1) << 63); + if (sign_bit) + PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), + (u64 & ~(((uint64)1) << 63))); + else + PUT_I64_TO_ADDR(frame_lp + GET_OFFSET(), + (u64 | (((uint64)1) << 63))); + HANDLE_OP_END(); } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&memory->mem_lock); - STORE_U32(maddr, sval); - os_mutex_unlock(&memory->mem_lock); - } - break; - } - - case WASM_OP_ATOMIC_I64_STORE: - case WASM_OP_ATOMIC_I64_STORE8: - case WASM_OP_ATOMIC_I64_STORE16: - case WASM_OP_ATOMIC_I64_STORE32: - { - uint64 sval; - - sval = (uint64)POP_I64(); - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_I64_STORE8) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&memory->mem_lock); - *(uint8*)maddr = (uint8)sval; - os_mutex_unlock(&memory->mem_lock); - } - else if(opcode == WASM_OP_ATOMIC_I64_STORE16) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&memory->mem_lock); - STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&memory->mem_lock); - STORE_U32(maddr, (uint32)sval); - os_mutex_unlock(&memory->mem_lock); + + HANDLE_OP(WASM_OP_F64_CEIL) + { + DEF_OP_MATH(float64, F64, ceil); + HANDLE_OP_END(); } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&memory->mem_lock); - STORE_I64(maddr, sval); - os_mutex_unlock(&memory->mem_lock); - } - break; - } - - case WASM_OP_ATOMIC_RMW_I32_CMPXCHG: - case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U: - case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U: - { - uint32 readv, sval, expect; - - sval = POP_I32(); - expect = POP_I32(); - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(1); - - os_mutex_lock(&memory->mem_lock); - readv = (uint32)(*(uint8*)maddr); - if (readv == expect) - *(uint8*)maddr = (uint8)(sval); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(2); - - os_mutex_lock(&memory->mem_lock); - readv = (uint32)LOAD_U16(maddr); - if (readv == expect) - STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&memory->mem_lock); + + HANDLE_OP(WASM_OP_F64_FLOOR) + { + DEF_OP_MATH(float64, F64, floor); + HANDLE_OP_END(); } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&memory->mem_lock); - readv = LOAD_I32(maddr); - if (readv == expect) - STORE_U32(maddr, sval); - os_mutex_unlock(&memory->mem_lock); - } - PUSH_I32(readv); - break; - } - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG: - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U: - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U: - case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U: - { - uint64 readv, sval, expect; - - sval = (uint64)POP_I64(); - expect = (uint64)POP_I64(); - addr = POP_I32(); - - if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(1); - - os_mutex_lock(&memory->mem_lock); - readv = (uint64)(*(uint8*)maddr); - if (readv == expect) - *(uint8*)maddr = (uint8)(sval); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(2); - - os_mutex_lock(&memory->mem_lock); - readv = (uint64)LOAD_U16(maddr); - if (readv == expect) - STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&memory->mem_lock); - } - else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(4); - - os_mutex_lock(&memory->mem_lock); - readv = (uint64)LOAD_U32(maddr); - if (readv == expect) - STORE_U32(maddr, (uint32)(sval)); - os_mutex_unlock(&memory->mem_lock); + HANDLE_OP(WASM_OP_F64_TRUNC) + { + DEF_OP_MATH(float64, F64, trunc); + HANDLE_OP_END(); } - else { - CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); - CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&memory->mem_lock); - readv = (uint64)LOAD_I64(maddr); - if (readv == expect) { - STORE_I64(maddr, sval); - } - os_mutex_unlock(&memory->mem_lock); - } - PUSH_I64(readv); - break; - } - - DEF_ATOMIC_RMW_OPCODE(ADD, +); - DEF_ATOMIC_RMW_OPCODE(SUB, -); - DEF_ATOMIC_RMW_OPCODE(AND, &); - DEF_ATOMIC_RMW_OPCODE(OR, |); - DEF_ATOMIC_RMW_OPCODE(XOR, ^); - /* xchg, ignore the read value, and store the given value: - readv * 0 + sval */ - DEF_ATOMIC_RMW_OPCODE(XCHG, *0 +); - } + HANDLE_OP(WASM_OP_F64_NEAREST) + { + DEF_OP_MATH(float64, F64, rint); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_SQRT) + { + DEF_OP_MATH(float64, F64, sqrt); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_ADD) + { + DEF_OP_NUMERIC_64(float64, float64, F64, +); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_SUB) + { + DEF_OP_NUMERIC_64(float64, float64, F64, -); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_MUL) + { + DEF_OP_NUMERIC_64(float64, float64, F64, *); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_DIV) + { + DEF_OP_NUMERIC_64(float64, float64, F64, /); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_MIN) + { + float64 a, b; + + b = POP_F64(); + a = POP_F64(); + + if (isnan(a)) + PUSH_F64(a); + else if (isnan(b)) + PUSH_F64(b); + else + PUSH_F64(wa_fmin(a, b)); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_MAX) + { + float64 a, b; + + b = POP_F64(); + a = POP_F64(); + + if (isnan(a)) + PUSH_F64(a); + else if (isnan(b)) + PUSH_F64(b); + else + PUSH_F64(wa_fmax(a, b)); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_COPYSIGN) + { + float64 a, b; + + b = POP_F64(); + a = POP_F64(); + PUSH_F64(signbit(b) ? -fabs(a) : fabs(a)); + HANDLE_OP_END(); + } + + /* conversions of i32 */ + HANDLE_OP(WASM_OP_I32_WRAP_I64) + { + int32 value = (int32)(POP_I64() & 0xFFFFFFFFLL); + PUSH_I32(value); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_TRUNC_S_F32) + { + /* We don't use INT32_MIN/INT32_MAX/UINT32_MIN/UINT32_MAX, + since float/double values of ieee754 cannot precisely + represent all int32/uint32/int64/uint64 values, e.g.: + UINT32_MAX is 4294967295, but (float32)4294967295 is + 4294967296.0f, but not 4294967295.0f. */ + DEF_OP_TRUNC_F32(-2147483904.0f, 2147483648.0f, true, true); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_TRUNC_U_F32) + { + DEF_OP_TRUNC_F32(-1.0f, 4294967296.0f, true, false); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_TRUNC_S_F64) + { + DEF_OP_TRUNC_F64(-2147483649.0, 2147483648.0, true, true); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_TRUNC_U_F64) + { + DEF_OP_TRUNC_F64(-1.0, 4294967296.0, true, false); + HANDLE_OP_END(); + } + + /* conversions of i64 */ + HANDLE_OP(WASM_OP_I64_EXTEND_S_I32) + { + DEF_OP_CONVERT(int64, I64, int32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_EXTEND_U_I32) + { + DEF_OP_CONVERT(int64, I64, uint32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_TRUNC_S_F32) + { + DEF_OP_TRUNC_F32(-9223373136366403584.0f, + 9223372036854775808.0f, false, true); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_TRUNC_U_F32) + { + DEF_OP_TRUNC_F32(-1.0f, 18446744073709551616.0f, false, false); + HANDLE_OP_END(); + } - HANDLE_OP_END (); - } + HANDLE_OP(WASM_OP_I64_TRUNC_S_F64) + { + DEF_OP_TRUNC_F64(-9223372036854777856.0, 9223372036854775808.0, + false, true); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_TRUNC_U_F64) + { + DEF_OP_TRUNC_F64(-1.0, 18446744073709551616.0, false, false); + HANDLE_OP_END(); + } + + /* conversions of f32 */ + HANDLE_OP(WASM_OP_F32_CONVERT_S_I32) + { + DEF_OP_CONVERT(float32, F32, int32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_CONVERT_U_I32) + { + DEF_OP_CONVERT(float32, F32, uint32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_CONVERT_S_I64) + { + DEF_OP_CONVERT(float32, F32, int64, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_CONVERT_U_I64) + { + DEF_OP_CONVERT(float32, F32, uint64, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F32_DEMOTE_F64) + { + DEF_OP_CONVERT(float32, F32, float64, F64); + HANDLE_OP_END(); + } + + /* conversions of f64 */ + HANDLE_OP(WASM_OP_F64_CONVERT_S_I32) + { + DEF_OP_CONVERT(float64, F64, int32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_CONVERT_U_I32) + { + DEF_OP_CONVERT(float64, F64, uint32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_CONVERT_S_I64) + { + DEF_OP_CONVERT(float64, F64, int64, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_CONVERT_U_I64) + { + DEF_OP_CONVERT(float64, F64, uint64, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_F64_PROMOTE_F32) + { + DEF_OP_CONVERT(float64, F64, float32, F32); + HANDLE_OP_END(); + } + + /* reinterpretations */ + HANDLE_OP(WASM_OP_I32_REINTERPRET_F32) + HANDLE_OP(WASM_OP_F32_REINTERPRET_I32) + { + DEF_OP_REINTERPRET(uint32, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_REINTERPRET_F64) + HANDLE_OP(WASM_OP_F64_REINTERPRET_I64) + { + DEF_OP_REINTERPRET(int64, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(EXT_OP_COPY_STACK_TOP) + { + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + frame_lp[addr2] = frame_lp[addr1]; + HANDLE_OP_END(); + } + + HANDLE_OP(EXT_OP_COPY_STACK_TOP_I64) + { + addr1 = GET_OFFSET(); + addr2 = GET_OFFSET(); + frame_lp[addr2] = frame_lp[addr1]; + frame_lp[addr2 + 1] = frame_lp[addr1 + 1]; + HANDLE_OP_END(); + } + + HANDLE_OP(EXT_OP_COPY_STACK_VALUES) + { + uint32 values_count, total_cell; + uint8 *cells; + int16 *src_offsets = NULL; + uint16 *dst_offsets = NULL; + + /* read values_count */ + values_count = read_uint32(frame_ip); + /* read total cell num */ + total_cell = read_uint32(frame_ip); + /* cells */ + cells = (uint8 *)frame_ip; + frame_ip += values_count * CELL_SIZE; + /* src offsets */ + src_offsets = (int16 *)frame_ip; + frame_ip += values_count * sizeof(int16); + /* dst offsets */ + dst_offsets = (uint16 *)frame_ip; + frame_ip += values_count * sizeof(uint16); + + if (!copy_stack_values(module, frame_lp, values_count, + total_cell, cells, src_offsets, + dst_offsets)) + goto got_exception; + + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_SET_LOCAL) + HANDLE_OP(WASM_OP_TEE_LOCAL) + { + GET_LOCAL_INDEX_TYPE_AND_OFFSET(); + addr1 = GET_OFFSET(); + + if (local_type == VALUE_TYPE_I32 + || local_type == VALUE_TYPE_F32) { + *(int32 *)(frame_lp + local_offset) = frame_lp[addr1]; + } + else if (local_type == VALUE_TYPE_I64 + || local_type == VALUE_TYPE_F64) { + PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset), + GET_I64_FROM_ADDR(frame_lp + addr1)); + } + else { + wasm_set_exception(module, "invalid local type"); + goto got_exception; + } + + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_EXTEND8_S) + { + DEF_OP_CONVERT(int32, I32, int8, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I32_EXTEND16_S) + { + DEF_OP_CONVERT(int32, I32, int16, I32); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_EXTEND8_S) + { + DEF_OP_CONVERT(int64, I64, int8, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_EXTEND16_S) + { + DEF_OP_CONVERT(int64, I64, int16, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_I64_EXTEND32_S) + { + DEF_OP_CONVERT(int64, I64, int32, I64); + HANDLE_OP_END(); + } + + HANDLE_OP(WASM_OP_MISC_PREFIX) + { + GET_OPCODE(); + switch (opcode) { + case WASM_OP_I32_TRUNC_SAT_S_F32: + DEF_OP_TRUNC_SAT_F32(-2147483904.0f, 2147483648.0f, + true, true); + break; + case WASM_OP_I32_TRUNC_SAT_U_F32: + DEF_OP_TRUNC_SAT_F32(-1.0f, 4294967296.0f, true, false); + break; + case WASM_OP_I32_TRUNC_SAT_S_F64: + DEF_OP_TRUNC_SAT_F64(-2147483649.0, 2147483648.0, true, + true); + break; + case WASM_OP_I32_TRUNC_SAT_U_F64: + DEF_OP_TRUNC_SAT_F64(-1.0, 4294967296.0, true, false); + break; + case WASM_OP_I64_TRUNC_SAT_S_F32: + DEF_OP_TRUNC_SAT_F32(-9223373136366403584.0f, + 9223372036854775808.0f, false, + true); + break; + case WASM_OP_I64_TRUNC_SAT_U_F32: + DEF_OP_TRUNC_SAT_F32(-1.0f, 18446744073709551616.0f, + false, false); + break; + case WASM_OP_I64_TRUNC_SAT_S_F64: + DEF_OP_TRUNC_SAT_F64(-9223372036854777856.0, + 9223372036854775808.0, false, + true); + break; + case WASM_OP_I64_TRUNC_SAT_U_F64: + DEF_OP_TRUNC_SAT_F64(-1.0, 18446744073709551616.0, + false, false); + break; +#if WASM_ENABLE_BULK_MEMORY != 0 + case WASM_OP_MEMORY_INIT: + { + uint32 addr, segment; + uint64 bytes, offset, seg_len; + uint8 *data; + + segment = read_uint32(frame_ip); + + bytes = (uint64)POP_I32(); + offset = (uint64)POP_I32(); + addr = POP_I32(); + + CHECK_BULK_MEMORY_OVERFLOW(addr, bytes, maddr); + + seg_len = (uint64)module->module->data_segments[segment] + ->data_length; + data = module->module->data_segments[segment]->data; + if (offset + bytes > seg_len) + goto out_of_bounds; + + bh_memcpy_s(maddr, linear_mem_size - addr, + data + offset, (uint32)bytes); + break; + } + case WASM_OP_DATA_DROP: + { + uint32 segment; + + segment = read_uint32(frame_ip); + + module->module->data_segments[segment]->data_length = 0; + + break; + } + case WASM_OP_MEMORY_COPY: + { + uint32 dst, src, len; + uint8 *mdst, *msrc; + + len = POP_I32(); + src = POP_I32(); + dst = POP_I32(); + + CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc); + CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); + + /* allowing the destination and source to overlap */ + bh_memmove_s(mdst, linear_mem_size - dst, msrc, len); + + break; + } + case WASM_OP_MEMORY_FILL: + { + uint32 dst, len; + uint8 val, *mdst; + + len = POP_I32(); + val = POP_I32(); + dst = POP_I32(); + + CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst); + + memset(mdst, val, len); + + break; + } +#endif /* WASM_ENABLE_BULK_MEMORY */ +#if WASM_ENABLE_REF_TYPES != 0 + case WASM_OP_TABLE_INIT: + { + uint32 tbl_idx, elem_idx; + uint64 n, s, d; + WASMTableInstance *tbl_inst; + + elem_idx = read_uint32(frame_ip); + bh_assert(elem_idx < module->module->table_seg_count); + + tbl_idx = read_uint32(frame_ip); + bh_assert(tbl_idx < module->module->table_count); + + tbl_inst = wasm_get_table_inst(module, tbl_idx); + + n = (uint32)POP_I32(); + s = (uint32)POP_I32(); + d = (uint32)POP_I32(); + + if (!n) { + break; + } + + if (n + s > module->module->table_segments[elem_idx] + .function_count + || d + n > tbl_inst->cur_size) { + wasm_set_exception(module, + "out of bounds table access"); + goto got_exception; + } + + if (module->module->table_segments[elem_idx] + .is_dropped) { + wasm_set_exception(module, + "out of bounds table access"); + goto got_exception; + } + + if (!wasm_elem_is_passive( + module->module->table_segments[elem_idx] + .mode)) { + wasm_set_exception(module, + "out of bounds table access"); + goto got_exception; + } + + bh_memcpy_s( + (uint8 *)tbl_inst + + offsetof(WASMTableInstance, base_addr) + + d * sizeof(uint32), + (uint32)((tbl_inst->cur_size - d) * sizeof(uint32)), + module->module->table_segments[elem_idx] + .func_indexes + + s, + (uint32)(n * sizeof(uint32))); + break; + } + case WASM_OP_ELEM_DROP: + { + uint32 elem_idx = read_uint32(frame_ip); + bh_assert(elem_idx < module->module->table_seg_count); + + module->module->table_segments[elem_idx].is_dropped = + true; + break; + } + case WASM_OP_TABLE_COPY: + { + uint32 src_tbl_idx, dst_tbl_idx; + uint64 n, s, d; + WASMTableInstance *src_tbl_inst, *dst_tbl_inst; + + dst_tbl_idx = read_uint32(frame_ip); + bh_assert(dst_tbl_idx < module->table_count); + + dst_tbl_inst = wasm_get_table_inst(module, dst_tbl_idx); + + src_tbl_idx = read_uint32(frame_ip); + bh_assert(src_tbl_idx < module->table_count); + + src_tbl_inst = wasm_get_table_inst(module, src_tbl_idx); + + n = (uint32)POP_I32(); + s = (uint32)POP_I32(); + d = (uint32)POP_I32(); + + if (s + n > dst_tbl_inst->cur_size + || d + n > src_tbl_inst->cur_size) { + wasm_set_exception(module, + "out of bounds table access"); + goto got_exception; + } + + /* if s >= d, copy from front to back */ + /* if s < d, copy from back to front */ + /* merge all together */ + bh_memmove_s( + (uint8 *)dst_tbl_inst + + offsetof(WASMTableInstance, base_addr) + + d * sizeof(uint32), + (uint32)((dst_tbl_inst->cur_size - d) + * sizeof(uint32)), + (uint8 *)src_tbl_inst + + offsetof(WASMTableInstance, base_addr) + + s * sizeof(uint32), + (uint32)(n * sizeof(uint32))); + break; + } + case WASM_OP_TABLE_GROW: + { + uint32 tbl_idx, n, init_val, orig_tbl_sz; + WASMTableInstance *tbl_inst; + + tbl_idx = read_uint32(frame_ip); + bh_assert(tbl_idx < module->table_count); + + tbl_inst = wasm_get_table_inst(module, tbl_idx); + + orig_tbl_sz = tbl_inst->cur_size; + + n = POP_I32(); + init_val = POP_I32(); + + if (!wasm_enlarge_table(module, tbl_idx, n, init_val)) { + PUSH_I32(-1); + } + else { + PUSH_I32(orig_tbl_sz); + } + + break; + } + case WASM_OP_TABLE_SIZE: + { + uint32 tbl_idx; + WASMTableInstance *tbl_inst; + + tbl_idx = read_uint32(frame_ip); + bh_assert(tbl_idx < module->table_count); + + tbl_inst = wasm_get_table_inst(module, tbl_idx); + + PUSH_I32(tbl_inst->cur_size); + break; + } + case WASM_OP_TABLE_FILL: + { + uint32 tbl_idx, n, val, i; + WASMTableInstance *tbl_inst; + + tbl_idx = read_uint32(frame_ip); + bh_assert(tbl_idx < module->table_count); + + tbl_inst = wasm_get_table_inst(module, tbl_idx); + + n = POP_I32(); + val = POP_I32(); + i = POP_I32(); + + if (i + n > tbl_inst->cur_size) { + wasm_set_exception(module, + "out of bounds table access"); + goto got_exception; + } + + for (; n != 0; i++, n--) { + ((uint32 *)(tbl_inst->base_addr))[i] = val; + } + + break; + } +#endif /* WASM_ENABLE_REF_TYPES */ + default: + wasm_set_exception(module, "unsupported opcode"); + goto got_exception; + } + HANDLE_OP_END(); + } + +#if WASM_ENABLE_SHARED_MEMORY != 0 + HANDLE_OP(WASM_OP_ATOMIC_PREFIX) + { + uint32 offset, addr; + + GET_OPCODE(); + + offset = read_uint32(frame_ip); + + switch (opcode) { + case WASM_OP_ATOMIC_NOTIFY: + { + uint32 count, ret; + + count = POP_I32(); + addr = POP_I32(); + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(4); + + ret = wasm_runtime_atomic_notify( + (WASMModuleInstanceCommon *)module, maddr, count); + bh_assert((int32)ret >= 0); + + PUSH_I32(ret); + break; + } + case WASM_OP_ATOMIC_WAIT32: + { + uint64 timeout; + uint32 expect, addr, ret; + + timeout = POP_I64(); + expect = POP_I32(); + addr = POP_I32(); + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(4); + + ret = wasm_runtime_atomic_wait( + (WASMModuleInstanceCommon *)module, maddr, + (uint64)expect, timeout, false); + if (ret == (uint32)-1) + goto got_exception; + + PUSH_I32(ret); + break; + } + case WASM_OP_ATOMIC_WAIT64: + { + uint64 timeout, expect; + uint32 ret; + + timeout = POP_I64(); + expect = POP_I64(); + addr = POP_I32(); + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(8); + + ret = wasm_runtime_atomic_wait( + (WASMModuleInstanceCommon *)module, maddr, expect, + timeout, true); + if (ret == (uint32)-1) + goto got_exception; + + PUSH_I32(ret); + break; + } + + case WASM_OP_ATOMIC_I32_LOAD: + case WASM_OP_ATOMIC_I32_LOAD8_U: + case WASM_OP_ATOMIC_I32_LOAD16_U: + { + uint32 readv; + + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(1); + os_mutex_lock(&memory->mem_lock); + readv = (uint32)(*(uint8 *)maddr); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(2); + os_mutex_lock(&memory->mem_lock); + readv = (uint32)LOAD_U16(maddr); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(4); + os_mutex_lock(&memory->mem_lock); + readv = LOAD_I32(maddr); + os_mutex_unlock(&memory->mem_lock); + } + + PUSH_I32(readv); + break; + } + + case WASM_OP_ATOMIC_I64_LOAD: + case WASM_OP_ATOMIC_I64_LOAD8_U: + case WASM_OP_ATOMIC_I64_LOAD16_U: + case WASM_OP_ATOMIC_I64_LOAD32_U: + { + uint64 readv; + + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(1); + os_mutex_lock(&memory->mem_lock); + readv = (uint64)(*(uint8 *)maddr); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(2); + os_mutex_lock(&memory->mem_lock); + readv = (uint64)LOAD_U16(maddr); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(4); + os_mutex_lock(&memory->mem_lock); + readv = (uint64)LOAD_U32(maddr); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(8); + os_mutex_lock(&memory->mem_lock); + readv = LOAD_I64(maddr); + os_mutex_unlock(&memory->mem_lock); + } + + PUSH_I64(readv); + break; + } + case WASM_OP_ATOMIC_I32_STORE: + case WASM_OP_ATOMIC_I32_STORE8: + case WASM_OP_ATOMIC_I32_STORE16: + { + uint32 sval; + + sval = (uint32)POP_I32(); + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_I32_STORE8) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(1); + os_mutex_lock(&memory->mem_lock); + *(uint8 *)maddr = (uint8)sval; + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(2); + os_mutex_lock(&memory->mem_lock); + STORE_U16(maddr, (uint16)sval); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(4); + os_mutex_lock(&memory->mem_lock); + STORE_U32(maddr, sval); + os_mutex_unlock(&memory->mem_lock); + } + break; + } + + case WASM_OP_ATOMIC_I64_STORE: + case WASM_OP_ATOMIC_I64_STORE8: + case WASM_OP_ATOMIC_I64_STORE16: + case WASM_OP_ATOMIC_I64_STORE32: + { + uint64 sval; + + sval = (uint64)POP_I64(); + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_I64_STORE8) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(1); + os_mutex_lock(&memory->mem_lock); + *(uint8 *)maddr = (uint8)sval; + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I64_STORE16) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(2); + os_mutex_lock(&memory->mem_lock); + STORE_U16(maddr, (uint16)sval); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(4); + os_mutex_lock(&memory->mem_lock); + STORE_U32(maddr, (uint32)sval); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(8); + os_mutex_lock(&memory->mem_lock); + STORE_I64(maddr, sval); + os_mutex_unlock(&memory->mem_lock); + } + break; + } + + case WASM_OP_ATOMIC_RMW_I32_CMPXCHG: + case WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U: + case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U: + { + uint32 readv, sval, expect; + + sval = POP_I32(); + expect = POP_I32(); + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(1); + + os_mutex_lock(&memory->mem_lock); + readv = (uint32)(*(uint8 *)maddr); + if (readv == expect) + *(uint8 *)maddr = (uint8)(sval); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(2); + + os_mutex_lock(&memory->mem_lock); + readv = (uint32)LOAD_U16(maddr); + if (readv == expect) + STORE_U16(maddr, (uint16)(sval)); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(4); + + os_mutex_lock(&memory->mem_lock); + readv = LOAD_I32(maddr); + if (readv == expect) + STORE_U32(maddr, sval); + os_mutex_unlock(&memory->mem_lock); + } + PUSH_I32(readv); + break; + } + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG: + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U: + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U: + case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U: + { + uint64 readv, sval, expect; + + sval = (uint64)POP_I64(); + expect = (uint64)POP_I64(); + addr = POP_I32(); + + if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(1); + + os_mutex_lock(&memory->mem_lock); + readv = (uint64)(*(uint8 *)maddr); + if (readv == expect) + *(uint8 *)maddr = (uint8)(sval); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(2); + + os_mutex_lock(&memory->mem_lock); + readv = (uint64)LOAD_U16(maddr); + if (readv == expect) + STORE_U16(maddr, (uint16)(sval)); + os_mutex_unlock(&memory->mem_lock); + } + else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(4); + + os_mutex_lock(&memory->mem_lock); + readv = (uint64)LOAD_U32(maddr); + if (readv == expect) + STORE_U32(maddr, (uint32)(sval)); + os_mutex_unlock(&memory->mem_lock); + } + else { + CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); + CHECK_ATOMIC_MEMORY_ACCESS(8); + + os_mutex_lock(&memory->mem_lock); + readv = (uint64)LOAD_I64(maddr); + if (readv == expect) { + STORE_I64(maddr, sval); + } + os_mutex_unlock(&memory->mem_lock); + } + PUSH_I64(readv); + break; + } + + DEF_ATOMIC_RMW_OPCODE(ADD, +); + DEF_ATOMIC_RMW_OPCODE(SUB, -); + DEF_ATOMIC_RMW_OPCODE(AND, &); + DEF_ATOMIC_RMW_OPCODE(OR, |); + DEF_ATOMIC_RMW_OPCODE(XOR, ^); + /* xchg, ignore the read value, and store the given + value: readv * 0 + sval */ + DEF_ATOMIC_RMW_OPCODE(XCHG, *0 +); + } + + HANDLE_OP_END(); + } #endif - HANDLE_OP (WASM_OP_IMPDEP): - frame = prev_frame; - frame_ip = frame->ip; - goto call_func_from_entry; + HANDLE_OP(WASM_OP_IMPDEP) + { + frame = prev_frame; + frame_ip = frame->ip; + goto call_func_from_entry; + } - HANDLE_OP (WASM_OP_CALL): + HANDLE_OP(WASM_OP_CALL) + { #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - fidx = read_uint32(frame_ip); + fidx = read_uint32(frame_ip); #if WASM_ENABLE_MULTI_MODULE != 0 - if (fidx >= module->function_count) { - wasm_set_exception(module, "unknown function"); - goto got_exception; - } + if (fidx >= module->function_count) { + wasm_set_exception(module, "unknown function"); + goto got_exception; + } #endif - cur_func = module->functions + fidx; - goto call_func_from_interp; + cur_func = module->functions + fidx; + goto call_func_from_interp; + } #if WASM_ENABLE_TAIL_CALL != 0 - HANDLE_OP (WASM_OP_RETURN_CALL): + HANDLE_OP(WASM_OP_RETURN_CALL) + { #if WASM_ENABLE_THREAD_MGR != 0 - CHECK_SUSPEND_FLAGS(); + CHECK_SUSPEND_FLAGS(); #endif - fidx = read_uint32(frame_ip); + fidx = read_uint32(frame_ip); #if WASM_ENABLE_MULTI_MODULE != 0 - if (fidx >= module->function_count) { - wasm_set_exception(module, "unknown function"); - goto got_exception; - } + if (fidx >= module->function_count) { + wasm_set_exception(module, "unknown function"); + goto got_exception; + } #endif - cur_func = module->functions + fidx; - goto call_func_from_return_call; + cur_func = module->functions + fidx; + goto call_func_from_return_call; + } #endif /* WASM_ENABLE_TAIL_CALL */ #if WASM_ENABLE_LABELS_AS_VALUES == 0 - default: - wasm_set_exception(module, "unsupported opcode"); - goto got_exception; - } + default: + wasm_set_exception(module, "unsupported opcode"); + goto got_exception; + } #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): + 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): - HANDLE_OP (WASM_OP_RETURN_CALL_INDIRECT): + HANDLE_OP(WASM_OP_RETURN_CALL) + HANDLE_OP(WASM_OP_RETURN_CALL_INDIRECT) #endif #if WASM_ENABLE_SHARED_MEMORY == 0 - HANDLE_OP (WASM_OP_ATOMIC_PREFIX): + HANDLE_OP(WASM_OP_ATOMIC_PREFIX) #endif #if WASM_ENABLE_REF_TYPES == 0 - HANDLE_OP (WASM_OP_TABLE_GET): - HANDLE_OP (WASM_OP_TABLE_SET): - HANDLE_OP (WASM_OP_REF_NULL): - HANDLE_OP (WASM_OP_REF_IS_NULL): - HANDLE_OP (WASM_OP_REF_FUNC): + HANDLE_OP(WASM_OP_TABLE_GET) + HANDLE_OP(WASM_OP_TABLE_SET) + HANDLE_OP(WASM_OP_REF_NULL) + HANDLE_OP(WASM_OP_REF_IS_NULL) + HANDLE_OP(WASM_OP_REF_FUNC) #endif - /* SELECT_T is converted to SELECT or SELECT_64 */ - HANDLE_OP (WASM_OP_SELECT_T): - HANDLE_OP (WASM_OP_UNUSED_0x14): - 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): - HANDLE_OP (WASM_OP_F64_STORE): - HANDLE_OP (WASM_OP_F32_LOAD): - HANDLE_OP (WASM_OP_F64_LOAD): - HANDLE_OP (EXT_OP_GET_LOCAL_FAST): - HANDLE_OP (WASM_OP_GET_LOCAL): - HANDLE_OP (WASM_OP_F64_CONST): - HANDLE_OP (WASM_OP_I64_CONST): - HANDLE_OP (WASM_OP_F32_CONST): - HANDLE_OP (WASM_OP_I32_CONST): - HANDLE_OP (WASM_OP_DROP): - HANDLE_OP (WASM_OP_DROP_64): - HANDLE_OP (WASM_OP_BLOCK): - HANDLE_OP (WASM_OP_LOOP): - HANDLE_OP (WASM_OP_END): - HANDLE_OP (WASM_OP_NOP): - HANDLE_OP (EXT_OP_BLOCK): - HANDLE_OP (EXT_OP_LOOP): - HANDLE_OP (EXT_OP_IF): - { - wasm_set_exception(module, "unsupported opcode"); - goto got_exception; - } + /* SELECT_T is converted to SELECT or SELECT_64 */ + HANDLE_OP(WASM_OP_SELECT_T) + HANDLE_OP(WASM_OP_UNUSED_0x14) + 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) + HANDLE_OP(WASM_OP_F64_STORE) + HANDLE_OP(WASM_OP_F32_LOAD) + HANDLE_OP(WASM_OP_F64_LOAD) + HANDLE_OP(EXT_OP_GET_LOCAL_FAST) + HANDLE_OP(WASM_OP_GET_LOCAL) + HANDLE_OP(WASM_OP_F64_CONST) + HANDLE_OP(WASM_OP_I64_CONST) + HANDLE_OP(WASM_OP_F32_CONST) + HANDLE_OP(WASM_OP_I32_CONST) + HANDLE_OP(WASM_OP_DROP) + HANDLE_OP(WASM_OP_DROP_64) + HANDLE_OP(WASM_OP_BLOCK) + HANDLE_OP(WASM_OP_LOOP) + HANDLE_OP(WASM_OP_END) + HANDLE_OP(WASM_OP_NOP) + HANDLE_OP(EXT_OP_BLOCK) + HANDLE_OP(EXT_OP_LOOP) + HANDLE_OP(EXT_OP_IF) + { + wasm_set_exception(module, "unsupported opcode"); + goto got_exception; + } #endif #if WASM_ENABLE_LABELS_AS_VALUES == 0 - continue; + continue; #else - FETCH_OPCODE_AND_DISPATCH (); + FETCH_OPCODE_AND_DISPATCH(); #endif -#if WASM_ENABLE_TAIL_CALL !=0 - call_func_from_return_call: - { - uint32 *lp_base; - uint32 *lp; - int i; - - if (!(lp_base = lp = - wasm_runtime_malloc(cur_func->param_cell_num * sizeof(uint32)))) { - wasm_set_exception(module, "allocate memory failed"); - goto got_exception; - } - for (i = 0; i < cur_func->param_count; i++) { - if (cur_func->param_types[i] == VALUE_TYPE_I64 - || cur_func->param_types[i] == VALUE_TYPE_F64) { - PUT_I64_TO_ADDR(lp, GET_OPERAND(uint64, I64, - 2 * (cur_func->param_count - i - 1))); - lp += 2; - } - else { - *lp = GET_OPERAND(uint32, I32, (2 * (cur_func->param_count - i - 1))); - lp ++; - } - } - frame->lp = frame->operand + cur_func->const_cell_num; - word_copy(frame->lp, lp_base, lp - lp_base); - wasm_runtime_free(lp_base); - FREE_FRAME(exec_env, frame); - frame_ip += cur_func->param_count * sizeof(int16); - wasm_exec_env_set_cur_frame(exec_env, - (WASMRuntimeFrame *)prev_frame); - goto call_func_from_entry; - } -#endif /* WASM_ENABLE_TAIL_CALL */ - call_func_from_interp: - /* Only do the copy when it's called from interpreter. */ +#if WASM_ENABLE_TAIL_CALL != 0 + call_func_from_return_call: { - WASMInterpFrame *outs_area = wasm_exec_env_wasm_stack_top(exec_env); - outs_area->lp = outs_area->operand + cur_func->const_cell_num; - for (int i = 0; i < cur_func->param_count; i++) { - if (cur_func->param_types[i] == VALUE_TYPE_I64 - || cur_func->param_types[i] == VALUE_TYPE_F64) { - PUT_I64_TO_ADDR(outs_area->lp, - GET_OPERAND(uint64, I64, - 2 * (cur_func->param_count - i - 1))); - outs_area->lp += 2; + uint32 *lp_base; + uint32 *lp; + int i; + + if (!(lp_base = lp = wasm_runtime_malloc(cur_func->param_cell_num + * sizeof(uint32)))) { + wasm_set_exception(module, "allocate memory failed"); + goto got_exception; } - else { - *outs_area->lp = GET_OPERAND(uint32, I32, - (2 * (cur_func->param_count - i - 1))); - outs_area->lp ++; + for (i = 0; i < cur_func->param_count; i++) { + if (cur_func->param_types[i] == VALUE_TYPE_I64 + || cur_func->param_types[i] == VALUE_TYPE_F64) { + PUT_I64_TO_ADDR( + lp, GET_OPERAND(uint64, I64, + 2 * (cur_func->param_count - i - 1))); + lp += 2; + } + else { + *lp = GET_OPERAND(uint32, I32, + (2 * (cur_func->param_count - i - 1))); + lp++; + } } - } - frame_ip += cur_func->param_count * sizeof(int16); - if (cur_func->ret_cell_num != 0) { - /* Get the first return value's offset. Since loader emit all return - * values' offset so we must skip remain return values' offsets. - */ - WASMType *func_type; - if (cur_func->is_import_func) - func_type = cur_func->u.func_import->func_type; - else - func_type = cur_func->u.func->func_type; - frame->ret_offset = GET_OFFSET(); - frame_ip += 2 * (func_type->result_count - 1); - } - SYNC_ALL_TO_FRAME(); - prev_frame = frame; + frame->lp = frame->operand + cur_func->const_cell_num; + word_copy(frame->lp, lp_base, lp - lp_base); + wasm_runtime_free(lp_base); + FREE_FRAME(exec_env, frame); + frame_ip += cur_func->param_count * sizeof(int16); + wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame); + goto call_func_from_entry; } +#endif /* WASM_ENABLE_TAIL_CALL */ - call_func_from_entry: + call_func_from_interp: { - if (cur_func->is_import_func) { + /* Only do the copy when it's called from interpreter. */ + WASMInterpFrame *outs_area = wasm_exec_env_wasm_stack_top(exec_env); + int i; + #if WASM_ENABLE_MULTI_MODULE != 0 - if (cur_func->import_func_inst) { - wasm_interp_call_func_import(module, exec_env, cur_func, - prev_frame); - } - else + if (cur_func->is_import_func) { + outs_area->lp = outs_area->operand + + (cur_func->import_func_inst + ? cur_func->import_func_inst->const_cell_num + : 0); + } + else #endif - { - wasm_interp_call_func_native(module, exec_env, cur_func, - prev_frame); - } - - prev_frame = frame->prev_frame; - cur_func = frame->function; - UPDATE_ALL_FROM_FRAME(); - - /* update memory instance ptr and memory size */ - memory = module->default_memory; - if (memory) - linear_mem_size = num_bytes_per_page * memory->cur_page_count; - if (wasm_get_exception(module)) - goto got_exception; - } - else { - WASMFunction *cur_wasm_func = cur_func->u.func; - - all_cell_num = (uint64)cur_func->param_cell_num - + (uint64)cur_func->local_cell_num - + (uint64)cur_func->const_cell_num - + (uint64)cur_wasm_func->max_stack_cell_num; - if (all_cell_num >= UINT32_MAX) { - wasm_set_exception(module, "wasm operand stack overflow"); - goto got_exception; + { + outs_area->lp = outs_area->operand + cur_func->const_cell_num; + } + for (i = 0; i < cur_func->param_count; i++) { + if (cur_func->param_types[i] == VALUE_TYPE_I64 + || cur_func->param_types[i] == VALUE_TYPE_F64) { + PUT_I64_TO_ADDR( + outs_area->lp, + GET_OPERAND(uint64, I64, + 2 * (cur_func->param_count - i - 1))); + outs_area->lp += 2; + } + else { + *outs_area->lp = GET_OPERAND( + uint32, I32, (2 * (cur_func->param_count - i - 1))); + outs_area->lp++; + } } + frame_ip += cur_func->param_count * sizeof(int16); + if (cur_func->ret_cell_num != 0) { + /* Get the first return value's offset. Since loader emit + * all return values' offset so we must skip remain return + * values' offsets. + */ + WASMType *func_type; + if (cur_func->is_import_func) + func_type = cur_func->u.func_import->func_type; + else + func_type = cur_func->u.func->func_type; + frame->ret_offset = GET_OFFSET(); + frame_ip += 2 * (func_type->result_count - 1); + } + SYNC_ALL_TO_FRAME(); + prev_frame = frame; + } - frame_size = wasm_interp_interp_frame_size((uint32)all_cell_num); - if (!(frame = ALLOC_FRAME(exec_env, frame_size, prev_frame))) { - frame = prev_frame; - goto got_exception; + call_func_from_entry: + { + if (cur_func->is_import_func) { +#if WASM_ENABLE_MULTI_MODULE != 0 + if (cur_func->import_func_inst) { + wasm_interp_call_func_import(module, exec_env, cur_func, + prev_frame); + } + else +#endif + { + wasm_interp_call_func_native(module, exec_env, cur_func, + prev_frame); + } + + prev_frame = frame->prev_frame; + cur_func = frame->function; + UPDATE_ALL_FROM_FRAME(); + + /* update memory instance ptr and memory size */ + memory = module->default_memory; + if (memory) + linear_mem_size = num_bytes_per_page * memory->cur_page_count; + if (wasm_get_exception(module)) + goto got_exception; } + else { + WASMFunction *cur_wasm_func = cur_func->u.func; + + all_cell_num = (uint64)cur_func->param_cell_num + + (uint64)cur_func->local_cell_num + + (uint64)cur_func->const_cell_num + + (uint64)cur_wasm_func->max_stack_cell_num; + if (all_cell_num >= UINT32_MAX) { + wasm_set_exception(module, "wasm operand stack overflow"); + goto got_exception; + } - /* Initialize the interpreter context. */ - frame->function = cur_func; - frame_ip = wasm_get_func_code(cur_func); - frame_ip_end = wasm_get_func_code_end(cur_func); + frame_size = wasm_interp_interp_frame_size((uint32)all_cell_num); + if (!(frame = ALLOC_FRAME(exec_env, frame_size, prev_frame))) { + frame = prev_frame; + goto got_exception; + } - frame_lp = frame->lp = frame->operand + cur_wasm_func->const_cell_num; + /* Initialize the interpreter context. */ + frame->function = cur_func; + frame_ip = wasm_get_func_code(cur_func); + frame_ip_end = wasm_get_func_code_end(cur_func); - /* Initialize the consts */ - word_copy(frame->operand, (uint32*)cur_wasm_func->consts, - cur_wasm_func->const_cell_num); + frame_lp = frame->lp = + frame->operand + cur_wasm_func->const_cell_num; - /* Initialize the local varialbes */ - memset(frame_lp + cur_func->param_cell_num, 0, - (uint32)(cur_func->local_cell_num * 4)); + /* Initialize the consts */ + word_copy(frame->operand, (uint32 *)cur_wasm_func->consts, + cur_wasm_func->const_cell_num); - wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)frame); - } - HANDLE_OP_END (); + /* Initialize the local varialbes */ + memset(frame_lp + cur_func->param_cell_num, 0, + (uint32)(cur_func->local_cell_num * 4)); + + wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)frame); + } + HANDLE_OP_END(); } - return_func: + return_func: { - FREE_FRAME(exec_env, frame); - wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)prev_frame); + FREE_FRAME(exec_env, frame); + wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame); - if (!prev_frame->ip) - /* Called from native. */ - return; + if (!prev_frame->ip) + /* Called from native. */ + return; - RECOVER_CONTEXT(prev_frame); - HANDLE_OP_END (); + RECOVER_CONTEXT(prev_frame); + HANDLE_OP_END(); } - (void)frame_ip_end; + (void)frame_ip_end; #if WASM_ENABLE_SHARED_MEMORY != 0 - unaligned_atomic: - wasm_set_exception(module, "unaligned atomic"); - goto got_exception; + unaligned_atomic: + wasm_set_exception(module, "unaligned atomic"); + goto got_exception; #endif - out_of_bounds: - wasm_set_exception(module, "out of bounds memory access"); + out_of_bounds: + wasm_set_exception(module, "out of bounds memory access"); - got_exception: - return; + got_exception: + SYNC_ALL_TO_FRAME(); + return; #if WASM_ENABLE_LABELS_AS_VALUES == 0 - } + } #else - FETCH_OPCODE_AND_DISPATCH (); + FETCH_OPCODE_AND_DISPATCH(); #endif } @@ -3449,37 +3714,37 @@ wasm_interp_get_handle_table() #endif void -wasm_interp_call_wasm(WASMModuleInstance *module_inst, - WASMExecEnv *exec_env, - WASMFunctionInstance *function, - uint32 argc, uint32 argv[]) +wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, + WASMFunctionInstance *function, uint32 argc, + uint32 argv[]) { WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env); WASMInterpFrame *frame, *outs_area; /* Allocate sufficient cells for all kinds of return values. */ - unsigned all_cell_num = function->ret_cell_num > 2 ? - function->ret_cell_num : 2, i; + unsigned all_cell_num = + function->ret_cell_num > 2 ? function->ret_cell_num : 2, + i; /* This frame won't be used by JITed code, so only allocate interp frame here. */ unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num); if (argc != function->param_cell_num) { char buf[128]; - snprintf(buf, sizeof(buf), - "invalid argument count %d, expected %d", + snprintf(buf, sizeof(buf), "invalid argument count %d, expected %d", argc, function->param_cell_num); wasm_set_exception(module_inst, buf); return; } - if ((uint8*)&prev_frame < exec_env->native_stack_boundary) { - wasm_set_exception((WASMModuleInstance*)exec_env->module_inst, + if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) { + wasm_set_exception((WASMModuleInstance *)exec_env->module_inst, "native stack overflow"); return; } - if (!(frame = ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame*)prev_frame))) + if (!(frame = + ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame *)prev_frame))) return; outs_area = wasm_exec_env_wasm_stack_top(exec_env); @@ -3498,15 +3763,15 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, #if WASM_ENABLE_MULTI_MODULE != 0 if (function->import_module_inst) { LOG_DEBUG("it is a function of a sub module"); - wasm_interp_call_func_import(module_inst, exec_env, - function, frame); + wasm_interp_call_func_import(module_inst, exec_env, function, + frame); } else #endif { LOG_DEBUG("it is an native function"); - wasm_interp_call_func_native(module_inst, exec_env, - function, frame); + wasm_interp_call_func_native(module_inst, exec_env, function, + frame); } } else { diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index a3db0a2d08..979ab0be26 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -10,25 +10,27 @@ #include "wasm_opcode.h" #include "wasm_runtime.h" #include "../common/wasm_native.h" +#if WASM_ENABLE_DEBUG_INTERP != 0 +#include "../libraries/debug-engine/debug_engine.h" +#endif /* Read a value of given type from the address pointed to by the given pointer and increase the pointer to the position just after the value being read. */ -#define TEMPLATE_READ_VALUE(Type, p) \ +#define TEMPLATE_READ_VALUE(Type, p) \ (p += sizeof(Type), *(Type *)(p - sizeof(Type))) static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) { if (error_buf != NULL) { - snprintf(error_buf, error_buf_size, - "WASM module load failed: %s", string); + snprintf(error_buf, error_buf_size, "WASM module load failed: %s", + string); } } static void -set_error_buf_v(char *error_buf, uint32 error_buf_size, - const char *format, ...) +set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...) { va_list args; char buf[128]; @@ -37,8 +39,7 @@ set_error_buf_v(char *error_buf, uint32 error_buf_size, va_start(args, format); vsnprintf(buf, sizeof(buf), format, args); va_end(args); - snprintf(error_buf, error_buf_size, - "WASM module load failed: %s", buf); + snprintf(error_buf, error_buf_size, "WASM module load failed: %s", buf); } } @@ -65,19 +66,19 @@ check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length, return true; } -#define CHECK_BUF(buf, buf_end, length) do { \ - if (!check_buf(buf, buf_end, length, \ - error_buf, error_buf_size)) { \ - goto fail; \ - } \ -} while (0) +#define CHECK_BUF(buf, buf_end, length) \ + do { \ + if (!check_buf(buf, buf_end, length, error_buf, error_buf_size)) { \ + goto fail; \ + } \ + } while (0) -#define CHECK_BUF1(buf, buf_end, length) do { \ - if (!check_buf1(buf, buf_end, length, \ - error_buf, error_buf_size)) { \ - goto fail; \ - } \ -} while (0) +#define CHECK_BUF1(buf, buf_end, length) \ + do { \ + if (!check_buf1(buf, buf_end, length, error_buf, error_buf_size)) { \ + goto fail; \ + } \ + } while (0) #define skip_leb(p) while (*p++ & 0x80) #define skip_leb_int64(p, p_end) skip_leb(p) @@ -85,9 +86,8 @@ check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length, #define skip_leb_int32(p, p_end) skip_leb(p) static bool -read_leb(uint8 **p_buf, const uint8 *buf_end, - uint32 maxbits, bool sign, uint64 *p_result, - char* error_buf, uint32 error_buf_size) +read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, + uint64 *p_result, char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; uint64 result = 0; @@ -121,9 +121,9 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, } else if (sign && maxbits == 32) { if (shift < maxbits) { - /* Sign extend */ - result = (((int32)result) << (maxbits - shift)) - >> (maxbits - shift); + /* Sign extend, second highest bit is the sign bit */ + if ((uint8)byte & 0x40) + result |= (~((uint64)0)) << shift; } else { /* The top bits should be a sign-extension of the sign bit */ @@ -136,9 +136,9 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, } else if (sign && maxbits == 64) { if (shift < maxbits) { - /* Sign extend */ - result = (((int64)result) << (maxbits - shift)) - >> (maxbits - shift); + /* Sign extend, second highest bit is the sign bit */ + if ((uint8)byte & 0x40) + result |= (~((uint64)0)) << shift; } else { /* The top bits should be a sign-extension of the sign bit */ @@ -161,33 +161,36 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, return false; } -#define read_uint8(p) TEMPLATE_READ_VALUE(uint8, p) +#define read_uint8(p) TEMPLATE_READ_VALUE(uint8, p) #define read_uint32(p) TEMPLATE_READ_VALUE(uint32, p) -#define read_bool(p) TEMPLATE_READ_VALUE(bool, p) - -#define read_leb_int64(p, p_end, res) do { \ - uint64 res64; \ - if (!read_leb((uint8**)&p, p_end, 64, true, &res64,\ - error_buf, error_buf_size)) \ - goto fail; \ - res = (int64)res64; \ -} while (0) - -#define read_leb_uint32(p, p_end, res) do { \ - uint64 res64; \ - if (!read_leb((uint8**)&p, p_end, 32, false, &res64,\ - error_buf, error_buf_size)) \ - goto fail; \ - res = (uint32)res64; \ -} while (0) - -#define read_leb_int32(p, p_end, res) do { \ - uint64 res64; \ - if (!read_leb((uint8**)&p, p_end, 32, true, &res64,\ - error_buf, error_buf_size)) \ - goto fail; \ - res = (int32)res64; \ -} while (0) +#define read_bool(p) TEMPLATE_READ_VALUE(bool, p) + +#define read_leb_int64(p, p_end, res) \ + do { \ + uint64 res64; \ + if (!read_leb((uint8 **)&p, p_end, 64, true, &res64, error_buf, \ + error_buf_size)) \ + goto fail; \ + res = (int64)res64; \ + } while (0) + +#define read_leb_uint32(p, p_end, res) \ + do { \ + uint64 res64; \ + if (!read_leb((uint8 **)&p, p_end, 32, false, &res64, error_buf, \ + error_buf_size)) \ + goto fail; \ + res = (uint32)res64; \ + } while (0) + +#define read_leb_int32(p, p_end, res) \ + do { \ + uint64 res64; \ + if (!read_leb((uint8 **)&p, p_end, 32, true, &res64, error_buf, \ + error_buf_size)) \ + goto fail; \ + res = (int32)res64; \ + } while (0) static char * type2str(uint8 type) @@ -239,7 +242,7 @@ is_value_type(uint8 type) || type == VALUE_TYPE_V128 #endif #endif - ) + ) return true; return false; } @@ -253,7 +256,7 @@ is_byte_a_type(uint8 type) #if WASM_ENABLE_SIMD != 0 #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) static V128 -read_i8x16(uint8 *p_buf, char* error_buf, uint32 error_buf_size) +read_i8x16(uint8 *p_buf, char *error_buf, uint32 error_buf_size) { V128 result; uint8 i; @@ -272,10 +275,8 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) { void *mem; - if (size >= UINT32_MAX - || !(mem = wasm_runtime_malloc((uint32)size))) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); return NULL; } @@ -284,7 +285,7 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) } static bool -check_utf8_str(const uint8* str, uint32 len) +check_utf8_str(const uint8 *str, uint32 len) { /* The valid ranges are taken from page 125, below link https://www.unicode.org/versions/Unicode9.0.0/ch03.pdf */ @@ -304,20 +305,17 @@ check_utf8_str(const uint8* str, uint32 len) } else if (chr >= 0xE0 && chr <= 0xEF && p + 2 < p_end) { if (chr == 0xE0) { - if (p[1] < 0xA0 || p[1] > 0xBF - || p[2] < 0x80 || p[2] > 0xBF) { + if (p[1] < 0xA0 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) { return false; } } else if (chr == 0xED) { - if (p[1] < 0x80 || p[1] > 0x9F - || p[2] < 0x80 || p[2] > 0xBF) { + if (p[1] < 0x80 || p[1] > 0x9F || p[2] < 0x80 || p[2] > 0xBF) { return false; } } else if (chr >= 0xE1 && chr <= 0xEF) { - if (p[1] < 0x80 || p[1] > 0xBF - || p[2] < 0x80 || p[2] > 0xBF) { + if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) { return false; } } @@ -325,22 +323,19 @@ check_utf8_str(const uint8* str, uint32 len) } else if (chr >= 0xF0 && chr <= 0xF4 && p + 3 < p_end) { if (chr == 0xF0) { - if (p[1] < 0x90 || p[1] > 0xBF - || p[2] < 0x80 || p[2] > 0xBF + if (p[1] < 0x90 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF || p[3] < 0x80 || p[3] > 0xBF) { return false; } } else if (chr >= 0xF1 && chr <= 0xF3) { - if (p[1] < 0x80 || p[1] > 0xBF - || p[2] < 0x80 || p[2] > 0xBF + if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF || p[3] < 0x80 || p[3] > 0xBF) { return false; } } else if (chr == 0xF4) { - if (p[1] < 0x80 || p[1] > 0x8F - || p[2] < 0x80 || p[2] > 0xBF + if (p[1] < 0x80 || p[1] > 0x8F || p[2] < 0x80 || p[2] > 0xBF || p[3] < 0x80 || p[3] > 0xBF) { return false; } @@ -354,15 +349,14 @@ check_utf8_str(const uint8* str, uint32 len) return (p == p_end); } -static char* +static char * const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, - char* error_buf, uint32 error_buf_size) + char *error_buf, uint32 error_buf_size) { StringNode *node, *node_next; if (!check_utf8_str(str, len)) { - set_error_buf(error_buf, error_buf_size, - "invalid UTF-8 encoding"); + set_error_buf(error_buf, error_buf_size, "invalid UTF-8 encoding"); return NULL; } @@ -370,8 +364,7 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, node = module->const_str_list; while (node) { node_next = node->next; - if (strlen(node->str) == len - && !memcmp(node->str, str, len)) + if (strlen(node->str) == len && !memcmp(node->str, str, len)) break; node = node_next; } @@ -380,12 +373,12 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, return node->str; } - if (!(node = loader_malloc(sizeof(StringNode) + len + 1, - error_buf, error_buf_size))) { + if (!(node = loader_malloc(sizeof(StringNode) + len + 1, error_buf, + error_buf_size))) { return NULL; } - node->str = ((char*)node) + sizeof(StringNode); + node->str = ((char *)node) + sizeof(StringNode); bh_memcpy_s(node->str, len + 1, str, len); node->str[len] = '\0'; @@ -405,8 +398,8 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, static bool load_init_expr(const uint8 **p_buf, const uint8 *buf_end, - InitializerExpression *init_expr, uint8 type, - char *error_buf, uint32 error_buf_size) + InitializerExpression *init_expr, uint8 type, char *error_buf, + uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint8 flag, end_byte, *p_float; @@ -434,7 +427,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, if (type != VALUE_TYPE_F32) goto fail_type_mismatch; CHECK_BUF(p, p_end, 4); - p_float = (uint8*)&init_expr->u.f32; + p_float = (uint8 *)&init_expr->u.f32; for (i = 0; i < sizeof(float32); i++) *p_float++ = *p++; break; @@ -443,7 +436,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, if (type != VALUE_TYPE_F64) goto fail_type_mismatch; CHECK_BUF(p, p_end, 8); - p_float = (uint8*)&init_expr->u.f64; + p_float = (uint8 *)&init_expr->u.f64; for (i = 0; i < sizeof(float64); i++) *p_float++ = *p++; break; @@ -461,7 +454,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, (void)flag; CHECK_BUF(p, p_end, 16); - wasm_runtime_read_v128(p, &high, &low); + wasm_runtime_read_v128(p, &high, &low); p += 16; init_expr->u.v128.i64x2[0] = high; @@ -503,9 +496,10 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, case INIT_EXPR_TYPE_GET_GLOBAL: read_leb_uint32(p, p_end, init_expr->u.global_index); break; - default: { + default: + { #if WASM_ENABLE_REF_TYPES != 0 -illegal_opcode: + illegal_opcode: #endif set_error_buf(error_buf, error_buf_size, "illegal opcode " @@ -543,9 +537,9 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (type_count) { module->type_count = type_count; - total_size = sizeof(WASMType*) * (uint64)type_count; - if (!(module->types = loader_malloc - (total_size, error_buf, error_buf_size))) { + total_size = sizeof(WASMType *) * (uint64)type_count; + if (!(module->types = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -553,8 +547,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, CHECK_BUF(p, p_end, 1); flag = read_uint8(p); if (flag != 0x60) { - set_error_buf(error_buf, error_buf_size, - "invalid type flag"); + set_error_buf(error_buf, error_buf_size, "invalid type flag"); return false; } @@ -574,10 +567,10 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } - total_size = offsetof(WASMType, types) + - sizeof(uint8) * (uint64)(param_count + result_count); + total_size = offsetof(WASMType, types) + + sizeof(uint8) * (uint64)(param_count + result_count); if (!(type = module->types[i] = - loader_malloc(total_size, error_buf, error_buf_size))) { + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -595,8 +588,8 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } param_cell_num = wasm_get_cell_num(type->types, param_count); - ret_cell_num = wasm_get_cell_num(type->types + param_count, - result_count); + ret_cell_num = + wasm_get_cell_num(type->types + param_count, result_count); if (param_cell_num > UINT16_MAX || ret_cell_num > UINT16_MAX) { set_error_buf(error_buf, error_buf_size, "param count or result count too large"); @@ -622,7 +615,7 @@ static void adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size) { uint32 default_max_size = - init_size * 2 > TABLE_MAX_SIZE ? init_size * 2 : TABLE_MAX_SIZE; + init_size * 2 > TABLE_MAX_SIZE ? init_size * 2 : TABLE_MAX_SIZE; if (max_size_flag) { /* module defines the table limitation */ @@ -630,7 +623,7 @@ adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size) if (init_size < *max_size) { *max_size = - *max_size < default_max_size ? *max_size : default_max_size; + *max_size < default_max_size ? *max_size : default_max_size; } } else { @@ -645,12 +638,10 @@ adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size) * module name, field name and export kind */ static WASMExport * -wasm_loader_find_export(const WASMModule *module, - const char *module_name, - const char *field_name, - uint8 export_kind, - uint32 export_index_boundary, - char *error_buf, uint32 error_buf_size) +wasm_loader_find_export(const WASMModule *module, const char *module_name, + const char *field_name, uint8 export_kind, + uint32 export_index_boundary, char *error_buf, + uint32 error_buf_size) { WASMExport *export; uint32 i; @@ -677,9 +668,8 @@ wasm_loader_find_export(const WASMModule *module, } if (export->index >= export_index_boundary) { - LOG_DEBUG("%s in the module %s is out of index (%d >= %d )", - field_name, module_name, - export->index, export_index_boundary); + LOG_DEBUG("%s in the module %s is out of index (%d >= %d )", field_name, + module_name, export->index, export_index_boundary); set_error_buf(error_buf, error_buf_size, "incompatible import type"); return NULL; } @@ -688,8 +678,7 @@ wasm_loader_find_export(const WASMModule *module, } static WASMFunction * -wasm_loader_resolve_function(const char *module_name, - const char *function_name, +wasm_loader_resolve_function(const char *module_name, const char *function_name, const WASMType *expected_function_type, char *error_buf, uint32 error_buf_size) { @@ -700,20 +689,18 @@ wasm_loader_resolve_function(const char *module_name, WASMType *target_function_type = 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 function %s", - module_name, function_name); + if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) { + LOG_DEBUG("can not find a module named %s for function %s", module_name, + function_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, function_name, - EXPORT_KIND_FUNC, - module->import_function_count - + module->function_count, - error_buf, error_buf_size); + export = wasm_loader_find_export( + module, module_name, function_name, EXPORT_KIND_FUNC, + module->import_function_count + module->function_count, error_buf, + error_buf_size); if (!export) { return NULL; } @@ -721,16 +708,16 @@ wasm_loader_resolve_function(const char *module_name, /* resolve function type and function */ if (export->index < module->import_function_count) { target_function_type = - module->import_functions[export->index].u.function.func_type; + module->import_functions[export->index].u.function.func_type; function = module->import_functions[export->index] - .u.function.import_func_linked; + .u.function.import_func_linked; } else { target_function_type = - module->functions[export->index - module->import_function_count] - ->func_type; + module->functions[export->index - module->import_function_count] + ->func_type; function = - module->functions[export->index - module->import_function_count]; + module->functions[export->index - module->import_function_count]; } /* check function type */ @@ -745,8 +732,8 @@ wasm_loader_resolve_function(const char *module_name, static WASMTable * wasm_loader_resolve_table(const char *module_name, const char *table_name, - uint32 init_size, uint32 max_size, - char *error_buf, uint32 error_buf_size) + uint32 init_size, uint32 max_size, char *error_buf, + uint32 error_buf_size) { WASMModuleCommon *module_reg; WASMTable *table = NULL; @@ -754,19 +741,17 @@ wasm_loader_resolve_table(const char *module_name, const char *table_name, WASMModule *module = NULL; module_reg = wasm_runtime_find_module_registered(module_name); - if (!module_reg - || module_reg->module_type != Wasm_Module_Bytecode) { + if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) { LOG_DEBUG("can not find a module named %s for table", module_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, table_name, - EXPORT_KIND_TABLE, - module->table_count - + module->import_table_count, - error_buf, error_buf_size); + export = wasm_loader_find_export( + module, module_name, table_name, EXPORT_KIND_TABLE, + module->table_count + module->import_table_count, error_buf, + error_buf_size); if (!export) { return NULL; } @@ -774,7 +759,7 @@ wasm_loader_resolve_table(const char *module_name, const char *table_name, /* resolve table and check the init/max size */ if (export->index < module->import_table_count) { table = - module->import_tables[export->index].u.table.import_table_linked; + module->import_tables[export->index].u.table.import_table_linked; } else { table = &(module->tables[export->index - module->import_table_count]); @@ -801,35 +786,32 @@ wasm_loader_resolve_memory(const char *module_name, const char *memory_name, WASMModule *module = NULL; module_reg = wasm_runtime_find_module_registered(module_name); - if (!module_reg - || module_reg->module_type != Wasm_Module_Bytecode) { + if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) { LOG_DEBUG("can not find a module named %s for memory", module_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, memory_name, - EXPORT_KIND_MEMORY, - module->import_memory_count - + module->memory_count, - error_buf, error_buf_size); + export = wasm_loader_find_export( + module, module_name, memory_name, EXPORT_KIND_MEMORY, + module->import_memory_count + module->memory_count, error_buf, + error_buf_size); if (!export) { return NULL; } - /* resolve memory and check the init/max page count */ if (export->index < module->import_memory_count) { - memory = - module->import_memories[export->index].u.memory.import_memory_linked; + memory = module->import_memories[export->index] + .u.memory.import_memory_linked; } else { memory = - &(module->memories[export->index - module->import_memory_count]); + &(module->memories[export->index - module->import_memory_count]); } - if (memory->init_page_count < init_page_count || - memory->max_page_count > max_page_count) { + if (memory->init_page_count < init_page_count + || memory->max_page_count > max_page_count) { LOG_DEBUG("%s,%s failed type check(%d-%d), expected(%d-%d)", module_name, memory_name, memory->init_page_count, memory->max_page_count, init_page_count, max_page_count); @@ -840,10 +822,9 @@ wasm_loader_resolve_memory(const char *module_name, const char *memory_name, } static WASMGlobal * -wasm_loader_resolve_global(const char *module_name, - const char *global_name, - uint8 type, bool is_mutable, - char *error_buf, uint32 error_buf_size) +wasm_loader_resolve_global(const char *module_name, const char *global_name, + uint8 type, bool is_mutable, char *error_buf, + uint32 error_buf_size) { WASMModuleCommon *module_reg; WASMGlobal *global = NULL; @@ -851,19 +832,17 @@ wasm_loader_resolve_global(const char *module_name, WASMModule *module = NULL; module_reg = wasm_runtime_find_module_registered(module_name); - if (!module_reg - || module_reg->module_type != Wasm_Module_Bytecode) { + if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) { LOG_DEBUG("can not find a module named %s for global", module_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, global_name, - EXPORT_KIND_GLOBAL, - module->import_global_count - + module->global_count, - error_buf, error_buf_size); + export = wasm_loader_find_export( + module, module_name, global_name, EXPORT_KIND_GLOBAL, + module->import_global_count + module->global_count, error_buf, + error_buf_size); if (!export) { return NULL; } @@ -871,11 +850,11 @@ wasm_loader_resolve_global(const char *module_name, /* resolve and check the global */ if (export->index < module->import_global_count) { global = - module->import_globals[export->index].u.global.import_global_linked; + module->import_globals[export->index].u.global.import_global_linked; } else { global = - &(module->globals[export->index - module->import_global_count]); + &(module->globals[export->index - module->import_global_count]); } if (global->type != type || global->is_mutable != is_mutable) { LOG_DEBUG("%s,%s failed type check(%d, %d), expected(%d, %d)", @@ -891,11 +870,11 @@ static WASMModule * search_sub_module(const WASMModule *parent_module, const char *sub_module_name) { WASMRegisteredModule *node = - bh_list_first_elem(parent_module->import_module_list); + bh_list_first_elem(parent_module->import_module_list); while (node && strcmp(sub_module_name, node->module_name)) { node = bh_list_elem_next(node); } - return node ? (WASMModule*)node->module : NULL; + return node ? (WASMModule *)node->module : NULL; } static bool @@ -917,7 +896,7 @@ register_sub_module(const WASMModule *parent_module, } node->module_name = sub_module_name; - node->module = (WASMModuleCommon*)sub_module; + node->module = (WASMModuleCommon *)sub_module; ret = bh_list_insert(parent_module->import_module_list, node); bh_assert(BH_LIST_SUCCESS == ret); (void)ret; @@ -945,7 +924,7 @@ load_depended_module(const WASMModule *parent_module, /* check the global registered module list */ sub_module = - (WASMModule *)wasm_runtime_find_module_registered(sub_module_name); + (WASMModule *)wasm_runtime_find_module_registered(sub_module_name); if (sub_module) { LOG_DEBUG("%s has been loaded", sub_module_name); goto register_sub_module; @@ -955,8 +934,7 @@ load_depended_module(const WASMModule *parent_module, if (!reader) { set_error_buf_v(error_buf, error_buf_size, - "no sub module reader to load %s", - sub_module_name); + "no sub module reader to load %s", sub_module_name); return NULL; } @@ -964,16 +942,14 @@ load_depended_module(const WASMModule *parent_module, ret = wasm_runtime_is_loading_module(sub_module_name); if (ret) { set_error_buf_v(error_buf, error_buf_size, - "found circular dependency on %s", - sub_module_name); + "found circular dependency on %s", sub_module_name); return NULL; } ret = wasm_runtime_add_loading_module(sub_module_name, error_buf, error_buf_size); if (!ret) { - LOG_DEBUG("can not add %s into loading module list\n", - sub_module_name); + LOG_DEBUG("can not add %s into loading module list\n", sub_module_name); return NULL; } @@ -986,7 +962,7 @@ load_depended_module(const WASMModule *parent_module, } sub_module = - wasm_loader_load(buffer, buffer_size, error_buf, error_buf_size); + wasm_loader_load(buffer, buffer_size, error_buf, error_buf_size); if (!sub_module) { LOG_DEBUG("error: can not load the sub_module %s", sub_module_name); /* others will be destroyed in runtime_destroy() */ @@ -996,12 +972,12 @@ load_depended_module(const WASMModule *parent_module, wasm_runtime_delete_loading_module(sub_module_name); /* register on a global list */ - ret = wasm_runtime_register_module_internal(sub_module_name, - (WASMModuleCommon*)sub_module, - buffer, buffer_size, error_buf, - error_buf_size); + ret = wasm_runtime_register_module_internal( + sub_module_name, (WASMModuleCommon *)sub_module, buffer, buffer_size, + error_buf, error_buf_size); if (!ret) { - LOG_DEBUG("error: can not register module %s globally\n", sub_module_name); + LOG_DEBUG("error: can not register module %s globally\n", + sub_module_name); /* others will be unloaded in runtime_destroy() */ goto unload_module; } @@ -1011,8 +987,7 @@ load_depended_module(const WASMModule *parent_module, ret = register_sub_module(parent_module, sub_module_name, sub_module); if (!ret) { set_error_buf_v(error_buf, error_buf_size, - "failed to register sub module %s", - sub_module_name); + "failed to register sub module %s", sub_module_name); /* since it is in the global module list, no need to * unload the module. the runtime_destroy() will do it */ @@ -1042,10 +1017,9 @@ load_depended_module(const WASMModule *parent_module, static bool load_function_import(const uint8 **p_buf, const uint8 *buf_end, const WASMModule *parent_module, - const char *sub_module_name, - const char *function_name, - WASMFunctionImport *function, - char *error_buf, uint32 error_buf_size) + const char *sub_module_name, const char *function_name, + WASMFunctionImport *function, char *error_buf, + uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint32 declare_type_index = 0; @@ -1059,7 +1033,6 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end, bool linked_call_conv_raw = false; bool is_native_symbol = false; - CHECK_BUF(p, p_end, 1); read_leb_uint32(p, p_end, declare_type_index); *p_buf = p; @@ -1071,19 +1044,15 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end, #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) declare_type_index = wasm_get_smallest_type_idx( - parent_module->types, parent_module->type_count, - declare_type_index); + parent_module->types, parent_module->type_count, declare_type_index); #endif declare_func_type = parent_module->types[declare_type_index]; /* lookup registered native symbols first */ - linked_func = wasm_native_resolve_symbol(sub_module_name, - function_name, - declare_func_type, - &linked_signature, - &linked_attachment, - &linked_call_conv_raw); + linked_func = wasm_native_resolve_symbol( + sub_module_name, function_name, declare_func_type, &linked_signature, + &linked_attachment, &linked_call_conv_raw); if (linked_func) { is_native_symbol = true; } @@ -1096,11 +1065,9 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end, return false; } } - linked_func = wasm_loader_resolve_function(sub_module_name, - function_name, - declare_func_type, - error_buf, - error_buf_size); + linked_func = wasm_loader_resolve_function( + sub_module_name, function_name, declare_func_type, error_buf, + error_buf_size); } #endif @@ -1122,8 +1089,8 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end, } static bool -check_table_max_size(uint32 init_size, uint32 max_size, - char *error_buf, uint32 error_buf_size) +check_table_max_size(uint32 init_size, uint32 max_size, char *error_buf, + uint32 error_buf_size) { if (max_size < init_size) { set_error_buf(error_buf, error_buf_size, @@ -1135,10 +1102,8 @@ check_table_max_size(uint32 init_size, uint32 max_size, static bool load_table_import(const uint8 **p_buf, const uint8 *buf_end, - WASMModule *parent_module, - const char *sub_module_name, - const char *table_name, - WASMTableImport *table, + WASMModule *parent_module, const char *sub_module_name, + const char *table_name, WASMTableImport *table, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; @@ -1191,9 +1156,8 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, } linked_table = wasm_loader_resolve_table( - sub_module_name, table_name, - declare_init_size, declare_max_size, - error_buf, error_buf_size); + sub_module_name, table_name, declare_init_size, declare_max_size, + error_buf, error_buf_size); if (!linked_table) { return false; } @@ -1245,8 +1209,7 @@ unsigned wasm_runtime_memory_pool_size(); static bool -check_memory_init_size(uint32 init_size, - char *error_buf, uint32 error_buf_size) +check_memory_init_size(uint32 init_size, char *error_buf, uint32 error_buf_size) { if (init_size > 65536) { set_error_buf(error_buf, error_buf_size, @@ -1257,8 +1220,8 @@ check_memory_init_size(uint32 init_size, } static bool -check_memory_max_size(uint32 init_size, uint32 max_size, - char *error_buf, uint32 error_buf_size) +check_memory_max_size(uint32 init_size, uint32 max_size, char *error_buf, + uint32 error_buf_size) { if (max_size < init_size) { set_error_buf(error_buf, error_buf_size, @@ -1276,10 +1239,8 @@ check_memory_max_size(uint32 init_size, uint32 max_size, static bool load_memory_import(const uint8 **p_buf, const uint8 *buf_end, - WASMModule *parent_module, - const char *sub_module_name, - const char *memory_name, - WASMMemoryImport *memory, + WASMModule *parent_module, const char *sub_module_name, + const char *memory_name, WASMMemoryImport *memory, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; @@ -1330,9 +1291,8 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, } linked_memory = wasm_loader_resolve_memory( - sub_module_name, memory_name, - declare_init_page_count, declare_max_page_count, - error_buf, error_buf_size); + sub_module_name, memory_name, declare_init_page_count, + declare_max_page_count, error_buf, error_buf_size); if (!linked_memory) { return false; } @@ -1383,10 +1343,9 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, static bool load_global_import(const uint8 **p_buf, const uint8 *buf_end, - const WASMModule *parent_module, - char *sub_module_name, char *global_name, - WASMGlobalImport *global, - char *error_buf, uint32 error_buf_size) + const WASMModule *parent_module, char *sub_module_name, + char *global_name, WASMGlobalImport *global, char *error_buf, + uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint8 declare_type = 0; @@ -1408,7 +1367,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, #if WASM_ENABLE_LIBC_BUILTIN != 0 global->is_linked = wasm_native_lookup_libc_builtin_global( - sub_module_name, global_name, global); + sub_module_name, global_name, global); if (global->is_linked) { if (global->type != declare_type || global->is_mutable != declare_mutable) { @@ -1428,10 +1387,9 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, } /* check sub modules */ - linked_global = - wasm_loader_resolve_global(sub_module_name, global_name, - declare_type, declare_mutable, - error_buf, error_buf_size); + linked_global = wasm_loader_resolve_global( + sub_module_name, global_name, declare_type, declare_mutable, + error_buf, error_buf_size); if (linked_global) { global->import_module = sub_module; global->import_global_linked = linked_global; @@ -1547,22 +1505,23 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory, return false; } else if (memory->flags == 2) { - set_error_buf(error_buf, error_buf_size, "shared memory must have maximum"); + set_error_buf(error_buf, error_buf_size, + "shared memory must have maximum"); return false; } #endif read_leb_uint32(p, p_end, memory->init_page_count); - if (!check_memory_init_size(memory->init_page_count, - error_buf, error_buf_size)) + if (!check_memory_init_size(memory->init_page_count, error_buf, + error_buf_size)) return false; if (memory->flags & 1) { read_leb_uint32(p, p_end, memory->max_page_count); if (!check_memory_max_size(memory->init_page_count, - memory->max_page_count, - error_buf, error_buf_size)) - return false; + memory->max_page_count, error_buf, + error_buf_size)) + return false; if (memory->max_page_count > max_page_count) memory->max_page_count = max_page_count; } @@ -1593,10 +1552,11 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, uint8 u8, kind; /* insert builtin module names into const str list */ - if (!const_str_list_insert((uint8*)"env", 3, module, error_buf, error_buf_size) - || !const_str_list_insert((uint8*)"wasi_unstable", 13, module, + if (!const_str_list_insert((uint8 *)"env", 3, module, error_buf, + error_buf_size) + || !const_str_list_insert((uint8 *)"wasi_unstable", 13, module, error_buf, error_buf_size) - || !const_str_list_insert((uint8*)"wasi_snapshot_preview1", 22, module, + || !const_str_list_insert((uint8 *)"wasi_snapshot_preview1", 22, module, error_buf, error_buf_size)) { return false; } @@ -1606,8 +1566,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (import_count) { module->import_count = import_count; total_size = sizeof(WASMImport) * (uint64)import_count; - if (!(module->imports = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->imports = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -1647,10 +1607,10 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if ( #if WASM_ENABLE_REF_TYPES != 0 - !wasm_get_ref_types_flag() && + !wasm_get_ref_types_flag() && #endif - module->import_table_count > 1) { + module->import_table_count > 1) { set_error_buf(error_buf, error_buf_size, "multiple tables"); return false; @@ -1690,11 +1650,12 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module->imports + module->import_function_count; if (module->import_memory_count) import_memories = module->import_memories = - module->imports + module->import_function_count + module->import_table_count; + module->imports + module->import_function_count + + module->import_table_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->imports + module->import_function_count + + module->import_table_count + module->import_memory_count; p = p_old; @@ -1704,7 +1665,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, name_len); CHECK_BUF(p, p_end, name_len); if (!(sub_module_name = const_str_list_insert( - p, name_len, module, error_buf, error_buf_size))) { + p, name_len, module, error_buf, error_buf_size))) { return false; } p += name_len; @@ -1713,7 +1674,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, name_len); CHECK_BUF(p, p_end, name_len); if (!(field_name = const_str_list_insert( - p, name_len, module, error_buf, error_buf_size))) { + p, name_len, module, error_buf, error_buf_size))) { return false; } p += name_len; @@ -1726,10 +1687,9 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, case IMPORT_KIND_FUNC: /* import function */ bh_assert(import_functions); import = import_functions++; - if (!load_function_import(&p, p_end, module, - sub_module_name, field_name, - &import->u.function, - error_buf, error_buf_size)) { + if (!load_function_import( + &p, p_end, module, sub_module_name, field_name, + &import->u.function, error_buf, error_buf_size)) { return false; } break; @@ -1737,9 +1697,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, case IMPORT_KIND_TABLE: /* import table */ bh_assert(import_tables); import = import_tables++; - if (!load_table_import(&p, p_end, module, - sub_module_name, field_name, - &import->u.table, + if (!load_table_import(&p, p_end, module, sub_module_name, + field_name, &import->u.table, error_buf, error_buf_size)) { LOG_DEBUG("can not import such a table (%s,%s)", sub_module_name, field_name); @@ -1750,9 +1709,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, case IMPORT_KIND_MEMORY: /* import memory */ bh_assert(import_memories); import = import_memories++; - if (!load_memory_import(&p, p_end, module, - sub_module_name, field_name, - &import->u.memory, + if (!load_memory_import(&p, p_end, module, sub_module_name, + field_name, &import->u.memory, error_buf, error_buf_size)) { return false; } @@ -1761,9 +1719,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, case IMPORT_KIND_GLOBAL: /* import global */ bh_assert(import_globals); import = import_globals++; - if (!load_global_import(&p, p_end, module, - sub_module_name, field_name, - &import->u.global, + if (!load_global_import(&p, p_end, module, sub_module_name, + field_name, &import->u.global, error_buf, error_buf_size)) { return false; } @@ -1783,7 +1740,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, import = module->import_functions; for (i = 0; i < module->import_function_count; i++, import++) { if (!strcmp(import->u.names.module_name, "wasi_unstable") - || !strcmp(import->u.names.module_name, "wasi_snapshot_preview1")) { + || !strcmp(import->u.names.module_name, + "wasi_snapshot_preview1")) { module->is_wasi_module = true; break; } @@ -1806,8 +1764,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } static bool -init_function_local_offsets(WASMFunction *func, - char *error_buf, uint32 error_buf_size) +init_function_local_offsets(WASMFunction *func, char *error_buf, + uint32 error_buf_size) { WASMType *param_type = func->func_type; uint32 param_count = param_type->param_count; @@ -1824,7 +1782,7 @@ init_function_local_offsets(WASMFunction *func, */ if (total_size > 0 && !(func->local_offsets = - loader_malloc(total_size, error_buf, error_buf_size))) { + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -1845,8 +1803,8 @@ init_function_local_offsets(WASMFunction *func, static bool load_function_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) + WASMModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; const uint8 *p_code = buf_code, *p_code_end, *p_code_save; @@ -1871,9 +1829,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, if (func_count) { module->function_count = func_count; - total_size = sizeof(WASMFunction*) * (uint64)func_count; + total_size = sizeof(WASMFunction *) * (uint64)func_count; if (!(module->functions = - loader_malloc(total_size, error_buf, error_buf_size))) { + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -1887,12 +1845,11 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) type_index = wasm_get_smallest_type_idx( - module->types, module->type_count, type_index); + module->types, module->type_count, type_index); #endif read_leb_uint32(p_code, buf_code_end, code_size); - if (code_size == 0 - || p_code + code_size > buf_code_end) { + if (code_size == 0 || p_code + code_size > buf_code_end) { set_error_buf(error_buf, error_buf_size, "invalid function code size"); return false; @@ -1908,8 +1865,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, for (j = 0; j < local_set_count; j++) { read_leb_uint32(p_code, buf_code_end, sub_local_count); if (sub_local_count > UINT32_MAX - local_count) { - set_error_buf(error_buf, error_buf_size, - "too many locals"); + set_error_buf(error_buf, error_buf_size, "too many locals"); return false; } CHECK_BUF(p_code, buf_code_end, 1); @@ -1923,7 +1879,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, total_size = sizeof(WASMFunction) + (uint64)local_count; if (!(func = module->functions[i] = - loader_malloc(total_size, error_buf, error_buf_size))) { + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -1931,7 +1887,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, func->func_type = module->types[type_index]; func->local_count = local_count; if (local_count > 0) - func->local_types = (uint8*)func + sizeof(WASMFunction); + func->local_types = (uint8 *)func + sizeof(WASMFunction); func->code_size = code_size; /* * we shall make a copy of code body [p_code, p_code + code_size] @@ -1943,14 +1899,15 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, * memcpy(code_body_cp, p_code, code_size); * func->code = code_body_cp; */ - func->code = (uint8*)p_code; + func->code = (uint8 *)p_code; /* Load each local type */ p_code = p_code_save; local_type_index = 0; for (j = 0; j < local_set_count; j++) { read_leb_uint32(p_code, buf_code_end, sub_local_count); - if (local_type_index + sub_local_count <= local_type_index + if (!sub_local_count + || local_type_index > UINT32_MAX - sub_local_count || local_type_index + sub_local_count > local_count) { set_error_buf(error_buf, error_buf_size, "invalid local count"); @@ -2012,10 +1969,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, } static bool -check_function_index(const WASMModule *module, - uint32 function_index, - char *error_buf, - uint32 error_buf_size) +check_function_index(const WASMModule *module, uint32 function_index, + char *error_buf, uint32 error_buf_size) { if (function_index >= module->import_function_count + module->function_count) { @@ -2038,9 +1993,9 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, table_count); if ( #if WASM_ENABLE_REF_TYPES != 0 - !wasm_get_ref_types_flag() && + !wasm_get_ref_types_flag() && #endif - module->import_table_count + table_count > 1) { + module->import_table_count + table_count > 1) { /* a total of one table is allowed */ set_error_buf(error_buf, error_buf_size, "multiple tables"); return false; @@ -2049,8 +2004,8 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (table_count) { module->table_count = table_count; total_size = sizeof(WASMTable) * (uint64)table_count; - if (!(module->tables = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->tables = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -2091,8 +2046,8 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (memory_count) { module->memory_count = memory_count; total_size = sizeof(WASMMemory) * (uint64)memory_count; - if (!(module->memories = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->memories = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -2129,14 +2084,14 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (global_count) { module->global_count = global_count; total_size = sizeof(WASMGlobal) * (uint64)global_count; - if (!(module->globals = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->globals = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } global = module->globals; - for(i = 0; i < global_count; i++, global++) { + for (i = 0; i < global_count; i++, global++) { CHECK_BUF(p, p_end, 2); global->type = read_uint8(p); mutable = read_uint8(p); @@ -2147,8 +2102,8 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, global->is_mutable = mutable ? true : false; /* initialize expression */ - if (!load_init_expr(&p, p_end, &(global->init_expr), - global->type, error_buf, error_buf_size)) + if (!load_init_expr(&p, p_end, &(global->init_expr), global->type, + error_buf, error_buf_size)) return false; if (INIT_EXPR_TYPE_GET_GLOBAL == global->init_expr.init_expr_type) { @@ -2164,9 +2119,9 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } } - else if (INIT_EXPR_TYPE_FUNCREF_CONST == global->init_expr.init_expr_type) { - if (!check_function_index(module, - global->init_expr.u.ref_index, + else if (INIT_EXPR_TYPE_FUNCREF_CONST + == global->init_expr.init_expr_type) { + if (!check_function_index(module, global->init_expr.u.ref_index, error_buf, error_buf_size)) { return false; } @@ -2201,28 +2156,27 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (export_count) { module->export_count = export_count; total_size = sizeof(WASMExport) * (uint64)export_count; - if (!(module->exports = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->exports = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } export = module->exports; - for (i = 0; i < export_count; i++, export++) { + for (i = 0; i < export_count; i++, export ++) { read_leb_uint32(p, p_end, str_len); CHECK_BUF(p, p_end, str_len); for (j = 0; j < i; j++) { name = module->exports[j].name; - if (strlen(name) == str_len - && memcmp(name, p, str_len) == 0) { - set_error_buf(error_buf, error_buf_size, - "duplicate export name"); - return false; + if (strlen(name) == str_len && memcmp(name, p, str_len) == 0) { + set_error_buf(error_buf, error_buf_size, + "duplicate export name"); + return false; } } - if (!(export->name = const_str_list_insert(p, str_len, module, - error_buf, error_buf_size))) { + if (!(export->name = const_str_list_insert( + p, str_len, module, error_buf, error_buf_size))) { return false; } @@ -2232,11 +2186,11 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, index); export->index = index; - switch(export->kind) { + switch (export->kind) { /* function index */ case EXPORT_KIND_FUNC: if (index >= module->function_count - + module->import_function_count) { + + module->import_function_count) { set_error_buf(error_buf, error_buf_size, "unknown function"); return false; @@ -2250,8 +2204,8 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, break; /* table index */ case EXPORT_KIND_TABLE: - if (index >= module->table_count - + module->import_table_count) { + if (index + >= module->table_count + module->import_table_count) { set_error_buf(error_buf, error_buf_size, "unknown table"); return false; @@ -2259,8 +2213,8 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, break; /* memory index */ case EXPORT_KIND_MEMORY: - if (index >= module->memory_count - + module->import_memory_count) { + if (index + >= module->memory_count + module->import_memory_count) { set_error_buf(error_buf, error_buf_size, "unknown memory"); return false; @@ -2268,8 +2222,8 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, break; /* global index */ case EXPORT_KIND_GLOBAL: - if (index >= module->global_count - + module->import_global_count) { + if (index + >= module->global_count + module->import_global_count) { set_error_buf(error_buf, error_buf_size, "unknown global"); return false; @@ -2284,8 +2238,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } if (p != p_end) { - set_error_buf(error_buf, error_buf_size, - "section size mismatch"); + set_error_buf(error_buf, error_buf_size, "section size mismatch"); return false; } @@ -2296,14 +2249,14 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } static bool -check_table_index(const WASMModule *module, uint32 table_index, - char *error_buf, uint32 error_buf_size) +check_table_index(const WASMModule *module, uint32 table_index, char *error_buf, + uint32 error_buf_size) { if ( #if WASM_ENABLE_REF_TYPES != 0 - !wasm_get_ref_types_flag() && + !wasm_get_ref_types_flag() && #endif - table_index != 0) { + table_index != 0) { set_error_buf(error_buf, error_buf_size, "zero byte expected"); return false; } @@ -2317,9 +2270,8 @@ check_table_index(const WASMModule *module, uint32 table_index, } static bool -load_table_index(const uint8 **p_buf, const uint8 *buf_end, - WASMModule *module, uint32 *p_table_index, - char *error_buf, uint32 error_buf_size) +load_table_index(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module, + uint32 *p_table_index, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint32 table_index; @@ -2338,9 +2290,8 @@ load_table_index(const uint8 **p_buf, const uint8 *buf_end, #if WASM_ENABLE_REF_TYPES != 0 static bool -load_elem_type(const uint8 **p_buf, const uint8 *buf_end, - uint32 *p_elem_type, bool elemkind_zero, - char *error_buf, uint32 error_buf_size) +load_elem_type(const uint8 **p_buf, const uint8 *buf_end, uint32 *p_elem_type, + bool elemkind_zero, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint8 elem_type; @@ -2368,8 +2319,7 @@ load_elem_type(const uint8 **p_buf, const uint8 *buf_end, static bool load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module, WASMTableSeg *table_segment, - bool use_init_expr, - char *error_buf, uint32 error_buf_size) + bool use_init_expr, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint32 function_count, function_index = 0, i; @@ -2379,8 +2329,8 @@ load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end, table_segment->function_count = function_count; total_size = sizeof(uint32) * (uint64)function_count; if (total_size > 0 - && !(table_segment->func_indexes = (uint32 *) - loader_malloc(total_size, error_buf, error_buf_size))) { + && !(table_segment->func_indexes = (uint32 *)loader_malloc( + total_size, error_buf, error_buf_size))) { return false; } @@ -2424,8 +2374,9 @@ load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end, } static bool -load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, - char *error_buf, uint32 error_buf_size) +load_table_segment_section(const uint8 *buf, const uint8 *buf_end, + WASMModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; uint32 table_segment_count, i; @@ -2437,8 +2388,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m if (table_segment_count) { module->table_seg_count = table_segment_count; total_size = sizeof(WASMTableSeg) * (uint64)table_segment_count; - if (!(module->table_segments = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->table_segments = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -2468,13 +2419,13 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m error_buf, error_buf_size)) return false; if (!load_init_expr( - &p, p_end, &table_segment->base_offset, - VALUE_TYPE_I32, error_buf, error_buf_size)) + &p, p_end, &table_segment->base_offset, + VALUE_TYPE_I32, error_buf, error_buf_size)) return false; if (!load_func_index_vec( - &p, p_end, module, table_segment, - table_segment->mode == 0 ? false : true, - error_buf, error_buf_size)) + &p, p_end, module, table_segment, + table_segment->mode == 0 ? false : true, + error_buf, error_buf_size)) return false; break; /* elemkind + passive/declarative */ @@ -2497,18 +2448,18 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m error_buf, error_buf_size)) return false; if (!load_init_expr( - &p, p_end, &table_segment->base_offset, - VALUE_TYPE_I32, error_buf, error_buf_size)) + &p, p_end, &table_segment->base_offset, + VALUE_TYPE_I32, error_buf, error_buf_size)) return false; if (!load_elem_type( - &p, p_end, &table_segment->elem_type, - table_segment->mode == 2 ? true : false, - error_buf, error_buf_size)) + &p, p_end, &table_segment->elem_type, + table_segment->mode == 2 ? true : false, + error_buf, error_buf_size)) return false; if (!load_func_index_vec( - &p, p_end, module, table_segment, - table_segment->mode == 2 ? false : true, - error_buf, error_buf_size)) + &p, p_end, module, table_segment, + table_segment->mode == 2 ? false : true, + error_buf, error_buf_size)) return false; break; case 5: @@ -2518,8 +2469,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m error_buf, error_buf_size)) return false; if (!load_func_index_vec(&p, p_end, module, - table_segment, true, - error_buf, error_buf_size)) + table_segment, true, error_buf, + error_buf_size)) return false; break; default: @@ -2562,8 +2513,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m static bool load_data_segment_section(const uint8 *buf, const uint8 *buf_end, - WASMModule *module, - char *error_buf, uint32 error_buf_size) + WASMModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; uint32 data_seg_count, i, mem_index, data_seg_len; @@ -2588,9 +2539,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, if (data_seg_count) { module->data_seg_count = data_seg_count; - total_size = sizeof(WASMDataSeg*) * (uint64)data_seg_count; - if (!(module->data_segments = loader_malloc - (total_size, error_buf, error_buf_size))) { + total_size = sizeof(WASMDataSeg *) * (uint64)data_seg_count; + if (!(module->data_segments = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -2610,7 +2561,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, case 0x02: /* read following memory index */ read_leb_uint32(p, p_end, mem_index); -check_mem_index: + check_mem_index: if (mem_index >= module->import_memory_count + module->memory_count) { set_error_buf_v(error_buf, error_buf_size, @@ -2621,7 +2572,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, case 0x03: default: set_error_buf(error_buf, error_buf_size, "unknown memory"); - return false; + return false; break; } #else @@ -2642,8 +2593,8 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, read_leb_uint32(p, p_end, data_seg_len); - if (!(dataseg = module->data_segments[i] = loader_malloc - (sizeof(WASMDataSeg), error_buf, error_buf_size))) { + if (!(dataseg = module->data_segments[i] = loader_malloc( + sizeof(WASMDataSeg), error_buf, error_buf_size))) { return false; } @@ -2652,15 +2603,16 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, if (!is_passive) #endif { - bh_memcpy_s(&dataseg->base_offset, sizeof(InitializerExpression), - &init_expr, sizeof(InitializerExpression)); + bh_memcpy_s(&dataseg->base_offset, + sizeof(InitializerExpression), &init_expr, + sizeof(InitializerExpression)); dataseg->memory_index = mem_index; } dataseg->data_length = data_seg_len; CHECK_BUF(p, p_end, data_seg_len); - dataseg->data = (uint8*)p; + dataseg->data = (uint8 *)p; p += data_seg_len; } } @@ -2678,8 +2630,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, #if WASM_ENABLE_BULK_MEMORY != 0 static bool -load_datacount_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, - char *error_buf, uint32 error_buf_size) +load_datacount_section(const uint8 *buf, const uint8 *buf_end, + WASMModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; uint32 data_seg_count1 = 0; @@ -2700,10 +2653,8 @@ load_datacount_section(const uint8 *buf, const uint8 *buf_end, WASMModule *modul #endif static bool -load_code_section(const uint8 *buf, const uint8 *buf_end, - const uint8 *buf_func, - const uint8 *buf_func_end, - WASMModule *module, +load_code_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_func, + const uint8 *buf_func_end, WASMModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; @@ -2748,9 +2699,8 @@ load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (start_function < module->import_function_count) type = module->import_functions[start_function].u.function.func_type; else - type = - module->functions[start_function - module->import_function_count] - ->func_type; + type = module->functions[start_function - module->import_function_count] + ->func_type; if (type->param_count != 0 || type->result_count != 0) { set_error_buf(error_buf, error_buf_size, "invalid start function"); return false; @@ -2771,8 +2721,7 @@ load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 static bool -handle_name_section(const uint8 *buf, const uint8 *buf_end, - WASMModule *module, +handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; @@ -2837,9 +2786,9 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end, return false; } if (!(module->functions[func_index]->field_name = - const_str_list_insert(p, func_name_len, - module, error_buf, - error_buf_size))) { + const_str_list_insert(p, func_name_len, + module, error_buf, + error_buf_size))) { return false; } } @@ -2847,8 +2796,9 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end, } } break; - case SUB_SECTION_TYPE_MODULE: /* TODO: Parse for module subsection */ - case SUB_SECTION_TYPE_LOCAL: /* TODO: Parse for local subsection */ + case SUB_SECTION_TYPE_MODULE: /* TODO: Parse for module subsection + */ + case SUB_SECTION_TYPE_LOCAL: /* TODO: Parse for local subsection */ default: p = p + subsection_size; break; @@ -2876,15 +2826,13 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, name_len); - if (name_len == 0 - || p + name_len > p_end) { + if (name_len == 0 || p + name_len > p_end) { set_error_buf(error_buf, error_buf_size, "unexpected end"); return false; } if (!check_utf8_str(p, name_len)) { - set_error_buf(error_buf, error_buf_size, - "invalid UTF-8 encoding"); + set_error_buf(error_buf, error_buf_size, "invalid UTF-8 encoding"); return false; } @@ -2901,9 +2849,9 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } static bool -wasm_loader_prepare_bytecode(WASMModule *module, - WASMFunction *func, uint32 cur_func_idx, - char *error_buf, uint32 error_buf_size); +wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, + uint32 cur_func_idx, char *error_buf, + uint32 error_buf_size); #if WASM_ENABLE_FAST_INTERP != 0 && WASM_ENABLE_LABELS_AS_VALUES != 0 void ** @@ -2913,13 +2861,13 @@ static void **handle_table; #endif static bool -load_from_sections(WASMModule *module, WASMSection *sections, - char *error_buf, uint32 error_buf_size) +load_from_sections(WASMModule *module, WASMSection *sections, char *error_buf, + uint32 error_buf_size) { WASMExport *export; WASMSection *section = sections; const uint8 *buf, *buf_end, *buf_code = NULL, *buf_code_end = NULL, - *buf_func = NULL, *buf_func_end = NULL; + *buf_func = NULL, *buf_func_end = NULL; WASMGlobal *aux_data_end_global = NULL, *aux_heap_base_global = NULL; WASMGlobal *aux_stack_top_global = NULL, *global; uint32 aux_data_end = (uint32)-1, aux_heap_base = (uint32)-1; @@ -2933,6 +2881,10 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (section->section_type == SECTION_TYPE_CODE) { buf_code = section->section_body; buf_code_end = buf_code + section->section_body_size; +#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_DEBUG_AOT != 0 + module->buf_code = (uint8 *)buf_code; + module->buf_code_size = section->section_body_size; +#endif } else if (section->section_type == SECTION_TYPE_FUNC) { buf_func = section->section_body; @@ -2948,18 +2900,18 @@ load_from_sections(WASMModule *module, WASMSection *sections, switch (section->section_type) { case SECTION_TYPE_USER: /* unsupported user section, ignore it. */ - if (!load_user_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_user_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_TYPE: - if (!load_type_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_type_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_IMPORT: - if (!load_import_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_import_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_FUNC: @@ -2968,33 +2920,33 @@ load_from_sections(WASMModule *module, WASMSection *sections, return false; break; case SECTION_TYPE_TABLE: - if (!load_table_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_table_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_MEMORY: - if (!load_memory_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_memory_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_GLOBAL: - if (!load_global_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_global_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_EXPORT: - if (!load_export_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_export_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_START: - if (!load_start_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_start_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_ELEM: - if (!load_table_segment_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_table_segment_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_CODE: @@ -3003,20 +2955,19 @@ load_from_sections(WASMModule *module, WASMSection *sections, return false; break; case SECTION_TYPE_DATA: - if (!load_data_segment_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_data_segment_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; #if WASM_ENABLE_BULK_MEMORY != 0 case SECTION_TYPE_DATACOUNT: - if (!load_datacount_section(buf, buf_end, module, - error_buf, error_buf_size)) + if (!load_datacount_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; #endif default: - set_error_buf(error_buf, error_buf_size, - "invalid section id"); + set_error_buf(error_buf, error_buf_size, "invalid section id"); return false; } @@ -3029,15 +2980,14 @@ load_from_sections(WASMModule *module, WASMSection *sections, /* Resolve auxiliary data/stack/heap info and reset memory info */ export = module->exports; - for (i = 0; i < module->export_count; i++, export++) { + for (i = 0; i < module->export_count; i++, export ++) { if (export->kind == EXPORT_KIND_GLOBAL) { if (!strcmp(export->name, "__heap_base")) { global_index = export->index - module->import_global_count; global = module->globals + global_index; - if (global->type == VALUE_TYPE_I32 - && !global->is_mutable - && global->init_expr.init_expr_type == - INIT_EXPR_TYPE_I32_CONST) { + if (global->type == VALUE_TYPE_I32 && !global->is_mutable + && global->init_expr.init_expr_type + == INIT_EXPR_TYPE_I32_CONST) { aux_heap_base_global = global; aux_heap_base = global->init_expr.u.i32; aux_heap_base_global_index = export->index; @@ -3048,10 +2998,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, else if (!strcmp(export->name, "__data_end")) { global_index = export->index - module->import_global_count; global = module->globals + global_index; - if (global->type == VALUE_TYPE_I32 - && !global->is_mutable - && global->init_expr.init_expr_type == - INIT_EXPR_TYPE_I32_CONST) { + if (global->type == VALUE_TYPE_I32 && !global->is_mutable + && global->init_expr.init_expr_type + == INIT_EXPR_TYPE_I32_CONST) { aux_data_end_global = global; aux_data_end = global->init_expr.u.i32; aux_data_end_global_index = export->index; @@ -3092,17 +3041,18 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (global->is_mutable /* heap_base and data_end is not mutable */ && global->type == VALUE_TYPE_I32 - && global->init_expr.init_expr_type == - INIT_EXPR_TYPE_I32_CONST + && global->init_expr.init_expr_type + == INIT_EXPR_TYPE_I32_CONST && (uint32)global->init_expr.u.i32 <= aux_heap_base) { aux_stack_top_global = global; aux_stack_top = (uint32)global->init_expr.u.i32; module->aux_stack_top_global_index = - module->import_global_count + global_index; + module->import_global_count + global_index; module->aux_stack_bottom = aux_stack_top; - module->aux_stack_size = aux_stack_top > aux_data_end - ? aux_stack_top - aux_data_end - : aux_stack_top; + module->aux_stack_size = + aux_stack_top > aux_data_end + ? aux_stack_top - aux_data_end + : aux_stack_top; LOG_VERBOSE("Found aux stack top global, value: %d, " "global index: %d, stack size: %d", aux_stack_top, global_index, @@ -3121,14 +3071,13 @@ load_from_sections(WASMModule *module, WASMSection *sections, /* Resolve malloc/free function exported by wasm module */ export = module->exports; - for (i = 0; i < module->export_count; i++, export++) { + for (i = 0; i < module->export_count; i++, export ++) { if (export->kind == EXPORT_KIND_FUNC) { if (!strcmp(export->name, "malloc") && export->index >= module->import_function_count) { func_index = export->index - module->import_function_count; func_type = module->functions[func_index]->func_type; - if (func_type->param_count == 1 - && func_type->result_count == 1 + if (func_type->param_count == 1 && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32) { bh_assert(module->malloc_function == (uint32)-1); @@ -3142,8 +3091,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, /* __new && __pin for AssemblyScript */ func_index = export->index - module->import_function_count; func_type = module->functions[func_index]->func_type; - if (func_type->param_count == 2 - && func_type->result_count == 1 + if (func_type->param_count == 2 && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32 && func_type->types[2] == VALUE_TYPE_I32) { @@ -3165,19 +3113,20 @@ load_from_sections(WASMModule *module, WASMSection *sections, && (export_tmp->index >= module->import_function_count)) { func_index = export_tmp->index - - module->import_function_count; + - module->import_function_count; func_type = - module->functions[func_index]->func_type; + module->functions[func_index]->func_type; if (func_type->param_count == 1 && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32) { - bh_assert( - module->retain_function == (uint32)-1); + bh_assert(module->retain_function + == (uint32)-1); module->retain_function = export_tmp->index; - LOG_VERBOSE( - "Found retain function, name: %s, index: %u", - export_tmp->name, export_tmp->index); + LOG_VERBOSE("Found retain function, name: %s, " + "index: %u", + export_tmp->name, + export_tmp->index); break; } } @@ -3195,8 +3144,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, && export->index >= module->import_function_count) { func_index = export->index - module->import_function_count; func_type = module->functions[func_index]->func_type; - if (func_type->param_count == 1 - && func_type->result_count == 0 + if (func_type->param_count == 1 && func_type->result_count == 0 && func_type->types[0] == VALUE_TYPE_I32) { bh_assert(module->free_function == (uint32)-1); module->free_function = export->index; @@ -3213,8 +3161,8 @@ load_from_sections(WASMModule *module, WASMSection *sections, for (i = 0; i < module->function_count; i++) { WASMFunction *func = module->functions[i]; - if (!wasm_loader_prepare_bytecode(module, func, i, - error_buf, error_buf_size)) { + if (!wasm_loader_prepare_bytecode(module, func, i, error_buf, + error_buf_size)) { return false; } } @@ -3223,16 +3171,15 @@ load_from_sections(WASMModule *module, WASMSection *sections, WASMMemoryImport *memory_import; WASMMemory *memory; - if (aux_data_end_global - && aux_heap_base_global + if (aux_data_end_global && aux_heap_base_global && aux_stack_top_global) { uint64 init_memory_size; uint32 shrunk_memory_size = align_uint(aux_heap_base, 8); if (module->import_memory_count) { memory_import = &module->import_memories[0].u.memory; - init_memory_size = (uint64)memory_import->num_bytes_per_page * - memory_import->init_page_count; + init_memory_size = (uint64)memory_import->num_bytes_per_page + * memory_import->init_page_count; if (shrunk_memory_size <= init_memory_size) { /* Reset memory info to decrease memory usage */ memory_import->num_bytes_per_page = shrunk_memory_size; @@ -3243,8 +3190,8 @@ load_from_sections(WASMModule *module, WASMSection *sections, } if (module->memory_count) { memory = &module->memories[0]; - init_memory_size = (uint64)memory->num_bytes_per_page * - memory->init_page_count; + init_memory_size = (uint64)memory->num_bytes_per_page + * memory->init_page_count; if (shrunk_memory_size <= init_memory_size) { /* Reset memory info to decrease memory usage */ memory->num_bytes_per_page = shrunk_memory_size; @@ -3273,16 +3220,16 @@ load_from_sections(WASMModule *module, WASMSection *sections, } #if WASM_ENABLE_MEMORY_TRACING != 0 - wasm_runtime_dump_module_mem_consumption((WASMModuleCommon*)module); + wasm_runtime_dump_module_mem_consumption((WASMModuleCommon *)module); #endif return true; } -static WASMModule* +static WASMModule * create_module(char *error_buf, uint32 error_buf_size) { - WASMModule *module = loader_malloc(sizeof(WASMModule), - error_buf, error_buf_size); + WASMModule *module = + loader_malloc(sizeof(WASMModule), error_buf, error_buf_size); if (!module) { return NULL; @@ -3295,13 +3242,30 @@ create_module(char *error_buf, uint32 error_buf_size) #if WASM_ENABLE_MULTI_MODULE != 0 module->import_module_list = &module->import_module_list_head; +#endif +#if WASM_ENABLE_DEBUG_INTERP != 0 + bh_list_init(&module->fast_opcode_list); #endif return module; } +#if WASM_ENABLE_DEBUG_INTERP != 0 +static void +record_fast_op(WASMModule *module, uint8 *pos, uint8 orig_op) +{ + WASMFastOPCodeNode *fast_op = + wasm_runtime_malloc(sizeof(WASMFastOPCodeNode)); + if (fast_op) { + fast_op->offset = pos - module->load_addr; + fast_op->orig_op = orig_op; + bh_list_insert(&module->fast_opcode_list, fast_op); + } +} +#endif + WASMModule * -wasm_loader_load_from_sections(WASMSection *section_list, - char *error_buf, uint32 error_buf_size) +wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf, + uint32 error_buf_size) { WASMModule *module = create_module(error_buf, error_buf_size); if (!module) @@ -3327,6 +3291,7 @@ destroy_sections(WASMSection *section_list) } } +/* clang-format off */ static uint8 section_ids[] = { SECTION_TYPE_USER, SECTION_TYPE_TYPE, @@ -3344,6 +3309,7 @@ static uint8 section_ids[] = { SECTION_TYPE_CODE, SECTION_TYPE_DATA }; +/* clang-format on */ static uint8 get_section_index(uint8 section_type) @@ -3359,12 +3325,11 @@ get_section_index(uint8 section_type) } static bool -create_sections(const uint8 *buf, uint32 size, - WASMSection **p_section_list, +create_sections(const uint8 *buf, uint32 size, WASMSection **p_section_list, char *error_buf, uint32 error_buf_size) { WASMSection *section_list_end = NULL, *section; - const uint8 *p = buf, *p_end = buf + size/*, *section_body*/; + const uint8 *p = buf, *p_end = buf + size /*, *section_body*/; uint8 section_type, section_index, last_section_index = (uint8)-1; uint32 section_size; @@ -3392,13 +3357,13 @@ create_sections(const uint8 *buf, uint32 size, read_leb_uint32(p, p_end, section_size); CHECK_BUF1(p, p_end, section_size); - if (!(section = loader_malloc(sizeof(WASMSection), - error_buf, error_buf_size))) { + if (!(section = loader_malloc(sizeof(WASMSection), error_buf, + error_buf_size))) { return false; } section->section_type = section_type; - section->section_body = (uint8*)p; + section->section_body = (uint8 *)p; section->section_body_size = section_size; if (!section_list_end) @@ -3411,8 +3376,7 @@ create_sections(const uint8 *buf, uint32 size, p += section_size; } else { - set_error_buf(error_buf, error_buf_size, - "invalid section id"); + set_error_buf(error_buf, error_buf_size, "invalid section id"); return false; } } @@ -3423,7 +3387,7 @@ create_sections(const uint8 *buf, uint32 size, } static void -exchange32(uint8* p_data) +exchange32(uint8 *p_data) { uint8 value = *p_data; *p_data = *(p_data + 3); @@ -3442,8 +3406,8 @@ static union { #define is_little_endian() (__ue.b == 1) static bool -load(const uint8 *buf, uint32 size, WASMModule *module, - char *error_buf, uint32 error_buf_size) +load(const uint8 *buf, uint32 size, WASMModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *buf_end = buf + size; const uint8 *p = buf, *p_end = buf_end; @@ -3453,27 +3417,26 @@ load(const uint8 *buf, uint32 size, WASMModule *module, CHECK_BUF1(p, p_end, sizeof(uint32)); magic_number = read_uint32(p); if (!is_little_endian()) - exchange32((uint8*)&magic_number); + exchange32((uint8 *)&magic_number); if (magic_number != WASM_MAGIC_NUMBER) { - set_error_buf(error_buf, error_buf_size, - "magic header not detected"); + set_error_buf(error_buf, error_buf_size, "magic header not detected"); return false; } CHECK_BUF1(p, p_end, sizeof(uint32)); version = read_uint32(p); if (!is_little_endian()) - exchange32((uint8*)&version); + exchange32((uint8 *)&version); if (version != WASM_CURRENT_VERSION) { - set_error_buf(error_buf, error_buf_size, - "unknown binary version"); + set_error_buf(error_buf, error_buf_size, "unknown binary version"); return false; } if (!create_sections(buf, size, §ion_list, error_buf, error_buf_size) - || !load_from_sections(module, section_list, error_buf, error_buf_size)) { + || !load_from_sections(module, section_list, error_buf, + error_buf_size)) { destroy_sections(section_list); return false; } @@ -3484,14 +3447,20 @@ load(const uint8 *buf, uint32 size, WASMModule *module, return false; } -WASMModule* -wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size) +WASMModule * +wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, + uint32 error_buf_size) { WASMModule *module = create_module(error_buf, error_buf_size); if (!module) { return NULL; } +#if WASM_ENABLE_DEBUG_INTERP != 0 + module->load_addr = (uint8 *)buf; + module->load_size = size; +#endif + if (!load(buf, size, module, error_buf, error_buf_size)) { goto fail; } @@ -3581,7 +3550,7 @@ wasm_loader_unload(WASMModule *module) /* just release the sub module list */ if (module->import_module_list) { WASMRegisteredModule *node = - bh_list_first_elem(module->import_module_list); + bh_list_first_elem(module->import_module_list); while (node) { WASMRegisteredModule *next = bh_list_elem_next(node); bh_list_remove(module->import_module_list, node); @@ -3592,7 +3561,6 @@ wasm_loader_unload(WASMModule *module) */ wasm_runtime_free(node); /* - * * the module file reading buffer will be released * in runtime_destroy() */ @@ -3600,16 +3568,22 @@ wasm_loader_unload(WASMModule *module) } } #endif - +#if WASM_ENABLE_DEBUG_INTERP != 0 + WASMFastOPCodeNode *fast_opcode = + bh_list_first_elem(&module->fast_opcode_list); + while (fast_opcode) { + WASMFastOPCodeNode *next = bh_list_elem_next(fast_opcode); + wasm_runtime_free(fast_opcode); + fast_opcode = next; + } +#endif wasm_runtime_free(module); } bool -wasm_loader_find_block_addr(BlockAddr *block_addr_cache, - const uint8 *start_addr, - const uint8 *code_end_addr, - uint8 label_type, - uint8 **p_else_addr, +wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, + const uint8 *start_addr, const uint8 *code_end_addr, + uint8 label_type, uint8 **p_else_addr, uint8 **p_end_addr) { const uint8 *p = start_addr, *p_end = code_end_addr; @@ -3618,7 +3592,7 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, uint32 block_nested_depth = 1, count, i, j, t; uint32 error_buf_size = sizeof(error_buf); uint8 opcode, u8; - BlockAddr block_stack[16] = {{0}}, *block; + BlockAddr block_stack[16] = { { 0 } }, *block; i = ((uintptr_t)start_addr) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1); block = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i; @@ -3637,7 +3611,9 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, while (p < code_end_addr) { opcode = *p++; - +#if WASM_ENABLE_DEBUG_INTERP != 0 + op_break_retry: +#endif switch (opcode) { case WASM_OP_UNREACHABLE: case WASM_OP_NOP: @@ -3648,7 +3624,8 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, case WASM_OP_IF: /* block result type: 0x40/0x7F/0x7E/0x7D/0x7C */ u8 = read_uint8(p); - if (block_nested_depth < sizeof(block_stack)/sizeof(BlockAddr)) { + 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; } @@ -3660,7 +3637,8 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, case EXT_OP_IF: /* block type */ skip_leb_uint32(p, p_end); - if (block_nested_depth < sizeof(block_stack)/sizeof(BlockAddr)) { + 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; } @@ -3669,33 +3647,37 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, case WASM_OP_ELSE: if (label_type == LABEL_TYPE_IF && block_nested_depth == 1) - else_addr = (uint8*)(p - 1); - if (block_nested_depth - 1 < sizeof(block_stack)/sizeof(BlockAddr)) - block_stack[block_nested_depth - 1].else_addr = (uint8*)(p - 1); + else_addr = (uint8 *)(p - 1); + if (block_nested_depth - 1 + < sizeof(block_stack) / sizeof(BlockAddr)) + block_stack[block_nested_depth - 1].else_addr = + (uint8 *)(p - 1); break; case WASM_OP_END: if (block_nested_depth == 1) { if (label_type == LABEL_TYPE_IF) *p_else_addr = else_addr; - *p_end_addr = (uint8*)(p - 1); + *p_end_addr = (uint8 *)(p - 1); - block_stack[0].end_addr = (uint8*)(p - 1); - for (t = 0; t < sizeof(block_stack)/sizeof(BlockAddr); t++) { + block_stack[0].end_addr = (uint8 *)(p - 1); + for (t = 0; t < sizeof(block_stack) / sizeof(BlockAddr); + t++) { start_addr = block_stack[t].start_addr; if (start_addr) { i = ((uintptr_t)start_addr) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1); - block = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i; + block = + block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i; for (j = 0; j < BLOCK_ADDR_CONFLICT_SIZE; j++) if (!block[j].start_addr) break; if (j == BLOCK_ADDR_CONFLICT_SIZE) { - memmove(block + 1, block, (BLOCK_ADDR_CONFLICT_SIZE - 1) * - sizeof(BlockAddr)); + memmove(block + 1, block, + (BLOCK_ADDR_CONFLICT_SIZE - 1) + * sizeof(BlockAddr)); j = 0; - } block[j].start_addr = block_stack[t].start_addr; block[j].else_addr = block_stack[t].else_addr; @@ -3708,8 +3690,10 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, } else { block_nested_depth--; - if (block_nested_depth < sizeof(block_stack)/sizeof(BlockAddr)) - block_stack[block_nested_depth].end_addr = (uint8*)(p - 1); + if (block_nested_depth + < sizeof(block_stack) / sizeof(BlockAddr)) + block_stack[block_nested_depth].end_addr = + (uint8 *)(p - 1); } break; @@ -3720,7 +3704,7 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, case WASM_OP_BR_TABLE: read_leb_uint32(p, p_end, count); /* lable num */ - for (i = 0; i <= count; i++) /* lableidxs */ + for (i = 0; i <= count; i++) /* lableidxs */ skip_leb_uint32(p, p_end); break; @@ -4052,44 +4036,37 @@ wasm_loader_find_block_addr(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); - if (SIMD_i8x16_eq <= opcode - && opcode <= SIMD_f32x4_convert_i32x4_u) { - break; - } - + /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h + */ switch (opcode) { case SIMD_v128_load: - case SIMD_i16x8_load8x8_s: - case SIMD_i16x8_load8x8_u: - case SIMD_i32x4_load16x4_s: - case SIMD_i32x4_load16x4_u: - case SIMD_i64x2_load32x2_s: - case SIMD_i64x2_load32x2_u: - case SIMD_v8x16_load_splat: - case SIMD_v16x8_load_splat: - case SIMD_v32x4_load_splat: - case SIMD_v64x2_load_splat: + case SIMD_v128_load8x8_s: + case SIMD_v128_load8x8_u: + case SIMD_v128_load16x4_s: + case SIMD_v128_load16x4_u: + case SIMD_v128_load32x2_s: + case SIMD_v128_load32x2_u: + case SIMD_v128_load8_splat: + case SIMD_v128_load16_splat: + case SIMD_v128_load32_splat: + case SIMD_v128_load64_splat: case SIMD_v128_store: - skip_leb_uint32(p, p_end); /* align */ - skip_leb_uint32(p, p_end); /* offset */ + /* memarg align */ + skip_leb_uint32(p, p_end); + /* memarg offset*/ + skip_leb_uint32(p, p_end); break; case SIMD_v128_const: case SIMD_v8x16_shuffle: + /* immByte[16] immLaneId[16] */ CHECK_BUF1(p, p_end, 16); p += 16; break; - case SIMD_v8x16_swizzle: - case SIMD_i8x16_splat: - case SIMD_i16x8_splat: - case SIMD_i32x4_splat: - case SIMD_i64x2_splat: - case SIMD_f32x4_splat: - case SIMD_f64x2_splat: - break; - case SIMD_i8x16_extract_lane_s: case SIMD_i8x16_extract_lane_u: case SIMD_i8x16_replace_lane: @@ -4104,14 +4081,44 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, case SIMD_f32x4_replace_lane: case SIMD_f64x2_extract_lane: case SIMD_f64x2_replace_lane: + /* ImmLaneId */ + CHECK_BUF(p, p_end, 1); + p++; + break; + + case SIMD_v128_load8_lane: + case SIMD_v128_load16_lane: + case SIMD_v128_load32_lane: + case SIMD_v128_load64_lane: + case SIMD_v128_store8_lane: + case SIMD_v128_store16_lane: + case SIMD_v128_store32_lane: + case SIMD_v128_store64_lane: + /* memarg align */ + skip_leb_uint32(p, p_end); + /* memarg offset*/ + skip_leb_uint32(p, p_end); + /* ImmLaneId */ CHECK_BUF(p, p_end, 1); p++; break; + case SIMD_v128_load32_zero: + case SIMD_v128_load64_zero: + /* memarg align */ + skip_leb_uint32(p, p_end); + /* memarg offset*/ + skip_leb_uint32(p, p_end); + break; + default: - LOG_WARNING("WASM loader find block addr failed: " - "invalid opcode fd 0x%02x.", opcode); - return false; + /* + * since latest SIMD specific used almost every value + * from 0x00 to 0xff, the default branch will present + * all opcodes without imm + * https://github.com/WebAssembly/simd/blob/main/proposals/simd/NewOpcodes.md + */ + break; } break; } @@ -4134,6 +4141,32 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, break; } #endif +#if WASM_ENABLE_DEBUG_INTERP != 0 + case DEBUG_OP_BREAK: + { + WASMDebugInstance *debug_instance = + wasm_exec_env_get_instance(exec_env); + char orignal_opcode[1]; + uint64 size = 1; + WASMModuleInstance *module_inst = + (WASMModuleInstance *)exec_env->module_inst; + uint64 offset = (p - 1) >= module_inst->module->load_addr + ? (p - 1) - module_inst->module->load_addr + : ~0; + if (debug_instance) { + if (wasm_debug_instance_get_obj_mem(debug_instance, offset, + orignal_opcode, &size) + && size == 1) { + LOG_VERBOSE("WASM loader find OP_BREAK , recover it " + "with %02x: ", + orignal_opcode[0]); + opcode = orignal_opcode[0]; + goto op_break_retry; + } + } + break; + } +#endif default: return false; @@ -4146,9 +4179,9 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, return false; } -#define REF_ANY VALUE_TYPE_ANY -#define REF_I32 VALUE_TYPE_I32 -#define REF_F32 VALUE_TYPE_F32 +#define REF_ANY VALUE_TYPE_ANY +#define REF_I32 VALUE_TYPE_I32 +#define REF_F32 VALUE_TYPE_F32 #define REF_I64_1 VALUE_TYPE_I64 #define REF_I64_2 VALUE_TYPE_I64 #define REF_F64_1 VALUE_TYPE_F64 @@ -4157,19 +4190,19 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, #define REF_V128_2 VALUE_TYPE_V128 #define REF_V128_3 VALUE_TYPE_V128 #define REF_V128_4 VALUE_TYPE_V128 -#define REF_FUNCREF VALUE_TYPE_FUNCREF +#define REF_FUNCREF VALUE_TYPE_FUNCREF #define REF_EXTERNREF VALUE_TYPE_EXTERNREF #if WASM_ENABLE_FAST_INTERP != 0 #if WASM_DEBUG_PREPROCESSOR != 0 -#define LOG_OP(...) os_printf(__VA_ARGS__) +#define LOG_OP(...) os_printf(__VA_ARGS__) #else -#define LOG_OP(...) (void)0 +#define LOG_OP(...) (void)0 #endif #define PATCH_ELSE 0 -#define PATCH_END 1 +#define PATCH_END 1 typedef struct BranchBlockPatch { struct BranchBlockPatch *next; uint8 patch_type; @@ -4250,14 +4283,13 @@ typedef struct Const { uint8 value_type; } Const; -static void* -memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, - char *error_buf, uint32 error_buf_size) +static void * +memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf, + uint32 error_buf_size) { uint8 *mem_new; bh_assert(size_new > size_old); - if ((mem_new = loader_malloc - (size_new, error_buf, error_buf_size))) { + if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) { bh_memcpy_s(mem_new, size_new, mem_old, size_old); memset(mem_new + size_old, 0, size_new - size_old); wasm_runtime_free(mem_old); @@ -4265,47 +4297,51 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, return mem_new; } -#define MEM_REALLOC(mem, size_old, size_new) do { \ - void *mem_new = memory_realloc(mem, size_old, size_new, \ - error_buf, error_buf_size); \ - if (!mem_new) \ - goto fail; \ - mem = mem_new; \ - } while (0) - -#define CHECK_CSP_PUSH() do { \ - if (ctx->frame_csp >= ctx->frame_csp_boundary) { \ - MEM_REALLOC(ctx->frame_csp_bottom, ctx->frame_csp_size, \ - (uint32)(ctx->frame_csp_size \ - + 8 * sizeof(BranchBlock))); \ - ctx->frame_csp_size += (uint32)(8 * sizeof(BranchBlock)); \ - ctx->frame_csp_boundary = ctx->frame_csp_bottom + \ - ctx->frame_csp_size / sizeof(BranchBlock); \ - ctx->frame_csp = ctx->frame_csp_bottom + ctx->csp_num; \ - } \ - } while (0) - -#define CHECK_CSP_POP() do { \ - if (ctx->csp_num < 1) { \ - set_error_buf(error_buf, error_buf_size, \ - "type mismatch: " \ - "expect data but block stack was empty"); \ - goto fail; \ - } \ - } while (0) +#define MEM_REALLOC(mem, size_old, size_new) \ + do { \ + void *mem_new = memory_realloc(mem, size_old, size_new, error_buf, \ + error_buf_size); \ + if (!mem_new) \ + goto fail; \ + mem = mem_new; \ + } while (0) + +#define CHECK_CSP_PUSH() \ + do { \ + if (ctx->frame_csp >= ctx->frame_csp_boundary) { \ + MEM_REALLOC( \ + ctx->frame_csp_bottom, ctx->frame_csp_size, \ + (uint32)(ctx->frame_csp_size + 8 * sizeof(BranchBlock))); \ + ctx->frame_csp_size += (uint32)(8 * sizeof(BranchBlock)); \ + ctx->frame_csp_boundary = \ + ctx->frame_csp_bottom \ + + ctx->frame_csp_size / sizeof(BranchBlock); \ + ctx->frame_csp = ctx->frame_csp_bottom + ctx->csp_num; \ + } \ + } while (0) + +#define CHECK_CSP_POP() \ + do { \ + if (ctx->csp_num < 1) { \ + set_error_buf(error_buf, error_buf_size, \ + "type mismatch: " \ + "expect data but block stack was empty"); \ + goto fail; \ + } \ + } while (0) #if WASM_ENABLE_FAST_INTERP != 0 static bool -check_offset_push(WASMLoaderContext *ctx, - char *error_buf, uint32 error_buf_size) +check_offset_push(WASMLoaderContext *ctx, char *error_buf, + uint32 error_buf_size) { uint32 cell_num = (uint32)(ctx->frame_offset - ctx->frame_offset_bottom); if (ctx->frame_offset >= ctx->frame_offset_boundary) { MEM_REALLOC(ctx->frame_offset_bottom, ctx->frame_offset_size, ctx->frame_offset_size + 16); ctx->frame_offset_size += 16; - ctx->frame_offset_boundary = ctx->frame_offset_bottom + - ctx->frame_offset_size / sizeof(int16); + ctx->frame_offset_boundary = + ctx->frame_offset_bottom + ctx->frame_offset_size / sizeof(int16); ctx->frame_offset = ctx->frame_offset_bottom + cell_num; } return true; @@ -4341,15 +4377,14 @@ free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num) for (uint32 i = 0; i < csp_num; i++) { free_label_patch_list(tmp_csp); - tmp_csp ++; + tmp_csp++; } } #endif /* end of WASM_ENABLE_FAST_INTERP */ static bool -check_stack_push(WASMLoaderContext *ctx, - char *error_buf, uint32 error_buf_size) +check_stack_push(WASMLoaderContext *ctx, char *error_buf, uint32 error_buf_size) { if (ctx->frame_ref >= ctx->frame_ref_boundary) { MEM_REALLOC(ctx->frame_ref_bottom, ctx->frame_ref_size, @@ -4363,7 +4398,6 @@ check_stack_push(WASMLoaderContext *ctx, return false; } - static bool check_stack_top_values(uint8 *frame_ref, int32 stack_cell_num, uint8 type, char *error_buf, uint32 error_buf_size) @@ -4375,7 +4409,7 @@ check_stack_top_values(uint8 *frame_ref, int32 stack_cell_num, uint8 type, || (type == VALUE_TYPE_V128 && stack_cell_num < 4) #endif #endif - ) { + ) { set_error_buf(error_buf, error_buf_size, "type mismatch: expect data but stack was empty"); return false; @@ -4387,16 +4421,14 @@ check_stack_top_values(uint8 *frame_ref, int32 stack_cell_num, uint8 type, #if WASM_ENABLE_SIMD != 0 #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) || (type == VALUE_TYPE_V128 - && (*(frame_ref - 4) != REF_V128_1 - || *(frame_ref - 3) != REF_V128_2 + && (*(frame_ref - 4) != REF_V128_1 || *(frame_ref - 3) != REF_V128_2 || *(frame_ref - 2) != REF_V128_3 || *(frame_ref - 1) != REF_V128_4)) #endif #endif - ) { + ) { set_error_buf_v(error_buf, error_buf_size, "%s%s%s", - "type mismatch: expect ", - type2str(type), + "type mismatch: expect ", type2str(type), " but got other"); return false; } @@ -4405,20 +4437,19 @@ check_stack_top_values(uint8 *frame_ref, int32 stack_cell_num, uint8 type, } static bool -check_stack_pop(WASMLoaderContext *ctx, uint8 type, - char *error_buf, uint32 error_buf_size) +check_stack_pop(WASMLoaderContext *ctx, uint8 type, char *error_buf, + uint32 error_buf_size) { - int32 block_stack_cell_num = (int32) - (ctx->stack_cell_num - (ctx->frame_csp - 1)->stack_cell_num); + int32 block_stack_cell_num = + (int32)(ctx->stack_cell_num - (ctx->frame_csp - 1)->stack_cell_num); - if (block_stack_cell_num > 0 - && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY) { + if (block_stack_cell_num > 0 && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY) { /* the stack top is a value of any type, return success */ return true; } - if (!check_stack_top_values(ctx->frame_ref, block_stack_cell_num, - type, error_buf, error_buf_size)) + if (!check_stack_top_values(ctx->frame_ref, block_stack_cell_num, type, + error_buf, error_buf_size)) return false; return true; @@ -4446,7 +4477,7 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx) } } -static WASMLoaderContext* +static WASMLoaderContext * wasm_loader_ctx_init(WASMFunction *func) { WASMLoaderContext *loader_ctx = @@ -4457,15 +4488,15 @@ wasm_loader_ctx_init(WASMFunction *func) loader_ctx->frame_ref_size = 32; if (!(loader_ctx->frame_ref_bottom = loader_ctx->frame_ref = - wasm_runtime_malloc(loader_ctx->frame_ref_size))) + wasm_runtime_malloc(loader_ctx->frame_ref_size))) goto fail; memset(loader_ctx->frame_ref_bottom, 0, loader_ctx->frame_ref_size); - loader_ctx->frame_ref_boundary = loader_ctx->frame_ref_bottom + - loader_ctx->frame_ref_size; + loader_ctx->frame_ref_boundary = + loader_ctx->frame_ref_bottom + loader_ctx->frame_ref_size; loader_ctx->frame_csp_size = sizeof(BranchBlock) * 8; if (!(loader_ctx->frame_csp_bottom = loader_ctx->frame_csp = - wasm_runtime_malloc(loader_ctx->frame_csp_size))) + wasm_runtime_malloc(loader_ctx->frame_csp_size))) goto fail; memset(loader_ctx->frame_csp_bottom, 0, loader_ctx->frame_csp_size); loader_ctx->frame_csp_boundary = loader_ctx->frame_csp_bottom + 8; @@ -4473,21 +4504,21 @@ wasm_loader_ctx_init(WASMFunction *func) #if WASM_ENABLE_FAST_INTERP != 0 loader_ctx->frame_offset_size = sizeof(int16) * 32; if (!(loader_ctx->frame_offset_bottom = loader_ctx->frame_offset = - wasm_runtime_malloc(loader_ctx->frame_offset_size))) + wasm_runtime_malloc(loader_ctx->frame_offset_size))) goto fail; - memset(loader_ctx->frame_offset_bottom, 0, - loader_ctx->frame_offset_size); + memset(loader_ctx->frame_offset_bottom, 0, loader_ctx->frame_offset_size); loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32; loader_ctx->num_const = 0; loader_ctx->const_buf_size = sizeof(Const) * 8; - if (!(loader_ctx->const_buf = wasm_runtime_malloc(loader_ctx->const_buf_size))) + if (!(loader_ctx->const_buf = + wasm_runtime_malloc(loader_ctx->const_buf_size))) goto fail; memset(loader_ctx->const_buf, 0, loader_ctx->const_buf_size); loader_ctx->start_dynamic_offset = loader_ctx->dynamic_offset = - loader_ctx->max_dynamic_offset = func->param_cell_num + - func->local_cell_num; + loader_ctx->max_dynamic_offset = + func->param_cell_num + func->local_cell_num; #endif return loader_ctx; @@ -4497,8 +4528,8 @@ wasm_loader_ctx_init(WASMFunction *func) } static bool -wasm_loader_push_frame_ref(WASMLoaderContext *ctx, uint8 type, - char *error_buf, uint32 error_buf_size) +wasm_loader_push_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf, + uint32 error_buf_size) { if (type == VALUE_TYPE_VOID) return true; @@ -4539,12 +4570,12 @@ wasm_loader_push_frame_ref(WASMLoaderContext *ctx, uint8 type, } static bool -wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, - char *error_buf, uint32 error_buf_size) +wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf, + uint32 error_buf_size) { BranchBlock *cur_block = ctx->frame_csp - 1; - int32 available_stack_cell = (int32) - (ctx->stack_cell_num - cur_block->stack_cell_num); + int32 available_stack_cell = + (int32)(ctx->stack_cell_num - cur_block->stack_cell_num); /* Directly return success if current block is in stack * polymorphic state while stack is empty. */ @@ -4579,11 +4610,12 @@ wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, static bool wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt, - uint8 type_push, uint8 type_pop, - char *error_buf, uint32 error_buf_size) + uint8 type_push, uint8 type_pop, char *error_buf, + uint32 error_buf_size) { for (int i = 0; i < pop_cnt; i++) { - if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf, error_buf_size)) + if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf, + error_buf_size)) return false; } if (!wasm_loader_push_frame_ref(ctx, type_push, error_buf, error_buf_size)) @@ -4593,7 +4625,7 @@ wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt, static bool wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 label_type, - BlockType block_type, uint8* start_addr, + BlockType block_type, uint8 *start_addr, char *error_buf, uint32 error_buf_size) { CHECK_CSP_PUSH(); @@ -4616,8 +4648,8 @@ wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 label_type, } static bool -wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, - char *error_buf, uint32 error_buf_size) +wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, char *error_buf, + uint32 error_buf_size) { CHECK_CSP_POP(); #if WASM_ENABLE_FAST_INTERP != 0 @@ -4636,124 +4668,132 @@ wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, #if WASM_ENABLE_LABELS_AS_VALUES != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 -#define emit_label(opcode) do { \ - wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \ - LOG_OP("\nemit_op [%02x]\t", opcode); \ - } while (0) -#define skip_label() do { \ - wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \ - LOG_OP("\ndelete last op\n"); \ - } while (0) +#define emit_label(opcode) \ + do { \ + wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) +#define skip_label() \ + do { \ + wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \ + LOG_OP("\ndelete last op\n"); \ + } while (0) #else /* else of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ -#define emit_label(opcode) do { \ - int32 offset = (int32)((uint8*)handle_table[opcode] \ - - (uint8*)handle_table[0]); \ - if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \ - set_error_buf(error_buf, error_buf_size, \ - "pre-compiled label offset out of range"); \ - goto fail; \ - } \ - wasm_loader_emit_int16(loader_ctx, offset); \ - LOG_OP("\nemit_op [%02x]\t", opcode); \ - } while (0) -#define skip_label() do { \ - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \ - LOG_OP("\ndelete last op\n"); \ - } while (0) +#define emit_label(opcode) \ + do { \ + int32 offset = \ + (int32)((uint8 *)handle_table[opcode] - (uint8 *)handle_table[0]); \ + if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \ + set_error_buf(error_buf, error_buf_size, \ + "pre-compiled label offset out of range"); \ + goto fail; \ + } \ + wasm_loader_emit_int16(loader_ctx, offset); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) +#define skip_label() \ + do { \ + wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \ + LOG_OP("\ndelete last op\n"); \ + } while (0) #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ -#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ -#define emit_label(opcode) do { \ - wasm_loader_emit_uint8(loader_ctx, opcode); \ - LOG_OP("\nemit_op [%02x]\t", opcode); \ - } while (0) -#define skip_label() do { \ - wasm_loader_emit_backspace(loader_ctx, sizeof(uint8)); \ - LOG_OP("\ndelete last op\n"); \ - } while (0) +#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ +#define emit_label(opcode) \ + do { \ + wasm_loader_emit_uint8(loader_ctx, opcode); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) +#define skip_label() \ + do { \ + wasm_loader_emit_backspace(loader_ctx, sizeof(uint8)); \ + LOG_OP("\ndelete last op\n"); \ + } while (0) #endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ -#define emit_empty_label_addr_and_frame_ip(type) do { \ - if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \ - loader_ctx->p_code_compiled, \ - error_buf, error_buf_size)) \ - goto fail; \ - /* label address, to be patched */ \ - wasm_loader_emit_ptr(loader_ctx, NULL); \ - } while (0) - -#define emit_br_info(frame_csp) do { \ - if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define LAST_OP_OUTPUT_I32() (last_op >= WASM_OP_I32_EQZ \ - && last_op <= WASM_OP_I32_ROTR) \ - || (last_op == WASM_OP_I32_LOAD \ - || last_op == WASM_OP_F32_LOAD) \ - || (last_op >= WASM_OP_I32_LOAD8_S \ - && last_op <= WASM_OP_I32_LOAD16_U) \ - || (last_op >= WASM_OP_F32_ABS \ - && last_op <= WASM_OP_F32_COPYSIGN) \ - || (last_op >= WASM_OP_I32_WRAP_I64 \ - && last_op <= WASM_OP_I32_TRUNC_U_F64) \ - || (last_op >= WASM_OP_F32_CONVERT_S_I32 \ - && last_op <= WASM_OP_F32_DEMOTE_F64) \ - || (last_op == WASM_OP_I32_REINTERPRET_F32) \ - || (last_op == WASM_OP_F32_REINTERPRET_I32) \ - || (last_op == EXT_OP_COPY_STACK_TOP) - -#define LAST_OP_OUTPUT_I64() (last_op >= WASM_OP_I64_CLZ \ - && last_op <= WASM_OP_I64_ROTR) \ - || (last_op >= WASM_OP_F64_ABS \ - && last_op <= WASM_OP_F64_COPYSIGN) \ - || (last_op == WASM_OP_I64_LOAD \ - || last_op == WASM_OP_F64_LOAD) \ - || (last_op >= WASM_OP_I64_LOAD8_S \ - && last_op <= WASM_OP_I64_LOAD32_U) \ - || (last_op >= WASM_OP_I64_EXTEND_S_I32 \ - && last_op <= WASM_OP_I64_TRUNC_U_F64) \ - || (last_op >= WASM_OP_F64_CONVERT_S_I32 \ - && last_op <= WASM_OP_F64_PROMOTE_F32) \ - || (last_op == WASM_OP_I64_REINTERPRET_F64) \ - || (last_op == WASM_OP_F64_REINTERPRET_I64) \ - || (last_op == EXT_OP_COPY_STACK_TOP_I64) - -#define GET_CONST_OFFSET(type, val) do { \ - if (!(wasm_loader_get_const_offset(loader_ctx, type, \ - &val, &operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define GET_CONST_F32_OFFSET(type, fval) do { \ - if (!(wasm_loader_get_const_offset(loader_ctx, type, \ - &fval, &operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define GET_CONST_F64_OFFSET(type, fval) do { \ - if (!(wasm_loader_get_const_offset(loader_ctx, type, \ - &fval, &operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define emit_operand(ctx, offset) do { \ - wasm_loader_emit_int16(ctx, offset); \ - LOG_OP("%d\t", offset); \ - } while (0) - -#define emit_byte(ctx, byte) do { \ - wasm_loader_emit_uint8(ctx, byte); \ - LOG_OP("%d\t", byte); \ - } while (0) - -#define emit_uint32(ctx, value) do { \ - wasm_loader_emit_uint32(ctx, value); \ - LOG_OP("%d\t", value); \ - } while (0) +#define emit_empty_label_addr_and_frame_ip(type) \ + do { \ + if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \ + loader_ctx->p_code_compiled, error_buf, \ + error_buf_size)) \ + goto fail; \ + /* label address, to be patched */ \ + wasm_loader_emit_ptr(loader_ctx, NULL); \ + } while (0) + +#define emit_br_info(frame_csp) \ + do { \ + if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, error_buf, \ + error_buf_size)) \ + goto fail; \ + } while (0) + +#define LAST_OP_OUTPUT_I32() \ + (last_op >= WASM_OP_I32_EQZ && last_op <= WASM_OP_I32_ROTR) \ + || (last_op == WASM_OP_I32_LOAD || last_op == WASM_OP_F32_LOAD) \ + || (last_op >= WASM_OP_I32_LOAD8_S && last_op <= WASM_OP_I32_LOAD16_U) \ + || (last_op >= WASM_OP_F32_ABS && last_op <= WASM_OP_F32_COPYSIGN) \ + || (last_op >= WASM_OP_I32_WRAP_I64 \ + && last_op <= WASM_OP_I32_TRUNC_U_F64) \ + || (last_op >= WASM_OP_F32_CONVERT_S_I32 \ + && last_op <= WASM_OP_F32_DEMOTE_F64) \ + || (last_op == WASM_OP_I32_REINTERPRET_F32) \ + || (last_op == WASM_OP_F32_REINTERPRET_I32) \ + || (last_op == EXT_OP_COPY_STACK_TOP) + +#define LAST_OP_OUTPUT_I64() \ + (last_op >= WASM_OP_I64_CLZ && last_op <= WASM_OP_I64_ROTR) \ + || (last_op >= WASM_OP_F64_ABS && last_op <= WASM_OP_F64_COPYSIGN) \ + || (last_op == WASM_OP_I64_LOAD || last_op == WASM_OP_F64_LOAD) \ + || (last_op >= WASM_OP_I64_LOAD8_S && last_op <= WASM_OP_I64_LOAD32_U) \ + || (last_op >= WASM_OP_I64_EXTEND_S_I32 \ + && last_op <= WASM_OP_I64_TRUNC_U_F64) \ + || (last_op >= WASM_OP_F64_CONVERT_S_I32 \ + && last_op <= WASM_OP_F64_PROMOTE_F32) \ + || (last_op == WASM_OP_I64_REINTERPRET_F64) \ + || (last_op == WASM_OP_F64_REINTERPRET_I64) \ + || (last_op == EXT_OP_COPY_STACK_TOP_I64) + +#define GET_CONST_OFFSET(type, val) \ + do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, &val, \ + &operand_offset, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define GET_CONST_F32_OFFSET(type, fval) \ + do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, &fval, \ + &operand_offset, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define GET_CONST_F64_OFFSET(type, fval) \ + do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, &fval, \ + &operand_offset, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define emit_operand(ctx, offset) \ + do { \ + wasm_loader_emit_int16(ctx, offset); \ + LOG_OP("%d\t", offset); \ + } while (0) + +#define emit_byte(ctx, byte) \ + do { \ + wasm_loader_emit_uint8(ctx, byte); \ + LOG_OP("%d\t", byte); \ + } while (0) + +#define emit_uint32(ctx, value) \ + do { \ + wasm_loader_emit_uint32(ctx, value); \ + LOG_OP("%d\t", value); \ + } while (0) static bool wasm_loader_ctx_reinit(WASMLoaderContext *ctx) @@ -4761,8 +4801,7 @@ wasm_loader_ctx_reinit(WASMLoaderContext *ctx) if (!(ctx->p_code_compiled = wasm_runtime_malloc(ctx->code_compiled_size))) return false; memset(ctx->p_code_compiled, 0, ctx->code_compiled_size); - ctx->p_code_compiled_end = ctx->p_code_compiled + - ctx->code_compiled_size; + ctx->p_code_compiled_end = ctx->p_code_compiled + ctx->code_compiled_size; /* clean up frame ref */ memset(ctx->frame_ref_bottom, 0, ctx->frame_ref_size); @@ -4886,8 +4925,9 @@ wasm_loader_emit_backspace(WASMLoaderContext *ctx, uint32 size) static bool preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode, - uint32 local_index, uint32 local_type, bool *preserved, - char *error_buf, uint32 error_buf_size) + uint32 local_index, uint32 local_type, + bool *preserved, char *error_buf, + uint32 error_buf_size) { uint32 i = 0; int16 preserved_offset = (int16)local_index; @@ -4896,7 +4936,8 @@ preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode, while (i < loader_ctx->stack_cell_num) { uint8 cur_type = loader_ctx->frame_ref_bottom[i]; - /* move previous local into dynamic space before a set/tee_local opcode */ + /* move previous local into dynamic space before a set/tee_local opcode + */ if (loader_ctx->frame_offset_bottom[i] == (int16)local_index) { if (!(*preserved)) { *preserved = true; @@ -4971,12 +5012,12 @@ preserve_local_for_block(WASMLoaderContext *loader_ctx, uint8 opcode, } static bool -add_label_patch_to_list(BranchBlock *frame_csp, - uint8 patch_type, uint8 *p_code_compiled, - char *error_buf, uint32 error_buf_size) +add_label_patch_to_list(BranchBlock *frame_csp, uint8 patch_type, + uint8 *p_code_compiled, char *error_buf, + uint32 error_buf_size) { - BranchBlockPatch *patch = loader_malloc - (sizeof(BranchBlockPatch), error_buf, error_buf_size); + BranchBlockPatch *patch = + loader_malloc(sizeof(BranchBlockPatch), error_buf, error_buf_size); if (!patch) { return false; } @@ -4994,8 +5035,7 @@ add_label_patch_to_list(BranchBlock *frame_csp, } static void -apply_label_patch(WASMLoaderContext *ctx, uint8 depth, - uint8 patch_type) +apply_label_patch(WASMLoaderContext *ctx, uint8 depth, uint8 patch_type) { BranchBlock *frame_csp = ctx->frame_csp - depth; BranchBlockPatch *node = frame_csp->patch_list; @@ -5068,11 +5108,11 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, for (i = (int32)arity - 1; i >= 0; i--) { cell = (uint8)wasm_value_type_cell_num(types[i]); frame_offset -= cell; - emit_operand(ctx, *(int16*)(frame_offset)); + emit_operand(ctx, *(int16 *)(frame_offset)); } /* Part e */ - dynamic_offset = frame_csp->dynamic_offset - + wasm_get_cell_num(types, arity); + dynamic_offset = + frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); for (i = (int32)arity - 1; i >= 0; i--) { cell = (uint8)wasm_value_type_cell_num(types[i]); dynamic_offset -= cell; @@ -5085,8 +5125,7 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, wasm_loader_emit_ptr(ctx, frame_csp->code_compiled); } else { - if (!add_label_patch_to_list(frame_csp, PATCH_END, - ctx->p_code_compiled, + if (!add_label_patch_to_list(frame_csp, PATCH_END, ctx->p_code_compiled, error_buf, error_buf_size)) return false; /* label address, to be patched */ @@ -5148,8 +5187,8 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type, then current block is the function block */ uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0; BranchBlock *cur_block = ctx->frame_csp - depth; - int32 available_stack_cell = (int32) - (ctx->stack_cell_num - cur_block->stack_cell_num); + int32 available_stack_cell = + (int32)(ctx->stack_cell_num - cur_block->stack_cell_num); /* Directly return success if current block is in stack * polymorphic state while stack is empty. */ @@ -5194,12 +5233,13 @@ wasm_loader_push_pop_frame_offset(WASMLoaderContext *ctx, uint8 pop_cnt, uint8 i; for (i = 0; i < pop_cnt; i++) { - if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf, error_buf_size)) + if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf, + error_buf_size)) return false; } - if (!wasm_loader_push_frame_offset(ctx, type_push, - disable_emit, operand_offset, - error_buf, error_buf_size)) + if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit, + operand_offset, error_buf, + error_buf_size)) return false; return true; @@ -5250,26 +5290,29 @@ wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt, } static bool -wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, - void *value, int16 *offset, - char *error_buf, uint32 error_buf_size) +wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value, + int16 *offset, char *error_buf, + uint32 error_buf_size) { int16 operand_offset = 0; Const *c; for (c = (Const *)ctx->const_buf; - (uint8*)c < ctx->const_buf + ctx->num_const * sizeof(Const); c ++) { + (uint8 *)c < ctx->const_buf + ctx->num_const * sizeof(Const); c++) { /* TODO: handle v128 type? */ if ((type == c->value_type) - && ((type == VALUE_TYPE_I64 && *(int64*)value == c->value.i64) - || (type == VALUE_TYPE_I32 && *(int32*)value == c->value.i32) + && ((type == VALUE_TYPE_I64 && *(int64 *)value == c->value.i64) + || (type == VALUE_TYPE_I32 && *(int32 *)value == c->value.i32) #if WASM_ENABLE_REF_TYPES != 0 - || (type == VALUE_TYPE_FUNCREF && *(int32*)value == c->value.i32) - || (type == VALUE_TYPE_EXTERNREF && *(int32*)value == c->value.i32) + || (type == VALUE_TYPE_FUNCREF + && *(int32 *)value == c->value.i32) + || (type == VALUE_TYPE_EXTERNREF + && *(int32 *)value == c->value.i32) #endif || (type == VALUE_TYPE_F64 && (0 == memcmp(value, &(c->value.f64), sizeof(float64)))) || (type == VALUE_TYPE_F32 - && (0 == memcmp(value, &(c->value.f32), sizeof(float32)))))) { + && (0 + == memcmp(value, &(c->value.f32), sizeof(float32)))))) { operand_offset = c->slot_index; break; } @@ -5280,48 +5323,49 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, } if ((uint8 *)c == ctx->const_buf + ctx->num_const * sizeof(Const)) { if ((uint8 *)c == ctx->const_buf + ctx->const_buf_size) { - MEM_REALLOC(ctx->const_buf, - ctx->const_buf_size, + MEM_REALLOC(ctx->const_buf, ctx->const_buf_size, ctx->const_buf_size + 4 * sizeof(Const)); ctx->const_buf_size += 4 * sizeof(Const); c = (Const *)(ctx->const_buf + ctx->num_const * sizeof(Const)); } c->value_type = type; switch (type) { - case VALUE_TYPE_F64: - bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value, sizeof(float64)); - ctx->const_cell_num += 2; - /* The const buf will be reversed, we use the second cell */ - /* of the i64/f64 const so the finnal offset is corrent */ - operand_offset ++; - break; - case VALUE_TYPE_I64: - c->value.i64 = *(int64*)value; - ctx->const_cell_num += 2; - operand_offset ++; - break; - case VALUE_TYPE_F32: - bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value, sizeof(float32)); - ctx->const_cell_num ++; - break; - case VALUE_TYPE_I32: - c->value.i32 = *(int32*)value; - ctx->const_cell_num ++; - break; + case VALUE_TYPE_F64: + bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value, + sizeof(float64)); + ctx->const_cell_num += 2; + /* The const buf will be reversed, we use the second cell */ + /* of the i64/f64 const so the finnal offset is corrent */ + operand_offset++; + break; + case VALUE_TYPE_I64: + c->value.i64 = *(int64 *)value; + ctx->const_cell_num += 2; + operand_offset++; + break; + case VALUE_TYPE_F32: + bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value, + sizeof(float32)); + ctx->const_cell_num++; + break; + case VALUE_TYPE_I32: + c->value.i32 = *(int32 *)value; + ctx->const_cell_num++; + break; #if WASM_ENABLE_REF_TYPES != 0 - case VALUE_TYPE_EXTERNREF: - case VALUE_TYPE_FUNCREF: - c->value.i32 = *(int32*)value; - ctx->const_cell_num ++; - break; + case VALUE_TYPE_EXTERNREF: + case VALUE_TYPE_FUNCREF: + c->value.i32 = *(int32 *)value; + ctx->const_cell_num++; + break; #endif - default: - break; + default: + break; } c->slot_index = operand_offset; - ctx->num_const ++; - LOG_OP("#### new const [%d]: %ld\n", - ctx->num_const, (int64)c->value.i64); + ctx->num_const++; + LOG_OP("#### new const [%d]: %ld\n", ctx->num_const, + (int64)c->value.i64); } /* use negetive index for const */ operand_offset = -(operand_offset + 1); @@ -5348,77 +5392,85 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, only push the frame_offset stack, no emit */ -#define TEMPLATE_PUSH(Type) do { \ - if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_##Type,\ - disable_emit, operand_offset,\ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define TEMPLATE_POP(Type) do { \ - if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_##Type,\ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define PUSH_OFFSET_TYPE(type) do { \ - if (!(wasm_loader_push_frame_offset(loader_ctx, type, \ - disable_emit, operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_OFFSET_TYPE(type) do { \ - if (!(wasm_loader_pop_frame_offset(loader_ctx, type, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_AND_PUSH(type_pop, type_push) do { \ - if (!(wasm_loader_push_pop_frame_ref_offset(loader_ctx, 1, \ - type_push, type_pop, \ - disable_emit, operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) +#define TEMPLATE_PUSH(Type) \ + do { \ + if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_##Type, \ + disable_emit, operand_offset, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define TEMPLATE_POP(Type) \ + do { \ + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_##Type, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_OFFSET_TYPE(type) \ + do { \ + if (!(wasm_loader_push_frame_offset(loader_ctx, type, disable_emit, \ + operand_offset, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_OFFSET_TYPE(type) \ + do { \ + if (!(wasm_loader_pop_frame_offset(loader_ctx, type, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_AND_PUSH(type_pop, type_push) \ + do { \ + if (!(wasm_loader_push_pop_frame_ref_offset( \ + loader_ctx, 1, type_push, type_pop, disable_emit, \ + operand_offset, error_buf, error_buf_size))) \ + goto fail; \ + } while (0) /* type of POPs should be the same */ -#define POP2_AND_PUSH(type_pop, type_push) do { \ - if (!(wasm_loader_push_pop_frame_ref_offset(loader_ctx, 2, \ - type_push, type_pop, \ - disable_emit, operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) +#define POP2_AND_PUSH(type_pop, type_push) \ + do { \ + if (!(wasm_loader_push_pop_frame_ref_offset( \ + loader_ctx, 2, type_push, type_pop, disable_emit, \ + operand_offset, error_buf, error_buf_size))) \ + goto fail; \ + } while (0) #else /* WASM_ENABLE_FAST_INTERP */ -#define TEMPLATE_PUSH(Type) do { \ - if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_##Type, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define TEMPLATE_POP(Type) do { \ - if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_##Type, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_AND_PUSH(type_pop, type_push) do { \ - if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1, \ - type_push, type_pop, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) +#define TEMPLATE_PUSH(Type) \ + do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_##Type, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define TEMPLATE_POP(Type) \ + do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_##Type, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_AND_PUSH(type_pop, type_push) \ + do { \ + if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1, type_push, \ + type_pop, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) /* type of POPs should be the same */ -#define POP2_AND_PUSH(type_pop, type_push) do { \ - if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 2, \ - type_push, type_pop, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) +#define POP2_AND_PUSH(type_pop, type_push) \ + do { \ + if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 2, type_push, \ + type_pop, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) #endif /* WASM_ENABLE_FAST_INTERP */ #define PUSH_I32() TEMPLATE_PUSH(I32) @@ -5440,19 +5492,18 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, #if WASM_ENABLE_FAST_INTERP != 0 static bool -reserve_block_ret(WASMLoaderContext *loader_ctx, - uint8 opcode, bool disable_emit, - char *error_buf, uint32 error_buf_size) +reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 opcode, + bool disable_emit, char *error_buf, uint32 error_buf_size) { int16 operand_offset = 0; - BranchBlock *block = (opcode == WASM_OP_ELSE) ? - loader_ctx->frame_csp - 1 : loader_ctx->frame_csp; + BranchBlock *block = (opcode == WASM_OP_ELSE) ? loader_ctx->frame_csp - 1 + : loader_ctx->frame_csp; BlockType *block_type = &block->block_type; uint8 *return_types = NULL; uint32 return_count = 0, value_count = 0, total_cel_num = 0; int32 i = 0; - int16 dynamic_offset, dynamic_offset_org, - *frame_offset = NULL, *frame_offset_org = NULL; + int16 dynamic_offset, dynamic_offset_org, *frame_offset = NULL, + *frame_offset_org = NULL; return_count = block_type_get_result_types(block_type, &return_types); @@ -5464,7 +5515,8 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, /* insert op_copy before else opcode */ if (opcode == WASM_OP_ELSE) skip_label(); - emit_label(cell == 1 ? EXT_OP_COPY_STACK_TOP : EXT_OP_COPY_STACK_TOP_I64); + emit_label(cell == 1 ? EXT_OP_COPY_STACK_TOP + : EXT_OP_COPY_STACK_TOP_I64); emit_operand(loader_ctx, *(loader_ctx->frame_offset - cell)); emit_operand(loader_ctx, block->dynamic_offset); @@ -5493,8 +5545,7 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, */ frame_offset = frame_offset_org = loader_ctx->frame_offset; dynamic_offset = dynamic_offset_org = - block->dynamic_offset - + wasm_get_cell_num(return_types, return_count); + block->dynamic_offset + wasm_get_cell_num(return_types, return_count); /* First traversal to get the count of values needed to be copied. */ for (i = (int32)return_count - 1; i >= 0; i--) { @@ -5513,9 +5564,9 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 *emit_data = NULL, *cells = NULL; int16 *src_offsets = NULL; uint16 *dst_offsets = NULL; - uint64 size = (uint64)value_count * (sizeof(*cells) - + sizeof(*src_offsets) - + sizeof(*dst_offsets)); + uint64 size = + (uint64)value_count + * (sizeof(*cells) + sizeof(*src_offsets) + sizeof(*dst_offsets)); /* Allocate memory for the emit data */ if (!(emit_data = loader_malloc(size, error_buf, error_buf_size))) @@ -5534,7 +5585,8 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, /* Part b) */ emit_uint32(loader_ctx, total_cel_num); - /* Second traversal to get each value's cell num, src offset and dst offset. */ + /* Second traversal to get each value's cell num, src offset and dst + * offset. */ frame_offset = frame_offset_org; dynamic_offset = dynamic_offset_org; for (i = (int32)return_count - 1, j = 0; i >= 0; i--) { @@ -5586,83 +5638,86 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, } #endif /* WASM_ENABLE_FAST_INTERP */ -#define RESERVE_BLOCK_RET() do { \ - if (!reserve_block_ret(loader_ctx, opcode, disable_emit, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define PUSH_TYPE(type) do { \ - if (!(wasm_loader_push_frame_ref(loader_ctx, type, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_TYPE(type) do { \ - if (!(wasm_loader_pop_frame_ref(loader_ctx, type, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define PUSH_CSP(label_type, block_type, _start_addr) do { \ - if (!wasm_loader_push_frame_csp(loader_ctx, label_type, block_type, \ - _start_addr, error_buf, \ - error_buf_size)) \ - goto fail; \ - } while (0) - -#define POP_CSP() do { \ - if (!wasm_loader_pop_frame_csp(loader_ctx, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() do { \ - read_leb_uint32(p, p_end, local_idx); \ - if (local_idx >= param_count + local_count) { \ - set_error_buf(error_buf, error_buf_size, \ - "unknown local"); \ - goto fail; \ - } \ - local_type = local_idx < param_count \ - ? param_types[local_idx] \ - : local_types[local_idx - param_count]; \ - local_offset = local_offsets[local_idx]; \ - } while (0) - -#define CHECK_BR(depth) do { \ - if (!wasm_loader_check_br(loader_ctx, depth, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) +#define RESERVE_BLOCK_RET() \ + do { \ + if (!reserve_block_ret(loader_ctx, opcode, disable_emit, error_buf, \ + error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_TYPE(type) \ + do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, type, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_TYPE(type) \ + do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, type, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_CSP(label_type, block_type, _start_addr) \ + do { \ + if (!wasm_loader_push_frame_csp(loader_ctx, label_type, block_type, \ + _start_addr, error_buf, \ + error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_CSP() \ + do { \ + if (!wasm_loader_pop_frame_csp(loader_ctx, error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() \ + do { \ + read_leb_uint32(p, p_end, local_idx); \ + if (local_idx >= param_count + local_count) { \ + set_error_buf(error_buf, error_buf_size, "unknown local"); \ + goto fail; \ + } \ + local_type = local_idx < param_count \ + ? param_types[local_idx] \ + : local_types[local_idx - param_count]; \ + local_offset = local_offsets[local_idx]; \ + } while (0) + +#define CHECK_BR(depth) \ + do { \ + if (!wasm_loader_check_br(loader_ctx, depth, error_buf, \ + error_buf_size)) \ + goto fail; \ + } while (0) static bool -check_memory(WASMModule *module, - char *error_buf, uint32 error_buf_size) +check_memory(WASMModule *module, char *error_buf, uint32 error_buf_size) { - if (module->memory_count == 0 - && module->import_memory_count == 0) { + if (module->memory_count == 0 && module->import_memory_count == 0) { set_error_buf(error_buf, error_buf_size, "unknown memory"); return false; } return true; } -#define CHECK_MEMORY() do { \ - if (!check_memory(module, error_buf, error_buf_size)) \ - goto fail; \ - } while (0) +#define CHECK_MEMORY() \ + do { \ + if (!check_memory(module, error_buf, error_buf_size)) \ + goto fail; \ + } while (0) static bool -check_memory_access_align(uint8 opcode, uint32 align, - char *error_buf, uint32 error_buf_size) +check_memory_access_align(uint8 opcode, uint32 align, char *error_buf, + uint32 error_buf_size) { uint8 mem_access_aligns[] = { 2, 3, 2, 3, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, /* loads */ 2, 3, 2, 3, 0, 1, 0, 1, 2 /* stores */ }; - bh_assert(opcode >= WASM_OP_I32_LOAD - && opcode <= WASM_OP_I64_STORE32); + bh_assert(opcode >= WASM_OP_I32_LOAD && opcode <= WASM_OP_I64_STORE32); if (align > mem_access_aligns[opcode - WASM_OP_I32_LOAD]) { set_error_buf(error_buf, error_buf_size, "alignment must not be larger than natural"); @@ -5674,19 +5729,35 @@ check_memory_access_align(uint8 opcode, uint32 align, #if WASM_ENABLE_SIMD != 0 #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) static bool -check_simd_memory_access_align(uint8 opcode, uint32 align, - char *error_buf, uint32 error_buf_size) +check_simd_memory_access_align(uint8 opcode, uint32 align, char *error_buf, + uint32 error_buf_size) { uint8 mem_access_aligns[] = { - 4, /* load */ - 3, 3, 3, 3, 3, 3, /* load and extend */ - 0, 1, 2, 3, /* load and splat */ - 4, /* store */ + 4, /* load */ + 3, 3, 3, 3, 3, 3, /* load and extend */ + 0, 1, 2, 3, /* load and splat */ + 4, /* store */ + }; + + uint8 mem_access_aligns_load_lane[] = { + 0, 1, 2, 3, /* load lane */ + 0, 1, 2, 3, /* store lane */ + 2, 3 /* store zero */ }; - bh_assert(opcode <= SIMD_v128_store); + if (!((opcode <= SIMD_v128_store) + || (SIMD_v128_load8_lane <= opcode + && opcode <= SIMD_v128_load64_zero))) { + set_error_buf(error_buf, error_buf_size, + "the opcode doesn't include memarg"); + return false; + } - if (align > mem_access_aligns[opcode - SIMD_v128_load]) { + if ((opcode <= SIMD_v128_store + && align > mem_access_aligns[opcode - SIMD_v128_load]) + || (SIMD_v128_load8_lane <= opcode && opcode <= SIMD_v128_load64_zero + && align > mem_access_aligns_load_lane[opcode + - SIMD_v128_load8_lane])) { set_error_buf(error_buf, error_buf_size, "alignment must not be larger than natural"); return false; @@ -5696,8 +5767,8 @@ check_simd_memory_access_align(uint8 opcode, uint32 align, } static bool -check_simd_access_lane(uint8 opcode, uint8 lane, - char *error_buf, uint32 error_buf_size) +check_simd_access_lane(uint8 opcode, uint8 lane, char *error_buf, + uint32 error_buf_size) { switch (opcode) { case SIMD_i8x16_extract_lane_s: @@ -5730,6 +5801,24 @@ check_simd_access_lane(uint8 opcode, uint8 lane, goto fail; } break; + + case SIMD_v128_load8_lane: + case SIMD_v128_load16_lane: + case SIMD_v128_load32_lane: + case SIMD_v128_load64_lane: + case SIMD_v128_store8_lane: + case SIMD_v128_store16_lane: + case SIMD_v128_store32_lane: + case SIMD_v128_store64_lane: + case SIMD_v128_load32_zero: + case SIMD_v128_load64_zero: + { + uint8 max_lanes[] = { 16, 8, 4, 2, 16, 8, 4, 2, 4, 2 }; + if (lane >= max_lanes[opcode - SIMD_v128_load8_lane]) { + goto fail; + } + break; + } default: goto fail; } @@ -5741,9 +5830,7 @@ check_simd_access_lane(uint8 opcode, uint8 lane, } static bool -check_simd_shuffle_mask(V128 mask, - char *error_buf, - uint32 error_buf_size) +check_simd_shuffle_mask(V128 mask, char *error_buf, uint32 error_buf_size) { uint8 i; for (i = 0; i != 16; ++i) { @@ -5759,10 +5846,10 @@ check_simd_shuffle_mask(V128 mask, #if WASM_ENABLE_SHARED_MEMORY != 0 static bool -check_memory_align_equal(uint8 opcode, uint32 align, - char *error_buf, uint32 error_buf_size) +check_memory_align_equal(uint8 opcode, uint32 align, char *error_buf, + uint32 error_buf_size) { - uint8 wait_notify_aligns[] = {2, 2, 3}; + uint8 wait_notify_aligns[] = { 2, 2, 3 }; uint8 mem_access_aligns[] = { 2, 3, 0, 1, 0, 1, 2, }; @@ -5799,10 +5886,10 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, uint16 cell_num; if (loader_ctx->csp_num < depth + 1) { - set_error_buf(error_buf, error_buf_size, - "unknown label, " - "unexpected end of section or function"); - return false; + set_error_buf(error_buf, error_buf_size, + "unknown label, " + "unexpected end of section or function"); + return false; } cur_block = loader_ctx->frame_csp - 1; @@ -5822,7 +5909,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, * and then re-push the values to make the stack top values * match block type. */ if (cur_block->is_stack_polymorphic) { - for (i = (int32)arity -1; i >= 0; i--) { + for (i = (int32)arity - 1; i >= 0; i--) { #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(types[i]); #endif @@ -5839,13 +5926,12 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, return true; } - available_stack_cell = (int32) - (loader_ctx->stack_cell_num - cur_block->stack_cell_num); + available_stack_cell = + (int32)(loader_ctx->stack_cell_num - cur_block->stack_cell_num); /* Check stack top values match target block type */ - for (i = (int32)arity -1; i >= 0; i--) { - if (!check_stack_top_values(frame_ref, available_stack_cell, - types[i], + for (i = (int32)arity - 1; i >= 0; i--) { + if (!check_stack_top_values(frame_ref, available_stack_cell, types[i], error_buf, error_buf_size)) return false; cell_num = wasm_value_type_cell_num(types[i]); @@ -5860,8 +5946,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, } static BranchBlock * -check_branch_block(WASMLoaderContext *loader_ctx, - uint8 **p_buf, uint8 *buf_end, +check_branch_block(WASMLoaderContext *loader_ctx, uint8 **p_buf, uint8 *buf_end, char *error_buf, uint32 error_buf_size) { uint8 *p = *p_buf, *p_end = buf_end; @@ -5891,19 +5976,18 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, int32 available_stack_cell, return_cell_num, i; uint8 *frame_ref = NULL; - available_stack_cell = (int32) - (loader_ctx->stack_cell_num - - block->stack_cell_num); + available_stack_cell = + (int32)(loader_ctx->stack_cell_num - block->stack_cell_num); return_count = block_type_get_result_types(block_type, &return_types); - return_cell_num = return_count > 0 ? - wasm_get_cell_num(return_types, return_count) : 0; + return_cell_num = + return_count > 0 ? wasm_get_cell_num(return_types, return_count) : 0; /* If the stack is in polymorphic state, just clear the stack * and then re-push the values to make the stack top values * match block type. */ if (block->is_stack_polymorphic) { - for (i = (int32)return_count -1; i >= 0; i--) { + for (i = (int32)return_count - 1; i >= 0; i--) { #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(return_types[i]); #endif @@ -5912,8 +5996,9 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, /* Check stack is empty */ if (loader_ctx->stack_cell_num != block->stack_cell_num) { - set_error_buf(error_buf, error_buf_size, - "type mismatch: stack size does not match block type"); + set_error_buf( + error_buf, error_buf_size, + "type mismatch: stack size does not match block type"); goto fail; } @@ -5937,10 +6022,9 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, /* Check stack values match return types */ frame_ref = loader_ctx->frame_ref; - for (i = (int32)return_count -1; i >= 0; i--) { + for (i = (int32)return_count - 1; i >= 0; i--) { if (!check_stack_top_values(frame_ref, available_stack_cell, - return_types[i], - error_buf, error_buf_size)) + return_types[i], error_buf, error_buf_size)) return false; frame_ref -= wasm_value_type_cell_num(return_types[i]); available_stack_cell -= wasm_value_type_cell_num(return_types[i]); @@ -5965,7 +6049,7 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, */ static bool copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, - char* error_buf, uint32 error_buf_size) + char *error_buf, uint32 error_buf_size) { int16 *frame_offset = NULL; uint8 *cells = NULL, cell; @@ -5980,8 +6064,7 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, bool disable_emit = false; int16 operand_offset = 0; - uint64 size = (uint64)param_count * (sizeof(*cells) - + sizeof(*src_offsets)); + uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets)); /* For if block, we also need copy the condition operand offset. */ if (is_if_block) @@ -6017,9 +6100,8 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, /* Part a) */ 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); + emit_uint32(loader_ctx, is_if_block ? wasm_type->param_cell_num + 1 + : wasm_type->param_cell_num); /* Part c) */ for (i = 0; i < param_count; i++) emit_byte(loader_ctx, cells[i]); @@ -6051,44 +6133,47 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, /* reset the stack to the state of before entering the last block */ #if WASM_ENABLE_FAST_INTERP != 0 -#define RESET_STACK() do { \ - loader_ctx->stack_cell_num = \ - (loader_ctx->frame_csp - 1)->stack_cell_num; \ - loader_ctx->frame_ref = \ - loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \ - loader_ctx->frame_offset = \ - loader_ctx->frame_offset_bottom + loader_ctx->stack_cell_num; \ -} while (0) +#define RESET_STACK() \ + do { \ + loader_ctx->stack_cell_num = \ + (loader_ctx->frame_csp - 1)->stack_cell_num; \ + loader_ctx->frame_ref = \ + loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \ + loader_ctx->frame_offset = \ + loader_ctx->frame_offset_bottom + loader_ctx->stack_cell_num; \ + } while (0) #else -#define RESET_STACK() do { \ - loader_ctx->stack_cell_num = \ - (loader_ctx->frame_csp - 1)->stack_cell_num; \ - loader_ctx->frame_ref = \ - loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \ -} while (0) +#define RESET_STACK() \ + do { \ + loader_ctx->stack_cell_num = \ + (loader_ctx->frame_csp - 1)->stack_cell_num; \ + loader_ctx->frame_ref = \ + loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \ + } while (0) #endif /* set current block's stack polymorphic state */ -#define SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(flag) do { \ - BranchBlock *cur_block = loader_ctx->frame_csp - 1; \ - cur_block->is_stack_polymorphic = flag; \ -} while (0) +#define SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(flag) \ + do { \ + BranchBlock *cur_block = loader_ctx->frame_csp - 1; \ + cur_block->is_stack_polymorphic = flag; \ + } while (0) #define BLOCK_HAS_PARAM(block_type) \ (!block_type.is_value_type && block_type.u.type->param_count > 0) -#define PRESERVE_LOCAL_FOR_BLOCK() do { \ - if (!(preserve_local_for_block(loader_ctx, opcode, \ - error_buf, error_buf_size))) { \ - goto fail; \ - } \ -} while (0) +#define PRESERVE_LOCAL_FOR_BLOCK() \ + do { \ + if (!(preserve_local_for_block(loader_ctx, opcode, error_buf, \ + error_buf_size))) { \ + goto fail; \ + } \ + } while (0) #if WASM_ENABLE_REF_TYPES != 0 static bool -get_table_elem_type(const WASMModule *module, - uint32 table_idx, uint8 *p_elem_type, - char *error_buf, uint32 error_buf_size) +get_table_elem_type(const WASMModule *module, uint32 table_idx, + uint8 *p_elem_type, char *error_buf, uint32 error_buf_size) { if (!check_table_index(module, table_idx, error_buf, error_buf_size)) { return false; @@ -6098,16 +6183,17 @@ get_table_elem_type(const WASMModule *module, if (table_idx < module->import_table_count) *p_elem_type = module->import_tables[table_idx].u.table.elem_type; else - *p_elem_type = module->tables[module->import_table_count - + table_idx].elem_type; + *p_elem_type = + module->tables[module->import_table_count + table_idx] + .elem_type; } return true; } static bool -get_table_seg_elem_type(const WASMModule *module, - uint32 table_seg_idx, uint8 *p_elem_type, - char *error_buf, uint32 error_buf_size) +get_table_seg_elem_type(const WASMModule *module, uint32 table_seg_idx, + uint8 *p_elem_type, char *error_buf, + uint32 error_buf_size) { if (table_seg_idx >= module->table_seg_count) { #if WASM_ENABLE_REF_TYPES != 0 @@ -6119,8 +6205,7 @@ get_table_seg_elem_type(const WASMModule *module, "unknown elem segment %u", table_seg_idx); } #else - set_error_buf(error_buf, error_buf_size, - "unknown table segment"); + set_error_buf(error_buf, error_buf_size, "unknown table segment"); #endif return false; } @@ -6133,9 +6218,9 @@ get_table_seg_elem_type(const WASMModule *module, #endif static bool -wasm_loader_prepare_bytecode(WASMModule *module, - WASMFunction *func, uint32 cur_func_idx, - char *error_buf, uint32 error_buf_size) +wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, + uint32 cur_func_idx, char *error_buf, + uint32 error_buf_size) { uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org; uint32 param_count, local_count, global_count; @@ -6159,9 +6244,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, float64 f64; LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n", - func->param_cell_num, - func->local_cell_num, - func->ret_cell_num); + func->param_cell_num, func->local_cell_num, func->ret_cell_num); #endif global_count = module->import_global_count + module->global_count; @@ -6177,8 +6260,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, local_offsets = func->local_offsets; if (!(loader_ctx = wasm_loader_ctx_init(func))) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); goto fail; } @@ -6186,8 +6268,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, re_scan: if (loader_ctx->code_compiled_size > 0) { if (!wasm_loader_ctx_reinit(loader_ctx)) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); goto fail; } p = func->code; @@ -6229,7 +6310,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if WASM_ENABLE_FAST_INTERP != 0 PRESERVE_LOCAL_FOR_BLOCK(); #endif -handle_op_block_and_loop: + handle_op_block_and_loop: { uint8 value_type; BlockType block_type; @@ -6254,13 +6335,15 @@ wasm_loader_prepare_bytecode(WASMModule *module, } block_type.is_value_type = false; block_type.u.type = module->types[type_index]; -#if WASM_ENABLE_FAST_INTERP == 0 \ - && WASM_ENABLE_WAMR_COMPILER == 0 \ +#if WASM_ENABLE_FAST_INTERP == 0 && WASM_ENABLE_WAMR_COMPILER == 0 \ && WASM_ENABLE_JIT == 0 /* If block use type index as block type, change the opcode - * to new extended opcode so that interpreter can resolve the - * block quickly. + * to new extended opcode so that interpreter can resolve + * the block quickly. */ +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p - 2, *(p - 2)); +#endif *(p - 2) = EXT_OP_BLOCK + (opcode - WASM_OP_BLOCK); #endif } @@ -6269,10 +6352,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, if (BLOCK_HAS_PARAM(block_type)) { WASMType *wasm_type = block_type.u.type; for (i = 0; i < block_type.u.type->param_count; i++) - POP_TYPE(wasm_type->types[wasm_type->param_count - i - 1]); + POP_TYPE( + wasm_type->types[wasm_type->param_count - i - 1]); } - PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK), block_type, p); + PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK), + block_type, p); /* Pass parameters to block */ if (BLOCK_HAS_PARAM(block_type)) { @@ -6288,14 +6373,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, skip_label(); if (BLOCK_HAS_PARAM(block_type)) { /* Make sure params are in dynamic space */ - if (!copy_params_to_dynamic_space(loader_ctx, - false, - error_buf, - error_buf_size)) + if (!copy_params_to_dynamic_space( + loader_ctx, false, error_buf, error_buf_size)) goto fail; } (loader_ctx->frame_csp - 1)->code_compiled = - loader_ctx->p_code_compiled; + loader_ctx->p_code_compiled; } else if (opcode == WASM_OP_IF) { /* If block has parameters, we should make sure they are in @@ -6305,8 +6388,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, * (func (export "params-id") (param i32) (result i32) * (i32.const 1) * (i32.const 2) - * (if (param i32 i32) (result i32 i32) (local.get 0) (then)) - * (i32.add) + * (if (param i32 i32) (result i32 i32) (local.get 0) + * (then)) (i32.add) * ) * * So we should emit a copy instruction before the if. @@ -6324,10 +6407,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, /* skip the if label */ skip_label(); /* Emit a copy instruction */ - if (!copy_params_to_dynamic_space(loader_ctx, - true, - error_buf, - error_buf_size)) + if (!copy_params_to_dynamic_space( + loader_ctx, true, error_buf, error_buf_size)) goto fail; /* Emit the if instruction */ @@ -6335,16 +6416,17 @@ wasm_loader_prepare_bytecode(WASMModule *module, /* Emit the new condition operand offset */ POP_OFFSET_TYPE(VALUE_TYPE_I32); - /* Save top param_count values of frame_offset stack, so that - * we can recover it before executing else branch */ - size = sizeof(int16) * - (uint64)block_type.u.type->param_cell_num; - if (!(block->param_frame_offsets = - loader_malloc(size, error_buf, error_buf_size))) + /* Save top param_count values of frame_offset stack, so + * that we can recover it before executing else branch + */ + size = sizeof(int16) + * (uint64)block_type.u.type->param_cell_num; + if (!(block->param_frame_offsets = loader_malloc( + size, error_buf, error_buf_size))) goto fail; - bh_memcpy_s(block->param_frame_offsets, - (uint32)size, - loader_ctx->frame_offset - size/sizeof(int16), + bh_memcpy_s(block->param_frame_offsets, (uint32)size, + loader_ctx->frame_offset + - size / sizeof(int16), (uint32)size); } @@ -6360,9 +6442,11 @@ wasm_loader_prepare_bytecode(WASMModule *module, BlockType block_type = (loader_ctx->frame_csp - 1)->block_type; if (loader_ctx->csp_num < 2 - || (loader_ctx->frame_csp - 1)->label_type != LABEL_TYPE_IF) { - set_error_buf(error_buf, error_buf_size, - "opcode else found without matched opcode if"); + || (loader_ctx->frame_csp - 1)->label_type + != LABEL_TYPE_IF) { + set_error_buf( + error_buf, error_buf_size, + "opcode else found without matched opcode if"); goto fail; } @@ -6374,7 +6458,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, (loader_ctx->frame_csp - 1)->else_addr = p - 1; #if WASM_ENABLE_FAST_INTERP != 0 - /* if the result of if branch is in local or const area, add a copy op */ + /* if the result of if branch is in local or const area, add a + * copy op */ RESERVE_BLOCK_RET(); emit_empty_label_addr_and_frame_ip(PATCH_END); @@ -6394,11 +6479,10 @@ wasm_loader_prepare_bytecode(WASMModule *module, if (BLOCK_HAS_PARAM((block_type))) { uint32 size; BranchBlock *block = loader_ctx->frame_csp - 1; - size = sizeof(int16) * - block_type.u.type->param_cell_num; + 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->frame_offset += (size / sizeof(int16)); } #endif @@ -6410,11 +6494,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, BranchBlock *cur_block = loader_ctx->frame_csp - 1; /* check whether block stack matches its result type */ - if (!check_block_stack(loader_ctx, cur_block, - error_buf, error_buf_size)) + if (!check_block_stack(loader_ctx, cur_block, error_buf, + error_buf_size)) goto fail; - /* if no else branch, and return types do not match param types, fail */ + /* if no else branch, and return types do not match param types, + * fail */ if (cur_block->label_type == LABEL_TYPE_IF && !cur_block->else_addr) { uint32 param_count = 0, ret_count = 0; @@ -6433,7 +6518,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, ret_types = block_type->u.type->types + param_count; } if (param_count != ret_count - || (param_count && memcmp(param_types, ret_types, param_count))) { + || (param_count + && memcmp(param_types, ret_types, param_count))) { set_error_buf(error_buf, error_buf_size, "type mismatch: else branch missing"); goto fail; @@ -6479,8 +6565,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, case WASM_OP_BR: { - if (!(frame_csp_tmp = check_branch_block(loader_ctx, &p, p_end, - error_buf, error_buf_size))) + if (!(frame_csp_tmp = check_branch_block( + loader_ctx, &p, p_end, error_buf, error_buf_size))) goto fail; RESET_STACK(); @@ -6492,8 +6578,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, { POP_I32(); - if (!(frame_csp_tmp = check_branch_block(loader_ctx, &p, p_end, - error_buf, error_buf_size))) + if (!(frame_csp_tmp = check_branch_block( + loader_ctx, &p, p_end, error_buf, error_buf_size))) goto fail; break; @@ -6512,32 +6598,34 @@ wasm_loader_prepare_bytecode(WASMModule *module, for (i = 0; i <= count; i++) { if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, - error_buf, error_buf_size))) + check_branch_block(loader_ctx, &p, p_end, + error_buf, error_buf_size))) goto fail; if (i == 0) { if (frame_csp_tmp->label_type != LABEL_TYPE_LOOP) - ret_count = - block_type_get_result_types(&frame_csp_tmp->block_type, - &ret_types); + ret_count = block_type_get_result_types( + &frame_csp_tmp->block_type, &ret_types); } else { uint8 *tmp_ret_types = NULL; uint32 tmp_ret_count = 0; - /* Check whether all table items have the same return type */ + /* Check whether all table items have the same return + * type */ if (frame_csp_tmp->label_type != LABEL_TYPE_LOOP) - tmp_ret_count = - block_type_get_result_types(&frame_csp_tmp->block_type, - &tmp_ret_types); + tmp_ret_count = block_type_get_result_types( + &frame_csp_tmp->block_type, &tmp_ret_types); if (ret_count != tmp_ret_count || (ret_count - && 0 != memcmp(ret_types, tmp_ret_types, ret_count))) { - set_error_buf(error_buf, error_buf_size, - "type mismatch: br_table targets must " - "all use same result type"); + && 0 + != memcmp(ret_types, tmp_ret_types, + ret_count))) { + set_error_buf( + error_buf, error_buf_size, + "type mismatch: br_table targets must " + "all use same result type"); goto fail; } } @@ -6552,7 +6640,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, { int32 idx; uint8 ret_type; - for (idx = (int32)func->func_type->result_count - 1; idx >= 0; idx--) { + for (idx = (int32)func->func_type->result_count - 1; idx >= 0; + idx--) { ret_type = *(func->func_type->types + func->func_type->param_count + idx); POP_TYPE(ret_type); @@ -6588,13 +6677,17 @@ wasm_loader_prepare_bytecode(WASMModule *module, } if (func_idx < module->import_function_count) - func_type = module->import_functions[func_idx].u.function.func_type; - else func_type = - module->functions[func_idx - module->import_function_count]->func_type; + module->import_functions[func_idx].u.function.func_type; + else + func_type = module + ->functions[func_idx + - module->import_function_count] + ->func_type; if (func_type->param_count > 0) { - for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { + 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]); @@ -6608,31 +6701,34 @@ wasm_loader_prepare_bytecode(WASMModule *module, for (i = 0; i < func_type->result_count; i++) { PUSH_TYPE(func_type->types[func_type->param_count + i]); #if WASM_ENABLE_FAST_INTERP != 0 - /* Here we emit each return value's dynamic_offset. But in fact - * these offsets are continuous, so interpreter only need to get - * the first return value's offset. + /* Here we emit each return value's dynamic_offset. But + * in fact these offsets are continuous, so interpreter + * only need to get the first return value's offset. */ - PUSH_OFFSET_TYPE(func_type->types[func_type->param_count + i]); + PUSH_OFFSET_TYPE( + func_type->types[func_type->param_count + i]); #endif } #if WASM_ENABLE_TAIL_CALL != 0 } else { uint8 type; - if (func_type->result_count != func->func_type->result_count) { - set_error_buf_v(error_buf, error_buf_size, - "%s%u%s", "type mismatch: expect ", + if (func_type->result_count + != func->func_type->result_count) { + set_error_buf_v(error_buf, error_buf_size, "%s%u%s", + "type mismatch: expect ", func->func_type->result_count, " return values but got other"); goto fail; } for (i = 0; i < func_type->result_count; i++) { - type = func->func_type->types[func->func_type->param_count + i]; - if (func_type->types[func_type->param_count + i] != type) { - set_error_buf_v(error_buf, error_buf_size, - "%s%s%s", "type mismatch: expect ", - type2str(type), - " but got other"); + type = func->func_type + ->types[func->func_type->param_count + i]; + if (func_type->types[func_type->param_count + i] + != type) { + set_error_buf_v(error_buf, error_buf_size, "%s%s%s", + "type mismatch: expect ", + type2str(type), " but got other"); goto fail; } } @@ -6688,15 +6784,15 @@ wasm_loader_prepare_bytecode(WASMModule *module, POP_I32(); if (type_idx >= module->type_count) { - set_error_buf(error_buf, error_buf_size, - "unknown type"); + set_error_buf(error_buf, error_buf_size, "unknown type"); goto fail; } func_type = module->types[type_idx]; if (func_type->param_count > 0) { - for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { + 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]); @@ -6710,27 +6806,30 @@ wasm_loader_prepare_bytecode(WASMModule *module, for (i = 0; i < func_type->result_count; i++) { PUSH_TYPE(func_type->types[func_type->param_count + i]); #if WASM_ENABLE_FAST_INTERP != 0 - PUSH_OFFSET_TYPE(func_type->types[func_type->param_count + i]); + PUSH_OFFSET_TYPE( + func_type->types[func_type->param_count + i]); #endif } #if WASM_ENABLE_TAIL_CALL != 0 } else { uint8 type; - if (func_type->result_count != func->func_type->result_count) { - set_error_buf_v(error_buf, error_buf_size, - "%s%u%s", "type mismatch: expect ", + if (func_type->result_count + != func->func_type->result_count) { + set_error_buf_v(error_buf, error_buf_size, "%s%u%s", + "type mismatch: expect ", func->func_type->result_count, " return values but got other"); goto fail; } for (i = 0; i < func_type->result_count; i++) { - type = func->func_type->types[func->func_type->param_count + i]; - if (func_type->types[func_type->param_count + i] != type) { - set_error_buf_v(error_buf, error_buf_size, - "%s%s%s", "type mismatch: expect ", - type2str(type), - " but got other"); + type = func->func_type + ->types[func->func_type->param_count + i]; + if (func_type->types[func_type->param_count + i] + != type) { + set_error_buf_v(error_buf, error_buf_size, "%s%s%s", + "type mismatch: expect ", + type2str(type), " but got other"); goto fail; } } @@ -6746,8 +6845,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, case WASM_OP_DROP_64: { BranchBlock *cur_block = loader_ctx->frame_csp - 1; - int32 available_stack_cell = (int32) - (loader_ctx->stack_cell_num - cur_block->stack_cell_num); + int32 available_stack_cell = + (int32)(loader_ctx->stack_cell_num + - cur_block->stack_cell_num); if (available_stack_cell <= 0 && !cur_block->is_stack_polymorphic) { @@ -6764,15 +6864,15 @@ wasm_loader_prepare_bytecode(WASMModule *module, || *(loader_ctx->frame_ref - 1) == REF_FUNCREF || *(loader_ctx->frame_ref - 1) == REF_EXTERNREF #endif - ) { + ) { loader_ctx->frame_ref--; loader_ctx->stack_cell_num--; #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); loader_ctx->frame_offset--; - if (*(loader_ctx->frame_offset) > - loader_ctx->start_dynamic_offset) - loader_ctx->dynamic_offset --; + if (*(loader_ctx->frame_offset) + > loader_ctx->start_dynamic_offset) + loader_ctx->dynamic_offset--; #endif } else if (*(loader_ctx->frame_ref - 1) == REF_I64_1 @@ -6785,8 +6885,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); loader_ctx->frame_offset -= 2; - if (*(loader_ctx->frame_offset) > - loader_ctx->start_dynamic_offset) + if (*(loader_ctx->frame_offset) + > loader_ctx->start_dynamic_offset) loader_ctx->dynamic_offset -= 2; #endif } @@ -6821,8 +6921,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, POP_I32(); - available_stack_cell = (int32) - (loader_ctx->stack_cell_num - cur_block->stack_cell_num); + available_stack_cell = (int32)(loader_ctx->stack_cell_num + - cur_block->stack_cell_num); if (available_stack_cell <= 0 && !cur_block->is_stack_polymorphic) { @@ -6850,21 +6950,24 @@ wasm_loader_prepare_bytecode(WASMModule *module, loader_ctx->p_code_compiled - 2; #if WASM_ENABLE_LABELS_AS_VALUES != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 - *(void**)(p_code_compiled_tmp - sizeof(void*)) = - handle_table[opcode_tmp]; + *(void **)(p_code_compiled_tmp + - sizeof(void *)) = + handle_table[opcode_tmp]; #else - int32 offset = (int32) - ((uint8*)handle_table[opcode_tmp] - - (uint8*)handle_table[0]); - if (!(offset >= INT16_MIN && offset < INT16_MAX)) { + int32 offset = + (int32)((uint8 *)handle_table[opcode_tmp] + - (uint8 *)handle_table[0]); + if (!(offset >= INT16_MIN + && offset < INT16_MAX)) { set_error_buf(error_buf, error_buf_size, - "pre-compiled label offset out of range"); + "pre-compiled label offset " + "out of range"); goto fail; } - *(int16*)(p_code_compiled_tmp - sizeof(int16)) = - (int16)offset; + *(int16 *)(p_code_compiled_tmp + - sizeof(int16)) = (int16)offset; #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ -#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ +#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 *(p_code_compiled_tmp - 1) = opcode_tmp; #else @@ -6880,7 +6983,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, break; #endif /* (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */ #endif /* WASM_ENABLE_SIMD != 0 */ - default: { + default: + { set_error_buf(error_buf, error_buf_size, "type mismatch"); goto fail; @@ -6950,25 +7054,25 @@ wasm_loader_prepare_bytecode(WASMModule *module, } else { if (ref_type == VALUE_TYPE_F64 - || ref_type == VALUE_TYPE_I64) + || ref_type == VALUE_TYPE_I64) opcode_tmp = WASM_OP_SELECT_64; #if WASM_ENABLE_LABELS_AS_VALUES != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 - *(void**)(p_code_compiled_tmp - sizeof(void*)) = - handle_table[opcode_tmp]; + *(void **)(p_code_compiled_tmp - sizeof(void *)) = + handle_table[opcode_tmp]; #else - int32 offset = (int32) - ((uint8*)handle_table[opcode_tmp] - - (uint8*)handle_table[0]); + int32 offset = (int32)((uint8 *)handle_table[opcode_tmp] + - (uint8 *)handle_table[0]); if (!(offset >= INT16_MIN && offset < INT16_MAX)) { - set_error_buf(error_buf, error_buf_size, - "pre-compiled label offset out of range"); + set_error_buf( + error_buf, error_buf_size, + "pre-compiled label offset out of range"); goto fail; } - *(int16*)(p_code_compiled_tmp - sizeof(int16)) = - (int16)offset; + *(int16 *)(p_code_compiled_tmp - sizeof(int16)) = + (int16)offset; #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ -#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ +#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 *(p_code_compiled_tmp - 1) = opcode_tmp; #else @@ -7059,21 +7163,20 @@ wasm_loader_prepare_bytecode(WASMModule *module, } #if WASM_ENABLE_FAST_INTERP != 0 - if (!wasm_loader_pop_frame_ref_offset( - loader_ctx, VALUE_TYPE_FUNCREF, - error_buf, error_buf_size) + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, + VALUE_TYPE_FUNCREF, + error_buf, error_buf_size) && !wasm_loader_pop_frame_ref_offset( - loader_ctx, VALUE_TYPE_EXTERNREF, - error_buf, error_buf_size)) { + loader_ctx, VALUE_TYPE_EXTERNREF, error_buf, + error_buf_size)) { goto fail; } #else - if (!wasm_loader_pop_frame_ref( - loader_ctx, VALUE_TYPE_FUNCREF, - error_buf, error_buf_size) - && !wasm_loader_pop_frame_ref( - loader_ctx, VALUE_TYPE_EXTERNREF, - error_buf, error_buf_size)) { + if (!wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF, + error_buf, error_buf_size) + && !wasm_loader_pop_frame_ref(loader_ctx, + VALUE_TYPE_EXTERNREF, + error_buf, error_buf_size)) { goto fail; } #endif @@ -7102,8 +7205,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, for (i = 0; i < module->table_seg_count; i++, table_seg++) { if (table_seg->elem_type == VALUE_TYPE_FUNCREF && wasm_elem_is_declarative(table_seg->mode)) { - for (j =0; j < table_seg->function_count; j++) { - if (table_seg->func_indexes[j] == cur_func_idx) { + for (j = 0; j < table_seg->function_count; j++) { + if (table_seg->func_indexes[j] + == cur_func_idx) { func_declared = true; break; } @@ -7140,13 +7244,28 @@ wasm_loader_prepare_bytecode(WASMModule *module, #else #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) if (local_offset < 0x80) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = EXT_OP_GET_LOCAL_FAST; - if (is_32bit_type(local_type)) + if (is_32bit_type(local_type)) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = (uint8)local_offset; - else + } + else { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = (uint8)(local_offset | 0x80); - while (p_org < p) + } + while (p_org < p) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = WASM_OP_NOP; + } } #endif #endif @@ -7160,22 +7279,24 @@ wasm_loader_prepare_bytecode(WASMModule *module, POP_TYPE(local_type); #if WASM_ENABLE_FAST_INTERP != 0 - if (!(preserve_referenced_local(loader_ctx, opcode, local_offset, - local_type, &preserve_local, - error_buf, error_buf_size))) + if (!(preserve_referenced_local( + loader_ctx, opcode, local_offset, local_type, + &preserve_local, error_buf, error_buf_size))) goto fail; if (local_offset < 256) { skip_label(); if ((!preserve_local) && (LAST_OP_OUTPUT_I32())) { if (loader_ctx->p_code_compiled) - STORE_U16(loader_ctx->p_code_compiled - 2, local_offset); - loader_ctx->frame_offset --; - loader_ctx->dynamic_offset --; + STORE_U16(loader_ctx->p_code_compiled - 2, + local_offset); + loader_ctx->frame_offset--; + loader_ctx->dynamic_offset--; } else if ((!preserve_local) && (LAST_OP_OUTPUT_I64())) { if (loader_ctx->p_code_compiled) - STORE_U16(loader_ctx->p_code_compiled - 2, local_offset); + STORE_U16(loader_ctx->p_code_compiled - 2, + local_offset); loader_ctx->frame_offset -= 2; loader_ctx->dynamic_offset -= 2; } @@ -7191,20 +7312,35 @@ wasm_loader_prepare_bytecode(WASMModule *module, POP_OFFSET_TYPE(local_type); } } - else { /* local index larger than 255, reserve leb */ + else { /* local index larger than 255, reserve leb */ emit_uint32(loader_ctx, local_idx); POP_OFFSET_TYPE(local_type); } #else #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) if (local_offset < 0x80) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = EXT_OP_SET_LOCAL_FAST; - if (is_32bit_type(local_type)) + if (is_32bit_type(local_type)) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = (uint8)local_offset; - else + } + else { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = (uint8)(local_offset | 0x80); - while (p_org < p) + } + while (p_org < p) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = WASM_OP_NOP; + } } #endif #endif @@ -7217,8 +7353,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, GET_LOCAL_INDEX_TYPE_AND_OFFSET(); #if WASM_ENABLE_FAST_INTERP != 0 /* If the stack is in polymorphic state, do fake pop and push on - offset stack to keep the depth of offset stack to be the same - with ref stack */ + offset stack to keep the depth of offset stack to be the + same with ref stack */ BranchBlock *cur_block = loader_ctx->frame_csp - 1; if (cur_block->is_stack_polymorphic) { POP_OFFSET_TYPE(local_type); @@ -7229,9 +7365,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, PUSH_TYPE(local_type); #if WASM_ENABLE_FAST_INTERP != 0 - if (!(preserve_referenced_local(loader_ctx, opcode, local_offset, - local_type, &preserve_local, - error_buf, error_buf_size))) + if (!(preserve_referenced_local( + loader_ctx, opcode, local_offset, local_type, + &preserve_local, error_buf, error_buf_size))) goto fail; if (local_offset < 256) { @@ -7245,21 +7381,37 @@ wasm_loader_prepare_bytecode(WASMModule *module, emit_byte(loader_ctx, (uint8)local_offset); } } - else { /* local index larger than 255, reserve leb */ + else { /* local index larger than 255, reserve leb */ emit_uint32(loader_ctx, local_idx); } - emit_operand(loader_ctx, *(loader_ctx->frame_offset - - wasm_value_type_cell_num(local_type))); + emit_operand(loader_ctx, + *(loader_ctx->frame_offset + - wasm_value_type_cell_num(local_type))); #else #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) if (local_offset < 0x80) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = EXT_OP_TEE_LOCAL_FAST; - if (is_32bit_type(local_type)) + if (is_32bit_type(local_type)) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = (uint8)local_offset; - else + } + else { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = (uint8)(local_offset | 0x80); - while (p_org < p) + } + while (p_org < p) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org++ = WASM_OP_NOP; + } } #endif #endif @@ -7271,16 +7423,17 @@ wasm_loader_prepare_bytecode(WASMModule *module, p_org = p - 1; read_leb_uint32(p, p_end, global_idx); if (global_idx >= global_count) { - set_error_buf(error_buf, error_buf_size, - "unknown global"); + set_error_buf(error_buf, error_buf_size, "unknown global"); goto fail; } global_type = - global_idx < module->import_global_count - ? module->import_globals[global_idx].u.global.type - : module->globals[global_idx - module->import_global_count] - .type; + global_idx < module->import_global_count + ? module->import_globals[global_idx].u.global.type + : module + ->globals[global_idx + - module->import_global_count] + .type; PUSH_TYPE(global_type); @@ -7288,10 +7441,13 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) if (global_type == VALUE_TYPE_I64 || global_type == VALUE_TYPE_F64) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org = WASM_OP_GET_GLOBAL_64; } #endif -#else /* else of WASM_ENABLE_FAST_INTERP */ +#else /* else of WASM_ENABLE_FAST_INTERP */ if (global_type == VALUE_TYPE_I64 || global_type == VALUE_TYPE_F64) { skip_label(); @@ -7310,16 +7466,17 @@ wasm_loader_prepare_bytecode(WASMModule *module, p_org = p - 1; read_leb_uint32(p, p_end, global_idx); if (global_idx >= global_count) { - set_error_buf(error_buf, error_buf_size, - "unknown global"); + set_error_buf(error_buf, error_buf_size, "unknown global"); goto fail; } is_mutable = - global_idx < module->import_global_count - ? module->import_globals[global_idx].u.global.is_mutable - : module->globals[global_idx - module->import_global_count] - .is_mutable; + global_idx < module->import_global_count + ? module->import_globals[global_idx].u.global.is_mutable + : module + ->globals[global_idx + - module->import_global_count] + .is_mutable; if (!is_mutable) { set_error_buf(error_buf, error_buf_size, "global is immutable"); @@ -7327,23 +7484,31 @@ wasm_loader_prepare_bytecode(WASMModule *module, } global_type = - global_idx < module->import_global_count - ? module->import_globals[global_idx].u.global.type - : module->globals[global_idx - module->import_global_count] - .type; + global_idx < module->import_global_count + ? module->import_globals[global_idx].u.global.type + : module + ->globals[global_idx + - module->import_global_count] + .type; POP_TYPE(global_type); #if WASM_ENABLE_FAST_INTERP == 0 if (global_type == VALUE_TYPE_I64 || global_type == VALUE_TYPE_F64) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org = WASM_OP_SET_GLOBAL_64; } else if (module->aux_stack_size > 0 && global_idx == module->aux_stack_top_global_index) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + record_fast_op(module, p_org, *p_org); +#endif *p_org = WASM_OP_SET_GLOBAL_AUX_STACK; } -#else /* else of WASM_ENABLE_FAST_INTERP */ +#else /* else of WASM_ENABLE_FAST_INTERP */ if (global_type == VALUE_TYPE_I64 || global_type == VALUE_TYPE_F64) { skip_label(); @@ -7406,17 +7571,16 @@ wasm_loader_prepare_bytecode(WASMModule *module, } #endif CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ + read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, mem_offset); /* offset */ - if (!check_memory_access_align(opcode, align, - error_buf, error_buf_size)) { + if (!check_memory_access_align(opcode, align, error_buf, + error_buf_size)) { goto fail; } #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, mem_offset); #endif - switch (opcode) - { + switch (opcode) { /* load */ case WASM_OP_I32_LOAD: case WASM_OP_I32_LOAD8_S: @@ -7522,7 +7686,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); disable_emit = true; - bh_memcpy_s((uint8*)&f32, sizeof(float32), p_org, sizeof(float32)); + bh_memcpy_s((uint8 *)&f32, sizeof(float32), p_org, + sizeof(float32)); GET_CONST_F32_OFFSET(VALUE_TYPE_F32, f32); #endif PUSH_F32(); @@ -7534,7 +7699,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, skip_label(); disable_emit = true; /* Some MCU may require 8-byte align */ - bh_memcpy_s((uint8*)&f64, sizeof(float64), p_org, sizeof(float64)); + bh_memcpy_s((uint8 *)&f64, sizeof(float64), p_org, + sizeof(float64)); GET_CONST_F64_OFFSET(VALUE_TYPE_F64, f64); #endif PUSH_F64(); @@ -7772,263 +7938,272 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if WASM_ENABLE_FAST_INTERP != 0 emit_byte(loader_ctx, ((uint8)opcode1)); #endif - switch (opcode1) - { - case WASM_OP_I32_TRUNC_SAT_S_F32: - case WASM_OP_I32_TRUNC_SAT_U_F32: - POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32); - break; - case WASM_OP_I32_TRUNC_SAT_S_F64: - case WASM_OP_I32_TRUNC_SAT_U_F64: - POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32); - break; - case WASM_OP_I64_TRUNC_SAT_S_F32: - case WASM_OP_I64_TRUNC_SAT_U_F32: - POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I64); - break; - case WASM_OP_I64_TRUNC_SAT_S_F64: - case WASM_OP_I64_TRUNC_SAT_U_F64: - POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64); - break; + switch (opcode1) { + case WASM_OP_I32_TRUNC_SAT_S_F32: + case WASM_OP_I32_TRUNC_SAT_U_F32: + POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32); + break; + case WASM_OP_I32_TRUNC_SAT_S_F64: + case WASM_OP_I32_TRUNC_SAT_U_F64: + POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32); + break; + case WASM_OP_I64_TRUNC_SAT_S_F32: + case WASM_OP_I64_TRUNC_SAT_U_F32: + POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I64); + break; + case WASM_OP_I64_TRUNC_SAT_S_F64: + case WASM_OP_I64_TRUNC_SAT_U_F64: + POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64); + break; #if WASM_ENABLE_BULK_MEMORY != 0 - case WASM_OP_MEMORY_INIT: - { - read_leb_uint32(p, p_end, data_seg_idx); + case WASM_OP_MEMORY_INIT: + { + read_leb_uint32(p, p_end, data_seg_idx); #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, data_seg_idx); + emit_uint32(loader_ctx, data_seg_idx); #endif - if (module->import_memory_count == 0 && module->memory_count == 0) - goto fail_unknown_memory; + if (module->import_memory_count == 0 + && module->memory_count == 0) + goto fail_unknown_memory; - if (*p++ != 0x00) - goto fail_zero_byte_expected; + if (*p++ != 0x00) + goto fail_zero_byte_expected; - if (data_seg_idx >= module->data_seg_count) { - set_error_buf_v(error_buf, error_buf_size, - "unknown data segment %d", data_seg_idx); - goto fail; - } + if (data_seg_idx >= module->data_seg_count) { + set_error_buf_v(error_buf, error_buf_size, + "unknown data segment %d", + data_seg_idx); + goto fail; + } - if (module->data_seg_count1 == 0) - goto fail_data_cnt_sec_require; + if (module->data_seg_count1 == 0) + goto fail_data_cnt_sec_require; - POP_I32(); - POP_I32(); - POP_I32(); - break; - } - case WASM_OP_DATA_DROP: - { - read_leb_uint32(p, p_end, data_seg_idx); + POP_I32(); + POP_I32(); + POP_I32(); + break; + } + case WASM_OP_DATA_DROP: + { + read_leb_uint32(p, p_end, data_seg_idx); #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, data_seg_idx); + emit_uint32(loader_ctx, data_seg_idx); #endif - if (data_seg_idx >= module->data_seg_count) { - set_error_buf(error_buf, error_buf_size, - "unknown data segment"); - goto fail; - } + if (data_seg_idx >= module->data_seg_count) { + set_error_buf(error_buf, error_buf_size, + "unknown data segment"); + goto fail; + } - if (module->data_seg_count1 == 0) - goto fail_data_cnt_sec_require; + if (module->data_seg_count1 == 0) + goto fail_data_cnt_sec_require; - break; - } - case WASM_OP_MEMORY_COPY: - { - /* both src and dst memory index should be 0 */ - if (*(int16*)p != 0x0000) - goto fail_zero_byte_expected; - p += 2; + break; + } + case WASM_OP_MEMORY_COPY: + { + /* both src and dst memory index should be 0 */ + if (*(int16 *)p != 0x0000) + goto fail_zero_byte_expected; + p += 2; - if (module->import_memory_count == 0 && module->memory_count == 0) - goto fail_unknown_memory; + if (module->import_memory_count == 0 + && module->memory_count == 0) + goto fail_unknown_memory; - POP_I32(); - POP_I32(); - POP_I32(); - break; - } - case WASM_OP_MEMORY_FILL: - { - if (*p++ != 0x00) { - goto fail_zero_byte_expected; - } - if (module->import_memory_count == 0 && module->memory_count == 0) { - goto fail_unknown_memory; + POP_I32(); + POP_I32(); + POP_I32(); + break; } + case WASM_OP_MEMORY_FILL: + { + if (*p++ != 0x00) { + goto fail_zero_byte_expected; + } + if (module->import_memory_count == 0 + && module->memory_count == 0) { + goto fail_unknown_memory; + } - POP_I32(); - POP_I32(); - POP_I32(); - break; -fail_zero_byte_expected: - set_error_buf(error_buf, error_buf_size, - "zero byte expected"); - goto fail; + POP_I32(); + POP_I32(); + POP_I32(); + break; + fail_zero_byte_expected: + set_error_buf(error_buf, error_buf_size, + "zero byte expected"); + goto fail; -fail_unknown_memory: - set_error_buf(error_buf, error_buf_size, - "unknown memory 0"); - goto fail; -fail_data_cnt_sec_require: - set_error_buf(error_buf, error_buf_size, - "data count section required"); - goto fail; - } + fail_unknown_memory: + set_error_buf(error_buf, error_buf_size, + "unknown memory 0"); + goto fail; + fail_data_cnt_sec_require: + set_error_buf(error_buf, error_buf_size, + "data count section required"); + goto fail; + } #endif /* WASM_ENABLE_BULK_MEMORY */ #if WASM_ENABLE_REF_TYPES != 0 - case WASM_OP_TABLE_INIT: - { - uint8 seg_ref_type, tbl_ref_type; - - if (!wasm_get_ref_types_flag()) { - goto unsupported_opcode; - } + case WASM_OP_TABLE_INIT: + { + uint8 seg_ref_type = 0, tbl_ref_type = 0; - read_leb_uint32(p, p_end, table_seg_idx); - read_leb_uint32(p, p_end, table_idx); + if (!wasm_get_ref_types_flag()) { + goto unsupported_opcode; + } - if (!get_table_elem_type(module, table_idx, &tbl_ref_type, - error_buf, error_buf_size)) - goto fail; + read_leb_uint32(p, p_end, table_seg_idx); + read_leb_uint32(p, p_end, table_idx); - if (!get_table_seg_elem_type(module, table_seg_idx, - &seg_ref_type, error_buf, + if (!get_table_elem_type(module, table_idx, + &tbl_ref_type, error_buf, error_buf_size)) - goto fail; + goto fail; - if (seg_ref_type != tbl_ref_type) { - set_error_buf(error_buf, error_buf_size, - "type mismatch"); - goto fail; - } + if (!get_table_seg_elem_type(module, table_seg_idx, + &seg_ref_type, error_buf, + error_buf_size)) + goto fail; + + if (seg_ref_type != tbl_ref_type) { + set_error_buf(error_buf, error_buf_size, + "type mismatch"); + goto fail; + } #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, table_seg_idx); - emit_uint32(loader_ctx, table_idx); + emit_uint32(loader_ctx, table_seg_idx); + emit_uint32(loader_ctx, table_idx); #endif - POP_I32(); - POP_I32(); - POP_I32(); - break; - } - case WASM_OP_ELEM_DROP: - { - if (!wasm_get_ref_types_flag()) { - goto unsupported_opcode; + POP_I32(); + POP_I32(); + POP_I32(); + break; } + case WASM_OP_ELEM_DROP: + { + if (!wasm_get_ref_types_flag()) { + goto unsupported_opcode; + } - read_leb_uint32(p, p_end, table_seg_idx); - if (!get_table_seg_elem_type(module, table_seg_idx, NULL, - error_buf, error_buf_size)) - goto fail; + read_leb_uint32(p, p_end, table_seg_idx); + if (!get_table_seg_elem_type(module, table_seg_idx, + NULL, error_buf, + error_buf_size)) + goto fail; #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, table_seg_idx); + emit_uint32(loader_ctx, table_seg_idx); #endif - break; - } - case WASM_OP_TABLE_COPY: - { - uint8 src_ref_type, dst_ref_type; - uint32 src_tbl_idx, dst_tbl_idx; - - if (!wasm_get_ref_types_flag()) { - goto unsupported_opcode; + break; } + case WASM_OP_TABLE_COPY: + { + uint8 src_ref_type, dst_ref_type; + uint32 src_tbl_idx, dst_tbl_idx; - read_leb_uint32(p, p_end, src_tbl_idx); - if (!get_table_elem_type(module, src_tbl_idx, &src_ref_type, - error_buf, error_buf_size)) - goto fail; + if (!wasm_get_ref_types_flag()) { + goto unsupported_opcode; + } - read_leb_uint32(p, p_end, dst_tbl_idx); - if (!get_table_elem_type(module, dst_tbl_idx, &dst_ref_type, - error_buf, error_buf_size)) - goto fail; + read_leb_uint32(p, p_end, src_tbl_idx); + if (!get_table_elem_type(module, src_tbl_idx, + &src_ref_type, error_buf, + error_buf_size)) + goto fail; - if (src_ref_type != dst_ref_type) { - set_error_buf(error_buf, error_buf_size, - "type mismatch"); - goto fail; - } + read_leb_uint32(p, p_end, dst_tbl_idx); + if (!get_table_elem_type(module, dst_tbl_idx, + &dst_ref_type, error_buf, + error_buf_size)) + goto fail; + + if (src_ref_type != dst_ref_type) { + set_error_buf(error_buf, error_buf_size, + "type mismatch"); + goto fail; + } #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, src_tbl_idx); - emit_uint32(loader_ctx, dst_tbl_idx); + emit_uint32(loader_ctx, src_tbl_idx); + emit_uint32(loader_ctx, dst_tbl_idx); #endif - POP_I32(); - POP_I32(); - POP_I32(); - break; - } - case WASM_OP_TABLE_SIZE: - { - if (!wasm_get_ref_types_flag()) { - goto unsupported_opcode; + POP_I32(); + POP_I32(); + POP_I32(); + break; } + case WASM_OP_TABLE_SIZE: + { + if (!wasm_get_ref_types_flag()) { + goto unsupported_opcode; + } - read_leb_uint32(p, p_end, table_idx); - /* TODO: shall we create a new function to check - table idx instead of using below function? */ - if (!get_table_elem_type(module, table_idx, NULL, - error_buf, error_buf_size)) - goto fail; + read_leb_uint32(p, p_end, table_idx); + /* TODO: shall we create a new function to check + table idx instead of using below function? */ + if (!get_table_elem_type(module, table_idx, NULL, + error_buf, error_buf_size)) + goto fail; #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, table_idx); + emit_uint32(loader_ctx, table_idx); #endif - PUSH_I32(); - break; - } - case WASM_OP_TABLE_GROW: - case WASM_OP_TABLE_FILL: - { - uint8 decl_ref_type; - - if (!wasm_get_ref_types_flag()) { - goto unsupported_opcode; + PUSH_I32(); + break; } + case WASM_OP_TABLE_GROW: + case WASM_OP_TABLE_FILL: + { + uint8 decl_ref_type; - read_leb_uint32(p, p_end, table_idx); - if (!get_table_elem_type(module, table_idx, - &decl_ref_type, error_buf, - error_buf_size)) - goto fail; - - if (opcode1 == WASM_OP_TABLE_GROW) { - if (table_idx < module->import_table_count) { - module->import_tables[table_idx] - .u.table.possible_grow = true; + if (!wasm_get_ref_types_flag()) { + goto unsupported_opcode; } - else { - module->tables[table_idx - module->import_table_count] - .possible_grow = true; + + read_leb_uint32(p, p_end, table_idx); + if (!get_table_elem_type(module, table_idx, + &decl_ref_type, error_buf, + error_buf_size)) + goto fail; + + if (opcode1 == WASM_OP_TABLE_GROW) { + if (table_idx < module->import_table_count) { + module->import_tables[table_idx] + .u.table.possible_grow = true; + } + else { + module + ->tables[table_idx + - module->import_table_count] + .possible_grow = true; + } } - } #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, table_idx); + emit_uint32(loader_ctx, table_idx); #endif - POP_I32(); + POP_I32(); #if WASM_ENABLE_FAST_INTERP != 0 - POP_OFFSET_TYPE(decl_ref_type); + POP_OFFSET_TYPE(decl_ref_type); #endif - POP_TYPE(decl_ref_type); - if (opcode1 == WASM_OP_TABLE_GROW) - PUSH_I32(); - else - POP_I32(); - break; - } + POP_TYPE(decl_ref_type); + if (opcode1 == WASM_OP_TABLE_GROW) + PUSH_I32(); + else + POP_I32(); + break; + } #endif /* WASM_ENABLE_REF_TYPES */ - default: - set_error_buf_v(error_buf, error_buf_size, - "%s %02x %02x", - "unsupported opcode", 0xfc, opcode1); - goto fail; + default: + set_error_buf_v(error_buf, error_buf_size, + "%s %02x %02x", "unsupported opcode", + 0xfc, opcode1); + goto fail; } break; } @@ -8037,33 +8212,33 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) case WASM_OP_SIMD_PREFIX: { - uint8 lane; - opcode = read_uint8(p); + /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h + */ switch (opcode) { + /* memory instruction */ case SIMD_v128_load: - case SIMD_i16x8_load8x8_s: - case SIMD_i16x8_load8x8_u: - case SIMD_i32x4_load16x4_s: - case SIMD_i32x4_load16x4_u: - case SIMD_i64x2_load32x2_s: - case SIMD_i64x2_load32x2_u: - case SIMD_v8x16_load_splat: - case SIMD_v16x8_load_splat: - case SIMD_v32x4_load_splat: - case SIMD_v64x2_load_splat: + case SIMD_v128_load8x8_s: + case SIMD_v128_load8x8_u: + case SIMD_v128_load16x4_s: + case SIMD_v128_load16x4_u: + case SIMD_v128_load32x2_s: + case SIMD_v128_load32x2_u: + case SIMD_v128_load8_splat: + case SIMD_v128_load16_splat: + case SIMD_v128_load32_splat: + case SIMD_v128_load64_splat: { CHECK_MEMORY(); read_leb_uint32(p, p_end, align); /* align */ if (!check_simd_memory_access_align( - opcode, align, error_buf, error_buf_size)) { + opcode, align, error_buf, error_buf_size)) { goto fail; } read_leb_uint32(p, p_end, mem_offset); /* offset */ - /* pop(i32 %i), push(v128 *result) */ POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_V128); break; } @@ -8074,24 +8249,25 @@ wasm_loader_prepare_bytecode(WASMModule *module, read_leb_uint32(p, p_end, align); /* align */ if (!check_simd_memory_access_align( - opcode, align, error_buf, error_buf_size)) { + opcode, align, error_buf, error_buf_size)) { goto fail; } read_leb_uint32(p, p_end, mem_offset); /* offset */ - /* pop(v128 %value) */ POP_V128(); - /* pop(i32 %i) */ POP_I32(); break; } + /* basic operation */ case SIMD_v128_const: + { CHECK_BUF1(p, p_end, 16); p += 16; PUSH_V128(); break; + } case SIMD_v8x16_shuffle: { @@ -8110,122 +8286,87 @@ wasm_loader_prepare_bytecode(WASMModule *module, } case SIMD_v8x16_swizzle: + { POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); break; + } + /* splat operation */ case SIMD_i8x16_splat: case SIMD_i16x8_splat: case SIMD_i32x4_splat: - POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_V128); - break; case SIMD_i64x2_splat: - POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_V128); - break; case SIMD_f32x4_splat: - POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_V128); - break; case SIMD_f64x2_splat: - POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_V128); + { + uint8 pop_type[] = { VALUE_TYPE_I32, VALUE_TYPE_I32, + VALUE_TYPE_I32, VALUE_TYPE_I64, + VALUE_TYPE_F32, VALUE_TYPE_F64 }; + POP_AND_PUSH(pop_type[opcode - SIMD_i8x16_splat], + VALUE_TYPE_V128); break; + } + /* lane operation */ case SIMD_i8x16_extract_lane_s: case SIMD_i8x16_extract_lane_u: + case SIMD_i8x16_replace_lane: case SIMD_i16x8_extract_lane_s: case SIMD_i16x8_extract_lane_u: + case SIMD_i16x8_replace_lane: case SIMD_i32x4_extract_lane: - CHECK_BUF(p, p_end, 1); - lane = read_uint8(p); - - if (!check_simd_access_lane(opcode, lane, error_buf, - error_buf_size)) { - goto fail; - } - - POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32); - break; + case SIMD_i32x4_replace_lane: case SIMD_i64x2_extract_lane: - CHECK_BUF(p, p_end, 1); - lane = read_uint8(p); - - if (!check_simd_access_lane(opcode, lane, error_buf, - error_buf_size)) { - goto fail; - } - - POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I64); - break; + case SIMD_i64x2_replace_lane: case SIMD_f32x4_extract_lane: - CHECK_BUF(p, p_end, 1); - lane = read_uint8(p); - - if (!check_simd_access_lane(opcode, lane, error_buf, - error_buf_size)) { - goto fail; - } - - POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_F32); - break; + case SIMD_f32x4_replace_lane: case SIMD_f64x2_extract_lane: - CHECK_BUF(p, p_end, 1); - lane = read_uint8(p); - - if (!check_simd_access_lane(opcode, lane, error_buf, - error_buf_size)) { - goto fail; - } + case SIMD_f64x2_replace_lane: + { + uint8 lane; + /* clang-format off */ + uint8 replace[] = { + /*i8x16*/ 0x0, 0x0, VALUE_TYPE_I32, + /*i16x8*/ 0x0, 0x0, VALUE_TYPE_I32, + /*i32x4*/ 0x0, VALUE_TYPE_I32, + /*i64x2*/ 0x0, VALUE_TYPE_I64, + /*f32x4*/ 0x0, VALUE_TYPE_F32, + /*f64x2*/ 0x0, VALUE_TYPE_F64, + }; + uint8 push_type[] = { + /*i8x16*/ VALUE_TYPE_I32, VALUE_TYPE_I32, + VALUE_TYPE_V128, + /*i16x8*/ VALUE_TYPE_I32, VALUE_TYPE_I32, + VALUE_TYPE_V128, + /*i32x4*/ VALUE_TYPE_I32, VALUE_TYPE_V128, + /*i64x2*/ VALUE_TYPE_I64, VALUE_TYPE_V128, + /*f32x4*/ VALUE_TYPE_F32, VALUE_TYPE_V128, + /*f64x2*/ VALUE_TYPE_F64, VALUE_TYPE_V128, + }; + /* clang-format on */ - POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_F64); - break; - case SIMD_i8x16_replace_lane: - case SIMD_i16x8_replace_lane: - case SIMD_i32x4_replace_lane: CHECK_BUF(p, p_end, 1); lane = read_uint8(p); - if (!check_simd_access_lane(opcode, lane, error_buf, error_buf_size)) { goto fail; } - POP_I32(); - POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); - break; - case SIMD_i64x2_replace_lane: - CHECK_BUF(p, p_end, 1); - lane = read_uint8(p); - - if (!check_simd_access_lane(opcode, lane, error_buf, - error_buf_size)) { - goto fail; + if (replace[opcode - SIMD_i8x16_extract_lane_s]) { + if (!(wasm_loader_pop_frame_ref( + loader_ctx, + replace[opcode - SIMD_i8x16_extract_lane_s], + error_buf, error_buf_size))) + goto fail; } - POP_I64(); - POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + POP_AND_PUSH( + VALUE_TYPE_V128, + push_type[opcode - SIMD_i8x16_extract_lane_s]); break; - case SIMD_f32x4_replace_lane: - CHECK_BUF(p, p_end, 1); - lane = read_uint8(p); - - if (!check_simd_access_lane(opcode, lane, error_buf, - error_buf_size)) { - goto fail; - } - - POP_F32(); - POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); - break; - case SIMD_f64x2_replace_lane: - CHECK_BUF(p, p_end, 1); - lane = read_uint8(p); - - if (!check_simd_access_lane(opcode, lane, error_buf, - error_buf_size)) { - goto fail; - } + } - POP_F64(); - POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); - break; + /* i8x16 compare operation */ case SIMD_i8x16_eq: case SIMD_i8x16_ne: case SIMD_i8x16_lt_s: @@ -8236,6 +8377,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, case SIMD_i8x16_le_u: case SIMD_i8x16_ge_s: case SIMD_i8x16_ge_u: + /* i16x8 compare operation */ case SIMD_i16x8_eq: case SIMD_i16x8_ne: case SIMD_i16x8_lt_s: @@ -8246,6 +8388,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, case SIMD_i16x8_le_u: case SIMD_i16x8_ge_s: case SIMD_i16x8_ge_u: + /* i32x4 compare operation */ case SIMD_i32x4_eq: case SIMD_i32x4_ne: case SIMD_i32x4_lt_s: @@ -8256,122 +8399,318 @@ wasm_loader_prepare_bytecode(WASMModule *module, case SIMD_i32x4_le_u: case SIMD_i32x4_ge_s: case SIMD_i32x4_ge_u: + /* f32x4 compare operation */ case SIMD_f32x4_eq: case SIMD_f32x4_ne: case SIMD_f32x4_lt: case SIMD_f32x4_gt: case SIMD_f32x4_le: case SIMD_f32x4_ge: + /* f64x2 compare operation */ case SIMD_f64x2_eq: case SIMD_f64x2_ne: case SIMD_f64x2_lt: case SIMD_f64x2_gt: case SIMD_f64x2_le: case SIMD_f64x2_ge: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + /* v128 operation */ + case SIMD_v128_not: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_v128_and: + case SIMD_v128_andnot: + case SIMD_v128_or: + case SIMD_v128_xor: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_v128_bitselect: + { + POP_V128(); + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_v128_any_true: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32); + break; + } + + /* Load Lane Operation */ + case SIMD_v128_load8_lane: + case SIMD_v128_load16_lane: + case SIMD_v128_load32_lane: + case SIMD_v128_load64_lane: + case SIMD_v128_store8_lane: + case SIMD_v128_store16_lane: + case SIMD_v128_store32_lane: + case SIMD_v128_store64_lane: + { + uint8 lane; + + CHECK_MEMORY(); + + read_leb_uint32(p, p_end, align); /* align */ + if (!check_simd_memory_access_align( + opcode, align, error_buf, error_buf_size)) { + goto fail; + } + + read_leb_uint32(p, p_end, mem_offset); /* offset */ + + CHECK_BUF(p, p_end, 1); + lane = read_uint8(p); + if (!check_simd_access_lane(opcode, lane, error_buf, + error_buf_size)) { + goto fail; + } + + POP_V128(); + POP_I32(); + if (opcode < SIMD_v128_store8_lane) { + PUSH_V128(); + } + break; + } + + case SIMD_v128_load32_zero: + case SIMD_v128_load64_zero: + { + CHECK_MEMORY(); + + read_leb_uint32(p, p_end, align); /* align */ + if (!check_simd_memory_access_align( + opcode, align, error_buf, error_buf_size)) { + goto fail; + } + + read_leb_uint32(p, p_end, mem_offset); /* offset */ + + POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_V128); + break; + } + + /* Float conversion */ + case SIMD_f32x4_demote_f64x2_zero: + case SIMD_f64x2_promote_low_f32x4_zero: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + /* i8x16 Operation */ + case SIMD_i8x16_abs: + case SIMD_i8x16_neg: + case SIMD_i8x16_popcnt: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i8x16_all_true: + case SIMD_i8x16_bitmask: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32); + break; + } + + case SIMD_i8x16_narrow_i16x8_s: + case SIMD_i8x16_narrow_i16x8_u: + { POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); break; + } case SIMD_f32x4_ceil: case SIMD_f32x4_floor: case SIMD_f32x4_trunc: case SIMD_f32x4_nearest: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i8x16_shl: + case SIMD_i8x16_shr_s: + case SIMD_i8x16_shr_u: + { + POP_I32(); + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i8x16_add: + case SIMD_i8x16_add_sat_s: + case SIMD_i8x16_add_sat_u: + case SIMD_i8x16_sub: + case SIMD_i8x16_sub_sat_s: + case SIMD_i8x16_sub_sat_u: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + case SIMD_f64x2_ceil: case SIMD_f64x2_floor: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i8x16_min_s: + case SIMD_i8x16_min_u: + case SIMD_i8x16_max_s: + case SIMD_i8x16_max_u: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + case SIMD_f64x2_trunc: - case SIMD_f64x2_nearest: - case SIMD_v128_not: - case SIMD_i8x16_abs: - case SIMD_i8x16_neg: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i8x16_avgr_u: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i16x8_extadd_pairwise_i8x16_s: + case SIMD_i16x8_extadd_pairwise_i8x16_u: + case SIMD_i32x4_extadd_pairwise_i16x8_s: + case SIMD_i32x4_extadd_pairwise_i16x8_u: + /* i16x8 operation */ case SIMD_i16x8_abs: case SIMD_i16x8_neg: - case SIMD_i32x4_abs: - case SIMD_i32x4_neg: - case SIMD_i64x2_neg: - case SIMD_f32x4_abs: - case SIMD_f32x4_neg: - case SIMD_f32x4_sqrt: - case SIMD_f64x2_abs: - case SIMD_f64x2_neg: - case SIMD_f64x2_sqrt: - case SIMD_i16x8_widen_low_i8x16_s: - case SIMD_i16x8_widen_high_i8x16_s: - case SIMD_i16x8_widen_low_i8x16_u: - case SIMD_i16x8_widen_high_i8x16_u: - case SIMD_i32x4_widen_low_i16x8_s: - case SIMD_i32x4_widen_high_i16x8_s: - case SIMD_i32x4_widen_low_i16x8_u: - case SIMD_i32x4_widen_high_i16x8_u: - case SIMD_i32x4_trunc_sat_f32x4_s: - case SIMD_i32x4_trunc_sat_f32x4_u: - case SIMD_f32x4_convert_i32x4_s: - case SIMD_f32x4_convert_i32x4_u: + { POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); break; + } - case SIMD_v128_bitselect: - POP_V128(); + case SIMD_i16x8_q15mulr_sat_s: + { POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); break; + } - case SIMD_i8x16_any_true: - case SIMD_i8x16_all_true: - case SIMD_i8x16_bitmask: - case SIMD_i16x8_any_true: case SIMD_i16x8_all_true: case SIMD_i16x8_bitmask: - case SIMD_i32x4_any_true: - case SIMD_i32x4_all_true: - case SIMD_i32x4_bitmask: + { POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32); break; + } + + case SIMD_i16x8_narrow_i32x4_s: + case SIMD_i16x8_narrow_i32x4_u: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i16x8_extend_low_i8x16_s: + case SIMD_i16x8_extend_high_i8x16_s: + case SIMD_i16x8_extend_low_i8x16_u: + case SIMD_i16x8_extend_high_i8x16_u: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } - case SIMD_i8x16_shl: - case SIMD_i8x16_shr_s: - case SIMD_i8x16_shr_u: case SIMD_i16x8_shl: case SIMD_i16x8_shr_s: case SIMD_i16x8_shr_u: - case SIMD_i32x4_shl: - case SIMD_i32x4_shr_s: - case SIMD_i32x4_shr_u: - case SIMD_i64x2_shl: - case SIMD_i64x2_shr_s: - case SIMD_i64x2_shr_u: + { POP_I32(); POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); break; + } - case SIMD_i8x16_narrow_i16x8_s: - case SIMD_i8x16_narrow_i16x8_u: - case SIMD_i16x8_narrow_i32x4_s: - case SIMD_i16x8_narrow_i32x4_u: - case SIMD_v128_and: - case SIMD_v128_andnot: - case SIMD_v128_or: - case SIMD_v128_xor: - case SIMD_i8x16_add: - case SIMD_i8x16_add_saturate_s: - case SIMD_i8x16_add_saturate_u: - case SIMD_i8x16_sub: - case SIMD_i8x16_sub_saturate_s: - case SIMD_i8x16_sub_saturate_u: - case SIMD_i8x16_min_s: - case SIMD_i8x16_min_u: - case SIMD_i8x16_max_s: - case SIMD_i8x16_max_u: - case SIMD_i8x16_avgr_u: case SIMD_i16x8_add: - case SIMD_i16x8_add_saturate_s: - case SIMD_i16x8_add_saturate_u: + case SIMD_i16x8_add_sat_s: + case SIMD_i16x8_add_sat_u: case SIMD_i16x8_sub: - case SIMD_i16x8_sub_saturate_s: - case SIMD_i16x8_sub_saturate_u: + case SIMD_i16x8_sub_sat_s: + case SIMD_i16x8_sub_sat_u: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_f64x2_nearest: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + case SIMD_i16x8_mul: case SIMD_i16x8_min_s: case SIMD_i16x8_min_u: case SIMD_i16x8_max_s: case SIMD_i16x8_max_u: case SIMD_i16x8_avgr_u: + case SIMD_i16x8_extmul_low_i8x16_s: + case SIMD_i16x8_extmul_high_i8x16_s: + case SIMD_i16x8_extmul_low_i8x16_u: + case SIMD_i16x8_extmul_high_i8x16_u: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + /* i32x4 operation */ + case SIMD_i32x4_abs: + case SIMD_i32x4_neg: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i32x4_all_true: + case SIMD_i32x4_bitmask: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32); + break; + } + + case SIMD_i32x4_narrow_i64x2_s: + case SIMD_i32x4_narrow_i64x2_u: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i32x4_extend_low_i16x8_s: + case SIMD_i32x4_extend_high_i16x8_s: + case SIMD_i32x4_extend_low_i16x8_u: + case SIMD_i32x4_extend_high_i16x8_u: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i32x4_shl: + case SIMD_i32x4_shr_s: + case SIMD_i32x4_shr_u: + { + POP_I32(); + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + case SIMD_i32x4_add: case SIMD_i32x4_sub: case SIMD_i32x4_mul: @@ -8379,31 +8718,137 @@ wasm_loader_prepare_bytecode(WASMModule *module, case SIMD_i32x4_min_u: case SIMD_i32x4_max_s: case SIMD_i32x4_max_u: + case SIMD_i32x4_dot_i16x8_s: + case SIMD_i32x4_avgr_u: + case SIMD_i32x4_extmul_low_i16x8_s: + case SIMD_i32x4_extmul_high_i16x8_s: + case SIMD_i32x4_extmul_low_i16x8_u: + case SIMD_i32x4_extmul_high_i16x8_u: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + /* i64x2 operation */ + case SIMD_i64x2_abs: + case SIMD_i64x2_neg: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i64x2_all_true: + case SIMD_i64x2_bitmask: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_I32); + break; + } + + case SIMD_i64x2_extend_low_i32x4_s: + case SIMD_i64x2_extend_high_i32x4_s: + case SIMD_i64x2_extend_low_i32x4_u: + case SIMD_i64x2_extend_high_i32x4_u: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + case SIMD_i64x2_shl: + case SIMD_i64x2_shr_s: + case SIMD_i64x2_shr_u: + { + POP_I32(); + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + case SIMD_i64x2_add: case SIMD_i64x2_sub: case SIMD_i64x2_mul: + case SIMD_i64x2_eq: + case SIMD_i64x2_ne: + case SIMD_i64x2_lt_s: + case SIMD_i64x2_gt_s: + case SIMD_i64x2_le_s: + case SIMD_i64x2_ge_s: + case SIMD_i64x2_extmul_low_i32x4_s: + case SIMD_i64x2_extmul_high_i32x4_s: + case SIMD_i64x2_extmul_low_i32x4_u: + case SIMD_i64x2_extmul_high_i32x4_u: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + /* f32x4 operation */ + case SIMD_f32x4_abs: + case SIMD_f32x4_neg: + case SIMD_f32x4_round: + case SIMD_f32x4_sqrt: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + case SIMD_f32x4_add: case SIMD_f32x4_sub: case SIMD_f32x4_mul: case SIMD_f32x4_div: case SIMD_f32x4_min: case SIMD_f32x4_max: + case SIMD_f32x4_pmin: + case SIMD_f32x4_pmax: + { + POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + + /* f64x2 operation */ + case SIMD_f64x2_abs: + case SIMD_f64x2_neg: + case SIMD_f64x2_round: + case SIMD_f64x2_sqrt: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } + case SIMD_f64x2_add: case SIMD_f64x2_sub: case SIMD_f64x2_mul: case SIMD_f64x2_div: case SIMD_f64x2_min: case SIMD_f64x2_max: + case SIMD_f64x2_pmin: + case SIMD_f64x2_pmax: + { POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); break; + } + + case SIMD_i32x4_trunc_sat_f32x4_s: + case SIMD_i32x4_trunc_sat_f32x4_u: + case SIMD_f32x4_convert_i32x4_s: + case SIMD_f32x4_convert_i32x4_u: + case SIMD_i32x4_trunc_sat_f64x2_s_zero: + case SIMD_i32x4_trunc_sat_f64x2_u_zero: + case SIMD_f64x2_convert_low_i32x4_s: + case SIMD_f64x2_convert_low_i32x4_u: + { + POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); + break; + } default: + { if (error_buf != NULL) { snprintf(error_buf, error_buf_size, - "WASM module load failed: " - "invalid opcode 0xfd %02x.", opcode); + "WASM module load failed: " + "invalid opcode 0xfd %02x.", + opcode); } goto fail; + } } break; } @@ -8419,10 +8864,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, #endif if (opcode != WASM_OP_ATOMIC_FENCE) { CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ + read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, mem_offset); /* offset */ - if (!check_memory_align_equal(opcode, align, - error_buf, + if (!check_memory_align_equal(opcode, align, error_buf, error_buf_size)) { goto fail; } @@ -8545,8 +8989,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, break; default: set_error_buf_v(error_buf, error_buf_size, - "%s %02x %02x", - "unsupported opcode", 0xfe, opcode); + "%s %02x %02x", "unsupported opcode", + 0xfe, opcode); goto fail; } break; @@ -8555,10 +8999,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, default: #if WASM_ENABLE_REF_TYPES != 0 -unsupported_opcode: + unsupported_opcode: #endif - set_error_buf_v(error_buf, error_buf_size, - "%s %02x", + set_error_buf_v(error_buf, error_buf_size, "%s %02x", "unsupported opcode", opcode); goto fail; } @@ -8579,31 +9022,31 @@ wasm_loader_prepare_bytecode(WASMModule *module, goto re_scan; func->const_cell_num = loader_ctx->const_cell_num; - if (func->const_cell_num > 0 - && !(func->consts = func_const = - loader_malloc(func->const_cell_num * 4, - error_buf, error_buf_size))) { - goto fail; - } - func_const_end = func->consts + func->const_cell_num * 4; - /* reverse the const buf */ - for (int i = loader_ctx->num_const - 1; i >= 0; i--) { - Const *c = (Const*)(loader_ctx->const_buf + i * sizeof(Const)); - if (c->value_type == VALUE_TYPE_F64 - || c->value_type == VALUE_TYPE_I64) { - bh_memcpy_s(func_const, (uint32)(func_const_end - func_const), - &(c->value.f64), (uint32)sizeof(int64)); - func_const += sizeof(int64); - } - else { - bh_memcpy_s(func_const, (uint32)(func_const_end - func_const), - &(c->value.f32), (uint32)sizeof(int32)); - func_const += sizeof(int32); + if (func->const_cell_num > 0) { + if (!(func->consts = func_const = loader_malloc( + func->const_cell_num * 4, error_buf, error_buf_size))) + goto fail; + + func_const_end = func->consts + func->const_cell_num * 4; + /* reverse the const buf */ + for (int i = loader_ctx->num_const - 1; i >= 0; i--) { + Const *c = (Const *)(loader_ctx->const_buf + i * sizeof(Const)); + if (c->value_type == VALUE_TYPE_F64 + || c->value_type == VALUE_TYPE_I64) { + bh_memcpy_s(func_const, (uint32)(func_const_end - func_const), + &(c->value.f64), (uint32)sizeof(int64)); + func_const += sizeof(int64); + } + else { + bh_memcpy_s(func_const, (uint32)(func_const_end - func_const), + &(c->value.f32), (uint32)sizeof(int32)); + func_const += sizeof(int32); + } } } - func->max_stack_cell_num = loader_ctx->preserved_local_offset - - loader_ctx->start_dynamic_offset + 1; + func->max_stack_cell_num = loader_ctx->preserved_local_offset + - loader_ctx->start_dynamic_offset + 1; #else func->max_stack_cell_num = loader_ctx->max_stack_cell_num; #endif @@ -8639,4 +9082,3 @@ wasm_get_ref_types_flag() return ref_types_flag; } #endif - diff --git a/core/iwasm/interpreter/wasm_loader.h b/core/iwasm/interpreter/wasm_loader.h index 13daeaf656..403df27f87 100644 --- a/core/iwasm/interpreter/wasm_loader.h +++ b/core/iwasm/interpreter/wasm_loader.h @@ -23,8 +23,9 @@ extern "C" { * * @return return module loaded, NULL if failed */ -WASMModule* -wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size); +WASMModule * +wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, + uint32 error_buf_size); /** * Load a WASM module from a specified WASM section list. @@ -35,9 +36,9 @@ wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_bu * * @return return WASM module loaded, NULL if failed */ -WASMModule* -wasm_loader_load_from_sections(WASMSection *section_list, - char *error_buf, uint32 error_buf_size); +WASMModule * +wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf, + uint32 error_buf_size); /** * Unload a WASM module. @@ -62,12 +63,11 @@ wasm_loader_unload(WASMModule *module); * * @return true if success, false otherwise */ + bool -wasm_loader_find_block_addr(BlockAddr *block_addr_cache, - const uint8 *start_addr, - const uint8 *code_end_addr, - uint8 block_type, - uint8 **p_else_addr, +wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, + const uint8 *start_addr, const uint8 *code_end_addr, + uint8 block_type, uint8 **p_else_addr, uint8 **p_end_addr); #if WASM_ENABLE_REF_TYPES != 0 diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index 9340682027..f0a75a762a 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -14,24 +14,26 @@ /* Read a value of given type from the address pointed to by the given pointer and increase the pointer to the position just after the value being read. */ -#define TEMPLATE_READ_VALUE(Type, p) \ +#define TEMPLATE_READ_VALUE(Type, p) \ (p += sizeof(Type), *(Type *)(p - sizeof(Type))) static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) { if (error_buf != NULL) - snprintf(error_buf, error_buf_size, - "WASM module load failed: %s", string); + snprintf(error_buf, error_buf_size, "WASM module load failed: %s", + string); } -#define CHECK_BUF(buf, buf_end, length) do { \ - bh_assert(buf + length <= buf_end); \ - } while (0) +#define CHECK_BUF(buf, buf_end, length) \ + do { \ + bh_assert(buf + length <= buf_end); \ + } while (0) -#define CHECK_BUF1(buf, buf_end, length) do { \ - bh_assert(buf + length <= buf_end); \ - } while (0) +#define CHECK_BUF1(buf, buf_end, length) \ + do { \ + bh_assert(buf + length <= buf_end); \ + } while (0) #define skip_leb(p) while (*p++ & 0x80) #define skip_leb_int64(p, p_end) skip_leb(p) @@ -60,9 +62,8 @@ is_64bit_type(uint8 type) } static void -read_leb(uint8 **p_buf, const uint8 *buf_end, - uint32 maxbits, bool sign, uint64 *p_result, - char* error_buf, uint32 error_buf_size) +read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, + uint64 *p_result, char *error_buf, uint32 error_buf_size) { const uint8 *buf = *p_buf; uint64 result = 0; @@ -89,9 +90,9 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, } else if (sign && maxbits == 32) { if (shift < maxbits) { - /* Sign extend */ - result = (((int32)result) << (maxbits - shift)) - >> (maxbits - shift); + /* Sign extend, second highest bit is the sign bit */ + if ((uint8)byte & 0x40) + result |= (~((uint64)0)) << shift; } else { /* The top bits should be a sign-extension of the sign bit */ @@ -105,9 +106,9 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, } else if (sign && maxbits == 64) { if (shift < maxbits) { - /* Sign extend */ - result = (((int64)result) << (maxbits - shift)) - >> (maxbits - shift); + /* Sign extend, second highest bit is the sign bit */ + if ((uint8)byte & 0x40) + result |= (~((uint64)0)) << shift; } else { /* The top bits should be a sign-extension of the sign bit */ @@ -125,40 +126,41 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, *p_result = result; } -#define read_uint8(p) TEMPLATE_READ_VALUE(uint8, p) +#define read_uint8(p) TEMPLATE_READ_VALUE(uint8, p) #define read_uint32(p) TEMPLATE_READ_VALUE(uint32, p) -#define read_bool(p) TEMPLATE_READ_VALUE(bool, p) - -#define read_leb_int64(p, p_end, res) do { \ - uint64 res64; \ - read_leb((uint8**)&p, p_end, 64, true, &res64, \ - error_buf, error_buf_size); \ - res = (int64)res64; \ -} while (0) - -#define read_leb_uint32(p, p_end, res) do { \ - uint64 res64; \ - read_leb((uint8**)&p, p_end, 32, false, &res64, \ - error_buf, error_buf_size); \ - res = (uint32)res64; \ -} while (0) - -#define read_leb_int32(p, p_end, res) do { \ - uint64 res64; \ - read_leb((uint8**)&p, p_end, 32, true, &res64, \ - error_buf, error_buf_size); \ - res = (int32)res64; \ -} while (0) +#define read_bool(p) TEMPLATE_READ_VALUE(bool, p) + +#define read_leb_int64(p, p_end, res) \ + do { \ + uint64 res64; \ + read_leb((uint8 **)&p, p_end, 64, true, &res64, error_buf, \ + error_buf_size); \ + res = (int64)res64; \ + } while (0) + +#define read_leb_uint32(p, p_end, res) \ + do { \ + uint64 res64; \ + read_leb((uint8 **)&p, p_end, 32, false, &res64, error_buf, \ + error_buf_size); \ + res = (uint32)res64; \ + } while (0) + +#define read_leb_int32(p, p_end, res) \ + do { \ + uint64 res64; \ + read_leb((uint8 **)&p, p_end, 32, true, &res64, error_buf, \ + error_buf_size); \ + res = (int32)res64; \ + } while (0) static void * loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) { void *mem; - if (size >= UINT32_MAX - || !(mem = wasm_runtime_malloc((uint32)size))) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); return NULL; } @@ -168,7 +170,7 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size) static char * const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, - char *error_buf, uint32 error_buf_size) + char *error_buf, uint32 error_buf_size) { StringNode *node, *node_next; @@ -176,8 +178,7 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, node = module->const_str_list; while (node) { node_next = node->next; - if (strlen(node->str) == len - && !memcmp(node->str, str, len)) + if (strlen(node->str) == len && !memcmp(node->str, str, len)) break; node = node_next; } @@ -187,12 +188,12 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, return node->str; } - if (!(node = loader_malloc(sizeof(StringNode) + len + 1, - error_buf, error_buf_size))) { + if (!(node = loader_malloc(sizeof(StringNode) + len + 1, error_buf, + error_buf_size))) { return NULL; } - node->str = ((char*)node) + sizeof(StringNode); + node->str = ((char *)node) + sizeof(StringNode); bh_memcpy_s(node->str, len + 1, str, len); node->str[len] = '\0'; @@ -212,8 +213,8 @@ const_str_list_insert(const uint8 *str, uint32 len, WASMModule *module, static bool load_init_expr(const uint8 **p_buf, const uint8 *buf_end, - InitializerExpression *init_expr, uint8 type, - char *error_buf, uint32 error_buf_size) + InitializerExpression *init_expr, uint8 type, char *error_buf, + uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint8 flag, end_byte, *p_float; @@ -238,7 +239,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, case INIT_EXPR_TYPE_F32_CONST: bh_assert(type == VALUE_TYPE_F32); CHECK_BUF(p, p_end, 4); - p_float = (uint8*)&init_expr->u.f32; + p_float = (uint8 *)&init_expr->u.f32; for (i = 0; i < sizeof(float32); i++) *p_float++ = *p++; break; @@ -246,7 +247,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, case INIT_EXPR_TYPE_F64_CONST: bh_assert(type == VALUE_TYPE_F64); CHECK_BUF(p, p_end, 8); - p_float = (uint8*)&init_expr->u.f64; + p_float = (uint8 *)&init_expr->u.f64; for (i = 0; i < sizeof(float64); i++) *p_float++ = *p++; break; @@ -311,9 +312,9 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (type_count) { module->type_count = type_count; - total_size = sizeof(WASMType*) * (uint64)type_count; - if (!(module->types = loader_malloc - (total_size, error_buf, error_buf_size))) { + total_size = sizeof(WASMType *) * (uint64)type_count; + if (!(module->types = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -334,10 +335,10 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, bh_assert(param_count <= UINT16_MAX && result_count <= UINT16_MAX); - total_size = offsetof(WASMType, types) + - sizeof(uint8) * (uint64)(param_count + result_count); + total_size = offsetof(WASMType, types) + + sizeof(uint8) * (uint64)(param_count + result_count); if (!(type = module->types[i] = - loader_malloc(total_size, error_buf, error_buf_size))) { + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -355,9 +356,10 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } param_cell_num = wasm_get_cell_num(type->types, param_count); - ret_cell_num = wasm_get_cell_num(type->types + param_count, - result_count); - bh_assert(param_cell_num <= UINT16_MAX && ret_cell_num <= UINT16_MAX); + ret_cell_num = + wasm_get_cell_num(type->types + param_count, result_count); + bh_assert(param_cell_num <= UINT16_MAX + && ret_cell_num <= UINT16_MAX); type->param_cell_num = (uint16)param_cell_num; type->ret_cell_num = (uint16)ret_cell_num; } @@ -373,7 +375,7 @@ static void adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size) { uint32 default_max_size = - init_size * 2 > TABLE_MAX_SIZE ? init_size * 2 : TABLE_MAX_SIZE; + init_size * 2 > TABLE_MAX_SIZE ? init_size * 2 : TABLE_MAX_SIZE; if (max_size_flag) { /* module defines the table limitation */ @@ -381,7 +383,7 @@ adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size) if (init_size < *max_size) { *max_size = - *max_size < default_max_size ? *max_size : default_max_size; + *max_size < default_max_size ? *max_size : default_max_size; } } else { @@ -393,10 +395,9 @@ adjust_table_max_size(uint32 init_size, uint32 max_size_flag, uint32 *max_size) static bool load_function_import(const uint8 **p_buf, const uint8 *buf_end, const WASMModule *parent_module, - const char *sub_module_name, - const char *function_name, - WASMFunctionImport *function, - char *error_buf, uint32 error_buf_size) + const char *sub_module_name, const char *function_name, + WASMFunctionImport *function, char *error_buf, + uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint32 declare_type_index = 0; @@ -415,12 +416,9 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end, declare_func_type = parent_module->types[declare_type_index]; /* check built-in modules */ - linked_func = wasm_native_resolve_symbol(sub_module_name, - function_name, - declare_func_type, - &linked_signature, - &linked_attachment, - &linked_call_conv_raw); + linked_func = wasm_native_resolve_symbol( + sub_module_name, function_name, declare_func_type, &linked_signature, + &linked_attachment, &linked_call_conv_raw); function->module_name = (char *)sub_module_name; function->field_name = (char *)function_name; @@ -434,10 +432,8 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end, static bool load_table_import(const uint8 **p_buf, const uint8 *buf_end, - WASMModule *parent_module, - const char *sub_module_name, - const char *table_name, - WASMTableImport *table, + WASMModule *parent_module, const char *sub_module_name, + const char *table_name, WASMTableImport *table, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; @@ -449,8 +445,8 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, declare_elem_type = read_uint8(p); bh_assert(VALUE_TYPE_FUNCREF == declare_elem_type #if WASM_ENABLE_REF_TYPES != 0 - || (wasm_get_ref_types_flag() && - VALUE_TYPE_EXTERNREF == declare_elem_type) + || (wasm_get_ref_types_flag() + && VALUE_TYPE_EXTERNREF == declare_elem_type) #endif ); @@ -465,8 +461,8 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, &declare_max_size); *p_buf = p; - bh_assert(!((declare_max_size_flag & 1) - && declare_init_size > declare_max_size)); + bh_assert( + !((declare_max_size_flag & 1) && declare_init_size > declare_max_size)); /* now we believe all declaration are ok */ table->elem_type = declare_elem_type; @@ -481,10 +477,8 @@ wasm_runtime_memory_pool_size(); static bool load_memory_import(const uint8 **p_buf, const uint8 *buf_end, - WASMModule *parent_module, - const char *sub_module_name, - const char *memory_name, - WASMMemoryImport *memory, + WASMModule *parent_module, const char *sub_module_name, + const char *memory_name, WASMMemoryImport *memory, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; @@ -528,10 +522,9 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, static bool load_global_import(const uint8 **p_buf, const uint8 *buf_end, - const WASMModule *parent_module, - char *sub_module_name, char *global_name, - WASMGlobalImport *global, - char *error_buf, uint32 error_buf_size) + const WASMModule *parent_module, char *sub_module_name, + char *global_name, WASMGlobalImport *global, char *error_buf, + uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint8 declare_type = 0; @@ -550,8 +543,8 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, #if WASM_ENABLE_LIBC_BUILTIN != 0 /* check built-in modules */ - ret = wasm_native_lookup_libc_builtin_global(sub_module_name, - global_name, global); + ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name, + global); if (ret) { bh_assert(global->type == declare_type && global->is_mutable != declare_mutable); @@ -578,8 +571,8 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMTable *table, table->elem_type = read_uint8(p); bh_assert((VALUE_TYPE_FUNCREF == table->elem_type) #if WASM_ENABLE_REF_TYPES != 0 - || (wasm_get_ref_types_flag() && - VALUE_TYPE_EXTERNREF == table->elem_type) + || (wasm_get_ref_types_flag() + && VALUE_TYPE_EXTERNREF == table->elem_type) #endif ); @@ -659,10 +652,11 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, uint8 u8, kind; /* insert builtin module names into const str list */ - if (!const_str_list_insert((uint8*)"env", 3, module, error_buf, error_buf_size) - || !const_str_list_insert((uint8*)"wasi_unstable", 13, module, + if (!const_str_list_insert((uint8 *)"env", 3, module, error_buf, + error_buf_size) + || !const_str_list_insert((uint8 *)"wasi_unstable", 13, module, error_buf, error_buf_size) - || !const_str_list_insert((uint8*)"wasi_snapshot_preview1", 22, module, + || !const_str_list_insert((uint8 *)"wasi_snapshot_preview1", 22, module, error_buf, error_buf_size)) { return false; } @@ -672,8 +666,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (import_count) { module->import_count = import_count; total_size = sizeof(WASMImport) * (uint64)import_count; - if (!(module->imports = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->imports = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -712,9 +706,9 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module->import_table_count++; bh_assert( #if WASM_ENABLE_REF_TYPES != 0 - wasm_get_ref_types_flag() || + wasm_get_ref_types_flag() || #endif - module->import_table_count <= 1); + module->import_table_count <= 1); break; @@ -746,11 +740,12 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module->imports + module->import_function_count; if (module->import_memory_count) import_memories = module->import_memories = - module->imports + module->import_function_count + module->import_table_count; + module->imports + module->import_function_count + + module->import_table_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->imports + module->import_function_count + + module->import_table_count + module->import_memory_count; p = p_old; @@ -762,7 +757,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, name_len); CHECK_BUF(p, p_end, name_len); if (!(sub_module_name = const_str_list_insert( - p, name_len, module, error_buf, error_buf_size))) { + p, name_len, module, error_buf, error_buf_size))) { return false; } p += name_len; @@ -771,7 +766,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, name_len); CHECK_BUF(p, p_end, name_len); if (!(field_name = const_str_list_insert( - p, name_len, module, error_buf, error_buf_size))) { + p, name_len, module, error_buf, error_buf_size))) { return false; } p += name_len; @@ -780,16 +775,15 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, /* 0x00/0x01/0x02/0x03 */ kind = read_uint8(p); - LOG_DEBUG("import #%d: (%s, %s), kind: %d", - i, sub_module_name, field_name, kind); + LOG_DEBUG("import #%d: (%s, %s), kind: %d", i, sub_module_name, + field_name, kind); switch (kind) { case IMPORT_KIND_FUNC: /* import function */ bh_assert(import_functions); import = import_functions++; - if (!load_function_import(&p, p_end, module, - sub_module_name, field_name, - &import->u.function, - error_buf, error_buf_size)) { + if (!load_function_import( + &p, p_end, module, sub_module_name, field_name, + &import->u.function, error_buf, error_buf_size)) { return false; } break; @@ -797,9 +791,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, case IMPORT_KIND_TABLE: /* import table */ bh_assert(import_tables); import = import_tables++; - if (!load_table_import(&p, p_end, module, - sub_module_name, field_name, - &import->u.table, + if (!load_table_import(&p, p_end, module, sub_module_name, + field_name, &import->u.table, error_buf, error_buf_size)) { LOG_DEBUG("can not import such a table (%s,%s)", sub_module_name, field_name); @@ -810,9 +803,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, case IMPORT_KIND_MEMORY: /* import memory */ bh_assert(import_memories); import = import_memories++; - if (!load_memory_import(&p, p_end, module, - sub_module_name, field_name, - &import->u.memory, + if (!load_memory_import(&p, p_end, module, sub_module_name, + field_name, &import->u.memory, error_buf, error_buf_size)) { return false; } @@ -821,9 +813,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, case IMPORT_KIND_GLOBAL: /* import global */ bh_assert(import_globals); import = import_globals++; - if (!load_global_import(&p, p_end, module, - sub_module_name, field_name, - &import->u.global, + if (!load_global_import(&p, p_end, module, sub_module_name, + field_name, &import->u.global, error_buf, error_buf_size)) { return false; } @@ -844,7 +835,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, import = module->import_functions; for (i = 0; i < module->import_function_count; i++, import++) { if (!strcmp(import->u.names.module_name, "wasi_unstable") - || !strcmp(import->u.names.module_name, "wasi_snapshot_preview1")) { + || !strcmp(import->u.names.module_name, + "wasi_snapshot_preview1")) { module->is_wasi_module = true; break; } @@ -862,8 +854,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } static bool -init_function_local_offsets(WASMFunction *func, - char *error_buf, uint32 error_buf_size) +init_function_local_offsets(WASMFunction *func, char *error_buf, + uint32 error_buf_size) { WASMType *param_type = func->func_type; uint32 param_count = param_type->param_count; @@ -875,7 +867,7 @@ init_function_local_offsets(WASMFunction *func, if (total_size > 0 && !(func->local_offsets = - loader_malloc(total_size, error_buf, error_buf_size))) { + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -896,8 +888,8 @@ init_function_local_offsets(WASMFunction *func, static bool load_function_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) + WASMModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; const uint8 *p_code = buf_code, *p_code_end, *p_code_save; @@ -917,9 +909,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, if (func_count) { module->function_count = func_count; - total_size = sizeof(WASMFunction*) * (uint64)func_count; + total_size = sizeof(WASMFunction *) * (uint64)func_count; if (!(module->functions = - loader_malloc(total_size, error_buf, error_buf_size))) { + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -929,8 +921,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, bh_assert(type_index < module->type_count); read_leb_uint32(p_code, buf_code_end, code_size); - bh_assert(code_size > 0 - && p_code + code_size <= buf_code_end); + bh_assert(code_size > 0 && p_code + code_size <= buf_code_end); /* Resolve local set count */ p_code_end = p_code + code_size; @@ -954,7 +945,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, total_size = sizeof(WASMFunction) + (uint64)local_count; if (!(func = module->functions[i] = - loader_malloc(total_size, error_buf, error_buf_size))) { + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -962,7 +953,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, func->func_type = module->types[type_index]; func->local_count = local_count; if (local_count > 0) - func->local_types = (uint8*)func + sizeof(WASMFunction); + func->local_types = (uint8 *)func + sizeof(WASMFunction); func->code_size = code_size; /* * we shall make a copy of code body [p_code, p_code + code_size] @@ -974,15 +965,16 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, * memcpy(code_body_cp, p_code, code_size); * func->code = code_body_cp; */ - func->code = (uint8*)p_code; + func->code = (uint8 *)p_code; /* Load each local type */ p_code = p_code_save; local_type_index = 0; for (j = 0; j < local_set_count; j++) { read_leb_uint32(p_code, buf_code_end, sub_local_count); - bh_assert(!(local_type_index + sub_local_count <= local_type_index - || local_type_index + sub_local_count > local_count)); + bh_assert(sub_local_count + && local_type_index <= UINT32_MAX - sub_local_count + && local_type_index + sub_local_count <= local_count); CHECK_BUF(p_code, buf_code_end, 1); /* 0x7F/0x7E/0x7D/0x7C */ @@ -1018,10 +1010,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, } static bool -check_function_index(const WASMModule *module, - uint32 function_index, - char *error_buf, - uint32 error_buf_size) +check_function_index(const WASMModule *module, uint32 function_index, + char *error_buf, uint32 error_buf_size) { return (function_index < module->import_function_count + module->function_count); @@ -1039,15 +1029,15 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, table_count); bh_assert( #if WASM_ENABLE_REF_TYPES != 0 - wasm_get_ref_types_flag() || + wasm_get_ref_types_flag() || #endif - module->import_table_count + table_count <= 1); + module->import_table_count + table_count <= 1); if (table_count) { module->table_count = table_count; total_size = sizeof(WASMTable) * (uint64)table_count; - if (!(module->tables = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->tables = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -1078,8 +1068,8 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (memory_count) { module->memory_count = memory_count; total_size = sizeof(WASMMemory) * (uint64)memory_count; - if (!(module->memories = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->memories = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -1110,14 +1100,14 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (global_count) { module->global_count = global_count; total_size = sizeof(WASMGlobal) * (uint64)global_count; - if (!(module->globals = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->globals = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } global = module->globals; - for(i = 0; i < global_count; i++, global++) { + for (i = 0; i < global_count; i++, global++) { CHECK_BUF(p, p_end, 2); global->type = read_uint8(p); mutable = read_uint8(p); @@ -1125,8 +1115,8 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, global->is_mutable = mutable ? true : false; /* initialize expression */ - if (!load_init_expr(&p, p_end, &(global->init_expr), - global->type, error_buf, error_buf_size)) + if (!load_init_expr(&p, p_end, &(global->init_expr), global->type, + error_buf, error_buf_size)) return false; if (INIT_EXPR_TYPE_GET_GLOBAL == global->init_expr.init_expr_type) { @@ -1144,7 +1134,7 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, == global->init_expr.init_expr_type) { bh_assert(global->init_expr.u.ref_index < module->import_function_count - + module->function_count); + + module->function_count); } } } @@ -1170,13 +1160,13 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (export_count) { module->export_count = export_count; total_size = sizeof(WASMExport) * (uint64)export_count; - if (!(module->exports = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->exports = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } export = module->exports; - for (i = 0; i < export_count; i++, export++) { + for (i = 0; i < export_count; i++, export ++) { read_leb_uint32(p, p_end, str_len); CHECK_BUF(p, p_end, str_len); @@ -1186,8 +1176,8 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, && memcmp(name, p, str_len) == 0)); } - if (!(export->name = const_str_list_insert(p, str_len, module, - error_buf, error_buf_size))) { + if (!(export->name = const_str_list_insert( + p, str_len, module, error_buf, error_buf_size))) { return false; } @@ -1197,26 +1187,26 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, index); export->index = index; - switch(export->kind) { + switch (export->kind) { /* function index */ case EXPORT_KIND_FUNC: bh_assert(index < module->function_count - + module->import_function_count); + + module->import_function_count); break; /* table index */ case EXPORT_KIND_TABLE: bh_assert(index < module->table_count - + module->import_table_count); + + module->import_table_count); break; /* memory index */ case EXPORT_KIND_MEMORY: bh_assert(index < module->memory_count - + module->import_memory_count); + + module->import_memory_count); break; /* global index */ case EXPORT_KIND_GLOBAL: bh_assert(index < module->global_count - + module->import_global_count); + + module->import_global_count); break; default: bh_assert(0); @@ -1232,14 +1222,14 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } static bool -check_table_index(const WASMModule *module, uint32 table_index, - char *error_buf, uint32 error_buf_size) +check_table_index(const WASMModule *module, uint32 table_index, char *error_buf, + uint32 error_buf_size) { if ( #if WASM_ENABLE_REF_TYPES != 0 - !wasm_get_ref_types_flag() && + !wasm_get_ref_types_flag() && #endif - table_index != 0) { + table_index != 0) { return false; } @@ -1251,9 +1241,8 @@ check_table_index(const WASMModule *module, uint32 table_index, #if WASM_ENABLE_REF_TYPES != 0 static bool -load_table_index(const uint8 **p_buf, const uint8 *buf_end, - WASMModule *module, uint32 *p_table_index, - char *error_buf, uint32 error_buf_size) +load_table_index(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module, + uint32 *p_table_index, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint32 table_index; @@ -1269,9 +1258,8 @@ load_table_index(const uint8 **p_buf, const uint8 *buf_end, } static bool -load_elem_type(const uint8 **p_buf, const uint8 *buf_end, - uint32 *p_elem_type, bool elemkind_zero, - char *error_buf, uint32 error_buf_size) +load_elem_type(const uint8 **p_buf, const uint8 *buf_end, uint32 *p_elem_type, + bool elemkind_zero, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint8 elem_type; @@ -1299,8 +1287,7 @@ load_elem_type(const uint8 **p_buf, const uint8 *buf_end, static bool load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module, WASMTableSeg *table_segment, - bool use_init_expr, - char *error_buf, uint32 error_buf_size) + bool use_init_expr, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; uint32 function_count, function_index = 0, i; @@ -1310,8 +1297,8 @@ load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end, table_segment->function_count = function_count; total_size = sizeof(uint32) * (uint64)function_count; if (total_size > 0 - && !(table_segment->func_indexes = (uint32 *) - loader_malloc(total_size, error_buf, error_buf_size))) { + && !(table_segment->func_indexes = (uint32 *)loader_malloc( + total_size, error_buf, error_buf_size))) { return false; } @@ -1353,8 +1340,9 @@ load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end, } static bool -load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, - char *error_buf, uint32 error_buf_size) +load_table_segment_section(const uint8 *buf, const uint8 *buf_end, + WASMModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; uint32 table_segment_count, i, table_index, function_count; @@ -1366,8 +1354,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m if (table_segment_count) { module->table_seg_count = table_segment_count; total_size = sizeof(WASMTableSeg) * (uint64)table_segment_count; - if (!(module->table_segments = loader_malloc - (total_size, error_buf, error_buf_size))) { + if (!(module->table_segments = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -1393,14 +1381,14 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m return false; if (!load_init_expr( - &p, p_end, &table_segment->base_offset, - VALUE_TYPE_I32, error_buf, error_buf_size)) + &p, p_end, &table_segment->base_offset, + VALUE_TYPE_I32, error_buf, error_buf_size)) return false; if (!load_func_index_vec( - &p, p_end, module, table_segment, - table_segment->mode == 0 ? false : true, - error_buf, error_buf_size)) + &p, p_end, module, table_segment, + table_segment->mode == 0 ? false : true, + error_buf, error_buf_size)) return false; break; /* elemkind + passive/declarative */ @@ -1423,18 +1411,18 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m error_buf, error_buf_size)) return false; if (!load_init_expr( - &p, p_end, &table_segment->base_offset, - VALUE_TYPE_I32, error_buf, error_buf_size)) + &p, p_end, &table_segment->base_offset, + VALUE_TYPE_I32, error_buf, error_buf_size)) return false; if (!load_elem_type( - &p, p_end, &table_segment->elem_type, - table_segment->mode == 2 ? true : false, - error_buf, error_buf_size)) + &p, p_end, &table_segment->elem_type, + table_segment->mode == 2 ? true : false, + error_buf, error_buf_size)) return false; if (!load_func_index_vec( - &p, p_end, module, table_segment, - table_segment->mode == 2 ? false : true, - error_buf, error_buf_size)) + &p, p_end, module, table_segment, + table_segment->mode == 2 ? false : true, + error_buf, error_buf_size)) return false; break; case 5: @@ -1444,8 +1432,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m error_buf, error_buf_size)) return false; if (!load_func_index_vec(&p, p_end, module, - table_segment, true, - error_buf, error_buf_size)) + table_segment, true, error_buf, + error_buf_size)) return false; break; default: @@ -1471,7 +1459,7 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m total_size = sizeof(uint32) * (uint64)function_count; if (total_size > 0 && !(table_segment->func_indexes = (uint32 *)loader_malloc( - total_size, error_buf, error_buf_size))) { + total_size, error_buf, error_buf_size))) { return false; } @@ -1491,8 +1479,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m static bool load_data_segment_section(const uint8 *buf, const uint8 *buf_end, - WASMModule *module, - char *error_buf, uint32 error_buf_size) + WASMModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; uint32 data_seg_count, i, mem_index, data_seg_len; @@ -1513,9 +1501,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, if (data_seg_count) { module->data_seg_count = data_seg_count; - total_size = sizeof(WASMDataSeg*) * (uint64)data_seg_count; - if (!(module->data_segments = loader_malloc - (total_size, error_buf, error_buf_size))) { + total_size = sizeof(WASMDataSeg *) * (uint64)data_seg_count; + if (!(module->data_segments = + loader_malloc(total_size, error_buf, error_buf_size))) { return false; } @@ -1535,9 +1523,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, case 0x02: /* read following memory index */ read_leb_uint32(p, p_end, mem_index); -check_mem_index: + check_mem_index: bh_assert(mem_index < module->import_memory_count - + module->memory_count); + + module->memory_count); break; case 0x03: default: @@ -1545,8 +1533,8 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, break; } #else - bh_assert(mem_index < module->import_memory_count - + module->memory_count); + bh_assert(mem_index + < module->import_memory_count + module->memory_count); #endif /* WASM_ENABLE_BULK_MEMORY */ #if WASM_ENABLE_BULK_MEMORY != 0 @@ -1558,8 +1546,8 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, read_leb_uint32(p, p_end, data_seg_len); - if (!(dataseg = module->data_segments[i] = loader_malloc - (sizeof(WASMDataSeg), error_buf, error_buf_size))) { + if (!(dataseg = module->data_segments[i] = loader_malloc( + sizeof(WASMDataSeg), error_buf, error_buf_size))) { return false; } @@ -1568,15 +1556,16 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, if (!is_passive) #endif { - bh_memcpy_s(&dataseg->base_offset, sizeof(InitializerExpression), - &init_expr, sizeof(InitializerExpression)); + bh_memcpy_s(&dataseg->base_offset, + sizeof(InitializerExpression), &init_expr, + sizeof(InitializerExpression)); dataseg->memory_index = mem_index; } dataseg->data_length = data_seg_len; CHECK_BUF(p, p_end, data_seg_len); - dataseg->data = (uint8*)p; + dataseg->data = (uint8 *)p; p += data_seg_len; } } @@ -1588,8 +1577,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, #if WASM_ENABLE_BULK_MEMORY != 0 static bool -load_datacount_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, - char *error_buf, uint32 error_buf_size) +load_datacount_section(const uint8 *buf, const uint8 *buf_end, + WASMModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; uint32 data_seg_count1 = 0; @@ -1604,10 +1594,8 @@ load_datacount_section(const uint8 *buf, const uint8 *buf_end, WASMModule *modul #endif static bool -load_code_section(const uint8 *buf, const uint8 *buf_end, - const uint8 *buf_func, - const uint8 *buf_func_end, - WASMModule *module, +load_code_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_func, + const uint8 *buf_func_end, WASMModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; @@ -1638,14 +1626,14 @@ load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, start_function); - bh_assert(start_function < module->function_count - + module->import_function_count); + bh_assert(start_function + < module->function_count + module->import_function_count); if (start_function < module->import_function_count) type = module->import_functions[start_function].u.function.func_type; else type = module->functions[start_function - module->import_function_count] - ->func_type; + ->func_type; bh_assert(type->param_count == 0 && type->result_count == 0); @@ -1659,8 +1647,7 @@ load_start_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 static bool -handle_name_section(const uint8 *buf, const uint8 *buf_end, - WASMModule *module, +handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, char *error_buf, uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; @@ -1699,9 +1686,9 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end, func_index -= module->import_count; bh_assert(func_index < module->function_count); if (!(module->functions[func_index]->field_name = - const_str_list_insert(p, func_name_len, - module, error_buf, - error_buf_size))) { + const_str_list_insert(p, func_name_len, + module, error_buf, + error_buf_size))) { return false; } } @@ -1709,8 +1696,9 @@ handle_name_section(const uint8 *buf, const uint8 *buf_end, } } break; - case SUB_SECTION_TYPE_MODULE: /* TODO: Parse for module subsection */ - case SUB_SECTION_TYPE_LOCAL: /* TODO: Parse for local subsection */ + case SUB_SECTION_TYPE_MODULE: /* TODO: Parse for module subsection + */ + case SUB_SECTION_TYPE_LOCAL: /* TODO: Parse for local subsection */ default: p = p + subsection_size; break; @@ -1735,8 +1723,7 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint32(p, p_end, name_len); - bh_assert(name_len > 0 - && p + name_len <= p_end); + bh_assert(name_len > 0 && p + name_len <= p_end); #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 if (memcmp(p, "name", 4) == 0) { @@ -1751,9 +1738,8 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, #if WASM_ENABLE_REF_TYPES != 0 static bool -get_table_elem_type(const WASMModule *module, - uint32 table_idx, uint8 *p_elem_type, - char *error_buf, uint32 error_buf_size) +get_table_elem_type(const WASMModule *module, uint32 table_idx, + uint8 *p_elem_type, char *error_buf, uint32 error_buf_size) { if (!check_table_index(module, table_idx, error_buf, error_buf_size)) { return false; @@ -1763,16 +1749,17 @@ get_table_elem_type(const WASMModule *module, if (table_idx < module->import_table_count) *p_elem_type = module->import_tables[table_idx].u.table.elem_type; else - *p_elem_type = module->tables[module->import_table_count - + table_idx].elem_type; + *p_elem_type = + module->tables[module->import_table_count + table_idx] + .elem_type; } return true; } static bool -get_table_seg_elem_type(const WASMModule *module, - uint32 table_seg_idx, uint8 *p_elem_type, - char *error_buf, uint32 error_buf_size) +get_table_seg_elem_type(const WASMModule *module, uint32 table_seg_idx, + uint8 *p_elem_type, char *error_buf, + uint32 error_buf_size) { if (table_seg_idx >= module->table_seg_count) { return false; @@ -1786,10 +1773,8 @@ get_table_seg_elem_type(const WASMModule *module, #endif static bool -wasm_loader_prepare_bytecode(WASMModule *module, - WASMFunction *func, - uint32 cur_func_idx, - char *error_buf, +wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, + uint32 cur_func_idx, char *error_buf, uint32 error_buf_size); #if WASM_ENABLE_FAST_INTERP != 0 && WASM_ENABLE_LABELS_AS_VALUES != 0 @@ -1800,13 +1785,13 @@ static void **handle_table; #endif static bool -load_from_sections(WASMModule *module, WASMSection *sections, - char *error_buf, uint32 error_buf_size) +load_from_sections(WASMModule *module, WASMSection *sections, char *error_buf, + uint32 error_buf_size) { WASMExport *export; WASMSection *section = sections; const uint8 *buf, *buf_end, *buf_code = NULL, *buf_code_end = NULL, - *buf_func = NULL, *buf_func_end = NULL; + *buf_func = NULL, *buf_func_end = NULL; WASMGlobal *aux_data_end_global = NULL, *aux_heap_base_global = NULL; WASMGlobal *aux_stack_top_global = NULL, *global; uint32 aux_data_end = (uint32)-1, aux_heap_base = (uint32)-1; @@ -1836,44 +1821,53 @@ load_from_sections(WASMModule *module, WASMSection *sections, switch (section->section_type) { case SECTION_TYPE_USER: /* unsupported user section, ignore it. */ - if (!load_user_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_user_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_TYPE: - if (!load_type_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_type_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_IMPORT: - if (!load_import_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_import_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_FUNC: if (!load_function_section(buf, buf_end, buf_code, buf_code_end, - module, error_buf, error_buf_size)) + module, error_buf, error_buf_size)) return false; break; case SECTION_TYPE_TABLE: - if (!load_table_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_table_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_MEMORY: - if (!load_memory_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_memory_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_GLOBAL: - if (!load_global_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_global_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_EXPORT: - if (!load_export_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_export_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_START: - if (!load_start_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_start_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_ELEM: - if (!load_table_segment_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_table_segment_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; case SECTION_TYPE_CODE: @@ -1882,18 +1876,19 @@ load_from_sections(WASMModule *module, WASMSection *sections, return false; break; case SECTION_TYPE_DATA: - if (!load_data_segment_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_data_segment_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; #if WASM_ENABLE_BULK_MEMORY != 0 case SECTION_TYPE_DATACOUNT: - if (!load_datacount_section(buf, buf_end, module, error_buf, error_buf_size)) + if (!load_datacount_section(buf, buf_end, module, error_buf, + error_buf_size)) return false; break; #endif default: - set_error_buf(error_buf, error_buf_size, - "invalid section id"); + set_error_buf(error_buf, error_buf_size, "invalid section id"); return false; } @@ -1906,15 +1901,14 @@ load_from_sections(WASMModule *module, WASMSection *sections, /* Resolve auxiliary data/stack/heap info and reset memory info */ export = module->exports; - for (i = 0; i < module->export_count; i++, export++) { + for (i = 0; i < module->export_count; i++, export ++) { if (export->kind == EXPORT_KIND_GLOBAL) { if (!strcmp(export->name, "__heap_base")) { global_index = export->index - module->import_global_count; global = module->globals + global_index; - if (global->type == VALUE_TYPE_I32 - && !global->is_mutable - && global->init_expr.init_expr_type == - INIT_EXPR_TYPE_I32_CONST) { + if (global->type == VALUE_TYPE_I32 && !global->is_mutable + && global->init_expr.init_expr_type + == INIT_EXPR_TYPE_I32_CONST) { aux_heap_base_global = global; aux_heap_base = global->init_expr.u.i32; aux_heap_base_global_index = export->index; @@ -1925,10 +1919,9 @@ load_from_sections(WASMModule *module, WASMSection *sections, else if (!strcmp(export->name, "__data_end")) { global_index = export->index - module->import_global_count; global = module->globals + global_index; - if (global->type == VALUE_TYPE_I32 - && !global->is_mutable - && global->init_expr.init_expr_type == - INIT_EXPR_TYPE_I32_CONST) { + if (global->type == VALUE_TYPE_I32 && !global->is_mutable + && global->init_expr.init_expr_type + == INIT_EXPR_TYPE_I32_CONST) { aux_data_end_global = global; aux_data_end = global->init_expr.u.i32; aux_data_end_global_index = export->index; @@ -1969,17 +1962,18 @@ load_from_sections(WASMModule *module, WASMSection *sections, if (global->is_mutable /* heap_base and data_end is not mutable */ && global->type == VALUE_TYPE_I32 - && global->init_expr.init_expr_type == - INIT_EXPR_TYPE_I32_CONST + && global->init_expr.init_expr_type + == INIT_EXPR_TYPE_I32_CONST && (uint32)global->init_expr.u.i32 <= aux_heap_base) { aux_stack_top_global = global; aux_stack_top = (uint32)global->init_expr.u.i32; module->aux_stack_top_global_index = - module->import_global_count + global_index; + module->import_global_count + global_index; module->aux_stack_bottom = aux_stack_top; - module->aux_stack_size = aux_stack_top > aux_data_end - ? aux_stack_top - aux_data_end - : aux_stack_top; + module->aux_stack_size = + aux_stack_top > aux_data_end + ? aux_stack_top - aux_data_end + : aux_stack_top; LOG_VERBOSE("Found aux stack top global, value: %d, " "global index: %d, stack size: %d", aux_stack_top, global_index, @@ -1997,14 +1991,13 @@ load_from_sections(WASMModule *module, WASMSection *sections, /* Resolve malloc/free function exported by wasm module */ export = module->exports; - for (i = 0; i < module->export_count; i++, export++) { + for (i = 0; i < module->export_count; i++, export ++) { if (export->kind == EXPORT_KIND_FUNC) { if (!strcmp(export->name, "malloc") && export->index >= module->import_function_count) { func_index = export->index - module->import_function_count; func_type = module->functions[func_index]->func_type; - if (func_type->param_count == 1 - && func_type->result_count == 1 + if (func_type->param_count == 1 && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32) { bh_assert(module->malloc_function == (uint32)-1); @@ -2018,8 +2011,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, /* __new && __pin for AssemblyScript */ func_index = export->index - module->import_function_count; func_type = module->functions[func_index]->func_type; - if (func_type->param_count == 2 - && func_type->result_count == 1 + if (func_type->param_count == 2 && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32 && func_type->types[2] == VALUE_TYPE_I32) { @@ -2041,19 +2033,20 @@ load_from_sections(WASMModule *module, WASMSection *sections, && (export_tmp->index >= module->import_function_count)) { func_index = export_tmp->index - - module->import_function_count; + - module->import_function_count; func_type = - module->functions[func_index]->func_type; + module->functions[func_index]->func_type; if (func_type->param_count == 1 && func_type->result_count == 1 && func_type->types[0] == VALUE_TYPE_I32 && func_type->types[1] == VALUE_TYPE_I32) { - bh_assert( - module->retain_function == (uint32)-1); + bh_assert(module->retain_function + == (uint32)-1); module->retain_function = export_tmp->index; - LOG_VERBOSE( - "Found retain function, name: %s, index: %u", - export_tmp->name, export_tmp->index); + LOG_VERBOSE("Found retain function, name: %s, " + "index: %u", + export_tmp->name, + export_tmp->index); break; } } @@ -2071,8 +2064,7 @@ load_from_sections(WASMModule *module, WASMSection *sections, && export->index >= module->import_function_count) { func_index = export->index - module->import_function_count; func_type = module->functions[func_index]->func_type; - if (func_type->param_count == 1 - && func_type->result_count == 0 + if (func_type->param_count == 1 && func_type->result_count == 0 && func_type->types[0] == VALUE_TYPE_I32) { bh_assert(module->free_function == (uint32)-1); module->free_function = export->index; @@ -2089,8 +2081,8 @@ load_from_sections(WASMModule *module, WASMSection *sections, for (i = 0; i < module->function_count; i++) { WASMFunction *func = module->functions[i]; - if (!wasm_loader_prepare_bytecode(module, func, i, - error_buf, error_buf_size)) { + if (!wasm_loader_prepare_bytecode(module, func, i, error_buf, + error_buf_size)) { return false; } } @@ -2099,16 +2091,15 @@ load_from_sections(WASMModule *module, WASMSection *sections, WASMMemoryImport *memory_import; WASMMemory *memory; - if (aux_data_end_global - && aux_heap_base_global + if (aux_data_end_global && aux_heap_base_global && aux_stack_top_global) { uint64 init_memory_size; uint32 shrunk_memory_size = align_uint(aux_heap_base, 8); if (module->import_memory_count) { memory_import = &module->import_memories[0].u.memory; - init_memory_size = (uint64)memory_import->num_bytes_per_page * - memory_import->init_page_count; + init_memory_size = (uint64)memory_import->num_bytes_per_page + * memory_import->init_page_count; if (shrunk_memory_size <= init_memory_size) { /* Reset memory info to decrease memory usage */ memory_import->num_bytes_per_page = shrunk_memory_size; @@ -2119,8 +2110,8 @@ load_from_sections(WASMModule *module, WASMSection *sections, } if (module->memory_count) { memory = &module->memories[0]; - init_memory_size = (uint64)memory->num_bytes_per_page * - memory->init_page_count; + init_memory_size = (uint64)memory->num_bytes_per_page + * memory->init_page_count; if (shrunk_memory_size <= init_memory_size) { /* Reset memory info to decrease memory usage */ memory->num_bytes_per_page = shrunk_memory_size; @@ -2154,11 +2145,11 @@ load_from_sections(WASMModule *module, WASMSection *sections, return true; } -static WASMModule* +static WASMModule * create_module(char *error_buf, uint32 error_buf_size) { - WASMModule *module = loader_malloc(sizeof(WASMModule), - error_buf, error_buf_size); + WASMModule *module = + loader_malloc(sizeof(WASMModule), error_buf, error_buf_size); if (!module) { return NULL; @@ -2176,8 +2167,8 @@ create_module(char *error_buf, uint32 error_buf_size) } WASMModule * -wasm_loader_load_from_sections(WASMSection *section_list, - char *error_buf, uint32 error_buf_size) +wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf, + uint32 error_buf_size) { WASMModule *module = create_module(error_buf, error_buf_size); if (!module) @@ -2203,6 +2194,7 @@ destroy_sections(WASMSection *section_list) } } +/* clang-format off */ static uint8 section_ids[] = { SECTION_TYPE_USER, SECTION_TYPE_TYPE, @@ -2220,6 +2212,7 @@ static uint8 section_ids[] = { SECTION_TYPE_CODE, SECTION_TYPE_DATA }; +/* clang-format on */ static uint8 get_section_index(uint8 section_type) @@ -2235,12 +2228,11 @@ get_section_index(uint8 section_type) } static bool -create_sections(const uint8 *buf, uint32 size, - WASMSection **p_section_list, +create_sections(const uint8 *buf, uint32 size, WASMSection **p_section_list, char *error_buf, uint32 error_buf_size) { WASMSection *section_list_end = NULL, *section; - const uint8 *p = buf, *p_end = buf + size/*, *section_body*/; + const uint8 *p = buf, *p_end = buf + size /*, *section_body*/; uint8 section_type, section_index, last_section_index = (uint8)-1; uint32 section_size; @@ -2264,13 +2256,13 @@ create_sections(const uint8 *buf, uint32 size, read_leb_uint32(p, p_end, section_size); CHECK_BUF1(p, p_end, section_size); - if (!(section = loader_malloc(sizeof(WASMSection), - error_buf, error_buf_size))) { + if (!(section = loader_malloc(sizeof(WASMSection), error_buf, + error_buf_size))) { return false; } section->section_type = section_type; - section->section_body = (uint8*)p; + section->section_body = (uint8 *)p; section->section_body_size = section_size; if (!*p_section_list) @@ -2292,7 +2284,7 @@ create_sections(const uint8 *buf, uint32 size, } static void -exchange32(uint8* p_data) +exchange32(uint8 *p_data) { uint8 value = *p_data; *p_data = *(p_data + 3); @@ -2311,8 +2303,8 @@ static union { #define is_little_endian() (__ue.b == 1) static bool -load(const uint8 *buf, uint32 size, WASMModule *module, - char *error_buf, uint32 error_buf_size) +load(const uint8 *buf, uint32 size, WASMModule *module, char *error_buf, + uint32 error_buf_size) { const uint8 *buf_end = buf + size; const uint8 *p = buf, *p_end = buf_end; @@ -2322,14 +2314,14 @@ load(const uint8 *buf, uint32 size, WASMModule *module, CHECK_BUF1(p, p_end, sizeof(uint32)); magic_number = read_uint32(p); if (!is_little_endian()) - exchange32((uint8*)&magic_number); + exchange32((uint8 *)&magic_number); bh_assert(magic_number == WASM_MAGIC_NUMBER); CHECK_BUF1(p, p_end, sizeof(uint32)); version = read_uint32(p); if (!is_little_endian()) - exchange32((uint8*)&version); + exchange32((uint8 *)&version); if (version != WASM_CURRENT_VERSION) { set_error_buf(error_buf, error_buf_size, "unknown binary version"); @@ -2337,7 +2329,8 @@ load(const uint8 *buf, uint32 size, WASMModule *module, } if (!create_sections(buf, size, §ion_list, error_buf, error_buf_size) - || !load_from_sections(module, section_list, error_buf, error_buf_size)) { + || !load_from_sections(module, section_list, error_buf, + error_buf_size)) { destroy_sections(section_list); return false; } @@ -2347,8 +2340,9 @@ load(const uint8 *buf, uint32 size, WASMModule *module, return true; } -WASMModule* -wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size) +WASMModule * +wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, + uint32 error_buf_size) { WASMModule *module = create_module(error_buf, error_buf_size); if (!module) { @@ -2444,11 +2438,9 @@ wasm_loader_unload(WASMModule *module) } bool -wasm_loader_find_block_addr(BlockAddr *block_addr_cache, - const uint8 *start_addr, - const uint8 *code_end_addr, - uint8 label_type, - uint8 **p_else_addr, +wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, + const uint8 *start_addr, const uint8 *code_end_addr, + uint8 label_type, uint8 **p_else_addr, uint8 **p_end_addr) { const uint8 *p = start_addr, *p_end = code_end_addr; @@ -2487,7 +2479,8 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, case WASM_OP_IF: /* block result type: 0x40/0x7F/0x7E/0x7D/0x7C */ u8 = read_uint8(p); - if (block_nested_depth < sizeof(block_stack)/sizeof(BlockAddr)) { + 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; } @@ -2499,7 +2492,8 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, case EXT_OP_IF: /* block type */ skip_leb_uint32(p, p_end); - if (block_nested_depth < sizeof(block_stack)/sizeof(BlockAddr)) { + 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; } @@ -2508,33 +2502,37 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, case WASM_OP_ELSE: if (label_type == LABEL_TYPE_IF && block_nested_depth == 1) - else_addr = (uint8*)(p - 1); - if (block_nested_depth - 1 < sizeof(block_stack)/sizeof(BlockAddr)) - block_stack[block_nested_depth - 1].else_addr = (uint8*)(p - 1); + else_addr = (uint8 *)(p - 1); + if (block_nested_depth - 1 + < sizeof(block_stack) / sizeof(BlockAddr)) + block_stack[block_nested_depth - 1].else_addr = + (uint8 *)(p - 1); break; case WASM_OP_END: if (block_nested_depth == 1) { if (label_type == LABEL_TYPE_IF) *p_else_addr = else_addr; - *p_end_addr = (uint8*)(p - 1); + *p_end_addr = (uint8 *)(p - 1); - block_stack[0].end_addr = (uint8*)(p - 1); - for (t = 0; t < sizeof(block_stack)/sizeof(BlockAddr); t++) { + block_stack[0].end_addr = (uint8 *)(p - 1); + for (t = 0; t < sizeof(block_stack) / sizeof(BlockAddr); + t++) { start_addr = block_stack[t].start_addr; if (start_addr) { i = ((uintptr_t)start_addr) & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1); - block = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i; + block = + block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i; for (j = 0; j < BLOCK_ADDR_CONFLICT_SIZE; j++) if (!block[j].start_addr) break; if (j == BLOCK_ADDR_CONFLICT_SIZE) { - memmove(block + 1, block, (BLOCK_ADDR_CONFLICT_SIZE - 1) * - sizeof(BlockAddr)); + memmove(block + 1, block, + (BLOCK_ADDR_CONFLICT_SIZE - 1) + * sizeof(BlockAddr)); j = 0; - } block[j].start_addr = block_stack[t].start_addr; block[j].else_addr = block_stack[t].else_addr; @@ -2547,8 +2545,10 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, } else { block_nested_depth--; - if (block_nested_depth < sizeof(block_stack)/sizeof(BlockAddr)) - block_stack[block_nested_depth].end_addr = (uint8*)(p - 1); + if (block_nested_depth + < sizeof(block_stack) / sizeof(BlockAddr)) + block_stack[block_nested_depth].end_addr = + (uint8 *)(p - 1); } break; @@ -2559,7 +2559,7 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, case WASM_OP_BR_TABLE: read_leb_uint32(p, p_end, count); /* lable num */ - for (i = 0; i <= count; i++) /* lableidxs */ + for (i = 0; i <= count; i++) /* lableidxs */ skip_leb_uint32(p, p_end); break; @@ -2914,24 +2914,24 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache, return false; } -#define REF_I32 VALUE_TYPE_I32 -#define REF_F32 VALUE_TYPE_F32 +#define REF_I32 VALUE_TYPE_I32 +#define REF_F32 VALUE_TYPE_F32 #define REF_I64_1 VALUE_TYPE_I64 #define REF_I64_2 VALUE_TYPE_I64 #define REF_F64_1 VALUE_TYPE_F64 #define REF_F64_2 VALUE_TYPE_F64 -#define REF_ANY VALUE_TYPE_ANY +#define REF_ANY VALUE_TYPE_ANY #if WASM_ENABLE_FAST_INTERP != 0 #if WASM_DEBUG_PREPROCESSOR != 0 -#define LOG_OP(...) os_printf(__VA_ARGS__) +#define LOG_OP(...) os_printf(__VA_ARGS__) #else -#define LOG_OP(...) (void)0 +#define LOG_OP(...) (void)0 #endif #define PATCH_ELSE 0 -#define PATCH_END 1 +#define PATCH_END 1 typedef struct BranchBlockPatch { struct BranchBlockPatch *next; uint8 patch_type; @@ -3012,14 +3012,13 @@ typedef struct Const { uint8 value_type; } Const; -static void* -memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, - char *error_buf, uint32 error_buf_size) +static void * +memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf, + uint32 error_buf_size) { uint8 *mem_new; bh_assert(size_new > size_old); - if ((mem_new = loader_malloc - (size_new, error_buf, error_buf_size))) { + if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) { bh_memcpy_s(mem_new, size_new, mem_old, size_old); memset(mem_new + size_old, 0, size_new - size_old); wasm_runtime_free(mem_old); @@ -3027,42 +3026,46 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, return mem_new; } -#define MEM_REALLOC(mem, size_old, size_new) do { \ - void *mem_new = memory_realloc(mem, size_old, size_new, \ - error_buf, error_buf_size); \ - if (!mem_new) \ - goto fail; \ - mem = mem_new; \ - } while (0) - -#define CHECK_CSP_PUSH() do { \ - if (ctx->frame_csp >= ctx->frame_csp_boundary) { \ - MEM_REALLOC(ctx->frame_csp_bottom, ctx->frame_csp_size, \ - (uint32)(ctx->frame_csp_size \ - + 8 * sizeof(BranchBlock))); \ - ctx->frame_csp_size += (uint32)(8 * sizeof(BranchBlock)); \ - ctx->frame_csp_boundary = ctx->frame_csp_bottom + \ - ctx->frame_csp_size / sizeof(BranchBlock); \ - ctx->frame_csp = ctx->frame_csp_bottom + ctx->csp_num; \ - } \ - } while (0) - -#define CHECK_CSP_POP() do { \ - bh_assert(ctx->csp_num >= 1); \ - } while (0) +#define MEM_REALLOC(mem, size_old, size_new) \ + do { \ + void *mem_new = memory_realloc(mem, size_old, size_new, error_buf, \ + error_buf_size); \ + if (!mem_new) \ + goto fail; \ + mem = mem_new; \ + } while (0) + +#define CHECK_CSP_PUSH() \ + do { \ + if (ctx->frame_csp >= ctx->frame_csp_boundary) { \ + MEM_REALLOC( \ + ctx->frame_csp_bottom, ctx->frame_csp_size, \ + (uint32)(ctx->frame_csp_size + 8 * sizeof(BranchBlock))); \ + ctx->frame_csp_size += (uint32)(8 * sizeof(BranchBlock)); \ + ctx->frame_csp_boundary = \ + ctx->frame_csp_bottom \ + + ctx->frame_csp_size / sizeof(BranchBlock); \ + ctx->frame_csp = ctx->frame_csp_bottom + ctx->csp_num; \ + } \ + } while (0) + +#define CHECK_CSP_POP() \ + do { \ + bh_assert(ctx->csp_num >= 1); \ + } while (0) #if WASM_ENABLE_FAST_INTERP != 0 static bool -check_offset_push(WASMLoaderContext *ctx, - char *error_buf, uint32 error_buf_size) +check_offset_push(WASMLoaderContext *ctx, char *error_buf, + uint32 error_buf_size) { uint32 cell_num = (uint32)(ctx->frame_offset - ctx->frame_offset_bottom); if (ctx->frame_offset >= ctx->frame_offset_boundary) { MEM_REALLOC(ctx->frame_offset_bottom, ctx->frame_offset_size, ctx->frame_offset_size + 16); ctx->frame_offset_size += 16; - ctx->frame_offset_boundary = ctx->frame_offset_bottom + - ctx->frame_offset_size / sizeof(int16); + ctx->frame_offset_boundary = + ctx->frame_offset_bottom + ctx->frame_offset_size / sizeof(int16); ctx->frame_offset = ctx->frame_offset_bottom + cell_num; } return true; @@ -3098,15 +3101,14 @@ free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num) for (uint32 i = 0; i < csp_num; i++) { free_label_patch_list(tmp_csp); - tmp_csp ++; + tmp_csp++; } } #endif static bool -check_stack_push(WASMLoaderContext *ctx, - char *error_buf, uint32 error_buf_size) +check_stack_push(WASMLoaderContext *ctx, char *error_buf, uint32 error_buf_size) { if (ctx->frame_ref >= ctx->frame_ref_boundary) { MEM_REALLOC(ctx->frame_ref_bottom, ctx->frame_ref_size, @@ -3120,7 +3122,6 @@ check_stack_push(WASMLoaderContext *ctx, return false; } - static bool check_stack_top_values(uint8 *frame_ref, int32 stack_cell_num, uint8 type, char *error_buf, uint32 error_buf_size) @@ -3128,32 +3129,31 @@ check_stack_top_values(uint8 *frame_ref, int32 stack_cell_num, uint8 type, bh_assert(!((is_32bit_type(type) && stack_cell_num < 1) || (is_64bit_type(type) && stack_cell_num < 2))); - bh_assert(!((type == VALUE_TYPE_I32 && *(frame_ref - 1) != REF_I32) - || (type == VALUE_TYPE_F32 && *(frame_ref - 1) != REF_F32) - || (type == VALUE_TYPE_I64 - && (*(frame_ref - 2) != REF_I64_1 - || *(frame_ref - 1) != REF_I64_2)) - || (type == VALUE_TYPE_F64 - && (*(frame_ref - 2) != REF_F64_1 - || *(frame_ref - 1) != REF_F64_2)))); + bh_assert(!( + (type == VALUE_TYPE_I32 && *(frame_ref - 1) != REF_I32) + || (type == VALUE_TYPE_F32 && *(frame_ref - 1) != REF_F32) + || (type == VALUE_TYPE_I64 + && (*(frame_ref - 2) != REF_I64_1 || *(frame_ref - 1) != REF_I64_2)) + || (type == VALUE_TYPE_F64 + && (*(frame_ref - 2) != REF_F64_1 + || *(frame_ref - 1) != REF_F64_2)))); return true; } static bool -check_stack_pop(WASMLoaderContext *ctx, uint8 type, - char *error_buf, uint32 error_buf_size) +check_stack_pop(WASMLoaderContext *ctx, uint8 type, char *error_buf, + uint32 error_buf_size) { - int32 block_stack_cell_num = (int32) - (ctx->stack_cell_num - (ctx->frame_csp - 1)->stack_cell_num); + int32 block_stack_cell_num = + (int32)(ctx->stack_cell_num - (ctx->frame_csp - 1)->stack_cell_num); - if (block_stack_cell_num > 0 - && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY) { + if (block_stack_cell_num > 0 && *(ctx->frame_ref - 1) == VALUE_TYPE_ANY) { /* the stack top is a value of any type, return success */ return true; } - if (!check_stack_top_values(ctx->frame_ref, block_stack_cell_num, - type, error_buf, error_buf_size)) + if (!check_stack_top_values(ctx->frame_ref, block_stack_cell_num, type, + error_buf, error_buf_size)) return false; return true; @@ -3181,7 +3181,7 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx) } } -static WASMLoaderContext* +static WASMLoaderContext * wasm_loader_ctx_init(WASMFunction *func) { WASMLoaderContext *loader_ctx = @@ -3192,15 +3192,15 @@ wasm_loader_ctx_init(WASMFunction *func) loader_ctx->frame_ref_size = 32; if (!(loader_ctx->frame_ref_bottom = loader_ctx->frame_ref = - wasm_runtime_malloc(loader_ctx->frame_ref_size))) + wasm_runtime_malloc(loader_ctx->frame_ref_size))) goto fail; memset(loader_ctx->frame_ref_bottom, 0, loader_ctx->frame_ref_size); - loader_ctx->frame_ref_boundary = loader_ctx->frame_ref_bottom + - loader_ctx->frame_ref_size; + loader_ctx->frame_ref_boundary = + loader_ctx->frame_ref_bottom + loader_ctx->frame_ref_size; loader_ctx->frame_csp_size = sizeof(BranchBlock) * 8; if (!(loader_ctx->frame_csp_bottom = loader_ctx->frame_csp = - wasm_runtime_malloc(loader_ctx->frame_csp_size))) + wasm_runtime_malloc(loader_ctx->frame_csp_size))) goto fail; memset(loader_ctx->frame_csp_bottom, 0, loader_ctx->frame_csp_size); loader_ctx->frame_csp_boundary = loader_ctx->frame_csp_bottom + 8; @@ -3208,21 +3208,21 @@ wasm_loader_ctx_init(WASMFunction *func) #if WASM_ENABLE_FAST_INTERP != 0 loader_ctx->frame_offset_size = sizeof(int16) * 32; if (!(loader_ctx->frame_offset_bottom = loader_ctx->frame_offset = - wasm_runtime_malloc(loader_ctx->frame_offset_size))) + wasm_runtime_malloc(loader_ctx->frame_offset_size))) goto fail; - memset(loader_ctx->frame_offset_bottom, 0, - loader_ctx->frame_offset_size); + memset(loader_ctx->frame_offset_bottom, 0, loader_ctx->frame_offset_size); loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32; loader_ctx->num_const = 0; loader_ctx->const_buf_size = sizeof(Const) * 8; - if (!(loader_ctx->const_buf = wasm_runtime_malloc(loader_ctx->const_buf_size))) + if (!(loader_ctx->const_buf = + wasm_runtime_malloc(loader_ctx->const_buf_size))) goto fail; memset(loader_ctx->const_buf, 0, loader_ctx->const_buf_size); loader_ctx->start_dynamic_offset = loader_ctx->dynamic_offset = - loader_ctx->max_dynamic_offset = func->param_cell_num + - func->local_cell_num; + loader_ctx->max_dynamic_offset = + func->param_cell_num + func->local_cell_num; #endif return loader_ctx; @@ -3232,8 +3232,8 @@ wasm_loader_ctx_init(WASMFunction *func) } static bool -wasm_loader_push_frame_ref(WASMLoaderContext *ctx, uint8 type, - char *error_buf, uint32 error_buf_size) +wasm_loader_push_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf, + uint32 error_buf_size) { if (type == VALUE_TYPE_VOID) return true; @@ -3259,12 +3259,12 @@ wasm_loader_push_frame_ref(WASMLoaderContext *ctx, uint8 type, } static bool -wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, - char *error_buf, uint32 error_buf_size) +wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf, + uint32 error_buf_size) { BranchBlock *cur_block = ctx->frame_csp - 1; - int32 available_stack_cell = (int32) - (ctx->stack_cell_num - cur_block->stack_cell_num); + int32 available_stack_cell = + (int32)(ctx->stack_cell_num - cur_block->stack_cell_num); /* Directly return success if current block is in stack * polymorphic state while stack is empty. */ @@ -3290,11 +3290,12 @@ wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type, static bool wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt, - uint8 type_push, uint8 type_pop, - char *error_buf, uint32 error_buf_size) + uint8 type_push, uint8 type_pop, char *error_buf, + uint32 error_buf_size) { for (int i = 0; i < pop_cnt; i++) { - if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf, error_buf_size)) + if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf, + error_buf_size)) return false; } if (!wasm_loader_push_frame_ref(ctx, type_push, error_buf, error_buf_size)) @@ -3304,7 +3305,7 @@ wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt, static bool wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 label_type, - BlockType block_type, uint8* start_addr, + BlockType block_type, uint8 *start_addr, char *error_buf, uint32 error_buf_size) { CHECK_CSP_PUSH(); @@ -3327,8 +3328,8 @@ wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 label_type, } static bool -wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, - char *error_buf, uint32 error_buf_size) +wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, char *error_buf, + uint32 error_buf_size) { CHECK_CSP_POP(); #if WASM_ENABLE_FAST_INTERP != 0 @@ -3344,124 +3345,132 @@ wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, #if WASM_ENABLE_LABELS_AS_VALUES != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 -#define emit_label(opcode) do { \ - wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \ - LOG_OP("\nemit_op [%02x]\t", opcode); \ - } while (0) -#define skip_label() do { \ - wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \ - LOG_OP("\ndelete last op\n"); \ - } while (0) +#define emit_label(opcode) \ + do { \ + wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) +#define skip_label() \ + do { \ + wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \ + LOG_OP("\ndelete last op\n"); \ + } while (0) #else /* else of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ -#define emit_label(opcode) do { \ - int32 offset = (int32)((uint8*)handle_table[opcode] \ - - (uint8*)handle_table[0]); \ - if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \ - set_error_buf(error_buf, error_buf_size, \ - "pre-compiled label offset out of range"); \ - goto fail; \ - } \ - wasm_loader_emit_int16(loader_ctx, offset); \ - LOG_OP("\nemit_op [%02x]\t", opcode); \ - } while (0) -#define skip_label() do { \ - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \ - LOG_OP("\ndelete last op\n"); \ - } while (0) +#define emit_label(opcode) \ + do { \ + int32 offset = \ + (int32)((uint8 *)handle_table[opcode] - (uint8 *)handle_table[0]); \ + if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \ + set_error_buf(error_buf, error_buf_size, \ + "pre-compiled label offset out of range"); \ + goto fail; \ + } \ + wasm_loader_emit_int16(loader_ctx, offset); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) +#define skip_label() \ + do { \ + wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \ + LOG_OP("\ndelete last op\n"); \ + } while (0) #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ -#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ -#define emit_label(opcode) do { \ - wasm_loader_emit_uint8(loader_ctx, opcode); \ - LOG_OP("\nemit_op [%02x]\t", opcode); \ - } while (0) -#define skip_label() do { \ - wasm_loader_emit_backspace(loader_ctx, sizeof(uint8)); \ - LOG_OP("\ndelete last op\n"); \ - } while (0) +#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ +#define emit_label(opcode) \ + do { \ + wasm_loader_emit_uint8(loader_ctx, opcode); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) +#define skip_label() \ + do { \ + wasm_loader_emit_backspace(loader_ctx, sizeof(uint8)); \ + LOG_OP("\ndelete last op\n"); \ + } while (0) #endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ -#define emit_empty_label_addr_and_frame_ip(type) do { \ - if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \ - loader_ctx->p_code_compiled, \ - error_buf, error_buf_size)) \ - goto fail; \ - /* label address, to be patched */ \ - wasm_loader_emit_ptr(loader_ctx, NULL); \ - } while (0) - -#define emit_br_info(frame_csp) do { \ - if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define LAST_OP_OUTPUT_I32() (last_op >= WASM_OP_I32_EQZ \ - && last_op <= WASM_OP_I32_ROTR) \ - || (last_op == WASM_OP_I32_LOAD \ - || last_op == WASM_OP_F32_LOAD) \ - || (last_op >= WASM_OP_I32_LOAD8_S \ - && last_op <= WASM_OP_I32_LOAD16_U) \ - || (last_op >= WASM_OP_F32_ABS \ - && last_op <= WASM_OP_F32_COPYSIGN) \ - || (last_op >= WASM_OP_I32_WRAP_I64 \ - && last_op <= WASM_OP_I32_TRUNC_U_F64) \ - || (last_op >= WASM_OP_F32_CONVERT_S_I32 \ - && last_op <= WASM_OP_F32_DEMOTE_F64) \ - || (last_op == WASM_OP_I32_REINTERPRET_F32) \ - || (last_op == WASM_OP_F32_REINTERPRET_I32) \ - || (last_op == EXT_OP_COPY_STACK_TOP) - -#define LAST_OP_OUTPUT_I64() (last_op >= WASM_OP_I64_CLZ \ - && last_op <= WASM_OP_I64_ROTR) \ - || (last_op >= WASM_OP_F64_ABS \ - && last_op <= WASM_OP_F64_COPYSIGN) \ - || (last_op == WASM_OP_I64_LOAD \ - || last_op == WASM_OP_F64_LOAD) \ - || (last_op >= WASM_OP_I64_LOAD8_S \ - && last_op <= WASM_OP_I64_LOAD32_U) \ - || (last_op >= WASM_OP_I64_EXTEND_S_I32 \ - && last_op <= WASM_OP_I64_TRUNC_U_F64) \ - || (last_op >= WASM_OP_F64_CONVERT_S_I32 \ - && last_op <= WASM_OP_F64_PROMOTE_F32) \ - || (last_op == WASM_OP_I64_REINTERPRET_F64) \ - || (last_op == WASM_OP_F64_REINTERPRET_I64) \ - || (last_op == EXT_OP_COPY_STACK_TOP_I64) - -#define GET_CONST_OFFSET(type, val) do { \ - if (!(wasm_loader_get_const_offset(loader_ctx, type, \ - &val, &operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define GET_CONST_F32_OFFSET(type, fval) do { \ - if (!(wasm_loader_get_const_offset(loader_ctx, type, \ - &fval, &operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define GET_CONST_F64_OFFSET(type, fval) do { \ - if (!(wasm_loader_get_const_offset(loader_ctx, type, \ - &fval, &operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define emit_operand(ctx, offset) do { \ - wasm_loader_emit_int16(ctx, offset); \ - LOG_OP("%d\t", offset); \ - } while (0) - -#define emit_byte(ctx, byte) do { \ - wasm_loader_emit_uint8(ctx, byte); \ - LOG_OP("%d\t", byte); \ - } while (0) - -#define emit_uint32(ctx, value) do { \ - wasm_loader_emit_uint32(ctx, value); \ - LOG_OP("%d\t", value); \ - } while (0) +#define emit_empty_label_addr_and_frame_ip(type) \ + do { \ + if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \ + loader_ctx->p_code_compiled, error_buf, \ + error_buf_size)) \ + goto fail; \ + /* label address, to be patched */ \ + wasm_loader_emit_ptr(loader_ctx, NULL); \ + } while (0) + +#define emit_br_info(frame_csp) \ + do { \ + if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, error_buf, \ + error_buf_size)) \ + goto fail; \ + } while (0) + +#define LAST_OP_OUTPUT_I32() \ + (last_op >= WASM_OP_I32_EQZ && last_op <= WASM_OP_I32_ROTR) \ + || (last_op == WASM_OP_I32_LOAD || last_op == WASM_OP_F32_LOAD) \ + || (last_op >= WASM_OP_I32_LOAD8_S && last_op <= WASM_OP_I32_LOAD16_U) \ + || (last_op >= WASM_OP_F32_ABS && last_op <= WASM_OP_F32_COPYSIGN) \ + || (last_op >= WASM_OP_I32_WRAP_I64 \ + && last_op <= WASM_OP_I32_TRUNC_U_F64) \ + || (last_op >= WASM_OP_F32_CONVERT_S_I32 \ + && last_op <= WASM_OP_F32_DEMOTE_F64) \ + || (last_op == WASM_OP_I32_REINTERPRET_F32) \ + || (last_op == WASM_OP_F32_REINTERPRET_I32) \ + || (last_op == EXT_OP_COPY_STACK_TOP) + +#define LAST_OP_OUTPUT_I64() \ + (last_op >= WASM_OP_I64_CLZ && last_op <= WASM_OP_I64_ROTR) \ + || (last_op >= WASM_OP_F64_ABS && last_op <= WASM_OP_F64_COPYSIGN) \ + || (last_op == WASM_OP_I64_LOAD || last_op == WASM_OP_F64_LOAD) \ + || (last_op >= WASM_OP_I64_LOAD8_S && last_op <= WASM_OP_I64_LOAD32_U) \ + || (last_op >= WASM_OP_I64_EXTEND_S_I32 \ + && last_op <= WASM_OP_I64_TRUNC_U_F64) \ + || (last_op >= WASM_OP_F64_CONVERT_S_I32 \ + && last_op <= WASM_OP_F64_PROMOTE_F32) \ + || (last_op == WASM_OP_I64_REINTERPRET_F64) \ + || (last_op == WASM_OP_F64_REINTERPRET_I64) \ + || (last_op == EXT_OP_COPY_STACK_TOP_I64) + +#define GET_CONST_OFFSET(type, val) \ + do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, &val, \ + &operand_offset, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define GET_CONST_F32_OFFSET(type, fval) \ + do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, &fval, \ + &operand_offset, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define GET_CONST_F64_OFFSET(type, fval) \ + do { \ + if (!(wasm_loader_get_const_offset(loader_ctx, type, &fval, \ + &operand_offset, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define emit_operand(ctx, offset) \ + do { \ + wasm_loader_emit_int16(ctx, offset); \ + LOG_OP("%d\t", offset); \ + } while (0) + +#define emit_byte(ctx, byte) \ + do { \ + wasm_loader_emit_uint8(ctx, byte); \ + LOG_OP("%d\t", byte); \ + } while (0) + +#define emit_uint32(ctx, value) \ + do { \ + wasm_loader_emit_uint32(ctx, value); \ + LOG_OP("%d\t", value); \ + } while (0) static bool wasm_loader_ctx_reinit(WASMLoaderContext *ctx) @@ -3469,8 +3478,7 @@ wasm_loader_ctx_reinit(WASMLoaderContext *ctx) if (!(ctx->p_code_compiled = wasm_runtime_malloc(ctx->code_compiled_size))) return false; memset(ctx->p_code_compiled, 0, ctx->code_compiled_size); - ctx->p_code_compiled_end = ctx->p_code_compiled + - ctx->code_compiled_size; + ctx->p_code_compiled_end = ctx->p_code_compiled + ctx->code_compiled_size; /* clean up frame ref */ memset(ctx->frame_ref_bottom, 0, ctx->frame_ref_size); @@ -3594,8 +3602,9 @@ wasm_loader_emit_backspace(WASMLoaderContext *ctx, uint32 size) static bool preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode, - uint32 local_index, uint32 local_type, bool *preserved, - char *error_buf, uint32 error_buf_size) + uint32 local_index, uint32 local_type, + bool *preserved, char *error_buf, + uint32 error_buf_size) { uint32 i = 0; int16 preserved_offset = (int16)local_index; @@ -3604,7 +3613,8 @@ preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode, while (i < loader_ctx->stack_cell_num) { uint8 cur_type = loader_ctx->frame_ref_bottom[i]; - /* move previous local into dynamic space before a set/tee_local opcode */ + /* move previous local into dynamic space before a set/tee_local opcode + */ if (loader_ctx->frame_offset_bottom[i] == (int16)local_index) { if (!(*preserved)) { *preserved = true; @@ -3680,12 +3690,12 @@ preserve_local_for_block(WASMLoaderContext *loader_ctx, uint8 opcode, } static bool -add_label_patch_to_list(BranchBlock *frame_csp, - uint8 patch_type, uint8 *p_code_compiled, - char *error_buf, uint32 error_buf_size) +add_label_patch_to_list(BranchBlock *frame_csp, uint8 patch_type, + uint8 *p_code_compiled, char *error_buf, + uint32 error_buf_size) { - BranchBlockPatch *patch = loader_malloc - (sizeof(BranchBlockPatch), error_buf, error_buf_size); + BranchBlockPatch *patch = + loader_malloc(sizeof(BranchBlockPatch), error_buf, error_buf_size); if (!patch) { return false; } @@ -3703,8 +3713,7 @@ add_label_patch_to_list(BranchBlock *frame_csp, } static void -apply_label_patch(WASMLoaderContext *ctx, uint8 depth, - uint8 patch_type) +apply_label_patch(WASMLoaderContext *ctx, uint8 depth, uint8 patch_type) { BranchBlock *frame_csp = ctx->frame_csp - depth; BranchBlockPatch *node = frame_csp->patch_list; @@ -3778,11 +3787,11 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, for (i = (int32)arity - 1; i >= 0; i--) { cell = (uint8)wasm_value_type_cell_num(types[i]); frame_offset -= cell; - emit_operand(ctx, *(int16*)(frame_offset)); + emit_operand(ctx, *(int16 *)(frame_offset)); } /* Part e */ - dynamic_offset = frame_csp->dynamic_offset - + wasm_get_cell_num(types, arity); + dynamic_offset = + frame_csp->dynamic_offset + wasm_get_cell_num(types, arity); for (i = (int32)arity - 1; i >= 0; i--) { cell = (uint8)wasm_value_type_cell_num(types[i]); dynamic_offset -= cell; @@ -3795,8 +3804,7 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp, wasm_loader_emit_ptr(ctx, frame_csp->code_compiled); } else { - if (!add_label_patch_to_list(frame_csp, PATCH_END, - ctx->p_code_compiled, + if (!add_label_patch_to_list(frame_csp, PATCH_END, ctx->p_code_compiled, error_buf, error_buf_size)) return false; /* label address, to be patched */ @@ -3858,8 +3866,8 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type, then current block is the function block */ uint32 depth = ctx->frame_csp > ctx->frame_csp_bottom ? 1 : 0; BranchBlock *cur_block = ctx->frame_csp - depth; - int32 available_stack_cell = (int32) - (ctx->stack_cell_num - cur_block->stack_cell_num); + int32 available_stack_cell = + (int32)(ctx->stack_cell_num - cur_block->stack_cell_num); /* Directly return success if current block is in stack * polymorphic state while stack is empty. */ @@ -3902,12 +3910,13 @@ wasm_loader_push_pop_frame_offset(WASMLoaderContext *ctx, uint8 pop_cnt, char *error_buf, uint32 error_buf_size) { for (int i = 0; i < pop_cnt; i++) { - if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf, error_buf_size)) + if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf, + error_buf_size)) return false; } - if (!wasm_loader_push_frame_offset(ctx, type_push, - disable_emit, operand_offset, - error_buf, error_buf_size)) + if (!wasm_loader_push_frame_offset(ctx, type_push, disable_emit, + operand_offset, error_buf, + error_buf_size)) return false; return true; @@ -3958,78 +3967,81 @@ wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt, } static bool -wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, - void *value, int16 *offset, - char *error_buf, uint32 error_buf_size) +wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value, + int16 *offset, char *error_buf, + uint32 error_buf_size) { int16 operand_offset = 0; Const *c; for (c = (Const *)ctx->const_buf; - (uint8*)c < ctx->const_buf + ctx->num_const * sizeof(Const); c ++) { + (uint8 *)c < ctx->const_buf + ctx->num_const * sizeof(Const); c++) { if ((type == c->value_type) - && ((type == VALUE_TYPE_I64 && *(int64*)value == c->value.i64) - || (type == VALUE_TYPE_I32 && *(int32*)value == c->value.i32) + && ((type == VALUE_TYPE_I64 && *(int64 *)value == c->value.i64) + || (type == VALUE_TYPE_I32 && *(int32 *)value == c->value.i32) #if WASM_ENABLE_REF_TYPES != 0 - || (type == VALUE_TYPE_FUNCREF && *(int32*)value == c->value.i32) - || (type == VALUE_TYPE_EXTERNREF && *(int32*)value == c->value.i32) + || (type == VALUE_TYPE_FUNCREF + && *(int32 *)value == c->value.i32) + || (type == VALUE_TYPE_EXTERNREF + && *(int32 *)value == c->value.i32) #endif - || (type == VALUE_TYPE_F64 - && (0 == memcmp(value, &(c->value.f64), sizeof(float64)))) - || (type == VALUE_TYPE_F32 - && (0 == memcmp(value, &(c->value.f32), sizeof(float32)))))) { + || (type == VALUE_TYPE_F64 + && (0 == memcmp(value, &(c->value.f64), sizeof(float64)))) + || (type == VALUE_TYPE_F32 + && (0 + == memcmp(value, &(c->value.f32), sizeof(float32)))))) { operand_offset = c->slot_index; break; } - if (c->value_type == VALUE_TYPE_I64 - || c->value_type == VALUE_TYPE_F64) + if (c->value_type == VALUE_TYPE_I64 || c->value_type == VALUE_TYPE_F64) operand_offset += 2; else operand_offset += 1; } if ((uint8 *)c == ctx->const_buf + ctx->num_const * sizeof(Const)) { if ((uint8 *)c == ctx->const_buf + ctx->const_buf_size) { - MEM_REALLOC(ctx->const_buf, - ctx->const_buf_size, + MEM_REALLOC(ctx->const_buf, ctx->const_buf_size, ctx->const_buf_size + 4 * sizeof(Const)); ctx->const_buf_size += 4 * sizeof(Const); c = (Const *)(ctx->const_buf + ctx->num_const * sizeof(Const)); } c->value_type = type; switch (type) { - case VALUE_TYPE_F64: - bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value, sizeof(float64)); - ctx->const_cell_num += 2; - /* The const buf will be reversed, we use the second cell */ - /* of the i64/f64 const so the finnal offset is corrent */ - operand_offset ++; - break; - case VALUE_TYPE_I64: - c->value.i64 = *(int64*)value; - ctx->const_cell_num += 2; - operand_offset ++; - break; - case VALUE_TYPE_F32: - bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value, sizeof(float32)); - ctx->const_cell_num ++; - break; - case VALUE_TYPE_I32: - c->value.i32 = *(int32*)value; - ctx->const_cell_num ++; - break; + case VALUE_TYPE_F64: + bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value, + sizeof(float64)); + ctx->const_cell_num += 2; + /* The const buf will be reversed, we use the second cell */ + /* of the i64/f64 const so the finnal offset is corrent */ + operand_offset++; + break; + case VALUE_TYPE_I64: + c->value.i64 = *(int64 *)value; + ctx->const_cell_num += 2; + operand_offset++; + break; + case VALUE_TYPE_F32: + bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value, + sizeof(float32)); + ctx->const_cell_num++; + break; + case VALUE_TYPE_I32: + c->value.i32 = *(int32 *)value; + ctx->const_cell_num++; + break; #if WASM_ENABLE_REF_TYPES != 0 - case VALUE_TYPE_EXTERNREF: - case VALUE_TYPE_FUNCREF: - c->value.i32 = *(int32*)value; - ctx->const_cell_num ++; - break; + case VALUE_TYPE_EXTERNREF: + case VALUE_TYPE_FUNCREF: + c->value.i32 = *(int32 *)value; + ctx->const_cell_num++; + break; #endif - default: - break; + default: + break; } c->slot_index = operand_offset; - ctx->num_const ++; - LOG_OP("#### new const [%d]: %ld\n", - ctx->num_const, (int64)c->value.i64); + ctx->num_const++; + LOG_OP("#### new const [%d]: %ld\n", ctx->num_const, + (int64)c->value.i64); } /* use negetive index for const */ operand_offset = -(operand_offset + 1); @@ -4055,189 +4067,211 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, PUSH_XXX(); only push the frame_offset stack, no emit */ -#define PUSH_I32() do { \ - if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_I32, \ - disable_emit, operand_offset,\ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define PUSH_F32() do { \ - if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_F32, \ - disable_emit, operand_offset,\ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define PUSH_I64() do { \ - if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_I64, \ - disable_emit, operand_offset,\ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define PUSH_F64() do { \ - if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_F64, \ - disable_emit, operand_offset,\ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define PUSH_FUNCREF() do { \ - if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_FUNCREF,\ - disable_emit, operand_offset,\ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define POP_I32() do { \ - if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_I32, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define POP_F32() do { \ - if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_F32, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define POP_I64() do { \ - if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_I64, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define POP_F64() do { \ - if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_F64, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define PUSH_OFFSET_TYPE(type) do { \ - if (!(wasm_loader_push_frame_offset(loader_ctx, type, \ - disable_emit, operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_OFFSET_TYPE(type) do { \ - if (!(wasm_loader_pop_frame_offset(loader_ctx, type, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_AND_PUSH(type_pop, type_push) do { \ - if (!(wasm_loader_push_pop_frame_ref_offset(loader_ctx, 1, \ - type_push, type_pop, \ - disable_emit, operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) +#define PUSH_I32() \ + do { \ + if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_I32, \ + disable_emit, operand_offset, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_F32() \ + do { \ + if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_F32, \ + disable_emit, operand_offset, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_I64() \ + do { \ + if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_I64, \ + disable_emit, operand_offset, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_F64() \ + do { \ + if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_F64, \ + disable_emit, operand_offset, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_FUNCREF() \ + do { \ + if (!wasm_loader_push_frame_ref_offset(loader_ctx, VALUE_TYPE_FUNCREF, \ + disable_emit, operand_offset, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_I32() \ + do { \ + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_I32, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_F32() \ + do { \ + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_F32, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_I64() \ + do { \ + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_I64, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_F64() \ + do { \ + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, VALUE_TYPE_F64, \ + error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_OFFSET_TYPE(type) \ + do { \ + if (!(wasm_loader_push_frame_offset(loader_ctx, type, disable_emit, \ + operand_offset, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_OFFSET_TYPE(type) \ + do { \ + if (!(wasm_loader_pop_frame_offset(loader_ctx, type, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_AND_PUSH(type_pop, type_push) \ + do { \ + if (!(wasm_loader_push_pop_frame_ref_offset( \ + loader_ctx, 1, type_push, type_pop, disable_emit, \ + operand_offset, error_buf, error_buf_size))) \ + goto fail; \ + } while (0) /* type of POPs should be the same */ -#define POP2_AND_PUSH(type_pop, type_push) do { \ - if (!(wasm_loader_push_pop_frame_ref_offset(loader_ctx, 2, \ - type_push, type_pop, \ - disable_emit, operand_offset, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) +#define POP2_AND_PUSH(type_pop, type_push) \ + do { \ + if (!(wasm_loader_push_pop_frame_ref_offset( \ + loader_ctx, 2, type_push, type_pop, disable_emit, \ + operand_offset, error_buf, error_buf_size))) \ + goto fail; \ + } while (0) #else /* WASM_ENABLE_FAST_INTERP */ -#define PUSH_I32() do { \ - if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_I32, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define PUSH_F32() do { \ - if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_F32, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define PUSH_I64() do { \ - if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_I64, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define PUSH_F64() do { \ - if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_F64, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define PUSH_FUNCREF() do { \ - if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF,\ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_I32() do { \ - if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I32, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_F32() do { \ - if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_F32, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_I64() do { \ - if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I64, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_F64() do { \ - if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_F64, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_FUNCREF() do { \ - if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_AND_PUSH(type_pop, type_push) do { \ - if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1, \ - type_push, type_pop, \ +#define PUSH_I32() \ + do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_I32, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_F32() \ + do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_F32, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_I64() \ + do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_I64, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_F64() \ + do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_F64, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_FUNCREF() \ + do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF, \ error_buf, error_buf_size))) \ - goto fail; \ - } while (0) + goto fail; \ + } while (0) + +#define POP_I32() \ + do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I32, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_F32() \ + do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_F32, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_I64() \ + do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I64, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_F64() \ + do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_F64, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_FUNCREF() \ + do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF, \ + error_buf, error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_AND_PUSH(type_pop, type_push) \ + do { \ + if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1, type_push, \ + type_pop, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) /* type of POPs should be the same */ -#define POP2_AND_PUSH(type_pop, type_push) do { \ - if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 2, \ - type_push, type_pop, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) +#define POP2_AND_PUSH(type_pop, type_push) \ + do { \ + if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 2, type_push, \ + type_pop, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) #endif /* WASM_ENABLE_FAST_INTERP */ #if WASM_ENABLE_FAST_INTERP != 0 static bool -reserve_block_ret(WASMLoaderContext *loader_ctx, - uint8 opcode, bool disable_emit, - char *error_buf, uint32 error_buf_size) +reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 opcode, + bool disable_emit, char *error_buf, uint32 error_buf_size) { int16 operand_offset = 0; - BranchBlock *block = (opcode == WASM_OP_ELSE) ? - loader_ctx->frame_csp - 1 : loader_ctx->frame_csp; + BranchBlock *block = (opcode == WASM_OP_ELSE) ? loader_ctx->frame_csp - 1 + : loader_ctx->frame_csp; BlockType *block_type = &block->block_type; uint8 *return_types = NULL; uint32 return_count = 0, value_count = 0, total_cel_num = 0; int32 i = 0; - int16 dynamic_offset, dynamic_offset_org, - *frame_offset = NULL, *frame_offset_org = NULL; + int16 dynamic_offset, dynamic_offset_org, *frame_offset = NULL, + *frame_offset_org = NULL; return_count = block_type_get_result_types(block_type, &return_types); @@ -4249,7 +4283,8 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, /* insert op_copy before else opcode */ if (opcode == WASM_OP_ELSE) skip_label(); - emit_label(cell == 1 ? EXT_OP_COPY_STACK_TOP : EXT_OP_COPY_STACK_TOP_I64); + emit_label(cell == 1 ? EXT_OP_COPY_STACK_TOP + : EXT_OP_COPY_STACK_TOP_I64); emit_operand(loader_ctx, *(loader_ctx->frame_offset - cell)); emit_operand(loader_ctx, block->dynamic_offset); @@ -4278,8 +4313,7 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, */ frame_offset = frame_offset_org = loader_ctx->frame_offset; dynamic_offset = dynamic_offset_org = - block->dynamic_offset - + wasm_get_cell_num(return_types, return_count); + block->dynamic_offset + wasm_get_cell_num(return_types, return_count); /* First traversal to get the count of values needed to be copied. */ for (i = (int32)return_count - 1; i >= 0; i--) { @@ -4298,9 +4332,9 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 *emit_data = NULL, *cells = NULL; int16 *src_offsets = NULL; uint16 *dst_offsets = NULL; - uint64 size = (uint64)value_count * (sizeof(*cells) - + sizeof(*src_offsets) - + sizeof(*dst_offsets)); + uint64 size = + (uint64)value_count + * (sizeof(*cells) + sizeof(*src_offsets) + sizeof(*dst_offsets)); /* Allocate memory for the emit data */ if (!(emit_data = loader_malloc(size, error_buf, error_buf_size))) @@ -4319,7 +4353,8 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, /* Part b) */ emit_uint32(loader_ctx, total_cel_num); - /* Second traversal to get each value's cell num, src offset and dst offset. */ + /* Second traversal to get each value's cell num, src offset and dst + * offset. */ frame_offset = frame_offset_org; dynamic_offset = dynamic_offset_org; for (i = (int32)return_count - 1, j = 0; i >= 0; i--) { @@ -4372,56 +4407,62 @@ reserve_block_ret(WASMLoaderContext *loader_ctx, #endif /* WASM_ENABLE_FAST_INTERP */ -#define RESERVE_BLOCK_RET() do { \ - if (!reserve_block_ret(loader_ctx, opcode, disable_emit, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define PUSH_TYPE(type) do { \ - if (!(wasm_loader_push_frame_ref(loader_ctx, type, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define POP_TYPE(type) do { \ - if (!(wasm_loader_pop_frame_ref(loader_ctx, type, \ - error_buf, error_buf_size))) \ - goto fail; \ - } while (0) - -#define PUSH_CSP(label_type, block_type, _start_addr) do { \ - if (!wasm_loader_push_frame_csp(loader_ctx, label_type, block_type, \ - _start_addr, error_buf, \ - error_buf_size)) \ - goto fail; \ - } while (0) - -#define POP_CSP() do { \ - if (!wasm_loader_pop_frame_csp(loader_ctx, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() do { \ - read_leb_uint32(p, p_end, local_idx); \ - bh_assert(local_idx < param_count + local_count);\ - local_type = local_idx < param_count \ - ? param_types[local_idx] \ - : local_types[local_idx - param_count]; \ - local_offset = local_offsets[local_idx]; \ - } while (0) - -#define CHECK_BR(depth) do { \ - if (!wasm_loader_check_br(loader_ctx, depth, \ - error_buf, error_buf_size)) \ - goto fail; \ - } while (0) - -#define CHECK_MEMORY() do { \ - bh_assert(module->import_memory_count \ - + module->memory_count > 0); \ - } while (0) +#define RESERVE_BLOCK_RET() \ + do { \ + if (!reserve_block_ret(loader_ctx, opcode, disable_emit, error_buf, \ + error_buf_size)) \ + goto fail; \ + } while (0) + +#define PUSH_TYPE(type) \ + do { \ + if (!(wasm_loader_push_frame_ref(loader_ctx, type, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define POP_TYPE(type) \ + do { \ + if (!(wasm_loader_pop_frame_ref(loader_ctx, type, error_buf, \ + error_buf_size))) \ + goto fail; \ + } while (0) + +#define PUSH_CSP(label_type, block_type, _start_addr) \ + do { \ + if (!wasm_loader_push_frame_csp(loader_ctx, label_type, block_type, \ + _start_addr, error_buf, \ + error_buf_size)) \ + goto fail; \ + } while (0) + +#define POP_CSP() \ + do { \ + if (!wasm_loader_pop_frame_csp(loader_ctx, error_buf, error_buf_size)) \ + goto fail; \ + } while (0) + +#define GET_LOCAL_INDEX_TYPE_AND_OFFSET() \ + do { \ + read_leb_uint32(p, p_end, local_idx); \ + bh_assert(local_idx < param_count + local_count); \ + local_type = local_idx < param_count \ + ? param_types[local_idx] \ + : local_types[local_idx - param_count]; \ + local_offset = local_offsets[local_idx]; \ + } while (0) + +#define CHECK_BR(depth) \ + do { \ + if (!wasm_loader_check_br(loader_ctx, depth, error_buf, \ + error_buf_size)) \ + goto fail; \ + } while (0) + +#define CHECK_MEMORY() \ + do { \ + bh_assert(module->import_memory_count + module->memory_count > 0); \ + } while (0) static bool is_value_type(uint8 type) @@ -4443,7 +4484,6 @@ is_byte_a_type(uint8 type) return is_value_type(type) || (type == VALUE_TYPE_VOID); } - static bool wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, char *error_buf, uint32 error_buf_size) @@ -4456,10 +4496,10 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, uint16 cell_num; if (loader_ctx->csp_num < depth + 1) { - set_error_buf(error_buf, error_buf_size, - "unknown label, " - "unexpected end of section or function"); - return false; + set_error_buf(error_buf, error_buf_size, + "unknown label, " + "unexpected end of section or function"); + return false; } cur_block = loader_ctx->frame_csp - 1; @@ -4479,7 +4519,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, * and then re-push the values to make the stack top values * match block type. */ if (cur_block->is_stack_polymorphic) { - for (i = (int32)arity -1; i >= 0; i--) { + for (i = (int32)arity - 1; i >= 0; i--) { #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(types[i]); #endif @@ -4496,13 +4536,12 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, return true; } - available_stack_cell = (int32) - (loader_ctx->stack_cell_num - cur_block->stack_cell_num); + available_stack_cell = + (int32)(loader_ctx->stack_cell_num - cur_block->stack_cell_num); /* Check stack top values match target block type */ - for (i = (int32)arity -1; i >= 0; i--) { - if (!check_stack_top_values(frame_ref, available_stack_cell, - types[i], + for (i = (int32)arity - 1; i >= 0; i--) { + if (!check_stack_top_values(frame_ref, available_stack_cell, types[i], error_buf, error_buf_size)) return false; cell_num = wasm_value_type_cell_num(types[i]); @@ -4517,8 +4556,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, } static BranchBlock * -check_branch_block(WASMLoaderContext *loader_ctx, - uint8 **p_buf, uint8 *buf_end, +check_branch_block(WASMLoaderContext *loader_ctx, uint8 **p_buf, uint8 *buf_end, char *error_buf, uint32 error_buf_size) { uint8 *p = *p_buf, *p_end = buf_end; @@ -4548,19 +4586,18 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, int32 available_stack_cell, return_cell_num, i; uint8 *frame_ref = NULL; - available_stack_cell = (int32) - (loader_ctx->stack_cell_num - - block->stack_cell_num); + available_stack_cell = + (int32)(loader_ctx->stack_cell_num - block->stack_cell_num); return_count = block_type_get_result_types(block_type, &return_types); - return_cell_num = return_count > 0 ? - wasm_get_cell_num(return_types, return_count) : 0; + return_cell_num = + return_count > 0 ? wasm_get_cell_num(return_types, return_count) : 0; /* If the stack is in polymorphic state, just clear the stack * and then re-push the values to make the stack top values * match block type. */ if (block->is_stack_polymorphic) { - for (i = (int32)return_count -1; i >= 0; i--) { + for (i = (int32)return_count - 1; i >= 0; i--) { #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(return_types[i]); #endif @@ -4586,10 +4623,9 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, /* Check stack values match return types */ frame_ref = loader_ctx->frame_ref; - for (i = (int32)return_count -1; i >= 0; i--) { + for (i = (int32)return_count - 1; i >= 0; i--) { if (!check_stack_top_values(frame_ref, available_stack_cell, - return_types[i], - error_buf, error_buf_size)) + return_types[i], error_buf, error_buf_size)) return false; frame_ref -= wasm_value_type_cell_num(return_types[i]); available_stack_cell -= wasm_value_type_cell_num(return_types[i]); @@ -4615,7 +4651,7 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, */ static bool copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, - char* error_buf, uint32 error_buf_size) + char *error_buf, uint32 error_buf_size) { int16 *frame_offset = NULL; uint8 *cells = NULL, cell; @@ -4630,8 +4666,7 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, bool disable_emit = false; int16 operand_offset = 0; - uint64 size = (uint64)param_count * (sizeof(*cells) - + sizeof(*src_offsets)); + uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets)); /* For if block, we also need copy the condition operand offset. */ if (is_if_block) @@ -4667,9 +4702,8 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, /* Part a) */ 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); + emit_uint32(loader_ctx, is_if_block ? wasm_type->param_cell_num + 1 + : wasm_type->param_cell_num); /* Part c) */ for (i = 0; i < param_count; i++) emit_byte(loader_ctx, cells[i]); @@ -4701,44 +4735,46 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, /* reset the stack to the state of before entering the last block */ #if WASM_ENABLE_FAST_INTERP != 0 -#define RESET_STACK() do { \ - loader_ctx->stack_cell_num = \ - (loader_ctx->frame_csp - 1)->stack_cell_num; \ - loader_ctx->frame_ref = \ - loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \ - loader_ctx->frame_offset = \ - loader_ctx->frame_offset_bottom + loader_ctx->stack_cell_num; \ -} while (0) +#define RESET_STACK() \ + do { \ + loader_ctx->stack_cell_num = \ + (loader_ctx->frame_csp - 1)->stack_cell_num; \ + loader_ctx->frame_ref = \ + loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \ + loader_ctx->frame_offset = \ + loader_ctx->frame_offset_bottom + loader_ctx->stack_cell_num; \ + } while (0) #else -#define RESET_STACK() do { \ - loader_ctx->stack_cell_num = \ - (loader_ctx->frame_csp - 1)->stack_cell_num; \ - loader_ctx->frame_ref = \ - loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \ -} while (0) +#define RESET_STACK() \ + do { \ + loader_ctx->stack_cell_num = \ + (loader_ctx->frame_csp - 1)->stack_cell_num; \ + loader_ctx->frame_ref = \ + loader_ctx->frame_ref_bottom + loader_ctx->stack_cell_num; \ + } while (0) #endif /* set current block's stack polymorphic state */ -#define SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(flag) do { \ - BranchBlock *cur_block = loader_ctx->frame_csp - 1; \ - cur_block->is_stack_polymorphic = flag; \ -} while (0) +#define SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(flag) \ + do { \ + BranchBlock *cur_block = loader_ctx->frame_csp - 1; \ + cur_block->is_stack_polymorphic = flag; \ + } while (0) #define BLOCK_HAS_PARAM(block_type) \ (!block_type.is_value_type && block_type.u.type->param_count > 0) -#define PRESERVE_LOCAL_FOR_BLOCK() do { \ - if (!(preserve_local_for_block(loader_ctx, opcode, \ - error_buf, error_buf_size))) { \ - goto fail; \ - } \ -} while (0) +#define PRESERVE_LOCAL_FOR_BLOCK() \ + do { \ + if (!(preserve_local_for_block(loader_ctx, opcode, error_buf, \ + error_buf_size))) { \ + goto fail; \ + } \ + } while (0) static bool -wasm_loader_prepare_bytecode(WASMModule *module, - WASMFunction *func, - uint32 cur_func_idx, - char *error_buf, +wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, + uint32 cur_func_idx, char *error_buf, uint32 error_buf_size) { uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org; @@ -4765,9 +4801,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, float64 f64; LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n", - func->param_cell_num, - func->local_cell_num, - func->ret_cell_num); + func->param_cell_num, func->local_cell_num, func->ret_cell_num); #endif global_count = module->import_global_count + module->global_count; @@ -4783,8 +4817,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, local_offsets = func->local_offsets; if (!(loader_ctx = wasm_loader_ctx_init(func))) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); goto fail; } @@ -4792,8 +4825,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, re_scan: if (loader_ctx->code_compiled_size > 0) { if (!wasm_loader_ctx_reinit(loader_ctx)) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); goto fail; } p = func->code; @@ -4835,7 +4867,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if WASM_ENABLE_FAST_INTERP != 0 PRESERVE_LOCAL_FOR_BLOCK(); #endif -handle_op_block_and_loop: + handle_op_block_and_loop: { uint8 value_type; BlockType block_type; @@ -4856,12 +4888,11 @@ wasm_loader_prepare_bytecode(WASMModule *module, bh_assert(type_index < module->type_count); block_type.is_value_type = false; block_type.u.type = module->types[type_index]; -#if WASM_ENABLE_FAST_INTERP == 0 \ - && WASM_ENABLE_WAMR_COMPILER == 0 \ +#if WASM_ENABLE_FAST_INTERP == 0 && WASM_ENABLE_WAMR_COMPILER == 0 \ && WASM_ENABLE_JIT == 0 /* If block use type index as block type, change the opcode - * to new extended opcode so that interpreter can resolve the - * block quickly. + * to new extended opcode so that interpreter can resolve + * the block quickly. */ *(p - 2) = EXT_OP_BLOCK + (opcode - WASM_OP_BLOCK); #endif @@ -4871,10 +4902,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, if (BLOCK_HAS_PARAM(block_type)) { WASMType *wasm_type = block_type.u.type; for (i = 0; i < block_type.u.type->param_count; i++) - POP_TYPE(wasm_type->types[wasm_type->param_count - i - 1]); + POP_TYPE( + wasm_type->types[wasm_type->param_count - i - 1]); } - PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK), block_type, p); + PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK), + block_type, p); /* Pass parameters to block */ if (BLOCK_HAS_PARAM(block_type)) { @@ -4890,14 +4923,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, skip_label(); if (BLOCK_HAS_PARAM(block_type)) { /* Make sure params are in dynamic space */ - if (!copy_params_to_dynamic_space(loader_ctx, - false, - error_buf, - error_buf_size)) + if (!copy_params_to_dynamic_space( + loader_ctx, false, error_buf, error_buf_size)) goto fail; } (loader_ctx->frame_csp - 1)->code_compiled = - loader_ctx->p_code_compiled; + loader_ctx->p_code_compiled; } else if (opcode == WASM_OP_IF) { /* If block has parameters, we should make sure they are in @@ -4907,8 +4938,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, * (func (export "params-id") (param i32) (result i32) * (i32.const 1) * (i32.const 2) - * (if (param i32 i32) (result i32 i32) (local.get 0) (then)) - * (i32.add) + * (if (param i32 i32) (result i32 i32) (local.get 0) + * (then)) (i32.add) * ) * * So we should emit a copy instruction before the if. @@ -4926,10 +4957,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, /* skip the if label */ skip_label(); /* Emit a copy instruction */ - if (!copy_params_to_dynamic_space(loader_ctx, - true, - error_buf, - error_buf_size)) + if (!copy_params_to_dynamic_space( + loader_ctx, true, error_buf, error_buf_size)) goto fail; /* Emit the if instruction */ @@ -4937,16 +4966,17 @@ wasm_loader_prepare_bytecode(WASMModule *module, /* Emit the new condition operand offset */ POP_OFFSET_TYPE(VALUE_TYPE_I32); - /* Save top param_count values of frame_offset stack, so that - * we can recover it before executing else branch */ - size = sizeof(int16) * - (uint64)block_type.u.type->param_cell_num; - if (!(block->param_frame_offsets = - loader_malloc(size, error_buf, error_buf_size))) + /* Save top param_count values of frame_offset stack, so + * that we can recover it before executing else branch + */ + size = sizeof(int16) + * (uint64)block_type.u.type->param_cell_num; + if (!(block->param_frame_offsets = loader_malloc( + size, error_buf, error_buf_size))) goto fail; - bh_memcpy_s(block->param_frame_offsets, - (uint32)size, - loader_ctx->frame_offset - size/sizeof(int16), + bh_memcpy_s(block->param_frame_offsets, (uint32)size, + loader_ctx->frame_offset + - size / sizeof(int16), (uint32)size); } @@ -4962,7 +4992,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, BlockType block_type = (loader_ctx->frame_csp - 1)->block_type; bh_assert(loader_ctx->csp_num >= 2 && (loader_ctx->frame_csp - 1)->label_type - == LABEL_TYPE_IF); + == LABEL_TYPE_IF); /* check whether if branch's stack matches its result type */ if (!check_block_stack(loader_ctx, loader_ctx->frame_csp - 1, @@ -4972,7 +5002,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, (loader_ctx->frame_csp - 1)->else_addr = p - 1; #if WASM_ENABLE_FAST_INTERP != 0 - /* if the result of if branch is in local or const area, add a copy op */ + /* if the result of if branch is in local or const area, add a + * copy op */ RESERVE_BLOCK_RET(); emit_empty_label_addr_and_frame_ip(PATCH_END); @@ -4992,11 +5023,10 @@ wasm_loader_prepare_bytecode(WASMModule *module, if (BLOCK_HAS_PARAM((block_type))) { uint32 size; BranchBlock *block = loader_ctx->frame_csp - 1; - size = sizeof(int16) * - block_type.u.type->param_cell_num; + 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->frame_offset += (size / sizeof(int16)); } #endif @@ -5008,11 +5038,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, BranchBlock *cur_block = loader_ctx->frame_csp - 1; /* check whether block stack matches its result type */ - if (!check_block_stack(loader_ctx, cur_block, - error_buf, error_buf_size)) + if (!check_block_stack(loader_ctx, cur_block, error_buf, + error_buf_size)) goto fail; - /* if no else branch, and return types do not match param types, fail */ + /* if no else branch, and return types do not match param types, + * fail */ if (cur_block->label_type == LABEL_TYPE_IF && !cur_block->else_addr) { uint32 param_count = 0, ret_count = 0; @@ -5030,9 +5061,10 @@ wasm_loader_prepare_bytecode(WASMModule *module, param_types = block_type->u.type->types; ret_types = block_type->u.type->types + param_count; } - bh_assert(param_count == ret_count - && (!param_count - || !memcmp(param_types, ret_types, param_count))); + bh_assert( + param_count == ret_count + && (!param_count + || !memcmp(param_types, ret_types, param_count))); (void)ret_types; (void)ret_count; (void)param_types; @@ -5077,8 +5109,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, case WASM_OP_BR: { - if (!(frame_csp_tmp = check_branch_block(loader_ctx, &p, p_end, - error_buf, error_buf_size))) + if (!(frame_csp_tmp = check_branch_block( + loader_ctx, &p, p_end, error_buf, error_buf_size))) goto fail; RESET_STACK(); @@ -5090,8 +5122,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, { POP_I32(); - if (!(frame_csp_tmp = check_branch_block(loader_ctx, &p, p_end, - error_buf, error_buf_size))) + if (!(frame_csp_tmp = check_branch_block( + loader_ctx, &p, p_end, error_buf, error_buf_size))) goto fail; break; @@ -5110,8 +5142,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, for (i = 0; i <= count; i++) { if (!(frame_csp_tmp = - check_branch_block(loader_ctx, &p, p_end, - error_buf, error_buf_size))) + check_branch_block(loader_ctx, &p, p_end, + error_buf, error_buf_size))) goto fail; } @@ -5127,7 +5159,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, { int32 idx; uint8 ret_type; - for (idx = (int32)func->func_type->result_count - 1; idx >= 0; idx--) { + for (idx = (int32)func->func_type->result_count - 1; idx >= 0; + idx--) { ret_type = *(func->func_type->types + func->func_type->param_count + idx); POP_TYPE(ret_type); @@ -5159,16 +5192,20 @@ wasm_loader_prepare_bytecode(WASMModule *module, #endif bh_assert(func_idx < module->import_function_count - + module->function_count); + + module->function_count); if (func_idx < module->import_function_count) - func_type = module->import_functions[func_idx].u.function.func_type; - else func_type = - module->functions[func_idx - module->import_function_count]->func_type; + module->import_functions[func_idx].u.function.func_type; + else + func_type = module + ->functions[func_idx + - module->import_function_count] + ->func_type; if (func_type->param_count > 0) { - for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { + 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]); @@ -5182,20 +5219,24 @@ wasm_loader_prepare_bytecode(WASMModule *module, for (i = 0; i < func_type->result_count; i++) { PUSH_TYPE(func_type->types[func_type->param_count + i]); #if WASM_ENABLE_FAST_INTERP != 0 - /* Here we emit each return value's dynamic_offset. But in fact - * these offsets are continuous, so interpreter only need to get - * the first return value's offset. + /* Here we emit each return value's dynamic_offset. But + * in fact these offsets are continuous, so interpreter + * only need to get the first return value's offset. */ - PUSH_OFFSET_TYPE(func_type->types[func_type->param_count + i]); + PUSH_OFFSET_TYPE( + func_type->types[func_type->param_count + i]); #endif } #if WASM_ENABLE_TAIL_CALL != 0 } else { - bh_assert(func_type->result_count == func->func_type->result_count); + bh_assert(func_type->result_count + == func->func_type->result_count); for (i = 0; i < func_type->result_count; i++) { - bh_assert(func_type->types[func_type->param_count + i] == - func->func_type->types[func->func_type->param_count + i]); + bh_assert( + func_type->types[func_type->param_count + i] + == func->func_type + ->types[func->func_type->param_count + i]); } } #endif @@ -5212,8 +5253,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMType *func_type; uint32 type_idx, table_idx; - bh_assert(module->import_table_count - + module->table_count > 0); + bh_assert(module->import_table_count + module->table_count > 0); read_leb_uint32(p, p_end, type_idx); @@ -5235,7 +5275,6 @@ wasm_loader_prepare_bytecode(WASMModule *module, goto fail; } - #if WASM_ENABLE_FAST_INTERP != 0 /* we need to emit before arguments */ emit_uint32(loader_ctx, type_idx); @@ -5250,7 +5289,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, func_type = module->types[type_idx]; if (func_type->param_count > 0) { - for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { + 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]); @@ -5264,16 +5304,20 @@ wasm_loader_prepare_bytecode(WASMModule *module, for (i = 0; i < func_type->result_count; i++) { PUSH_TYPE(func_type->types[func_type->param_count + i]); #if WASM_ENABLE_FAST_INTERP != 0 - PUSH_OFFSET_TYPE(func_type->types[func_type->param_count + i]); + PUSH_OFFSET_TYPE( + func_type->types[func_type->param_count + i]); #endif } #if WASM_ENABLE_TAIL_CALL != 0 } else { - bh_assert(func_type->result_count == func->func_type->result_count); + bh_assert(func_type->result_count + == func->func_type->result_count); for (i = 0; i < func_type->result_count; i++) { - bh_assert(func_type->types[func_type->param_count + i] == - func->func_type->types[func->func_type->param_count + i]); + bh_assert( + func_type->types[func_type->param_count + i] + == func->func_type + ->types[func->func_type->param_count + i]); } } #endif @@ -5286,8 +5330,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, case WASM_OP_DROP_64: { BranchBlock *cur_block = loader_ctx->frame_csp - 1; - int32 available_stack_cell = (int32) - (loader_ctx->stack_cell_num - cur_block->stack_cell_num); + int32 available_stack_cell = + (int32)(loader_ctx->stack_cell_num + - cur_block->stack_cell_num); bh_assert(!(available_stack_cell <= 0 && !cur_block->is_stack_polymorphic)); @@ -5300,9 +5345,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); loader_ctx->frame_offset--; - if (*(loader_ctx->frame_offset) > - loader_ctx->start_dynamic_offset) - loader_ctx->dynamic_offset --; + if (*(loader_ctx->frame_offset) + > loader_ctx->start_dynamic_offset) + loader_ctx->dynamic_offset--; #endif } else { @@ -5314,8 +5359,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); loader_ctx->frame_offset -= 2; - if (*(loader_ctx->frame_offset) > - loader_ctx->start_dynamic_offset) + if (*(loader_ctx->frame_offset) + > loader_ctx->start_dynamic_offset) loader_ctx->dynamic_offset -= 2; #endif } @@ -5337,8 +5382,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, POP_I32(); - available_stack_cell = (int32) - (loader_ctx->stack_cell_num - cur_block->stack_cell_num); + available_stack_cell = (int32)(loader_ctx->stack_cell_num + - cur_block->stack_cell_num); bh_assert(!(available_stack_cell <= 0 && !cur_block->is_stack_polymorphic)); @@ -5360,21 +5405,24 @@ wasm_loader_prepare_bytecode(WASMModule *module, loader_ctx->p_code_compiled - 2; #if WASM_ENABLE_LABELS_AS_VALUES != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 - *(void**)(p_code_compiled_tmp - sizeof(void*)) = - handle_table[opcode_tmp]; + *(void **)(p_code_compiled_tmp + - sizeof(void *)) = + handle_table[opcode_tmp]; #else - int32 offset = (int32) - ((uint8*)handle_table[opcode_tmp] - - (uint8*)handle_table[0]); - if (!(offset >= INT16_MIN && offset < INT16_MAX)) { + int32 offset = + (int32)((uint8 *)handle_table[opcode_tmp] + - (uint8 *)handle_table[0]); + if (!(offset >= INT16_MIN + && offset < INT16_MAX)) { set_error_buf(error_buf, error_buf_size, - "pre-compiled label offset out of range"); + "pre-compiled label offset " + "out of range"); goto fail; } - *(int16*)(p_code_compiled_tmp - sizeof(int16)) = - (int16)offset; + *(int16 *)(p_code_compiled_tmp + - sizeof(int16)) = (int16)offset; #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ -#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ +#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 *(p_code_compiled_tmp - 1) = opcode_tmp; #else @@ -5447,21 +5495,20 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if WASM_ENABLE_LABELS_AS_VALUES != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 - *(void**)(p_code_compiled_tmp - sizeof(void*)) = - handle_table[opcode_tmp]; + *(void **)(p_code_compiled_tmp - sizeof(void *)) = + handle_table[opcode_tmp]; #else - int32 offset = (int32) - ((uint8*)handle_table[opcode_tmp] - - (uint8*)handle_table[0]); + int32 offset = (int32)((uint8 *)handle_table[opcode_tmp] + - (uint8 *)handle_table[0]); if (!(offset >= INT16_MIN && offset < INT16_MAX)) { set_error_buf(error_buf, error_buf_size, "pre-compiled label offset out of range"); goto fail; } - *(int16*)(p_code_compiled_tmp - sizeof(int16)) = - (int16)offset; + *(int16 *)(p_code_compiled_tmp - sizeof(int16)) = + (int16)offset; #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ -#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ +#else /* else of WASM_ENABLE_LABELS_AS_VALUES */ #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 *(p_code_compiled_tmp - 1) = opcode_tmp; #else @@ -5495,7 +5542,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, uint32 table_idx; if (!wasm_get_ref_types_flag()) { - goto fail;; + goto fail; + ; } read_leb_uint32(p, p_end, table_idx); @@ -5528,7 +5576,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, uint8 ref_type; if (!wasm_get_ref_types_flag()) { - goto fail;; + goto fail; + ; } CHECK_BUF(p, p_end, 1); @@ -5548,25 +5597,25 @@ wasm_loader_prepare_bytecode(WASMModule *module, case WASM_OP_REF_IS_NULL: { if (!wasm_get_ref_types_flag()) { - goto fail;; + goto fail; + ; } #if WASM_ENABLE_FAST_INTERP != 0 - if (!wasm_loader_pop_frame_ref_offset( - loader_ctx, VALUE_TYPE_FUNCREF, - error_buf, error_buf_size) + if (!wasm_loader_pop_frame_ref_offset(loader_ctx, + VALUE_TYPE_FUNCREF, + error_buf, error_buf_size) && !wasm_loader_pop_frame_ref_offset( - loader_ctx, VALUE_TYPE_EXTERNREF, - error_buf, error_buf_size)) { + loader_ctx, VALUE_TYPE_EXTERNREF, error_buf, + error_buf_size)) { goto fail; } #else - if (!wasm_loader_pop_frame_ref( - loader_ctx, VALUE_TYPE_FUNCREF, - error_buf, error_buf_size) - && !wasm_loader_pop_frame_ref( - loader_ctx, VALUE_TYPE_EXTERNREF, - error_buf, error_buf_size)) { + if (!wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF, + error_buf, error_buf_size) + && !wasm_loader_pop_frame_ref(loader_ctx, + VALUE_TYPE_EXTERNREF, + error_buf, error_buf_size)) { goto fail; } #endif @@ -5577,7 +5626,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, { uint32 func_idx = 0; if (!wasm_get_ref_types_flag()) { - goto fail;; + goto fail; + ; } read_leb_uint32(p, p_end, func_idx); @@ -5596,8 +5646,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, for (i = 0; i < module->table_seg_count; i++, table_seg++) { if (table_seg->elem_type == VALUE_TYPE_FUNCREF && wasm_elem_is_declarative(table_seg->mode)) { - for (j =0; j < table_seg->function_count; j++) { - if (table_seg->func_indexes[j] == cur_func_idx) { + for (j = 0; j < table_seg->function_count; j++) { + if (table_seg->func_indexes[j] + == cur_func_idx) { func_declared = true; break; } @@ -5654,22 +5705,24 @@ wasm_loader_prepare_bytecode(WASMModule *module, POP_TYPE(local_type); #if WASM_ENABLE_FAST_INTERP != 0 - if (!(preserve_referenced_local(loader_ctx, opcode, local_offset, - local_type, &preserve_local, - error_buf, error_buf_size))) + if (!(preserve_referenced_local( + loader_ctx, opcode, local_offset, local_type, + &preserve_local, error_buf, error_buf_size))) goto fail; if (local_offset < 256) { skip_label(); if ((!preserve_local) && (LAST_OP_OUTPUT_I32())) { if (loader_ctx->p_code_compiled) - STORE_U16(loader_ctx->p_code_compiled - 2, local_offset); - loader_ctx->frame_offset --; - loader_ctx->dynamic_offset --; + STORE_U16(loader_ctx->p_code_compiled - 2, + local_offset); + loader_ctx->frame_offset--; + loader_ctx->dynamic_offset--; } else if ((!preserve_local) && (LAST_OP_OUTPUT_I64())) { if (loader_ctx->p_code_compiled) - STORE_U16(loader_ctx->p_code_compiled - 2, local_offset); + STORE_U16(loader_ctx->p_code_compiled - 2, + local_offset); loader_ctx->frame_offset -= 2; loader_ctx->dynamic_offset -= 2; } @@ -5685,7 +5738,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, POP_OFFSET_TYPE(local_type); } } - else { /* local index larger than 255, reserve leb */ + else { /* local index larger than 255, reserve leb */ emit_uint32(loader_ctx, local_idx); POP_OFFSET_TYPE(local_type); } @@ -5711,8 +5764,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, GET_LOCAL_INDEX_TYPE_AND_OFFSET(); #if WASM_ENABLE_FAST_INTERP != 0 /* If the stack is in polymorphic state, do fake pop and push on - offset stack to keep the depth of offset stack to be the same - with ref stack */ + offset stack to keep the depth of offset stack to be the + same with ref stack */ BranchBlock *cur_block = loader_ctx->frame_csp - 1; if (cur_block->is_stack_polymorphic) { POP_OFFSET_TYPE(local_type); @@ -5723,9 +5776,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, PUSH_TYPE(local_type); #if WASM_ENABLE_FAST_INTERP != 0 - if (!(preserve_referenced_local(loader_ctx, opcode, local_offset, - local_type, &preserve_local, - error_buf, error_buf_size))) + if (!(preserve_referenced_local( + loader_ctx, opcode, local_offset, local_type, + &preserve_local, error_buf, error_buf_size))) goto fail; if (local_offset < 256) { @@ -5739,11 +5792,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, emit_byte(loader_ctx, (uint8)local_offset); } } - else { /* local index larger than 255, reserve leb */ + else { /* local index larger than 255, reserve leb */ emit_uint32(loader_ctx, local_idx); } - emit_operand(loader_ctx, *(loader_ctx->frame_offset - - wasm_value_type_cell_num(local_type))); + emit_operand(loader_ctx, + *(loader_ctx->frame_offset + - wasm_value_type_cell_num(local_type))); #else #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) if (local_offset < 0x80) { @@ -5767,10 +5821,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, bh_assert(global_idx < global_count); global_type = - global_idx < module->import_global_count - ? module->import_globals[global_idx].u.global.type - : module->globals[global_idx - module->import_global_count] - .type; + global_idx < module->import_global_count + ? module->import_globals[global_idx].u.global.type + : module + ->globals[global_idx + - module->import_global_count] + .type; PUSH_TYPE(global_type); @@ -5781,7 +5837,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, *p_org = WASM_OP_GET_GLOBAL_64; } #endif -#else /* else of WASM_ENABLE_FAST_INTERP */ +#else /* else of WASM_ENABLE_FAST_INTERP */ if (is_64bit_type(global_type)) { skip_label(); emit_label(WASM_OP_GET_GLOBAL_64); @@ -5801,17 +5857,21 @@ wasm_loader_prepare_bytecode(WASMModule *module, bh_assert(global_idx < global_count); is_mutable = - global_idx < module->import_global_count - ? module->import_globals[global_idx].u.global.is_mutable - : module->globals[global_idx - module->import_global_count] - .is_mutable; + global_idx < module->import_global_count + ? module->import_globals[global_idx].u.global.is_mutable + : module + ->globals[global_idx + - module->import_global_count] + .is_mutable; bh_assert(is_mutable); global_type = - global_idx < module->import_global_count - ? module->import_globals[global_idx].u.global.type - : module->globals[global_idx - module->import_global_count] - .type; + global_idx < module->import_global_count + ? module->import_globals[global_idx].u.global.type + : module + ->globals[global_idx + - module->import_global_count] + .type; POP_TYPE(global_type); @@ -5825,7 +5885,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, *p_org = WASM_OP_SET_GLOBAL_AUX_STACK; } #endif -#else /* else of WASM_ENABLE_FAST_INTERP */ +#else /* else of WASM_ENABLE_FAST_INTERP */ if (is_64bit_type(global_type)) { skip_label(); emit_label(WASM_OP_SET_GLOBAL_64); @@ -5889,13 +5949,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, } #endif CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ + read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, mem_offset); /* offset */ #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, mem_offset); #endif - switch (opcode) - { + switch (opcode) { /* load */ case WASM_OP_I32_LOAD: case WASM_OP_I32_LOAD8_S: @@ -5995,7 +6054,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); disable_emit = true; - bh_memcpy_s((uint8*)&f32, sizeof(float32), p_org, sizeof(float32)); + bh_memcpy_s((uint8 *)&f32, sizeof(float32), p_org, + sizeof(float32)); GET_CONST_F32_OFFSET(VALUE_TYPE_F32, f32); #endif PUSH_F32(); @@ -6007,7 +6067,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, skip_label(); disable_emit = true; /* Some MCU may require 8-byte align */ - bh_memcpy_s((uint8*)&f64, sizeof(float64), p_org, sizeof(float64)); + bh_memcpy_s((uint8 *)&f64, sizeof(float64), p_org, + sizeof(float64)); GET_CONST_F64_OFFSET(VALUE_TYPE_F64, f64); #endif PUSH_F64(); @@ -6246,227 +6307,236 @@ wasm_loader_prepare_bytecode(WASMModule *module, emit_byte(loader_ctx, ((uint8)opcode1)); #endif switch (opcode1) { - case WASM_OP_I32_TRUNC_SAT_S_F32: - case WASM_OP_I32_TRUNC_SAT_U_F32: - POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32); - break; - case WASM_OP_I32_TRUNC_SAT_S_F64: - case WASM_OP_I32_TRUNC_SAT_U_F64: - POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32); - break; - case WASM_OP_I64_TRUNC_SAT_S_F32: - case WASM_OP_I64_TRUNC_SAT_U_F32: - POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I64); - break; - case WASM_OP_I64_TRUNC_SAT_S_F64: - case WASM_OP_I64_TRUNC_SAT_U_F64: - POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64); - break; + case WASM_OP_I32_TRUNC_SAT_S_F32: + case WASM_OP_I32_TRUNC_SAT_U_F32: + POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32); + break; + case WASM_OP_I32_TRUNC_SAT_S_F64: + case WASM_OP_I32_TRUNC_SAT_U_F64: + POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32); + break; + case WASM_OP_I64_TRUNC_SAT_S_F32: + case WASM_OP_I64_TRUNC_SAT_U_F32: + POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I64); + break; + case WASM_OP_I64_TRUNC_SAT_S_F64: + case WASM_OP_I64_TRUNC_SAT_U_F64: + POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64); + break; #if WASM_ENABLE_BULK_MEMORY != 0 - case WASM_OP_MEMORY_INIT: - read_leb_uint32(p, p_end, segment_index); + case WASM_OP_MEMORY_INIT: + read_leb_uint32(p, p_end, segment_index); #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, segment_index); + emit_uint32(loader_ctx, segment_index); #endif - bh_assert(module->import_memory_count - + module->memory_count > 0); + bh_assert(module->import_memory_count + + module->memory_count + > 0); - bh_assert(*p == 0x00); - p++; + bh_assert(*p == 0x00); + p++; - bh_assert(segment_index < module->data_seg_count); - bh_assert(module->data_seg_count1 > 0); + bh_assert(segment_index < module->data_seg_count); + bh_assert(module->data_seg_count1 > 0); - POP_I32(); - POP_I32(); - POP_I32(); - break; - case WASM_OP_DATA_DROP: - read_leb_uint32(p, p_end, segment_index); + POP_I32(); + POP_I32(); + POP_I32(); + break; + case WASM_OP_DATA_DROP: + read_leb_uint32(p, p_end, segment_index); #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, segment_index); + emit_uint32(loader_ctx, segment_index); #endif - bh_assert(segment_index < module->data_seg_count); - bh_assert(module->data_seg_count1 > 0); - break; - case WASM_OP_MEMORY_COPY: - /* both src and dst memory index should be 0 */ - bh_assert(*(int16*)p != 0x0000); - p += 2; + bh_assert(segment_index < module->data_seg_count); + bh_assert(module->data_seg_count1 > 0); + break; + case WASM_OP_MEMORY_COPY: + /* both src and dst memory index should be 0 */ + bh_assert(*(int16 *)p != 0x0000); + p += 2; - bh_assert(module->import_memory_count - + module->memory_count > 0); + bh_assert(module->import_memory_count + + module->memory_count + > 0); - POP_I32(); - POP_I32(); - POP_I32(); - break; - case WASM_OP_MEMORY_FILL: - bh_assert(*p == 0); - p++; + POP_I32(); + POP_I32(); + POP_I32(); + break; + case WASM_OP_MEMORY_FILL: + bh_assert(*p == 0); + p++; - bh_assert(module->import_memory_count - + module->memory_count > 0); + bh_assert(module->import_memory_count + + module->memory_count + > 0); - POP_I32(); - POP_I32(); - POP_I32(); - break; + POP_I32(); + POP_I32(); + POP_I32(); + break; #endif /* WASM_ENABLE_BULK_MEMORY */ #if WASM_ENABLE_REF_TYPES != 0 - case WASM_OP_TABLE_INIT: - { - uint8 seg_ref_type, tbl_ref_type; - uint32 table_seg_idx, table_idx; - - if (!wasm_get_ref_types_flag()) { - goto fail; - } + case WASM_OP_TABLE_INIT: + { + uint8 seg_ref_type, tbl_ref_type; + uint32 table_seg_idx, table_idx; - read_leb_uint32(p, p_end, table_seg_idx); - read_leb_uint32(p, p_end, table_idx); + if (!wasm_get_ref_types_flag()) { + goto fail; + } - if (!get_table_elem_type(module, table_idx, &tbl_ref_type, - error_buf, error_buf_size)) - goto fail; + read_leb_uint32(p, p_end, table_seg_idx); + read_leb_uint32(p, p_end, table_idx); - if (!get_table_seg_elem_type(module, table_seg_idx, - &seg_ref_type, error_buf, + if (!get_table_elem_type(module, table_idx, + &tbl_ref_type, error_buf, error_buf_size)) - goto fail; + goto fail; - if (seg_ref_type != tbl_ref_type) { - set_error_buf(error_buf, error_buf_size, - "type mismatch"); - goto fail; - } + if (!get_table_seg_elem_type(module, table_seg_idx, + &seg_ref_type, error_buf, + error_buf_size)) + goto fail; + + if (seg_ref_type != tbl_ref_type) { + set_error_buf(error_buf, error_buf_size, + "type mismatch"); + goto fail; + } #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, table_seg_idx); - emit_uint32(loader_ctx, table_idx); + emit_uint32(loader_ctx, table_seg_idx); + emit_uint32(loader_ctx, table_idx); #endif - POP_I32(); - POP_I32(); - POP_I32(); - break; - } - case WASM_OP_ELEM_DROP: - { - uint32 table_seg_idx; - if (!wasm_get_ref_types_flag()) { - goto fail; + POP_I32(); + POP_I32(); + POP_I32(); + break; } + case WASM_OP_ELEM_DROP: + { + uint32 table_seg_idx; + if (!wasm_get_ref_types_flag()) { + goto fail; + } - read_leb_uint32(p, p_end, table_seg_idx); - if (!get_table_seg_elem_type(module, table_seg_idx, NULL, - error_buf, error_buf_size)) - goto fail; + read_leb_uint32(p, p_end, table_seg_idx); + if (!get_table_seg_elem_type(module, table_seg_idx, + NULL, error_buf, + error_buf_size)) + goto fail; #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, table_seg_idx); + emit_uint32(loader_ctx, table_seg_idx); #endif - break; - } - case WASM_OP_TABLE_COPY: - { - uint8 src_ref_type, dst_ref_type; - uint32 src_tbl_idx, dst_tbl_idx; - - if (!wasm_get_ref_types_flag()) { - goto fail; + break; } + case WASM_OP_TABLE_COPY: + { + uint8 src_ref_type, dst_ref_type; + uint32 src_tbl_idx, dst_tbl_idx; - read_leb_uint32(p, p_end, src_tbl_idx); - if (!get_table_elem_type(module, src_tbl_idx, &src_ref_type, - error_buf, error_buf_size)) - goto fail; + if (!wasm_get_ref_types_flag()) { + goto fail; + } - read_leb_uint32(p, p_end, dst_tbl_idx); - if (!get_table_elem_type(module, dst_tbl_idx, &dst_ref_type, - error_buf, error_buf_size)) - goto fail; + read_leb_uint32(p, p_end, src_tbl_idx); + if (!get_table_elem_type(module, src_tbl_idx, + &src_ref_type, error_buf, + error_buf_size)) + goto fail; - if (src_ref_type != dst_ref_type) { - set_error_buf(error_buf, error_buf_size, - "type mismatch"); - goto fail; - } + read_leb_uint32(p, p_end, dst_tbl_idx); + if (!get_table_elem_type(module, dst_tbl_idx, + &dst_ref_type, error_buf, + error_buf_size)) + goto fail; + + if (src_ref_type != dst_ref_type) { + set_error_buf(error_buf, error_buf_size, + "type mismatch"); + goto fail; + } #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, src_tbl_idx); - emit_uint32(loader_ctx, dst_tbl_idx); + emit_uint32(loader_ctx, src_tbl_idx); + emit_uint32(loader_ctx, dst_tbl_idx); #endif - POP_I32(); - POP_I32(); - POP_I32(); - break; - } - case WASM_OP_TABLE_SIZE: - { - uint32 table_idx; - if (!wasm_get_ref_types_flag()) { - goto fail; + POP_I32(); + POP_I32(); + POP_I32(); + break; } + case WASM_OP_TABLE_SIZE: + { + uint32 table_idx; + if (!wasm_get_ref_types_flag()) { + goto fail; + } - read_leb_uint32(p, p_end, table_idx); - /* TODO: shall we create a new function to check - table idx instead of using below function? */ - if (!get_table_elem_type(module, table_idx, NULL, - error_buf, error_buf_size)) - goto fail; + read_leb_uint32(p, p_end, table_idx); + /* TODO: shall we create a new function to check + table idx instead of using below function? */ + if (!get_table_elem_type(module, table_idx, NULL, + error_buf, error_buf_size)) + goto fail; #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, table_idx); + emit_uint32(loader_ctx, table_idx); #endif - PUSH_I32(); - break; - } - case WASM_OP_TABLE_GROW: - case WASM_OP_TABLE_FILL: - { - uint8 decl_ref_type; - uint32 table_idx; - - if (!wasm_get_ref_types_flag()) { - goto fail; + PUSH_I32(); + break; } + case WASM_OP_TABLE_GROW: + case WASM_OP_TABLE_FILL: + { + uint8 decl_ref_type; + uint32 table_idx; - read_leb_uint32(p, p_end, table_idx); - if (!get_table_elem_type(module, table_idx, - &decl_ref_type, error_buf, - error_buf_size)) - goto fail; - - if (opcode1 == WASM_OP_TABLE_GROW) { - if (table_idx < module->import_table_count) { - module->import_tables[table_idx] - .u.table.possible_grow = true; + if (!wasm_get_ref_types_flag()) { + goto fail; } - else { - module->tables[table_idx - module->import_table_count] - .possible_grow = true; + + read_leb_uint32(p, p_end, table_idx); + if (!get_table_elem_type(module, table_idx, + &decl_ref_type, error_buf, + error_buf_size)) + goto fail; + + if (opcode1 == WASM_OP_TABLE_GROW) { + if (table_idx < module->import_table_count) { + module->import_tables[table_idx] + .u.table.possible_grow = true; + } + else { + module + ->tables[table_idx + - module->import_table_count] + .possible_grow = true; + } } - } #if WASM_ENABLE_FAST_INTERP != 0 - emit_uint32(loader_ctx, table_idx); + emit_uint32(loader_ctx, table_idx); #endif - POP_I32(); + POP_I32(); #if WASM_ENABLE_FAST_INTERP != 0 - POP_OFFSET_TYPE(decl_ref_type); + POP_OFFSET_TYPE(decl_ref_type); #endif - POP_TYPE(decl_ref_type); - if (opcode1 == WASM_OP_TABLE_GROW) - PUSH_I32(); - else - POP_I32(); - break; - } + POP_TYPE(decl_ref_type); + if (opcode1 == WASM_OP_TABLE_GROW) + PUSH_I32(); + else + POP_I32(); + break; + } #endif /* WASM_ENABLE_REF_TYPES */ - default: - bh_assert(0); - break; + default: + bh_assert(0); + break; } break; } @@ -6480,7 +6550,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, #endif if (opcode != WASM_OP_ATOMIC_FENCE) { CHECK_MEMORY(); - read_leb_uint32(p, p_end, align); /* align */ + read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, mem_offset); /* offset */ #if WASM_ENABLE_FAST_INTERP != 0 emit_uint32(loader_ctx, mem_offset); @@ -6626,15 +6696,14 @@ wasm_loader_prepare_bytecode(WASMModule *module, func->const_cell_num = loader_ctx->const_cell_num; if (func->const_cell_num > 0 - && !(func->consts = func_const = - loader_malloc(func->const_cell_num * 4, - error_buf, error_buf_size))) { + && !(func->consts = func_const = loader_malloc( + func->const_cell_num * 4, error_buf, error_buf_size))) { goto fail; } func_const_end = func->consts + func->const_cell_num * 4; /* reverse the const buf */ for (int i = loader_ctx->num_const - 1; i >= 0; i--) { - Const *c = (Const*)(loader_ctx->const_buf + i * sizeof(Const)); + Const *c = (Const *)(loader_ctx->const_buf + i * sizeof(Const)); if (c->value_type == VALUE_TYPE_F64 || c->value_type == VALUE_TYPE_I64) { bh_memcpy_s(func_const, (uint32)(func_const_end - func_const), @@ -6648,8 +6717,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, } } - func->max_stack_cell_num = loader_ctx->preserved_local_offset - - loader_ctx->start_dynamic_offset + 1; + func->max_stack_cell_num = loader_ctx->preserved_local_offset + - loader_ctx->start_dynamic_offset + 1; #else func->max_stack_cell_num = loader_ctx->max_stack_cell_num; #endif diff --git a/core/iwasm/interpreter/wasm_opcode.h b/core/iwasm/interpreter/wasm_opcode.h index 5f5508230a..f31d326268 100644 --- a/core/iwasm/interpreter/wasm_opcode.h +++ b/core/iwasm/interpreter/wasm_opcode.h @@ -14,591 +14,670 @@ extern "C" { typedef enum WASMOpcode { /* control instructions */ - WASM_OP_UNREACHABLE = 0x00, /* unreachable */ - WASM_OP_NOP = 0x01, /* nop */ - WASM_OP_BLOCK = 0x02, /* block */ - 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_UNUSED_0x0a = 0x0a, - - WASM_OP_END = 0x0b, /* end */ - WASM_OP_BR = 0x0c, /* br */ - WASM_OP_BR_IF = 0x0d, /* br if */ - WASM_OP_BR_TABLE = 0x0e, /* br table */ - WASM_OP_RETURN = 0x0f, /* return */ - WASM_OP_CALL = 0x10, /* call */ - WASM_OP_CALL_INDIRECT = 0x11, /* call_indirect */ - WASM_OP_RETURN_CALL = 0x12, /* return_call */ + WASM_OP_UNREACHABLE = 0x00, /* unreachable */ + WASM_OP_NOP = 0x01, /* nop */ + WASM_OP_BLOCK = 0x02, /* block */ + 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_UNUSED_0x0a = 0x0a, + + WASM_OP_END = 0x0b, /* end */ + WASM_OP_BR = 0x0c, /* br */ + WASM_OP_BR_IF = 0x0d, /* br if */ + WASM_OP_BR_TABLE = 0x0e, /* br table */ + WASM_OP_RETURN = 0x0f, /* return */ + WASM_OP_CALL = 0x10, /* call */ + WASM_OP_CALL_INDIRECT = 0x11, /* call_indirect */ + WASM_OP_RETURN_CALL = 0x12, /* return_call */ WASM_OP_RETURN_CALL_INDIRECT = 0x13, /* return_call_indirect */ - WASM_OP_UNUSED_0x14 = 0x14, - 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_UNUSED_0x14 = 0x14, + 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, /* parametric instructions */ - WASM_OP_DROP = 0x1a, /* drop */ - WASM_OP_SELECT = 0x1b, /* select */ - WASM_OP_SELECT_T = 0x1c, /* select t */ + WASM_OP_DROP = 0x1a, /* drop */ + WASM_OP_SELECT = 0x1b, /* select */ + WASM_OP_SELECT_T = 0x1c, /* select t */ WASM_OP_GET_GLOBAL_64 = 0x1d, WASM_OP_SET_GLOBAL_64 = 0x1e, WASM_OP_SET_GLOBAL_AUX_STACK = 0x1f, /* variable instructions */ - WASM_OP_GET_LOCAL = 0x20, /* get_local */ - WASM_OP_SET_LOCAL = 0x21, /* set_local */ - WASM_OP_TEE_LOCAL = 0x22, /* tee_local */ - WASM_OP_GET_GLOBAL = 0x23, /* get_global */ - WASM_OP_SET_GLOBAL = 0x24, /* set_global */ + WASM_OP_GET_LOCAL = 0x20, /* get_local */ + WASM_OP_SET_LOCAL = 0x21, /* set_local */ + WASM_OP_TEE_LOCAL = 0x22, /* tee_local */ + WASM_OP_GET_GLOBAL = 0x23, /* get_global */ + WASM_OP_SET_GLOBAL = 0x24, /* set_global */ - WASM_OP_TABLE_GET = 0x25, /* table.get */ - WASM_OP_TABLE_SET = 0x26, /* table.set */ - WASM_OP_UNUSED_0x27 = 0x27, + WASM_OP_TABLE_GET = 0x25, /* table.get */ + WASM_OP_TABLE_SET = 0x26, /* table.set */ + WASM_OP_UNUSED_0x27 = 0x27, /* memory instructions */ - WASM_OP_I32_LOAD = 0x28, /* i32.load */ - WASM_OP_I64_LOAD = 0x29, /* i64.load */ - WASM_OP_F32_LOAD = 0x2a, /* f32.load */ - WASM_OP_F64_LOAD = 0x2b, /* f64.load */ - WASM_OP_I32_LOAD8_S = 0x2c, /* i32.load8_s */ - WASM_OP_I32_LOAD8_U = 0x2d, /* i32.load8_u */ - WASM_OP_I32_LOAD16_S = 0x2e, /* i32.load16_s */ - WASM_OP_I32_LOAD16_U = 0x2f, /* i32.load16_u */ - WASM_OP_I64_LOAD8_S = 0x30, /* i64.load8_s */ - WASM_OP_I64_LOAD8_U = 0x31, /* i64.load8_u */ - WASM_OP_I64_LOAD16_S = 0x32, /* i64.load16_s */ - WASM_OP_I64_LOAD16_U = 0x33, /* i64.load16_u */ - WASM_OP_I64_LOAD32_S = 0x34, /* i32.load32_s */ - WASM_OP_I64_LOAD32_U = 0x35, /* i32.load32_u */ - WASM_OP_I32_STORE = 0x36, /* i32.store */ - WASM_OP_I64_STORE = 0x37, /* i64.store */ - WASM_OP_F32_STORE = 0x38, /* f32.store */ - WASM_OP_F64_STORE = 0x39, /* f64.store */ - WASM_OP_I32_STORE8 = 0x3a, /* i32.store8 */ - WASM_OP_I32_STORE16 = 0x3b, /* i32.store16 */ - WASM_OP_I64_STORE8 = 0x3c, /* i64.store8 */ - WASM_OP_I64_STORE16 = 0x3d, /* i64.sotre16 */ - WASM_OP_I64_STORE32 = 0x3e, /* i64.store32 */ - WASM_OP_MEMORY_SIZE = 0x3f, /* memory.size */ - WASM_OP_MEMORY_GROW = 0x40, /* memory.grow */ + WASM_OP_I32_LOAD = 0x28, /* i32.load */ + WASM_OP_I64_LOAD = 0x29, /* i64.load */ + WASM_OP_F32_LOAD = 0x2a, /* f32.load */ + WASM_OP_F64_LOAD = 0x2b, /* f64.load */ + WASM_OP_I32_LOAD8_S = 0x2c, /* i32.load8_s */ + WASM_OP_I32_LOAD8_U = 0x2d, /* i32.load8_u */ + WASM_OP_I32_LOAD16_S = 0x2e, /* i32.load16_s */ + WASM_OP_I32_LOAD16_U = 0x2f, /* i32.load16_u */ + WASM_OP_I64_LOAD8_S = 0x30, /* i64.load8_s */ + WASM_OP_I64_LOAD8_U = 0x31, /* i64.load8_u */ + WASM_OP_I64_LOAD16_S = 0x32, /* i64.load16_s */ + WASM_OP_I64_LOAD16_U = 0x33, /* i64.load16_u */ + WASM_OP_I64_LOAD32_S = 0x34, /* i32.load32_s */ + WASM_OP_I64_LOAD32_U = 0x35, /* i32.load32_u */ + WASM_OP_I32_STORE = 0x36, /* i32.store */ + WASM_OP_I64_STORE = 0x37, /* i64.store */ + WASM_OP_F32_STORE = 0x38, /* f32.store */ + WASM_OP_F64_STORE = 0x39, /* f64.store */ + WASM_OP_I32_STORE8 = 0x3a, /* i32.store8 */ + WASM_OP_I32_STORE16 = 0x3b, /* i32.store16 */ + WASM_OP_I64_STORE8 = 0x3c, /* i64.store8 */ + WASM_OP_I64_STORE16 = 0x3d, /* i64.sotre16 */ + WASM_OP_I64_STORE32 = 0x3e, /* i64.store32 */ + WASM_OP_MEMORY_SIZE = 0x3f, /* memory.size */ + WASM_OP_MEMORY_GROW = 0x40, /* memory.grow */ /* constant instructions */ - WASM_OP_I32_CONST = 0x41, /* i32.const */ - WASM_OP_I64_CONST = 0x42, /* i64.const */ - WASM_OP_F32_CONST = 0x43, /* f32.const */ - WASM_OP_F64_CONST = 0x44, /* f64.const */ + WASM_OP_I32_CONST = 0x41, /* i32.const */ + WASM_OP_I64_CONST = 0x42, /* i64.const */ + WASM_OP_F32_CONST = 0x43, /* f32.const */ + WASM_OP_F64_CONST = 0x44, /* f64.const */ /* comparison instructions */ - WASM_OP_I32_EQZ = 0x45, /* i32.eqz */ - WASM_OP_I32_EQ = 0x46, /* i32.eq */ - WASM_OP_I32_NE = 0x47, /* i32.ne */ - WASM_OP_I32_LT_S = 0x48, /* i32.lt_s */ - WASM_OP_I32_LT_U = 0x49, /* i32.lt_u */ - WASM_OP_I32_GT_S = 0x4a, /* i32.gt_s */ - WASM_OP_I32_GT_U = 0x4b, /* i32.gt_u */ - WASM_OP_I32_LE_S = 0x4c, /* i32.le_s */ - WASM_OP_I32_LE_U = 0x4d, /* i32.le_u */ - WASM_OP_I32_GE_S = 0x4e, /* i32.ge_s */ - WASM_OP_I32_GE_U = 0x4f, /* i32.ge_u */ - - WASM_OP_I64_EQZ = 0x50, /* i64.eqz */ - WASM_OP_I64_EQ = 0x51, /* i64.eq */ - WASM_OP_I64_NE = 0x52, /* i64.ne */ - WASM_OP_I64_LT_S = 0x53, /* i64.lt_s */ - WASM_OP_I64_LT_U = 0x54, /* i64.lt_u */ - WASM_OP_I64_GT_S = 0x55, /* i64.gt_s */ - WASM_OP_I64_GT_U = 0x56, /* i64.gt_u */ - WASM_OP_I64_LE_S = 0x57, /* i64.le_s */ - WASM_OP_I64_LE_U = 0x58, /* i64.le_u */ - WASM_OP_I64_GE_S = 0x59, /* i64.ge_s */ - WASM_OP_I64_GE_U = 0x5a, /* i64.ge_u */ - - WASM_OP_F32_EQ = 0x5b, /* f32.eq */ - WASM_OP_F32_NE = 0x5c, /* f32.ne */ - WASM_OP_F32_LT = 0x5d, /* f32.lt */ - WASM_OP_F32_GT = 0x5e, /* f32.gt */ - WASM_OP_F32_LE = 0x5f, /* f32.le */ - WASM_OP_F32_GE = 0x60, /* f32.ge */ - - WASM_OP_F64_EQ = 0x61, /* f64.eq */ - WASM_OP_F64_NE = 0x62, /* f64.ne */ - WASM_OP_F64_LT = 0x63, /* f64.lt */ - WASM_OP_F64_GT = 0x64, /* f64.gt */ - WASM_OP_F64_LE = 0x65, /* f64.le */ - WASM_OP_F64_GE = 0x66, /* f64.ge */ + WASM_OP_I32_EQZ = 0x45, /* i32.eqz */ + WASM_OP_I32_EQ = 0x46, /* i32.eq */ + WASM_OP_I32_NE = 0x47, /* i32.ne */ + WASM_OP_I32_LT_S = 0x48, /* i32.lt_s */ + WASM_OP_I32_LT_U = 0x49, /* i32.lt_u */ + WASM_OP_I32_GT_S = 0x4a, /* i32.gt_s */ + WASM_OP_I32_GT_U = 0x4b, /* i32.gt_u */ + WASM_OP_I32_LE_S = 0x4c, /* i32.le_s */ + WASM_OP_I32_LE_U = 0x4d, /* i32.le_u */ + WASM_OP_I32_GE_S = 0x4e, /* i32.ge_s */ + WASM_OP_I32_GE_U = 0x4f, /* i32.ge_u */ + + WASM_OP_I64_EQZ = 0x50, /* i64.eqz */ + WASM_OP_I64_EQ = 0x51, /* i64.eq */ + WASM_OP_I64_NE = 0x52, /* i64.ne */ + WASM_OP_I64_LT_S = 0x53, /* i64.lt_s */ + WASM_OP_I64_LT_U = 0x54, /* i64.lt_u */ + WASM_OP_I64_GT_S = 0x55, /* i64.gt_s */ + WASM_OP_I64_GT_U = 0x56, /* i64.gt_u */ + WASM_OP_I64_LE_S = 0x57, /* i64.le_s */ + WASM_OP_I64_LE_U = 0x58, /* i64.le_u */ + WASM_OP_I64_GE_S = 0x59, /* i64.ge_s */ + WASM_OP_I64_GE_U = 0x5a, /* i64.ge_u */ + + WASM_OP_F32_EQ = 0x5b, /* f32.eq */ + WASM_OP_F32_NE = 0x5c, /* f32.ne */ + WASM_OP_F32_LT = 0x5d, /* f32.lt */ + WASM_OP_F32_GT = 0x5e, /* f32.gt */ + WASM_OP_F32_LE = 0x5f, /* f32.le */ + WASM_OP_F32_GE = 0x60, /* f32.ge */ + + WASM_OP_F64_EQ = 0x61, /* f64.eq */ + WASM_OP_F64_NE = 0x62, /* f64.ne */ + WASM_OP_F64_LT = 0x63, /* f64.lt */ + WASM_OP_F64_GT = 0x64, /* f64.gt */ + WASM_OP_F64_LE = 0x65, /* f64.le */ + WASM_OP_F64_GE = 0x66, /* f64.ge */ /* numeric operators */ - WASM_OP_I32_CLZ = 0x67, /* i32.clz */ - WASM_OP_I32_CTZ = 0x68, /* i32.ctz */ - WASM_OP_I32_POPCNT = 0x69, /* i32.popcnt */ - WASM_OP_I32_ADD = 0x6a, /* i32.add */ - WASM_OP_I32_SUB = 0x6b, /* i32.sub */ - WASM_OP_I32_MUL = 0x6c, /* i32.mul */ - WASM_OP_I32_DIV_S = 0x6d, /* i32.div_s */ - WASM_OP_I32_DIV_U = 0x6e, /* i32.div_u */ - WASM_OP_I32_REM_S = 0x6f, /* i32.rem_s */ - WASM_OP_I32_REM_U = 0x70, /* i32.rem_u */ - WASM_OP_I32_AND = 0x71, /* i32.and */ - WASM_OP_I32_OR = 0x72, /* i32.or */ - WASM_OP_I32_XOR = 0x73, /* i32.xor */ - WASM_OP_I32_SHL = 0x74, /* i32.shl */ - WASM_OP_I32_SHR_S = 0x75, /* i32.shr_s */ - WASM_OP_I32_SHR_U = 0x76, /* i32.shr_u */ - WASM_OP_I32_ROTL = 0x77, /* i32.rotl */ - WASM_OP_I32_ROTR = 0x78, /* i32.rotr */ - - WASM_OP_I64_CLZ = 0x79, /* i64.clz */ - WASM_OP_I64_CTZ = 0x7a, /* i64.ctz */ - WASM_OP_I64_POPCNT = 0x7b, /* i64.popcnt */ - WASM_OP_I64_ADD = 0x7c, /* i64.add */ - WASM_OP_I64_SUB = 0x7d, /* i64.sub */ - WASM_OP_I64_MUL = 0x7e, /* i64.mul */ - WASM_OP_I64_DIV_S = 0x7f, /* i64.div_s */ - WASM_OP_I64_DIV_U = 0x80, /* i64.div_u */ - WASM_OP_I64_REM_S = 0x81, /* i64.rem_s */ - WASM_OP_I64_REM_U = 0x82, /* i64.rem_u */ - WASM_OP_I64_AND = 0x83, /* i64.and */ - WASM_OP_I64_OR = 0x84, /* i64.or */ - WASM_OP_I64_XOR = 0x85, /* i64.xor */ - WASM_OP_I64_SHL = 0x86, /* i64.shl */ - WASM_OP_I64_SHR_S = 0x87, /* i64.shr_s */ - WASM_OP_I64_SHR_U = 0x88, /* i64.shr_u */ - WASM_OP_I64_ROTL = 0x89, /* i64.rotl */ - WASM_OP_I64_ROTR = 0x8a, /* i64.rotr */ - - WASM_OP_F32_ABS = 0x8b, /* f32.abs */ - WASM_OP_F32_NEG = 0x8c, /* f32.neg */ - WASM_OP_F32_CEIL = 0x8d, /* f32.ceil */ - WASM_OP_F32_FLOOR = 0x8e, /* f32.floor */ - WASM_OP_F32_TRUNC = 0x8f, /* f32.trunc */ - WASM_OP_F32_NEAREST = 0x90, /* f32.nearest */ - WASM_OP_F32_SQRT = 0x91, /* f32.sqrt */ - WASM_OP_F32_ADD = 0x92, /* f32.add */ - WASM_OP_F32_SUB = 0x93, /* f32.sub */ - WASM_OP_F32_MUL = 0x94, /* f32.mul */ - WASM_OP_F32_DIV = 0x95, /* f32.div */ - WASM_OP_F32_MIN = 0x96, /* f32.min */ - WASM_OP_F32_MAX = 0x97, /* f32.max */ - WASM_OP_F32_COPYSIGN = 0x98, /* f32.copysign */ - - WASM_OP_F64_ABS = 0x99, /* f64.abs */ - WASM_OP_F64_NEG = 0x9a, /* f64.neg */ - WASM_OP_F64_CEIL = 0x9b, /* f64.ceil */ - WASM_OP_F64_FLOOR = 0x9c, /* f64.floor */ - WASM_OP_F64_TRUNC = 0x9d, /* f64.trunc */ - WASM_OP_F64_NEAREST = 0x9e, /* f64.nearest */ - WASM_OP_F64_SQRT = 0x9f, /* f64.sqrt */ - WASM_OP_F64_ADD = 0xa0, /* f64.add */ - WASM_OP_F64_SUB = 0xa1, /* f64.sub */ - WASM_OP_F64_MUL = 0xa2, /* f64.mul */ - WASM_OP_F64_DIV = 0xa3, /* f64.div */ - WASM_OP_F64_MIN = 0xa4, /* f64.min */ - WASM_OP_F64_MAX = 0xa5, /* f64.max */ - WASM_OP_F64_COPYSIGN = 0xa6, /* f64.copysign */ + WASM_OP_I32_CLZ = 0x67, /* i32.clz */ + WASM_OP_I32_CTZ = 0x68, /* i32.ctz */ + WASM_OP_I32_POPCNT = 0x69, /* i32.popcnt */ + WASM_OP_I32_ADD = 0x6a, /* i32.add */ + WASM_OP_I32_SUB = 0x6b, /* i32.sub */ + WASM_OP_I32_MUL = 0x6c, /* i32.mul */ + WASM_OP_I32_DIV_S = 0x6d, /* i32.div_s */ + WASM_OP_I32_DIV_U = 0x6e, /* i32.div_u */ + WASM_OP_I32_REM_S = 0x6f, /* i32.rem_s */ + WASM_OP_I32_REM_U = 0x70, /* i32.rem_u */ + WASM_OP_I32_AND = 0x71, /* i32.and */ + WASM_OP_I32_OR = 0x72, /* i32.or */ + WASM_OP_I32_XOR = 0x73, /* i32.xor */ + WASM_OP_I32_SHL = 0x74, /* i32.shl */ + WASM_OP_I32_SHR_S = 0x75, /* i32.shr_s */ + WASM_OP_I32_SHR_U = 0x76, /* i32.shr_u */ + WASM_OP_I32_ROTL = 0x77, /* i32.rotl */ + WASM_OP_I32_ROTR = 0x78, /* i32.rotr */ + + WASM_OP_I64_CLZ = 0x79, /* i64.clz */ + WASM_OP_I64_CTZ = 0x7a, /* i64.ctz */ + WASM_OP_I64_POPCNT = 0x7b, /* i64.popcnt */ + WASM_OP_I64_ADD = 0x7c, /* i64.add */ + WASM_OP_I64_SUB = 0x7d, /* i64.sub */ + WASM_OP_I64_MUL = 0x7e, /* i64.mul */ + WASM_OP_I64_DIV_S = 0x7f, /* i64.div_s */ + WASM_OP_I64_DIV_U = 0x80, /* i64.div_u */ + WASM_OP_I64_REM_S = 0x81, /* i64.rem_s */ + WASM_OP_I64_REM_U = 0x82, /* i64.rem_u */ + WASM_OP_I64_AND = 0x83, /* i64.and */ + WASM_OP_I64_OR = 0x84, /* i64.or */ + WASM_OP_I64_XOR = 0x85, /* i64.xor */ + WASM_OP_I64_SHL = 0x86, /* i64.shl */ + WASM_OP_I64_SHR_S = 0x87, /* i64.shr_s */ + WASM_OP_I64_SHR_U = 0x88, /* i64.shr_u */ + WASM_OP_I64_ROTL = 0x89, /* i64.rotl */ + WASM_OP_I64_ROTR = 0x8a, /* i64.rotr */ + + WASM_OP_F32_ABS = 0x8b, /* f32.abs */ + WASM_OP_F32_NEG = 0x8c, /* f32.neg */ + WASM_OP_F32_CEIL = 0x8d, /* f32.ceil */ + WASM_OP_F32_FLOOR = 0x8e, /* f32.floor */ + WASM_OP_F32_TRUNC = 0x8f, /* f32.trunc */ + WASM_OP_F32_NEAREST = 0x90, /* f32.nearest */ + WASM_OP_F32_SQRT = 0x91, /* f32.sqrt */ + WASM_OP_F32_ADD = 0x92, /* f32.add */ + WASM_OP_F32_SUB = 0x93, /* f32.sub */ + WASM_OP_F32_MUL = 0x94, /* f32.mul */ + WASM_OP_F32_DIV = 0x95, /* f32.div */ + WASM_OP_F32_MIN = 0x96, /* f32.min */ + WASM_OP_F32_MAX = 0x97, /* f32.max */ + WASM_OP_F32_COPYSIGN = 0x98, /* f32.copysign */ + + WASM_OP_F64_ABS = 0x99, /* f64.abs */ + WASM_OP_F64_NEG = 0x9a, /* f64.neg */ + WASM_OP_F64_CEIL = 0x9b, /* f64.ceil */ + WASM_OP_F64_FLOOR = 0x9c, /* f64.floor */ + WASM_OP_F64_TRUNC = 0x9d, /* f64.trunc */ + WASM_OP_F64_NEAREST = 0x9e, /* f64.nearest */ + WASM_OP_F64_SQRT = 0x9f, /* f64.sqrt */ + WASM_OP_F64_ADD = 0xa0, /* f64.add */ + WASM_OP_F64_SUB = 0xa1, /* f64.sub */ + WASM_OP_F64_MUL = 0xa2, /* f64.mul */ + WASM_OP_F64_DIV = 0xa3, /* f64.div */ + WASM_OP_F64_MIN = 0xa4, /* f64.min */ + WASM_OP_F64_MAX = 0xa5, /* f64.max */ + WASM_OP_F64_COPYSIGN = 0xa6, /* f64.copysign */ /* conversions */ - WASM_OP_I32_WRAP_I64 = 0xa7, /* i32.wrap/i64 */ - WASM_OP_I32_TRUNC_S_F32 = 0xa8, /* i32.trunc_s/f32 */ - WASM_OP_I32_TRUNC_U_F32 = 0xa9, /* i32.trunc_u/f32 */ - WASM_OP_I32_TRUNC_S_F64 = 0xaa, /* i32.trunc_s/f64 */ - WASM_OP_I32_TRUNC_U_F64 = 0xab, /* i32.trunc_u/f64 */ - - WASM_OP_I64_EXTEND_S_I32 = 0xac, /* i64.extend_s/i32 */ - WASM_OP_I64_EXTEND_U_I32 = 0xad, /* i64.extend_u/i32 */ - WASM_OP_I64_TRUNC_S_F32 = 0xae, /* i64.trunc_s/f32 */ - WASM_OP_I64_TRUNC_U_F32 = 0xaf, /* i64.trunc_u/f32 */ - WASM_OP_I64_TRUNC_S_F64 = 0xb0, /* i64.trunc_s/f64 */ - WASM_OP_I64_TRUNC_U_F64 = 0xb1, /* i64.trunc_u/f64 */ + WASM_OP_I32_WRAP_I64 = 0xa7, /* i32.wrap/i64 */ + WASM_OP_I32_TRUNC_S_F32 = 0xa8, /* i32.trunc_s/f32 */ + WASM_OP_I32_TRUNC_U_F32 = 0xa9, /* i32.trunc_u/f32 */ + WASM_OP_I32_TRUNC_S_F64 = 0xaa, /* i32.trunc_s/f64 */ + WASM_OP_I32_TRUNC_U_F64 = 0xab, /* i32.trunc_u/f64 */ + + WASM_OP_I64_EXTEND_S_I32 = 0xac, /* i64.extend_s/i32 */ + WASM_OP_I64_EXTEND_U_I32 = 0xad, /* i64.extend_u/i32 */ + WASM_OP_I64_TRUNC_S_F32 = 0xae, /* i64.trunc_s/f32 */ + WASM_OP_I64_TRUNC_U_F32 = 0xaf, /* i64.trunc_u/f32 */ + WASM_OP_I64_TRUNC_S_F64 = 0xb0, /* i64.trunc_s/f64 */ + WASM_OP_I64_TRUNC_U_F64 = 0xb1, /* i64.trunc_u/f64 */ WASM_OP_F32_CONVERT_S_I32 = 0xb2, /* f32.convert_s/i32 */ WASM_OP_F32_CONVERT_U_I32 = 0xb3, /* f32.convert_u/i32 */ WASM_OP_F32_CONVERT_S_I64 = 0xb4, /* f32.convert_s/i64 */ WASM_OP_F32_CONVERT_U_I64 = 0xb5, /* f32.convert_u/i64 */ - WASM_OP_F32_DEMOTE_F64 = 0xb6, /* f32.demote/f64 */ + WASM_OP_F32_DEMOTE_F64 = 0xb6, /* f32.demote/f64 */ WASM_OP_F64_CONVERT_S_I32 = 0xb7, /* f64.convert_s/i32 */ WASM_OP_F64_CONVERT_U_I32 = 0xb8, /* f64.convert_u/i32 */ WASM_OP_F64_CONVERT_S_I64 = 0xb9, /* f64.convert_s/i64 */ WASM_OP_F64_CONVERT_U_I64 = 0xba, /* f64.convert_u/i64 */ - WASM_OP_F64_PROMOTE_F32 = 0xbb, /* f64.promote/f32 */ + WASM_OP_F64_PROMOTE_F32 = 0xbb, /* f64.promote/f32 */ /* reinterpretations */ - WASM_OP_I32_REINTERPRET_F32 = 0xbc, /* i32.reinterpret/f32 */ - WASM_OP_I64_REINTERPRET_F64 = 0xbd, /* i64.reinterpret/f64 */ - WASM_OP_F32_REINTERPRET_I32 = 0xbe, /* f32.reinterpret/i32 */ - WASM_OP_F64_REINTERPRET_I64 = 0xbf, /* f64.reinterpret/i64 */ + WASM_OP_I32_REINTERPRET_F32 = 0xbc, /* i32.reinterpret/f32 */ + WASM_OP_I64_REINTERPRET_F64 = 0xbd, /* i64.reinterpret/f64 */ + WASM_OP_F32_REINTERPRET_I32 = 0xbe, /* f32.reinterpret/i32 */ + WASM_OP_F64_REINTERPRET_I64 = 0xbf, /* f64.reinterpret/i64 */ - WASM_OP_I32_EXTEND8_S = 0xc0, /* i32.extend8_s */ - WASM_OP_I32_EXTEND16_S = 0xc1, /* i32.extend16_s */ - WASM_OP_I64_EXTEND8_S = 0xc2, /* i64.extend8_s */ - WASM_OP_I64_EXTEND16_S = 0xc3, /* i64.extend16_s */ - WASM_OP_I64_EXTEND32_S = 0xc4, /* i64.extend32_s */ + WASM_OP_I32_EXTEND8_S = 0xc0, /* i32.extend8_s */ + WASM_OP_I32_EXTEND16_S = 0xc1, /* i32.extend16_s */ + WASM_OP_I64_EXTEND8_S = 0xc2, /* i64.extend8_s */ + WASM_OP_I64_EXTEND16_S = 0xc3, /* i64.extend16_s */ + WASM_OP_I64_EXTEND32_S = 0xc4, /* i64.extend32_s */ /* drop/select specified types*/ - WASM_OP_DROP_64 = 0xc5, - WASM_OP_SELECT_64 = 0xc6, + WASM_OP_DROP_64 = 0xc5, + WASM_OP_SELECT_64 = 0xc6, /* extend op code */ - EXT_OP_GET_LOCAL_FAST = 0xc7, - EXT_OP_SET_LOCAL_FAST_I64 = 0xc8, - EXT_OP_SET_LOCAL_FAST = 0xc9, - EXT_OP_TEE_LOCAL_FAST = 0xca, - EXT_OP_TEE_LOCAL_FAST_I64 = 0xcb, - EXT_OP_COPY_STACK_TOP = 0xcc, - EXT_OP_COPY_STACK_TOP_I64 = 0xcd, - EXT_OP_COPY_STACK_VALUES = 0xce, - - WASM_OP_IMPDEP = 0xcf, - - WASM_OP_REF_NULL = 0xd0, /* ref.null */ - WASM_OP_REF_IS_NULL = 0xd1, /* ref.is_null */ - WASM_OP_REF_FUNC = 0xd2, /* ref.func */ - - EXT_OP_BLOCK = 0xd3, /* block with blocktype */ - EXT_OP_LOOP = 0xd4, /* loop with blocktype */ - EXT_OP_IF = 0xd5, /* if with blocktype */ + EXT_OP_GET_LOCAL_FAST = 0xc7, + EXT_OP_SET_LOCAL_FAST_I64 = 0xc8, + EXT_OP_SET_LOCAL_FAST = 0xc9, + EXT_OP_TEE_LOCAL_FAST = 0xca, + EXT_OP_TEE_LOCAL_FAST_I64 = 0xcb, + EXT_OP_COPY_STACK_TOP = 0xcc, + EXT_OP_COPY_STACK_TOP_I64 = 0xcd, + EXT_OP_COPY_STACK_VALUES = 0xce, + + WASM_OP_IMPDEP = 0xcf, + + WASM_OP_REF_NULL = 0xd0, /* ref.null */ + WASM_OP_REF_IS_NULL = 0xd1, /* ref.is_null */ + WASM_OP_REF_FUNC = 0xd2, /* ref.func */ + + EXT_OP_BLOCK = 0xd3, /* block with blocktype */ + EXT_OP_LOOP = 0xd4, /* loop with blocktype */ + EXT_OP_IF = 0xd5, /* if with blocktype */ + +#if WASM_ENABLE_DEBUG_INTERP != 0 + DEBUG_OP_BREAK = 0xd6, /* debug break point */ +#endif /* Post-MVP extend op prefix */ - WASM_OP_MISC_PREFIX = 0xfc, - WASM_OP_SIMD_PREFIX = 0xfd, - WASM_OP_ATOMIC_PREFIX = 0xfe, + WASM_OP_MISC_PREFIX = 0xfc, + WASM_OP_SIMD_PREFIX = 0xfd, + WASM_OP_ATOMIC_PREFIX = 0xfe, } WASMOpcode; typedef enum WASMMiscEXTOpcode { - WASM_OP_I32_TRUNC_SAT_S_F32 = 0x00, - WASM_OP_I32_TRUNC_SAT_U_F32 = 0x01, - WASM_OP_I32_TRUNC_SAT_S_F64 = 0x02, - WASM_OP_I32_TRUNC_SAT_U_F64 = 0x03, - WASM_OP_I64_TRUNC_SAT_S_F32 = 0x04, - WASM_OP_I64_TRUNC_SAT_U_F32 = 0x05, - WASM_OP_I64_TRUNC_SAT_S_F64 = 0x06, - WASM_OP_I64_TRUNC_SAT_U_F64 = 0x07, - WASM_OP_MEMORY_INIT = 0x08, - WASM_OP_DATA_DROP = 0x09, - WASM_OP_MEMORY_COPY = 0x0a, - WASM_OP_MEMORY_FILL = 0x0b, - WASM_OP_TABLE_INIT = 0x0c, - WASM_OP_ELEM_DROP = 0x0d, - WASM_OP_TABLE_COPY = 0x0e, - WASM_OP_TABLE_GROW = 0x0f, - WASM_OP_TABLE_SIZE = 0x10, - WASM_OP_TABLE_FILL = 0x11, + WASM_OP_I32_TRUNC_SAT_S_F32 = 0x00, + WASM_OP_I32_TRUNC_SAT_U_F32 = 0x01, + WASM_OP_I32_TRUNC_SAT_S_F64 = 0x02, + WASM_OP_I32_TRUNC_SAT_U_F64 = 0x03, + WASM_OP_I64_TRUNC_SAT_S_F32 = 0x04, + WASM_OP_I64_TRUNC_SAT_U_F32 = 0x05, + WASM_OP_I64_TRUNC_SAT_S_F64 = 0x06, + WASM_OP_I64_TRUNC_SAT_U_F64 = 0x07, + WASM_OP_MEMORY_INIT = 0x08, + WASM_OP_DATA_DROP = 0x09, + WASM_OP_MEMORY_COPY = 0x0a, + WASM_OP_MEMORY_FILL = 0x0b, + WASM_OP_TABLE_INIT = 0x0c, + WASM_OP_ELEM_DROP = 0x0d, + WASM_OP_TABLE_COPY = 0x0e, + WASM_OP_TABLE_GROW = 0x0f, + WASM_OP_TABLE_SIZE = 0x10, + WASM_OP_TABLE_FILL = 0x11, } WASMMiscEXTOpcode; typedef enum WASMSimdEXTOpcode { /* memory instruction */ - SIMD_v128_load = 0x00, - SIMD_i16x8_load8x8_s = 0x01, - SIMD_i16x8_load8x8_u = 0x02, - SIMD_i32x4_load16x4_s = 0x03, - SIMD_i32x4_load16x4_u = 0x04, - SIMD_i64x2_load32x2_s = 0x05, - SIMD_i64x2_load32x2_u = 0x06, - SIMD_v8x16_load_splat = 0x07, - SIMD_v16x8_load_splat = 0x08, - SIMD_v32x4_load_splat = 0x09, - SIMD_v64x2_load_splat = 0x0a, - SIMD_v128_store = 0x0b, + SIMD_v128_load = 0x00, + SIMD_v128_load8x8_s = 0x01, + SIMD_v128_load8x8_u = 0x02, + SIMD_v128_load16x4_s = 0x03, + SIMD_v128_load16x4_u = 0x04, + SIMD_v128_load32x2_s = 0x05, + SIMD_v128_load32x2_u = 0x06, + SIMD_v128_load8_splat = 0x07, + SIMD_v128_load16_splat = 0x08, + SIMD_v128_load32_splat = 0x09, + SIMD_v128_load64_splat = 0x0a, + SIMD_v128_store = 0x0b, /* basic operation */ - SIMD_v128_const = 0x0c, - SIMD_v8x16_shuffle = 0x0d, - SIMD_v8x16_swizzle = 0x0e, + SIMD_v128_const = 0x0c, + SIMD_v8x16_shuffle = 0x0d, + SIMD_v8x16_swizzle = 0x0e, /* splat operation */ - SIMD_i8x16_splat = 0x0f, - SIMD_i16x8_splat = 0x10, - SIMD_i32x4_splat = 0x11, - SIMD_i64x2_splat = 0x12, - SIMD_f32x4_splat = 0x13, - SIMD_f64x2_splat = 0x14, + SIMD_i8x16_splat = 0x0f, + SIMD_i16x8_splat = 0x10, + SIMD_i32x4_splat = 0x11, + SIMD_i64x2_splat = 0x12, + SIMD_f32x4_splat = 0x13, + SIMD_f64x2_splat = 0x14, /* lane operation */ SIMD_i8x16_extract_lane_s = 0x15, SIMD_i8x16_extract_lane_u = 0x16, - SIMD_i8x16_replace_lane = 0x17, + SIMD_i8x16_replace_lane = 0x17, SIMD_i16x8_extract_lane_s = 0x18, SIMD_i16x8_extract_lane_u = 0x19, - SIMD_i16x8_replace_lane = 0x1a, - SIMD_i32x4_extract_lane = 0x1b, - SIMD_i32x4_replace_lane = 0x1c, - SIMD_i64x2_extract_lane = 0x1d, - SIMD_i64x2_replace_lane = 0x1e, - SIMD_f32x4_extract_lane = 0x1f, - SIMD_f32x4_replace_lane = 0x20, - SIMD_f64x2_extract_lane = 0x21, - SIMD_f64x2_replace_lane = 0x22, + SIMD_i16x8_replace_lane = 0x1a, + SIMD_i32x4_extract_lane = 0x1b, + SIMD_i32x4_replace_lane = 0x1c, + SIMD_i64x2_extract_lane = 0x1d, + SIMD_i64x2_replace_lane = 0x1e, + SIMD_f32x4_extract_lane = 0x1f, + SIMD_f32x4_replace_lane = 0x20, + SIMD_f64x2_extract_lane = 0x21, + SIMD_f64x2_replace_lane = 0x22, /* i8x16 compare operation */ - SIMD_i8x16_eq = 0x23, - SIMD_i8x16_ne = 0x24, - SIMD_i8x16_lt_s = 0x25, - SIMD_i8x16_lt_u = 0x26, - SIMD_i8x16_gt_s = 0x27, - SIMD_i8x16_gt_u = 0x28, - SIMD_i8x16_le_s = 0x29, - SIMD_i8x16_le_u = 0x2a, - SIMD_i8x16_ge_s = 0x2b, - SIMD_i8x16_ge_u = 0x2c, + SIMD_i8x16_eq = 0x23, + SIMD_i8x16_ne = 0x24, + SIMD_i8x16_lt_s = 0x25, + SIMD_i8x16_lt_u = 0x26, + SIMD_i8x16_gt_s = 0x27, + SIMD_i8x16_gt_u = 0x28, + SIMD_i8x16_le_s = 0x29, + SIMD_i8x16_le_u = 0x2a, + SIMD_i8x16_ge_s = 0x2b, + SIMD_i8x16_ge_u = 0x2c, /* i16x8 compare operation */ - SIMD_i16x8_eq = 0x2d, - SIMD_i16x8_ne = 0x2e, - SIMD_i16x8_lt_s = 0x2f, - SIMD_i16x8_lt_u = 0x30, - SIMD_i16x8_gt_s = 0x31, - SIMD_i16x8_gt_u = 0x32, - SIMD_i16x8_le_s = 0x33, - SIMD_i16x8_le_u = 0x34, - SIMD_i16x8_ge_s = 0x35, - SIMD_i16x8_ge_u = 0x36, + SIMD_i16x8_eq = 0x2d, + SIMD_i16x8_ne = 0x2e, + SIMD_i16x8_lt_s = 0x2f, + SIMD_i16x8_lt_u = 0x30, + SIMD_i16x8_gt_s = 0x31, + SIMD_i16x8_gt_u = 0x32, + SIMD_i16x8_le_s = 0x33, + SIMD_i16x8_le_u = 0x34, + SIMD_i16x8_ge_s = 0x35, + SIMD_i16x8_ge_u = 0x36, /* i32x4 compare operation */ - SIMD_i32x4_eq = 0x37, - SIMD_i32x4_ne = 0x38, - SIMD_i32x4_lt_s = 0x39, - SIMD_i32x4_lt_u = 0x3a, - SIMD_i32x4_gt_s = 0x3b, - SIMD_i32x4_gt_u = 0x3c, - SIMD_i32x4_le_s = 0x3d, - SIMD_i32x4_le_u = 0x3e, - SIMD_i32x4_ge_s = 0x3f, - SIMD_i32x4_ge_u = 0x40, + SIMD_i32x4_eq = 0x37, + SIMD_i32x4_ne = 0x38, + SIMD_i32x4_lt_s = 0x39, + SIMD_i32x4_lt_u = 0x3a, + SIMD_i32x4_gt_s = 0x3b, + SIMD_i32x4_gt_u = 0x3c, + SIMD_i32x4_le_s = 0x3d, + SIMD_i32x4_le_u = 0x3e, + SIMD_i32x4_ge_s = 0x3f, + SIMD_i32x4_ge_u = 0x40, /* f32x4 compare operation */ - SIMD_f32x4_eq = 0x41, - SIMD_f32x4_ne = 0x42, - SIMD_f32x4_lt = 0x43, - SIMD_f32x4_gt = 0x44, - SIMD_f32x4_le = 0x45, - SIMD_f32x4_ge = 0x46, + SIMD_f32x4_eq = 0x41, + SIMD_f32x4_ne = 0x42, + SIMD_f32x4_lt = 0x43, + SIMD_f32x4_gt = 0x44, + SIMD_f32x4_le = 0x45, + SIMD_f32x4_ge = 0x46, /* f64x2 compare operation */ - SIMD_f64x2_eq = 0x47, - SIMD_f64x2_ne = 0x48, - SIMD_f64x2_lt = 0x49, - SIMD_f64x2_gt = 0x4a, - SIMD_f64x2_le = 0x4b, - SIMD_f64x2_ge = 0x4c, + SIMD_f64x2_eq = 0x47, + SIMD_f64x2_ne = 0x48, + SIMD_f64x2_lt = 0x49, + SIMD_f64x2_gt = 0x4a, + SIMD_f64x2_le = 0x4b, + SIMD_f64x2_ge = 0x4c, /* v128 operation */ - SIMD_v128_not = 0x4d, - SIMD_v128_and = 0x4e, + SIMD_v128_not = 0x4d, + SIMD_v128_and = 0x4e, SIMD_v128_andnot = 0x4f, - SIMD_v128_or = 0x50, - SIMD_v128_xor = 0x51, + SIMD_v128_or = 0x50, + SIMD_v128_xor = 0x51, SIMD_v128_bitselect = 0x52, + SIMD_v128_any_true = 0x53, + + /* Load Lane Operation */ + SIMD_v128_load8_lane = 0x54, + SIMD_v128_load16_lane = 0x55, + SIMD_v128_load32_lane = 0x56, + SIMD_v128_load64_lane = 0x57, + SIMD_v128_store8_lane = 0x58, + SIMD_v128_store16_lane = 0x59, + SIMD_v128_store32_lane = 0x5a, + SIMD_v128_store64_lane = 0x5b, + SIMD_v128_load32_zero = 0x5c, + SIMD_v128_load64_zero = 0x5d, + + /* Float conversion */ + SIMD_f32x4_demote_f64x2_zero = 0x5e, + SIMD_f64x2_promote_low_f32x4_zero = 0x5f, /* i8x16 Operation */ - SIMD_i8x16_abs = 0x60, - SIMD_i8x16_neg = 0x61, - SIMD_i8x16_any_true = 0x62, - SIMD_i8x16_all_true = 0x63, - SIMD_i8x16_bitmask = 0x64, + SIMD_i8x16_abs = 0x60, + SIMD_i8x16_neg = 0x61, + SIMD_i8x16_popcnt = 0x62, + SIMD_i8x16_all_true = 0x63, + SIMD_i8x16_bitmask = 0x64, SIMD_i8x16_narrow_i16x8_s = 0x65, SIMD_i8x16_narrow_i16x8_u = 0x66, - SIMD_i8x16_shl = 0x6b, - SIMD_i8x16_shr_s = 0x6c, - SIMD_i8x16_shr_u = 0x6d, - SIMD_i8x16_add = 0x6e, - SIMD_i8x16_add_saturate_s = 0x6f, - SIMD_i8x16_add_saturate_u = 0x70, - SIMD_i8x16_sub = 0x71, - SIMD_i8x16_sub_saturate_s = 0x72, - SIMD_i8x16_sub_saturate_u = 0x73, - SIMD_i8x16_min_s = 0x76, - SIMD_i8x16_min_u = 0x77, - SIMD_i8x16_max_s = 0x78, - SIMD_i8x16_max_u = 0x79, - SIMD_i8x16_avgr_u = 0x7b, + SIMD_f32x4_ceil = 0x67, + SIMD_f32x4_floor = 0x68, + SIMD_f32x4_trunc = 0x69, + SIMD_f32x4_nearest = 0x6a, + SIMD_i8x16_shl = 0x6b, + SIMD_i8x16_shr_s = 0x6c, + SIMD_i8x16_shr_u = 0x6d, + SIMD_i8x16_add = 0x6e, + SIMD_i8x16_add_sat_s = 0x6f, + SIMD_i8x16_add_sat_u = 0x70, + SIMD_i8x16_sub = 0x71, + SIMD_i8x16_sub_sat_s = 0x72, + SIMD_i8x16_sub_sat_u = 0x73, + SIMD_f64x2_ceil = 0x74, + SIMD_f64x2_floor = 0x75, + SIMD_i8x16_min_s = 0x76, + SIMD_i8x16_min_u = 0x77, + SIMD_i8x16_max_s = 0x78, + SIMD_i8x16_max_u = 0x79, + SIMD_f64x2_trunc = 0x7a, + SIMD_i8x16_avgr_u = 0x7b, + SIMD_i16x8_extadd_pairwise_i8x16_s = 0x7c, + SIMD_i16x8_extadd_pairwise_i8x16_u = 0x7d, + SIMD_i32x4_extadd_pairwise_i16x8_s = 0x7e, + SIMD_i32x4_extadd_pairwise_i16x8_u = 0x7f, /* i16x8 operation */ - SIMD_i16x8_abs = 0x80, - SIMD_i16x8_neg = 0x81, - SIMD_i16x8_any_true = 0x82, - SIMD_i16x8_all_true = 0x83, - SIMD_i16x8_bitmask = 0x84, + SIMD_i16x8_abs = 0x80, + SIMD_i16x8_neg = 0x81, + SIMD_i16x8_q15mulr_sat_s = 0x82, + SIMD_i16x8_all_true = 0x83, + SIMD_i16x8_bitmask = 0x84, SIMD_i16x8_narrow_i32x4_s = 0x85, SIMD_i16x8_narrow_i32x4_u = 0x86, - SIMD_i16x8_widen_low_i8x16_s = 0x87, - SIMD_i16x8_widen_high_i8x16_s = 0x88, - SIMD_i16x8_widen_low_i8x16_u = 0x89, - SIMD_i16x8_widen_high_i8x16_u = 0x8a, - SIMD_i16x8_shl = 0x8b, - SIMD_i16x8_shr_s = 0x8c, - SIMD_i16x8_shr_u = 0x8d, - SIMD_i16x8_add = 0x8e, - SIMD_i16x8_add_saturate_s = 0x8f, - SIMD_i16x8_add_saturate_u = 0x90, - SIMD_i16x8_sub = 0x91, - SIMD_i16x8_sub_saturate_s = 0x92, - SIMD_i16x8_sub_saturate_u = 0x93, - SIMD_i16x8_mul = 0x95, - SIMD_i16x8_min_s = 0x96, - SIMD_i16x8_min_u = 0x97, - SIMD_i16x8_max_s = 0x98, - SIMD_i16x8_max_u = 0x99, - SIMD_i16x8_avgr_u = 0x9b, + SIMD_i16x8_extend_low_i8x16_s = 0x87, + SIMD_i16x8_extend_high_i8x16_s = 0x88, + SIMD_i16x8_extend_low_i8x16_u = 0x89, + SIMD_i16x8_extend_high_i8x16_u = 0x8a, + SIMD_i16x8_shl = 0x8b, + SIMD_i16x8_shr_s = 0x8c, + SIMD_i16x8_shr_u = 0x8d, + SIMD_i16x8_add = 0x8e, + SIMD_i16x8_add_sat_s = 0x8f, + SIMD_i16x8_add_sat_u = 0x90, + SIMD_i16x8_sub = 0x91, + SIMD_i16x8_sub_sat_s = 0x92, + SIMD_i16x8_sub_sat_u = 0x93, + SIMD_f64x2_nearest = 0x94, + SIMD_i16x8_mul = 0x95, + SIMD_i16x8_min_s = 0x96, + SIMD_i16x8_min_u = 0x97, + SIMD_i16x8_max_s = 0x98, + SIMD_i16x8_max_u = 0x99, + /* placeholder = 0x9a */ + SIMD_i16x8_avgr_u = 0x9b, + SIMD_i16x8_extmul_low_i8x16_s = 0x9c, + SIMD_i16x8_extmul_high_i8x16_s = 0x9d, + SIMD_i16x8_extmul_low_i8x16_u = 0x9e, + SIMD_i16x8_extmul_high_i8x16_u = 0x9f, /* i32x4 operation */ - SIMD_i32x4_abs = 0xa0, - SIMD_i32x4_neg = 0xa1, - SIMD_i32x4_any_true = 0xa2, - SIMD_i32x4_all_true = 0xa3, - SIMD_i32x4_bitmask = 0xa4, - SIMD_i32x4_widen_low_i16x8_s = 0xa7, - SIMD_i32x4_widen_high_i16x8_s = 0xa8, - SIMD_i32x4_widen_low_i16x8_u = 0xa9, - SIMD_i32x4_widen_high_i16x8_u = 0xaa, - SIMD_i32x4_shl = 0xab, - SIMD_i32x4_shr_s = 0xac, - SIMD_i32x4_shr_u = 0xad, - SIMD_i32x4_add = 0xae, - SIMD_i32x4_sub = 0xb1, - SIMD_i32x4_mul = 0xb5, - SIMD_i32x4_min_s = 0xb6, - SIMD_i32x4_min_u = 0xb7, - SIMD_i32x4_max_s = 0xb8, - SIMD_i32x4_max_u = 0xb9, + SIMD_i32x4_abs = 0xa0, + SIMD_i32x4_neg = 0xa1, + /* placeholder = 0xa2 */ + SIMD_i32x4_all_true = 0xa3, + SIMD_i32x4_bitmask = 0xa4, + SIMD_i32x4_narrow_i64x2_s = 0xa5, + SIMD_i32x4_narrow_i64x2_u = 0xa6, + SIMD_i32x4_extend_low_i16x8_s = 0xa7, + SIMD_i32x4_extend_high_i16x8_s = 0xa8, + SIMD_i32x4_extend_low_i16x8_u = 0xa9, + SIMD_i32x4_extend_high_i16x8_u = 0xaa, + SIMD_i32x4_shl = 0xab, + SIMD_i32x4_shr_s = 0xac, + SIMD_i32x4_shr_u = 0xad, + SIMD_i32x4_add = 0xae, + SIMD_i32x4_add_sat_s = 0xaf, + SIMD_i32x4_add_sat_u = 0xb0, + SIMD_i32x4_sub = 0xb1, + SIMD_i32x4_sub_sat_s = 0xb2, + SIMD_i32x4_sub_sat_u = 0xb3, + /* placeholder = 0xb4 */ + SIMD_i32x4_mul = 0xb5, + SIMD_i32x4_min_s = 0xb6, + SIMD_i32x4_min_u = 0xb7, + SIMD_i32x4_max_s = 0xb8, + SIMD_i32x4_max_u = 0xb9, + SIMD_i32x4_dot_i16x8_s = 0xba, + SIMD_i32x4_avgr_u = 0xbb, + SIMD_i32x4_extmul_low_i16x8_s = 0xbc, + SIMD_i32x4_extmul_high_i16x8_s = 0xbd, + SIMD_i32x4_extmul_low_i16x8_u = 0xbe, + SIMD_i32x4_extmul_high_i16x8_u = 0xbf, /* i64x2 operation */ - SIMD_i64x2_neg = 0xc1, - SIMD_i64x2_shl = 0xcb, - SIMD_i64x2_shr_s = 0xcc, - SIMD_i64x2_shr_u = 0xcd, - SIMD_i64x2_add = 0xce, - SIMD_i64x2_sub = 0xd1, - SIMD_i64x2_mul = 0xd5, - - /* float ceil/floor/trunc/nearest */ - SIMD_f32x4_ceil = 0xd8, - SIMD_f32x4_floor = 0xd9, - SIMD_f32x4_trunc = 0xda, - SIMD_f32x4_nearest = 0xdb, - SIMD_f64x2_ceil = 0xdc, - SIMD_f64x2_floor = 0xdd, - SIMD_f64x2_trunc = 0xde, - SIMD_f64x2_nearest = 0xdf, + SIMD_i64x2_abs = 0xc0, + SIMD_i64x2_neg = 0xc1, + /* placeholder = 0xc2 */ + SIMD_i64x2_all_true = 0xc3, + SIMD_i64x2_bitmask = 0xc4, + /* placeholder = 0xc5 */ + /* placeholder = 0xc6 */ + SIMD_i64x2_extend_low_i32x4_s = 0xc7, + SIMD_i64x2_extend_high_i32x4_s = 0xc8, + SIMD_i64x2_extend_low_i32x4_u = 0xc9, + SIMD_i64x2_extend_high_i32x4_u = 0xca, + SIMD_i64x2_shl = 0xcb, + SIMD_i64x2_shr_s = 0xcc, + SIMD_i64x2_shr_u = 0xcd, + SIMD_i64x2_add = 0xce, + /* placeholder = 0xcf */ + /* placeholder = 0xd0 */ + SIMD_i64x2_sub = 0xd1, + /* placeholder = 0xd2 */ + /* placeholder = 0xd3 */ + /* placeholder = 0xd4 */ + SIMD_i64x2_mul = 0xd5, + SIMD_i64x2_eq = 0xd6, + SIMD_i64x2_ne = 0xd7, + SIMD_i64x2_lt_s = 0xd8, + SIMD_i64x2_gt_s = 0xd9, + SIMD_i64x2_le_s = 0xda, + SIMD_i64x2_ge_s = 0xdb, + SIMD_i64x2_extmul_low_i32x4_s = 0xdc, + SIMD_i64x2_extmul_high_i32x4_s = 0xdd, + SIMD_i64x2_extmul_low_i32x4_u = 0xde, + SIMD_i64x2_extmul_high_i32x4_u = 0xdf, /* f32x4 operation */ - SIMD_f32x4_abs = 0xe0, - SIMD_f32x4_neg = 0xe1, - SIMD_f32x4_sqrt = 0xe3, - SIMD_f32x4_add = 0xe4, - SIMD_f32x4_sub = 0xe5, - SIMD_f32x4_mul = 0xe6, - SIMD_f32x4_div = 0xe7, - SIMD_f32x4_min = 0xe8, - SIMD_f32x4_max = 0xe9, + SIMD_f32x4_abs = 0xe0, + SIMD_f32x4_neg = 0xe1, + SIMD_f32x4_round = 0xe2, + SIMD_f32x4_sqrt = 0xe3, + SIMD_f32x4_add = 0xe4, + SIMD_f32x4_sub = 0xe5, + SIMD_f32x4_mul = 0xe6, + SIMD_f32x4_div = 0xe7, + SIMD_f32x4_min = 0xe8, + SIMD_f32x4_max = 0xe9, + SIMD_f32x4_pmin = 0xea, + SIMD_f32x4_pmax = 0xeb, /* f64x2 operation */ - SIMD_f64x2_abs = 0xec, - SIMD_f64x2_neg = 0xed, - SIMD_f64x2_sqrt = 0xef, - SIMD_f64x2_add = 0xf0, - SIMD_f64x2_sub = 0xf1, - SIMD_f64x2_mul = 0xf2, - SIMD_f64x2_div = 0xf3, - SIMD_f64x2_min = 0xf4, - SIMD_f64x2_max = 0xf5, + SIMD_f64x2_abs = 0xec, + SIMD_f64x2_neg = 0xed, + SIMD_f64x2_round = 0xee, + SIMD_f64x2_sqrt = 0xef, + SIMD_f64x2_add = 0xf0, + SIMD_f64x2_sub = 0xf1, + SIMD_f64x2_mul = 0xf2, + SIMD_f64x2_div = 0xf3, + SIMD_f64x2_min = 0xf4, + SIMD_f64x2_max = 0xf5, + SIMD_f64x2_pmin = 0xf6, + SIMD_f64x2_pmax = 0xf7, /* conversion operation */ SIMD_i32x4_trunc_sat_f32x4_s = 0xf8, SIMD_i32x4_trunc_sat_f32x4_u = 0xf9, - SIMD_f32x4_convert_i32x4_s = 0xfa, - SIMD_f32x4_convert_i32x4_u = 0xfb, + SIMD_f32x4_convert_i32x4_s = 0xfa, + SIMD_f32x4_convert_i32x4_u = 0xfb, + SIMD_i32x4_trunc_sat_f64x2_s_zero = 0xfc, + SIMD_i32x4_trunc_sat_f64x2_u_zero = 0xfd, + SIMD_f64x2_convert_low_i32x4_s = 0xfe, + SIMD_f64x2_convert_low_i32x4_u = 0xff, } WASMSimdEXTOpcode; typedef enum WASMAtomicEXTOpcode { /* atomic wait and notify */ - WASM_OP_ATOMIC_NOTIFY = 0x00, - WASM_OP_ATOMIC_WAIT32 = 0x01, - WASM_OP_ATOMIC_WAIT64 = 0x02, - WASM_OP_ATOMIC_FENCE = 0x03, + WASM_OP_ATOMIC_NOTIFY = 0x00, + WASM_OP_ATOMIC_WAIT32 = 0x01, + WASM_OP_ATOMIC_WAIT64 = 0x02, + WASM_OP_ATOMIC_FENCE = 0x03, /* atomic load and store */ - WASM_OP_ATOMIC_I32_LOAD = 0x10, - WASM_OP_ATOMIC_I64_LOAD = 0x11, - WASM_OP_ATOMIC_I32_LOAD8_U = 0x12, - WASM_OP_ATOMIC_I32_LOAD16_U = 0x13, - WASM_OP_ATOMIC_I64_LOAD8_U = 0x14, - WASM_OP_ATOMIC_I64_LOAD16_U = 0x15, - WASM_OP_ATOMIC_I64_LOAD32_U = 0x16, - WASM_OP_ATOMIC_I32_STORE = 0x17, - WASM_OP_ATOMIC_I64_STORE = 0x18, - WASM_OP_ATOMIC_I32_STORE8 = 0x19, - WASM_OP_ATOMIC_I32_STORE16 = 0x1a, - WASM_OP_ATOMIC_I64_STORE8 = 0x1b, - WASM_OP_ATOMIC_I64_STORE16 = 0x1c, - WASM_OP_ATOMIC_I64_STORE32 = 0x1d, + WASM_OP_ATOMIC_I32_LOAD = 0x10, + WASM_OP_ATOMIC_I64_LOAD = 0x11, + WASM_OP_ATOMIC_I32_LOAD8_U = 0x12, + WASM_OP_ATOMIC_I32_LOAD16_U = 0x13, + WASM_OP_ATOMIC_I64_LOAD8_U = 0x14, + WASM_OP_ATOMIC_I64_LOAD16_U = 0x15, + WASM_OP_ATOMIC_I64_LOAD32_U = 0x16, + WASM_OP_ATOMIC_I32_STORE = 0x17, + WASM_OP_ATOMIC_I64_STORE = 0x18, + WASM_OP_ATOMIC_I32_STORE8 = 0x19, + WASM_OP_ATOMIC_I32_STORE16 = 0x1a, + WASM_OP_ATOMIC_I64_STORE8 = 0x1b, + WASM_OP_ATOMIC_I64_STORE16 = 0x1c, + WASM_OP_ATOMIC_I64_STORE32 = 0x1d, /* atomic add */ - WASM_OP_ATOMIC_RMW_I32_ADD = 0x1e, - WASM_OP_ATOMIC_RMW_I64_ADD = 0x1f, - WASM_OP_ATOMIC_RMW_I32_ADD8_U = 0x20, - WASM_OP_ATOMIC_RMW_I32_ADD16_U = 0x21, - WASM_OP_ATOMIC_RMW_I64_ADD8_U = 0x22, - WASM_OP_ATOMIC_RMW_I64_ADD16_U = 0x23, - WASM_OP_ATOMIC_RMW_I64_ADD32_U = 0x24, + WASM_OP_ATOMIC_RMW_I32_ADD = 0x1e, + WASM_OP_ATOMIC_RMW_I64_ADD = 0x1f, + WASM_OP_ATOMIC_RMW_I32_ADD8_U = 0x20, + WASM_OP_ATOMIC_RMW_I32_ADD16_U = 0x21, + WASM_OP_ATOMIC_RMW_I64_ADD8_U = 0x22, + WASM_OP_ATOMIC_RMW_I64_ADD16_U = 0x23, + WASM_OP_ATOMIC_RMW_I64_ADD32_U = 0x24, /* atomic sub */ - WASM_OP_ATOMIC_RMW_I32_SUB = 0x25, - WASM_OP_ATOMIC_RMW_I64_SUB = 0x26, - WASM_OP_ATOMIC_RMW_I32_SUB8_U = 0x27, - WASM_OP_ATOMIC_RMW_I32_SUB16_U = 0x28, - WASM_OP_ATOMIC_RMW_I64_SUB8_U = 0x29, - WASM_OP_ATOMIC_RMW_I64_SUB16_U = 0x2a, - WASM_OP_ATOMIC_RMW_I64_SUB32_U = 0x2b, + WASM_OP_ATOMIC_RMW_I32_SUB = 0x25, + WASM_OP_ATOMIC_RMW_I64_SUB = 0x26, + WASM_OP_ATOMIC_RMW_I32_SUB8_U = 0x27, + WASM_OP_ATOMIC_RMW_I32_SUB16_U = 0x28, + WASM_OP_ATOMIC_RMW_I64_SUB8_U = 0x29, + WASM_OP_ATOMIC_RMW_I64_SUB16_U = 0x2a, + WASM_OP_ATOMIC_RMW_I64_SUB32_U = 0x2b, /* atomic and */ - WASM_OP_ATOMIC_RMW_I32_AND = 0x2c, - WASM_OP_ATOMIC_RMW_I64_AND = 0x2d, - WASM_OP_ATOMIC_RMW_I32_AND8_U = 0x2e, - WASM_OP_ATOMIC_RMW_I32_AND16_U = 0x2f, - WASM_OP_ATOMIC_RMW_I64_AND8_U = 0x30, - WASM_OP_ATOMIC_RMW_I64_AND16_U = 0x31, - WASM_OP_ATOMIC_RMW_I64_AND32_U = 0x32, + WASM_OP_ATOMIC_RMW_I32_AND = 0x2c, + WASM_OP_ATOMIC_RMW_I64_AND = 0x2d, + WASM_OP_ATOMIC_RMW_I32_AND8_U = 0x2e, + WASM_OP_ATOMIC_RMW_I32_AND16_U = 0x2f, + WASM_OP_ATOMIC_RMW_I64_AND8_U = 0x30, + WASM_OP_ATOMIC_RMW_I64_AND16_U = 0x31, + WASM_OP_ATOMIC_RMW_I64_AND32_U = 0x32, /* atomic or */ - WASM_OP_ATOMIC_RMW_I32_OR = 0x33, - WASM_OP_ATOMIC_RMW_I64_OR = 0x34, - WASM_OP_ATOMIC_RMW_I32_OR8_U = 0x35, - WASM_OP_ATOMIC_RMW_I32_OR16_U = 0x36, - WASM_OP_ATOMIC_RMW_I64_OR8_U = 0x37, - WASM_OP_ATOMIC_RMW_I64_OR16_U = 0x38, - WASM_OP_ATOMIC_RMW_I64_OR32_U = 0x39, + WASM_OP_ATOMIC_RMW_I32_OR = 0x33, + WASM_OP_ATOMIC_RMW_I64_OR = 0x34, + WASM_OP_ATOMIC_RMW_I32_OR8_U = 0x35, + WASM_OP_ATOMIC_RMW_I32_OR16_U = 0x36, + WASM_OP_ATOMIC_RMW_I64_OR8_U = 0x37, + WASM_OP_ATOMIC_RMW_I64_OR16_U = 0x38, + WASM_OP_ATOMIC_RMW_I64_OR32_U = 0x39, /* atomic xor */ - WASM_OP_ATOMIC_RMW_I32_XOR = 0x3a, - WASM_OP_ATOMIC_RMW_I64_XOR = 0x3b, - WASM_OP_ATOMIC_RMW_I32_XOR8_U = 0x3c, - WASM_OP_ATOMIC_RMW_I32_XOR16_U = 0x3d, - WASM_OP_ATOMIC_RMW_I64_XOR8_U = 0x3e, - WASM_OP_ATOMIC_RMW_I64_XOR16_U = 0x3f, - WASM_OP_ATOMIC_RMW_I64_XOR32_U = 0x40, + WASM_OP_ATOMIC_RMW_I32_XOR = 0x3a, + WASM_OP_ATOMIC_RMW_I64_XOR = 0x3b, + WASM_OP_ATOMIC_RMW_I32_XOR8_U = 0x3c, + WASM_OP_ATOMIC_RMW_I32_XOR16_U = 0x3d, + WASM_OP_ATOMIC_RMW_I64_XOR8_U = 0x3e, + WASM_OP_ATOMIC_RMW_I64_XOR16_U = 0x3f, + WASM_OP_ATOMIC_RMW_I64_XOR32_U = 0x40, /* atomic xchg */ - WASM_OP_ATOMIC_RMW_I32_XCHG = 0x41, - WASM_OP_ATOMIC_RMW_I64_XCHG = 0x42, - WASM_OP_ATOMIC_RMW_I32_XCHG8_U = 0x43, - WASM_OP_ATOMIC_RMW_I32_XCHG16_U = 0x44, - WASM_OP_ATOMIC_RMW_I64_XCHG8_U = 0x45, - WASM_OP_ATOMIC_RMW_I64_XCHG16_U = 0x46, - WASM_OP_ATOMIC_RMW_I64_XCHG32_U = 0x47, + WASM_OP_ATOMIC_RMW_I32_XCHG = 0x41, + WASM_OP_ATOMIC_RMW_I64_XCHG = 0x42, + WASM_OP_ATOMIC_RMW_I32_XCHG8_U = 0x43, + WASM_OP_ATOMIC_RMW_I32_XCHG16_U = 0x44, + WASM_OP_ATOMIC_RMW_I64_XCHG8_U = 0x45, + WASM_OP_ATOMIC_RMW_I64_XCHG16_U = 0x46, + WASM_OP_ATOMIC_RMW_I64_XCHG32_U = 0x47, /* atomic cmpxchg */ - WASM_OP_ATOMIC_RMW_I32_CMPXCHG = 0x48, - WASM_OP_ATOMIC_RMW_I64_CMPXCHG = 0x49, - WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U = 0x4a, - WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U = 0x4b, - WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U = 0x4c, - WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U = 0x4d, - WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U = 0x4e, + WASM_OP_ATOMIC_RMW_I32_CMPXCHG = 0x48, + WASM_OP_ATOMIC_RMW_I64_CMPXCHG = 0x49, + WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U = 0x4a, + WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U = 0x4b, + WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U = 0x4c, + WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U = 0x4d, + WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U = 0x4e, } WASMAtomicEXTOpcode; -#ifdef __cplusplus -} +#if WASM_ENABLE_DEBUG_INTERP != 0 +#define DEF_DEBUG_BREAK_HANDLE(_name) \ + _name[DEBUG_OP_BREAK] = HANDLE_OPCODE(DEBUG_OP_BREAK); /* 0xd6 */ +#else +#define DEF_DEBUG_BREAK_HANDLE(_name) #endif /* @@ -606,228 +685,233 @@ typedef enum WASMAtomicEXTOpcode { */ #define WASM_INSTRUCTION_NUM 256 -#define DEFINE_GOTO_TABLE(type, _name) \ -static type _name[WASM_INSTRUCTION_NUM] = { \ - HANDLE_OPCODE (WASM_OP_UNREACHABLE), /* 0x00 */ \ - HANDLE_OPCODE (WASM_OP_NOP), /* 0x01 */ \ - HANDLE_OPCODE (WASM_OP_BLOCK), /* 0x02 */ \ - 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_UNUSED_0x0a), /* 0x0a */ \ - HANDLE_OPCODE (WASM_OP_END), /* 0x0b */ \ - HANDLE_OPCODE (WASM_OP_BR), /* 0x0c */ \ - HANDLE_OPCODE (WASM_OP_BR_IF), /* 0x0d */ \ - HANDLE_OPCODE (WASM_OP_BR_TABLE), /* 0x0e */ \ - HANDLE_OPCODE (WASM_OP_RETURN), /* 0x0f */ \ - HANDLE_OPCODE (WASM_OP_CALL), /* 0x10 */ \ - HANDLE_OPCODE (WASM_OP_CALL_INDIRECT), /* 0x11 */ \ - HANDLE_OPCODE (WASM_OP_RETURN_CALL), /* 0x12 */ \ - HANDLE_OPCODE (WASM_OP_RETURN_CALL_INDIRECT), /* 0x13 */ \ - HANDLE_OPCODE (WASM_OP_UNUSED_0x14), /* 0x14 */ \ - 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_DROP), /* 0x1a */ \ - HANDLE_OPCODE (WASM_OP_SELECT), /* 0x1b */ \ - HANDLE_OPCODE (WASM_OP_SELECT_T), /* 0x1c */ \ - HANDLE_OPCODE (WASM_OP_GET_GLOBAL_64), /* 0x1d */ \ - HANDLE_OPCODE (WASM_OP_SET_GLOBAL_64), /* 0x1e */ \ - HANDLE_OPCODE (WASM_OP_SET_GLOBAL_AUX_STACK), /* 0x1f */ \ - HANDLE_OPCODE (WASM_OP_GET_LOCAL), /* 0x20 */ \ - HANDLE_OPCODE (WASM_OP_SET_LOCAL), /* 0x21 */ \ - HANDLE_OPCODE (WASM_OP_TEE_LOCAL), /* 0x22 */ \ - HANDLE_OPCODE (WASM_OP_GET_GLOBAL), /* 0x23 */ \ - HANDLE_OPCODE (WASM_OP_SET_GLOBAL), /* 0x24 */ \ - HANDLE_OPCODE (WASM_OP_TABLE_GET), /* 0x25 */ \ - HANDLE_OPCODE (WASM_OP_TABLE_SET), /* 0x26 */ \ - HANDLE_OPCODE (WASM_OP_UNUSED_0x27), /* 0x27 */ \ - HANDLE_OPCODE (WASM_OP_I32_LOAD), /* 0x28 */ \ - HANDLE_OPCODE (WASM_OP_I64_LOAD), /* 0x29 */ \ - HANDLE_OPCODE (WASM_OP_F32_LOAD), /* 0x2a */ \ - HANDLE_OPCODE (WASM_OP_F64_LOAD), /* 0x2b */ \ - HANDLE_OPCODE (WASM_OP_I32_LOAD8_S), /* 0x2c */ \ - HANDLE_OPCODE (WASM_OP_I32_LOAD8_U), /* 0x2d */ \ - HANDLE_OPCODE (WASM_OP_I32_LOAD16_S), /* 0x2e */ \ - HANDLE_OPCODE (WASM_OP_I32_LOAD16_U), /* 0x2f */ \ - HANDLE_OPCODE (WASM_OP_I64_LOAD8_S), /* 0x30 */ \ - HANDLE_OPCODE (WASM_OP_I64_LOAD8_U), /* 0x31 */ \ - HANDLE_OPCODE (WASM_OP_I64_LOAD16_S), /* 0x32 */ \ - HANDLE_OPCODE (WASM_OP_I64_LOAD16_U), /* 0x33 */ \ - HANDLE_OPCODE (WASM_OP_I64_LOAD32_S), /* 0x34 */ \ - HANDLE_OPCODE (WASM_OP_I64_LOAD32_U), /* 0x35 */ \ - HANDLE_OPCODE (WASM_OP_I32_STORE), /* 0x36 */ \ - HANDLE_OPCODE (WASM_OP_I64_STORE), /* 0x37 */ \ - HANDLE_OPCODE (WASM_OP_F32_STORE), /* 0x38 */ \ - HANDLE_OPCODE (WASM_OP_F64_STORE), /* 0x39 */ \ - HANDLE_OPCODE (WASM_OP_I32_STORE8), /* 0x3a */ \ - HANDLE_OPCODE (WASM_OP_I32_STORE16), /* 0x3b */ \ - HANDLE_OPCODE (WASM_OP_I64_STORE8), /* 0x3c */ \ - HANDLE_OPCODE (WASM_OP_I64_STORE16), /* 0x3d */ \ - HANDLE_OPCODE (WASM_OP_I64_STORE32), /* 0x3e */ \ - HANDLE_OPCODE (WASM_OP_MEMORY_SIZE), /* 0x3f */ \ - HANDLE_OPCODE (WASM_OP_MEMORY_GROW), /* 0x40 */ \ - HANDLE_OPCODE (WASM_OP_I32_CONST), /* 0x41 */ \ - HANDLE_OPCODE (WASM_OP_I64_CONST), /* 0x42 */ \ - HANDLE_OPCODE (WASM_OP_F32_CONST), /* 0x43 */ \ - HANDLE_OPCODE (WASM_OP_F64_CONST), /* 0x44 */ \ - HANDLE_OPCODE (WASM_OP_I32_EQZ), /* 0x45 */ \ - HANDLE_OPCODE (WASM_OP_I32_EQ), /* 0x46 */ \ - HANDLE_OPCODE (WASM_OP_I32_NE), /* 0x47 */ \ - HANDLE_OPCODE (WASM_OP_I32_LT_S), /* 0x48 */ \ - HANDLE_OPCODE (WASM_OP_I32_LT_U), /* 0x49 */ \ - HANDLE_OPCODE (WASM_OP_I32_GT_S), /* 0x4a */ \ - HANDLE_OPCODE (WASM_OP_I32_GT_U), /* 0x4b */ \ - HANDLE_OPCODE (WASM_OP_I32_LE_S), /* 0x4c */ \ - HANDLE_OPCODE (WASM_OP_I32_LE_U), /* 0x4d */ \ - HANDLE_OPCODE (WASM_OP_I32_GE_S), /* 0x4e */ \ - HANDLE_OPCODE (WASM_OP_I32_GE_U), /* 0x4f */ \ - HANDLE_OPCODE (WASM_OP_I64_EQZ), /* 0x50 */ \ - HANDLE_OPCODE (WASM_OP_I64_EQ), /* 0x51 */ \ - HANDLE_OPCODE (WASM_OP_I64_NE), /* 0x52 */ \ - HANDLE_OPCODE (WASM_OP_I64_LT_S), /* 0x53 */ \ - HANDLE_OPCODE (WASM_OP_I64_LT_U), /* 0x54 */ \ - HANDLE_OPCODE (WASM_OP_I64_GT_S), /* 0x55 */ \ - HANDLE_OPCODE (WASM_OP_I64_GT_U), /* 0x56 */ \ - HANDLE_OPCODE (WASM_OP_I64_LE_S), /* 0x57 */ \ - HANDLE_OPCODE (WASM_OP_I64_LE_U), /* 0x58 */ \ - HANDLE_OPCODE (WASM_OP_I64_GE_S), /* 0x59 */ \ - HANDLE_OPCODE (WASM_OP_I64_GE_U), /* 0x5a */ \ - HANDLE_OPCODE (WASM_OP_F32_EQ), /* 0x5b */ \ - HANDLE_OPCODE (WASM_OP_F32_NE), /* 0x5c */ \ - HANDLE_OPCODE (WASM_OP_F32_LT), /* 0x5d */ \ - HANDLE_OPCODE (WASM_OP_F32_GT), /* 0x5e */ \ - HANDLE_OPCODE (WASM_OP_F32_LE), /* 0x5f */ \ - HANDLE_OPCODE (WASM_OP_F32_GE), /* 0x60 */ \ - HANDLE_OPCODE (WASM_OP_F64_EQ), /* 0x61 */ \ - HANDLE_OPCODE (WASM_OP_F64_NE), /* 0x62 */ \ - HANDLE_OPCODE (WASM_OP_F64_LT), /* 0x63 */ \ - HANDLE_OPCODE (WASM_OP_F64_GT), /* 0x64 */ \ - HANDLE_OPCODE (WASM_OP_F64_LE), /* 0x65 */ \ - HANDLE_OPCODE (WASM_OP_F64_GE), /* 0x66 */ \ - HANDLE_OPCODE (WASM_OP_I32_CLZ), /* 0x67 */ \ - HANDLE_OPCODE (WASM_OP_I32_CTZ), /* 0x68 */ \ - HANDLE_OPCODE (WASM_OP_I32_POPCNT), /* 0x69 */ \ - HANDLE_OPCODE (WASM_OP_I32_ADD), /* 0x6a */ \ - HANDLE_OPCODE (WASM_OP_I32_SUB), /* 0x6b */ \ - HANDLE_OPCODE (WASM_OP_I32_MUL), /* 0x6c */ \ - HANDLE_OPCODE (WASM_OP_I32_DIV_S), /* 0x6d */ \ - HANDLE_OPCODE (WASM_OP_I32_DIV_U), /* 0x6e */ \ - HANDLE_OPCODE (WASM_OP_I32_REM_S), /* 0x6f */ \ - HANDLE_OPCODE (WASM_OP_I32_REM_U), /* 0x70 */ \ - HANDLE_OPCODE (WASM_OP_I32_AND), /* 0x71 */ \ - HANDLE_OPCODE (WASM_OP_I32_OR), /* 0x72 */ \ - HANDLE_OPCODE (WASM_OP_I32_XOR), /* 0x73 */ \ - HANDLE_OPCODE (WASM_OP_I32_SHL), /* 0x74 */ \ - HANDLE_OPCODE (WASM_OP_I32_SHR_S), /* 0x75 */ \ - HANDLE_OPCODE (WASM_OP_I32_SHR_U), /* 0x76 */ \ - HANDLE_OPCODE (WASM_OP_I32_ROTL), /* 0x77 */ \ - HANDLE_OPCODE (WASM_OP_I32_ROTR), /* 0x78 */ \ - HANDLE_OPCODE (WASM_OP_I64_CLZ), /* 0x79 */ \ - HANDLE_OPCODE (WASM_OP_I64_CTZ), /* 0x7a */ \ - HANDLE_OPCODE (WASM_OP_I64_POPCNT), /* 0x7b */ \ - HANDLE_OPCODE (WASM_OP_I64_ADD), /* 0x7c */ \ - HANDLE_OPCODE (WASM_OP_I64_SUB), /* 0x7d */ \ - HANDLE_OPCODE (WASM_OP_I64_MUL), /* 0x7e */ \ - HANDLE_OPCODE (WASM_OP_I64_DIV_S), /* 0x7f */ \ - HANDLE_OPCODE (WASM_OP_I64_DIV_U), /* 0x80 */ \ - HANDLE_OPCODE (WASM_OP_I64_REM_S), /* 0x81 */ \ - HANDLE_OPCODE (WASM_OP_I64_REM_U), /* 0x82 */ \ - HANDLE_OPCODE (WASM_OP_I64_AND), /* 0x83 */ \ - HANDLE_OPCODE (WASM_OP_I64_OR), /* 0x84 */ \ - HANDLE_OPCODE (WASM_OP_I64_XOR), /* 0x85 */ \ - HANDLE_OPCODE (WASM_OP_I64_SHL), /* 0x86 */ \ - HANDLE_OPCODE (WASM_OP_I64_SHR_S), /* 0x87 */ \ - HANDLE_OPCODE (WASM_OP_I64_SHR_U), /* 0x88 */ \ - HANDLE_OPCODE (WASM_OP_I64_ROTL), /* 0x89 */ \ - HANDLE_OPCODE (WASM_OP_I64_ROTR), /* 0x8a */ \ - HANDLE_OPCODE (WASM_OP_F32_ABS), /* 0x8b */ \ - HANDLE_OPCODE (WASM_OP_F32_NEG), /* 0x8c */ \ - HANDLE_OPCODE (WASM_OP_F32_CEIL), /* 0x8d */ \ - HANDLE_OPCODE (WASM_OP_F32_FLOOR), /* 0x8e */ \ - HANDLE_OPCODE (WASM_OP_F32_TRUNC), /* 0x8f */ \ - HANDLE_OPCODE (WASM_OP_F32_NEAREST), /* 0x90 */ \ - HANDLE_OPCODE (WASM_OP_F32_SQRT), /* 0x91 */ \ - HANDLE_OPCODE (WASM_OP_F32_ADD), /* 0x92 */ \ - HANDLE_OPCODE (WASM_OP_F32_SUB), /* 0x93 */ \ - HANDLE_OPCODE (WASM_OP_F32_MUL), /* 0x94 */ \ - HANDLE_OPCODE (WASM_OP_F32_DIV), /* 0x95 */ \ - HANDLE_OPCODE (WASM_OP_F32_MIN), /* 0x96 */ \ - HANDLE_OPCODE (WASM_OP_F32_MAX), /* 0x97 */ \ - HANDLE_OPCODE (WASM_OP_F32_COPYSIGN), /* 0x98 */ \ - HANDLE_OPCODE (WASM_OP_F64_ABS), /* 0x99 */ \ - HANDLE_OPCODE (WASM_OP_F64_NEG), /* 0x9a */ \ - HANDLE_OPCODE (WASM_OP_F64_CEIL), /* 0x9b */ \ - HANDLE_OPCODE (WASM_OP_F64_FLOOR), /* 0x9c */ \ - HANDLE_OPCODE (WASM_OP_F64_TRUNC), /* 0x9d */ \ - HANDLE_OPCODE (WASM_OP_F64_NEAREST), /* 0x9e */ \ - HANDLE_OPCODE (WASM_OP_F64_SQRT), /* 0x9f */ \ - HANDLE_OPCODE (WASM_OP_F64_ADD), /* 0xa0 */ \ - HANDLE_OPCODE (WASM_OP_F64_SUB), /* 0xa1 */ \ - HANDLE_OPCODE (WASM_OP_F64_MUL), /* 0xa2 */ \ - HANDLE_OPCODE (WASM_OP_F64_DIV), /* 0xa3 */ \ - HANDLE_OPCODE (WASM_OP_F64_MIN), /* 0xa4 */ \ - HANDLE_OPCODE (WASM_OP_F64_MAX), /* 0xa5 */ \ - HANDLE_OPCODE (WASM_OP_F64_COPYSIGN), /* 0xa6 */ \ - HANDLE_OPCODE (WASM_OP_I32_WRAP_I64), /* 0xa7 */ \ - HANDLE_OPCODE (WASM_OP_I32_TRUNC_S_F32), /* 0xa8 */ \ - HANDLE_OPCODE (WASM_OP_I32_TRUNC_U_F32), /* 0xa9 */ \ - HANDLE_OPCODE (WASM_OP_I32_TRUNC_S_F64), /* 0xaa */ \ - HANDLE_OPCODE (WASM_OP_I32_TRUNC_U_F64), /* 0xab */ \ - HANDLE_OPCODE (WASM_OP_I64_EXTEND_S_I32), /* 0xac */ \ - HANDLE_OPCODE (WASM_OP_I64_EXTEND_U_I32), /* 0xad */ \ - HANDLE_OPCODE (WASM_OP_I64_TRUNC_S_F32), /* 0xae */ \ - HANDLE_OPCODE (WASM_OP_I64_TRUNC_U_F32), /* 0xaf */ \ - HANDLE_OPCODE (WASM_OP_I64_TRUNC_S_F64), /* 0xb0 */ \ - HANDLE_OPCODE (WASM_OP_I64_TRUNC_U_F64), /* 0xb1 */ \ - HANDLE_OPCODE (WASM_OP_F32_CONVERT_S_I32), /* 0xb2 */ \ - HANDLE_OPCODE (WASM_OP_F32_CONVERT_U_I32), /* 0xb3 */ \ - HANDLE_OPCODE (WASM_OP_F32_CONVERT_S_I64), /* 0xb4 */ \ - HANDLE_OPCODE (WASM_OP_F32_CONVERT_U_I64), /* 0xb5 */ \ - HANDLE_OPCODE (WASM_OP_F32_DEMOTE_F64), /* 0xb6 */ \ - HANDLE_OPCODE (WASM_OP_F64_CONVERT_S_I32), /* 0xb7 */ \ - HANDLE_OPCODE (WASM_OP_F64_CONVERT_U_I32), /* 0xb8 */ \ - HANDLE_OPCODE (WASM_OP_F64_CONVERT_S_I64), /* 0xb9 */ \ - HANDLE_OPCODE (WASM_OP_F64_CONVERT_U_I64), /* 0xba */ \ - HANDLE_OPCODE (WASM_OP_F64_PROMOTE_F32), /* 0xbb */ \ - HANDLE_OPCODE (WASM_OP_I32_REINTERPRET_F32), /* 0xbc */ \ - HANDLE_OPCODE (WASM_OP_I64_REINTERPRET_F64), /* 0xbd */ \ - HANDLE_OPCODE (WASM_OP_F32_REINTERPRET_I32), /* 0xbe */ \ - HANDLE_OPCODE (WASM_OP_F64_REINTERPRET_I64), /* 0xbf */ \ - HANDLE_OPCODE (WASM_OP_I32_EXTEND8_S), /* 0xc0 */ \ - HANDLE_OPCODE (WASM_OP_I32_EXTEND16_S), /* 0xc1 */ \ - HANDLE_OPCODE (WASM_OP_I64_EXTEND8_S), /* 0xc2 */ \ - HANDLE_OPCODE (WASM_OP_I64_EXTEND16_S), /* 0xc3 */ \ - HANDLE_OPCODE (WASM_OP_I64_EXTEND32_S), /* 0xc4 */ \ - HANDLE_OPCODE (WASM_OP_DROP_64), /* 0xc5 */ \ - HANDLE_OPCODE (WASM_OP_SELECT_64), /* 0xc6 */ \ - HANDLE_OPCODE (EXT_OP_GET_LOCAL_FAST), /* 0xc7 */ \ - HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST_I64), /* 0xc8 */ \ - HANDLE_OPCODE (EXT_OP_SET_LOCAL_FAST), /* 0xc9 */ \ - HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST), /* 0xca */ \ - HANDLE_OPCODE (EXT_OP_TEE_LOCAL_FAST_I64), /* 0xcb */ \ - HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP), /* 0xcc */ \ - HANDLE_OPCODE (EXT_OP_COPY_STACK_TOP_I64), /* 0xcd */ \ - HANDLE_OPCODE (EXT_OP_COPY_STACK_VALUES), /* 0xce */ \ - HANDLE_OPCODE (WASM_OP_IMPDEP), /* 0xcf */ \ - HANDLE_OPCODE (WASM_OP_REF_NULL), /* 0xd0 */ \ - HANDLE_OPCODE (WASM_OP_REF_IS_NULL), /* 0xd1 */ \ - HANDLE_OPCODE (WASM_OP_REF_FUNC), /* 0xd2 */ \ - HANDLE_OPCODE (EXT_OP_BLOCK), /* 0xd3 */ \ - HANDLE_OPCODE (EXT_OP_LOOP), /* 0xd4 */ \ - HANDLE_OPCODE (EXT_OP_IF), /* 0xd5 */ \ -}; \ -do { \ - _name[WASM_OP_MISC_PREFIX] = \ - HANDLE_OPCODE (WASM_OP_MISC_PREFIX); /* 0xfc */ \ - _name[WASM_OP_ATOMIC_PREFIX] = \ - HANDLE_OPCODE (WASM_OP_ATOMIC_PREFIX); /* 0xfe */ \ -} while (0) -#endif /* end of _WASM_OPCODE_H */ +#define DEFINE_GOTO_TABLE(type, _name) \ + static type _name[WASM_INSTRUCTION_NUM] = { \ + HANDLE_OPCODE(WASM_OP_UNREACHABLE), /* 0x00 */ \ + HANDLE_OPCODE(WASM_OP_NOP), /* 0x01 */ \ + HANDLE_OPCODE(WASM_OP_BLOCK), /* 0x02 */ \ + 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_UNUSED_0x0a), /* 0x0a */ \ + HANDLE_OPCODE(WASM_OP_END), /* 0x0b */ \ + HANDLE_OPCODE(WASM_OP_BR), /* 0x0c */ \ + HANDLE_OPCODE(WASM_OP_BR_IF), /* 0x0d */ \ + HANDLE_OPCODE(WASM_OP_BR_TABLE), /* 0x0e */ \ + HANDLE_OPCODE(WASM_OP_RETURN), /* 0x0f */ \ + HANDLE_OPCODE(WASM_OP_CALL), /* 0x10 */ \ + HANDLE_OPCODE(WASM_OP_CALL_INDIRECT), /* 0x11 */ \ + HANDLE_OPCODE(WASM_OP_RETURN_CALL), /* 0x12 */ \ + HANDLE_OPCODE(WASM_OP_RETURN_CALL_INDIRECT), /* 0x13 */ \ + HANDLE_OPCODE(WASM_OP_UNUSED_0x14), /* 0x14 */ \ + 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_DROP), /* 0x1a */ \ + HANDLE_OPCODE(WASM_OP_SELECT), /* 0x1b */ \ + HANDLE_OPCODE(WASM_OP_SELECT_T), /* 0x1c */ \ + HANDLE_OPCODE(WASM_OP_GET_GLOBAL_64), /* 0x1d */ \ + HANDLE_OPCODE(WASM_OP_SET_GLOBAL_64), /* 0x1e */ \ + HANDLE_OPCODE(WASM_OP_SET_GLOBAL_AUX_STACK), /* 0x1f */ \ + HANDLE_OPCODE(WASM_OP_GET_LOCAL), /* 0x20 */ \ + HANDLE_OPCODE(WASM_OP_SET_LOCAL), /* 0x21 */ \ + HANDLE_OPCODE(WASM_OP_TEE_LOCAL), /* 0x22 */ \ + HANDLE_OPCODE(WASM_OP_GET_GLOBAL), /* 0x23 */ \ + HANDLE_OPCODE(WASM_OP_SET_GLOBAL), /* 0x24 */ \ + HANDLE_OPCODE(WASM_OP_TABLE_GET), /* 0x25 */ \ + HANDLE_OPCODE(WASM_OP_TABLE_SET), /* 0x26 */ \ + HANDLE_OPCODE(WASM_OP_UNUSED_0x27), /* 0x27 */ \ + HANDLE_OPCODE(WASM_OP_I32_LOAD), /* 0x28 */ \ + HANDLE_OPCODE(WASM_OP_I64_LOAD), /* 0x29 */ \ + HANDLE_OPCODE(WASM_OP_F32_LOAD), /* 0x2a */ \ + HANDLE_OPCODE(WASM_OP_F64_LOAD), /* 0x2b */ \ + HANDLE_OPCODE(WASM_OP_I32_LOAD8_S), /* 0x2c */ \ + HANDLE_OPCODE(WASM_OP_I32_LOAD8_U), /* 0x2d */ \ + HANDLE_OPCODE(WASM_OP_I32_LOAD16_S), /* 0x2e */ \ + HANDLE_OPCODE(WASM_OP_I32_LOAD16_U), /* 0x2f */ \ + HANDLE_OPCODE(WASM_OP_I64_LOAD8_S), /* 0x30 */ \ + HANDLE_OPCODE(WASM_OP_I64_LOAD8_U), /* 0x31 */ \ + HANDLE_OPCODE(WASM_OP_I64_LOAD16_S), /* 0x32 */ \ + HANDLE_OPCODE(WASM_OP_I64_LOAD16_U), /* 0x33 */ \ + HANDLE_OPCODE(WASM_OP_I64_LOAD32_S), /* 0x34 */ \ + HANDLE_OPCODE(WASM_OP_I64_LOAD32_U), /* 0x35 */ \ + HANDLE_OPCODE(WASM_OP_I32_STORE), /* 0x36 */ \ + HANDLE_OPCODE(WASM_OP_I64_STORE), /* 0x37 */ \ + HANDLE_OPCODE(WASM_OP_F32_STORE), /* 0x38 */ \ + HANDLE_OPCODE(WASM_OP_F64_STORE), /* 0x39 */ \ + HANDLE_OPCODE(WASM_OP_I32_STORE8), /* 0x3a */ \ + HANDLE_OPCODE(WASM_OP_I32_STORE16), /* 0x3b */ \ + HANDLE_OPCODE(WASM_OP_I64_STORE8), /* 0x3c */ \ + HANDLE_OPCODE(WASM_OP_I64_STORE16), /* 0x3d */ \ + HANDLE_OPCODE(WASM_OP_I64_STORE32), /* 0x3e */ \ + HANDLE_OPCODE(WASM_OP_MEMORY_SIZE), /* 0x3f */ \ + HANDLE_OPCODE(WASM_OP_MEMORY_GROW), /* 0x40 */ \ + HANDLE_OPCODE(WASM_OP_I32_CONST), /* 0x41 */ \ + HANDLE_OPCODE(WASM_OP_I64_CONST), /* 0x42 */ \ + HANDLE_OPCODE(WASM_OP_F32_CONST), /* 0x43 */ \ + HANDLE_OPCODE(WASM_OP_F64_CONST), /* 0x44 */ \ + HANDLE_OPCODE(WASM_OP_I32_EQZ), /* 0x45 */ \ + HANDLE_OPCODE(WASM_OP_I32_EQ), /* 0x46 */ \ + HANDLE_OPCODE(WASM_OP_I32_NE), /* 0x47 */ \ + HANDLE_OPCODE(WASM_OP_I32_LT_S), /* 0x48 */ \ + HANDLE_OPCODE(WASM_OP_I32_LT_U), /* 0x49 */ \ + HANDLE_OPCODE(WASM_OP_I32_GT_S), /* 0x4a */ \ + HANDLE_OPCODE(WASM_OP_I32_GT_U), /* 0x4b */ \ + HANDLE_OPCODE(WASM_OP_I32_LE_S), /* 0x4c */ \ + HANDLE_OPCODE(WASM_OP_I32_LE_U), /* 0x4d */ \ + HANDLE_OPCODE(WASM_OP_I32_GE_S), /* 0x4e */ \ + HANDLE_OPCODE(WASM_OP_I32_GE_U), /* 0x4f */ \ + HANDLE_OPCODE(WASM_OP_I64_EQZ), /* 0x50 */ \ + HANDLE_OPCODE(WASM_OP_I64_EQ), /* 0x51 */ \ + HANDLE_OPCODE(WASM_OP_I64_NE), /* 0x52 */ \ + HANDLE_OPCODE(WASM_OP_I64_LT_S), /* 0x53 */ \ + HANDLE_OPCODE(WASM_OP_I64_LT_U), /* 0x54 */ \ + HANDLE_OPCODE(WASM_OP_I64_GT_S), /* 0x55 */ \ + HANDLE_OPCODE(WASM_OP_I64_GT_U), /* 0x56 */ \ + HANDLE_OPCODE(WASM_OP_I64_LE_S), /* 0x57 */ \ + HANDLE_OPCODE(WASM_OP_I64_LE_U), /* 0x58 */ \ + HANDLE_OPCODE(WASM_OP_I64_GE_S), /* 0x59 */ \ + HANDLE_OPCODE(WASM_OP_I64_GE_U), /* 0x5a */ \ + HANDLE_OPCODE(WASM_OP_F32_EQ), /* 0x5b */ \ + HANDLE_OPCODE(WASM_OP_F32_NE), /* 0x5c */ \ + HANDLE_OPCODE(WASM_OP_F32_LT), /* 0x5d */ \ + HANDLE_OPCODE(WASM_OP_F32_GT), /* 0x5e */ \ + HANDLE_OPCODE(WASM_OP_F32_LE), /* 0x5f */ \ + HANDLE_OPCODE(WASM_OP_F32_GE), /* 0x60 */ \ + HANDLE_OPCODE(WASM_OP_F64_EQ), /* 0x61 */ \ + HANDLE_OPCODE(WASM_OP_F64_NE), /* 0x62 */ \ + HANDLE_OPCODE(WASM_OP_F64_LT), /* 0x63 */ \ + HANDLE_OPCODE(WASM_OP_F64_GT), /* 0x64 */ \ + HANDLE_OPCODE(WASM_OP_F64_LE), /* 0x65 */ \ + HANDLE_OPCODE(WASM_OP_F64_GE), /* 0x66 */ \ + HANDLE_OPCODE(WASM_OP_I32_CLZ), /* 0x67 */ \ + HANDLE_OPCODE(WASM_OP_I32_CTZ), /* 0x68 */ \ + HANDLE_OPCODE(WASM_OP_I32_POPCNT), /* 0x69 */ \ + HANDLE_OPCODE(WASM_OP_I32_ADD), /* 0x6a */ \ + HANDLE_OPCODE(WASM_OP_I32_SUB), /* 0x6b */ \ + HANDLE_OPCODE(WASM_OP_I32_MUL), /* 0x6c */ \ + HANDLE_OPCODE(WASM_OP_I32_DIV_S), /* 0x6d */ \ + HANDLE_OPCODE(WASM_OP_I32_DIV_U), /* 0x6e */ \ + HANDLE_OPCODE(WASM_OP_I32_REM_S), /* 0x6f */ \ + HANDLE_OPCODE(WASM_OP_I32_REM_U), /* 0x70 */ \ + HANDLE_OPCODE(WASM_OP_I32_AND), /* 0x71 */ \ + HANDLE_OPCODE(WASM_OP_I32_OR), /* 0x72 */ \ + HANDLE_OPCODE(WASM_OP_I32_XOR), /* 0x73 */ \ + HANDLE_OPCODE(WASM_OP_I32_SHL), /* 0x74 */ \ + HANDLE_OPCODE(WASM_OP_I32_SHR_S), /* 0x75 */ \ + HANDLE_OPCODE(WASM_OP_I32_SHR_U), /* 0x76 */ \ + HANDLE_OPCODE(WASM_OP_I32_ROTL), /* 0x77 */ \ + HANDLE_OPCODE(WASM_OP_I32_ROTR), /* 0x78 */ \ + HANDLE_OPCODE(WASM_OP_I64_CLZ), /* 0x79 */ \ + HANDLE_OPCODE(WASM_OP_I64_CTZ), /* 0x7a */ \ + HANDLE_OPCODE(WASM_OP_I64_POPCNT), /* 0x7b */ \ + HANDLE_OPCODE(WASM_OP_I64_ADD), /* 0x7c */ \ + HANDLE_OPCODE(WASM_OP_I64_SUB), /* 0x7d */ \ + HANDLE_OPCODE(WASM_OP_I64_MUL), /* 0x7e */ \ + HANDLE_OPCODE(WASM_OP_I64_DIV_S), /* 0x7f */ \ + HANDLE_OPCODE(WASM_OP_I64_DIV_U), /* 0x80 */ \ + HANDLE_OPCODE(WASM_OP_I64_REM_S), /* 0x81 */ \ + HANDLE_OPCODE(WASM_OP_I64_REM_U), /* 0x82 */ \ + HANDLE_OPCODE(WASM_OP_I64_AND), /* 0x83 */ \ + HANDLE_OPCODE(WASM_OP_I64_OR), /* 0x84 */ \ + HANDLE_OPCODE(WASM_OP_I64_XOR), /* 0x85 */ \ + HANDLE_OPCODE(WASM_OP_I64_SHL), /* 0x86 */ \ + HANDLE_OPCODE(WASM_OP_I64_SHR_S), /* 0x87 */ \ + HANDLE_OPCODE(WASM_OP_I64_SHR_U), /* 0x88 */ \ + HANDLE_OPCODE(WASM_OP_I64_ROTL), /* 0x89 */ \ + HANDLE_OPCODE(WASM_OP_I64_ROTR), /* 0x8a */ \ + HANDLE_OPCODE(WASM_OP_F32_ABS), /* 0x8b */ \ + HANDLE_OPCODE(WASM_OP_F32_NEG), /* 0x8c */ \ + HANDLE_OPCODE(WASM_OP_F32_CEIL), /* 0x8d */ \ + HANDLE_OPCODE(WASM_OP_F32_FLOOR), /* 0x8e */ \ + HANDLE_OPCODE(WASM_OP_F32_TRUNC), /* 0x8f */ \ + HANDLE_OPCODE(WASM_OP_F32_NEAREST), /* 0x90 */ \ + HANDLE_OPCODE(WASM_OP_F32_SQRT), /* 0x91 */ \ + HANDLE_OPCODE(WASM_OP_F32_ADD), /* 0x92 */ \ + HANDLE_OPCODE(WASM_OP_F32_SUB), /* 0x93 */ \ + HANDLE_OPCODE(WASM_OP_F32_MUL), /* 0x94 */ \ + HANDLE_OPCODE(WASM_OP_F32_DIV), /* 0x95 */ \ + HANDLE_OPCODE(WASM_OP_F32_MIN), /* 0x96 */ \ + HANDLE_OPCODE(WASM_OP_F32_MAX), /* 0x97 */ \ + HANDLE_OPCODE(WASM_OP_F32_COPYSIGN), /* 0x98 */ \ + HANDLE_OPCODE(WASM_OP_F64_ABS), /* 0x99 */ \ + HANDLE_OPCODE(WASM_OP_F64_NEG), /* 0x9a */ \ + HANDLE_OPCODE(WASM_OP_F64_CEIL), /* 0x9b */ \ + HANDLE_OPCODE(WASM_OP_F64_FLOOR), /* 0x9c */ \ + HANDLE_OPCODE(WASM_OP_F64_TRUNC), /* 0x9d */ \ + HANDLE_OPCODE(WASM_OP_F64_NEAREST), /* 0x9e */ \ + HANDLE_OPCODE(WASM_OP_F64_SQRT), /* 0x9f */ \ + HANDLE_OPCODE(WASM_OP_F64_ADD), /* 0xa0 */ \ + HANDLE_OPCODE(WASM_OP_F64_SUB), /* 0xa1 */ \ + HANDLE_OPCODE(WASM_OP_F64_MUL), /* 0xa2 */ \ + HANDLE_OPCODE(WASM_OP_F64_DIV), /* 0xa3 */ \ + HANDLE_OPCODE(WASM_OP_F64_MIN), /* 0xa4 */ \ + HANDLE_OPCODE(WASM_OP_F64_MAX), /* 0xa5 */ \ + HANDLE_OPCODE(WASM_OP_F64_COPYSIGN), /* 0xa6 */ \ + HANDLE_OPCODE(WASM_OP_I32_WRAP_I64), /* 0xa7 */ \ + HANDLE_OPCODE(WASM_OP_I32_TRUNC_S_F32), /* 0xa8 */ \ + HANDLE_OPCODE(WASM_OP_I32_TRUNC_U_F32), /* 0xa9 */ \ + HANDLE_OPCODE(WASM_OP_I32_TRUNC_S_F64), /* 0xaa */ \ + HANDLE_OPCODE(WASM_OP_I32_TRUNC_U_F64), /* 0xab */ \ + HANDLE_OPCODE(WASM_OP_I64_EXTEND_S_I32), /* 0xac */ \ + HANDLE_OPCODE(WASM_OP_I64_EXTEND_U_I32), /* 0xad */ \ + HANDLE_OPCODE(WASM_OP_I64_TRUNC_S_F32), /* 0xae */ \ + HANDLE_OPCODE(WASM_OP_I64_TRUNC_U_F32), /* 0xaf */ \ + HANDLE_OPCODE(WASM_OP_I64_TRUNC_S_F64), /* 0xb0 */ \ + HANDLE_OPCODE(WASM_OP_I64_TRUNC_U_F64), /* 0xb1 */ \ + HANDLE_OPCODE(WASM_OP_F32_CONVERT_S_I32), /* 0xb2 */ \ + HANDLE_OPCODE(WASM_OP_F32_CONVERT_U_I32), /* 0xb3 */ \ + HANDLE_OPCODE(WASM_OP_F32_CONVERT_S_I64), /* 0xb4 */ \ + HANDLE_OPCODE(WASM_OP_F32_CONVERT_U_I64), /* 0xb5 */ \ + HANDLE_OPCODE(WASM_OP_F32_DEMOTE_F64), /* 0xb6 */ \ + HANDLE_OPCODE(WASM_OP_F64_CONVERT_S_I32), /* 0xb7 */ \ + HANDLE_OPCODE(WASM_OP_F64_CONVERT_U_I32), /* 0xb8 */ \ + HANDLE_OPCODE(WASM_OP_F64_CONVERT_S_I64), /* 0xb9 */ \ + HANDLE_OPCODE(WASM_OP_F64_CONVERT_U_I64), /* 0xba */ \ + HANDLE_OPCODE(WASM_OP_F64_PROMOTE_F32), /* 0xbb */ \ + HANDLE_OPCODE(WASM_OP_I32_REINTERPRET_F32), /* 0xbc */ \ + HANDLE_OPCODE(WASM_OP_I64_REINTERPRET_F64), /* 0xbd */ \ + HANDLE_OPCODE(WASM_OP_F32_REINTERPRET_I32), /* 0xbe */ \ + HANDLE_OPCODE(WASM_OP_F64_REINTERPRET_I64), /* 0xbf */ \ + HANDLE_OPCODE(WASM_OP_I32_EXTEND8_S), /* 0xc0 */ \ + HANDLE_OPCODE(WASM_OP_I32_EXTEND16_S), /* 0xc1 */ \ + HANDLE_OPCODE(WASM_OP_I64_EXTEND8_S), /* 0xc2 */ \ + HANDLE_OPCODE(WASM_OP_I64_EXTEND16_S), /* 0xc3 */ \ + HANDLE_OPCODE(WASM_OP_I64_EXTEND32_S), /* 0xc4 */ \ + HANDLE_OPCODE(WASM_OP_DROP_64), /* 0xc5 */ \ + HANDLE_OPCODE(WASM_OP_SELECT_64), /* 0xc6 */ \ + HANDLE_OPCODE(EXT_OP_GET_LOCAL_FAST), /* 0xc7 */ \ + HANDLE_OPCODE(EXT_OP_SET_LOCAL_FAST_I64), /* 0xc8 */ \ + HANDLE_OPCODE(EXT_OP_SET_LOCAL_FAST), /* 0xc9 */ \ + HANDLE_OPCODE(EXT_OP_TEE_LOCAL_FAST), /* 0xca */ \ + HANDLE_OPCODE(EXT_OP_TEE_LOCAL_FAST_I64), /* 0xcb */ \ + HANDLE_OPCODE(EXT_OP_COPY_STACK_TOP), /* 0xcc */ \ + HANDLE_OPCODE(EXT_OP_COPY_STACK_TOP_I64), /* 0xcd */ \ + HANDLE_OPCODE(EXT_OP_COPY_STACK_VALUES), /* 0xce */ \ + HANDLE_OPCODE(WASM_OP_IMPDEP), /* 0xcf */ \ + HANDLE_OPCODE(WASM_OP_REF_NULL), /* 0xd0 */ \ + HANDLE_OPCODE(WASM_OP_REF_IS_NULL), /* 0xd1 */ \ + HANDLE_OPCODE(WASM_OP_REF_FUNC), /* 0xd2 */ \ + HANDLE_OPCODE(EXT_OP_BLOCK), /* 0xd3 */ \ + HANDLE_OPCODE(EXT_OP_LOOP), /* 0xd4 */ \ + HANDLE_OPCODE(EXT_OP_IF), /* 0xd5 */ \ + }; \ + do { \ + _name[WASM_OP_MISC_PREFIX] = \ + HANDLE_OPCODE(WASM_OP_MISC_PREFIX); /* 0xfc */ \ + _name[WASM_OP_ATOMIC_PREFIX] = \ + HANDLE_OPCODE(WASM_OP_ATOMIC_PREFIX); /* 0xfe */ \ + DEF_DEBUG_BREAK_HANDLE(_name) \ + } while (0) + +#ifdef __cplusplus +} +#endif +#endif /* end of _WASM_OPCODE_H */ diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 0b43f18958..372d572fbb 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -16,6 +16,9 @@ #if WASM_ENABLE_THREAD_MGR != 0 #include "../libraries/thread-mgr/thread_manager.h" #endif +#if WASM_ENABLE_DEBUG_INTERP != 0 +#include "../libraries/debug-engine/debug_engine.h" +#endif static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) @@ -27,8 +30,7 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) } static void -set_error_buf_v(char *error_buf, uint32 error_buf_size, - const char *format, ...) +set_error_buf_v(char *error_buf, uint32 error_buf_size, const char *format, ...) { va_list args; char buf[128]; @@ -42,19 +44,18 @@ set_error_buf_v(char *error_buf, uint32 error_buf_size, } } -WASMModule* -wasm_load(const uint8 *buf, uint32 size, - char *error_buf, uint32 error_buf_size) +WASMModule * +wasm_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_buf_size) { return wasm_loader_load(buf, size, error_buf, error_buf_size); } -WASMModule* -wasm_load_from_sections(WASMSection *section_list, - char *error_buf, uint32_t error_buf_size) +WASMModule * +wasm_load_from_sections(WASMSection *section_list, char *error_buf, + uint32_t error_buf_size) { - return wasm_loader_load_from_sections(section_list, - error_buf, error_buf_size); + return wasm_loader_load_from_sections(section_list, error_buf, + error_buf_size); } void @@ -68,10 +69,8 @@ runtime_malloc(uint64 size, char *error_buf, uint32 error_buf_size) { void *mem; - if (size >= UINT32_MAX - || !(mem = wasm_runtime_malloc((uint32)size))) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); return NULL; } @@ -99,8 +98,7 @@ get_sub_module_inst(const WASMModuleInstance *parent_module_inst, */ static void memories_deinstantiate(WASMModuleInstance *module_inst, - WASMMemoryInstance **memories, - uint32 count) + WASMMemoryInstance **memories, uint32 count) { uint32 i; if (memories) { @@ -112,9 +110,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst, #endif #if WASM_ENABLE_SHARED_MEMORY != 0 if (memories[i]->is_shared) { - int32 ref_count = - shared_memory_dec_reference( - (WASMModuleCommon *)module_inst->module); + int32 ref_count = shared_memory_dec_reference( + (WASMModuleCommon *)module_inst->module); bh_assert(ref_count >= 0); /* if the reference count is not zero, @@ -135,16 +132,15 @@ memories_deinstantiate(WASMModuleInstance *module_inst, } } wasm_runtime_free(memories); - } - (void)module_inst; + } + (void)module_inst; } -static WASMMemoryInstance* -memory_instantiate(WASMModuleInstance *module_inst, - uint32 num_bytes_per_page, +static WASMMemoryInstance * +memory_instantiate(WASMModuleInstance *module_inst, uint32 num_bytes_per_page, uint32 init_page_count, uint32 max_page_count, - uint32 heap_size, uint32 flags, - char *error_buf, uint32 error_buf_size) + uint32 heap_size, uint32 flags, char *error_buf, + uint32 error_buf_size) { WASMModule *module = module_inst->module; WASMMemoryInstance *memory; @@ -159,15 +155,14 @@ memory_instantiate(WASMModuleInstance *module_inst, /* shared memory */ if (is_shared_memory) { - WASMSharedMemNode *node = - wasm_module_get_shared_memory( - (WASMModuleCommon *)module_inst->module); + WASMSharedMemNode *node = wasm_module_get_shared_memory( + (WASMModuleCommon *)module_inst->module); /* If the memory of this module has been instantiated, return the memory instance directly */ if (node) { uint32 ref_count; ref_count = shared_memory_inc_reference( - (WASMModuleCommon *)module_inst->module); + (WASMModuleCommon *)module_inst->module); bh_assert(ref_count > 0); memory = (WASMMemoryInstance *)shared_memory_get_memory_inst(node); bh_assert(memory); @@ -178,8 +173,7 @@ memory_instantiate(WASMModuleInstance *module_inst, } #endif /* end of WASM_ENABLE_SHARED_MEMORY */ - if (heap_size > 0 - && module_inst->module->malloc_function != (uint32)-1 + if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1 && module_inst->module->free_function != (uint32)-1) { /* Disable app heap, use malloc/free function exported by wasm app to allocate/free memory instead */ @@ -200,16 +194,16 @@ memory_instantiate(WASMModuleInstance *module_inst, } else if (heap_size > 0) { if (module->aux_heap_base_global_index != (uint32)-1 - && module->aux_heap_base < num_bytes_per_page - * init_page_count) { + && module->aux_heap_base < num_bytes_per_page * init_page_count) { /* Insert app heap before __heap_base */ aux_heap_base = module->aux_heap_base; bytes_of_last_page = aux_heap_base % num_bytes_per_page; if (bytes_of_last_page == 0) bytes_of_last_page = num_bytes_per_page; bytes_to_page_end = num_bytes_per_page - bytes_of_last_page; - inc_page_count = (heap_size - bytes_to_page_end - + num_bytes_per_page - 1) / num_bytes_per_page; + inc_page_count = + (heap_size - bytes_to_page_end + num_bytes_per_page - 1) + / num_bytes_per_page; heap_offset = aux_heap_base; aux_heap_base += heap_size; @@ -224,15 +218,15 @@ memory_instantiate(WASMModuleInstance *module_inst, /* Adjust __heap_base global value */ global_idx = module->aux_heap_base_global_index; - global_addr = module_inst->global_data + - module_inst->globals[global_idx].data_offset; + global_addr = module_inst->global_data + + module_inst->globals[global_idx].data_offset; *(uint32 *)global_addr = aux_heap_base; LOG_VERBOSE("Reset __heap_base global to %u", aux_heap_base); } else { /* Insert app heap before new page */ - inc_page_count = (heap_size + num_bytes_per_page - 1) - / num_bytes_per_page; + inc_page_count = + (heap_size + num_bytes_per_page - 1) / num_bytes_per_page; heap_offset = num_bytes_per_page * init_page_count; heap_size = num_bytes_per_page * inc_page_count; if (heap_size > 0) @@ -263,15 +257,14 @@ memory_instantiate(WASMModuleInstance *module_inst, #endif /* Allocate memory space, addr data and global data */ - if (!(memory = runtime_malloc((uint64)sizeof(WASMMemoryInstance), - error_buf, error_buf_size))) { + if (!(memory = runtime_malloc((uint64)sizeof(WASMMemoryInstance), error_buf, + error_buf_size))) { return NULL; } if (memory_data_size > 0 && !(memory->memory_data = - runtime_malloc(memory_data_size, - error_buf, error_buf_size))) { + runtime_malloc(memory_data_size, error_buf, error_buf_size))) { goto fail1; } @@ -288,13 +281,13 @@ memory_instantiate(WASMModuleInstance *module_inst, if (heap_size > 0) { uint32 heap_struct_size = mem_allocator_get_heap_struct_size(); - if (!(memory->heap_handle = runtime_malloc((uint64)heap_struct_size, - error_buf, error_buf_size))) { + if (!(memory->heap_handle = runtime_malloc( + (uint64)heap_struct_size, error_buf, error_buf_size))) { goto fail2; } - if (!mem_allocator_create_with_struct_and_pool - (memory->heap_handle, heap_struct_size, - memory->heap_data, heap_size)) { + if (!mem_allocator_create_with_struct_and_pool( + memory->heap_handle, heap_struct_size, memory->heap_data, + heap_size)) { set_error_buf(error_buf, error_buf_size, "init app heap failed"); goto fail3; } @@ -310,8 +303,7 @@ memory_instantiate(WASMModuleInstance *module_inst, if (!shared_memory_set_memory_inst( (WASMModuleCommon *)module_inst->module, (WASMMemoryInstanceCommon *)memory)) { - set_error_buf(error_buf, error_buf_size, - "allocate memory failed"); + set_error_buf(error_buf, error_buf_size, "allocate memory failed"); goto fail5; } } @@ -340,20 +332,18 @@ memory_instantiate(WASMModuleInstance *module_inst, * Instantiate memories in a module. */ static WASMMemoryInstance ** -memories_instantiate(const WASMModule *module, - WASMModuleInstance *module_inst, +memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, uint32 heap_size, char *error_buf, uint32 error_buf_size) { WASMImport *import; - uint32 mem_index = 0, i, memory_count = - module->import_memory_count + module->memory_count; + uint32 mem_index = 0, i, + memory_count = module->import_memory_count + module->memory_count; uint64 total_size; WASMMemoryInstance **memories, *memory; - total_size = sizeof(WASMMemoryInstance*) * (uint64)memory_count; + total_size = sizeof(WASMMemoryInstance *) * (uint64)memory_count; - if (!(memories = runtime_malloc(total_size, - error_buf, error_buf_size))) { + if (!(memories = runtime_malloc(total_size, error_buf, error_buf_size))) { return NULL; } @@ -371,14 +361,14 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst_linked; if (!(module_inst_linked = get_sub_module_inst( - module_inst, import->u.memory.import_module))) { + module_inst, import->u.memory.import_module))) { set_error_buf(error_buf, error_buf_size, "unknown memory"); memories_deinstantiate(module_inst, memories, memory_count); return NULL; } if (!(memory = memories[mem_index++] = wasm_lookup_memory( - module_inst_linked, import->u.memory.field_name))) { + module_inst_linked, import->u.memory.field_name))) { set_error_buf(error_buf, error_buf_size, "unknown memory"); memories_deinstantiate(module_inst, memories, memory_count); return NULL; @@ -388,9 +378,9 @@ memories_instantiate(const WASMModule *module, #endif { if (!(memory = memories[mem_index++] = memory_instantiate( - module_inst, num_bytes_per_page, init_page_count, - max_page_count, actual_heap_size, flags, - error_buf, error_buf_size))) { + module_inst, num_bytes_per_page, init_page_count, + max_page_count, actual_heap_size, flags, error_buf, + error_buf_size))) { memories_deinstantiate(module_inst, memories, memory_count); return NULL; } @@ -406,13 +396,11 @@ memories_instantiate(const WASMModule *module, /* instantiate memories from memory section */ for (i = 0; i < module->memory_count; i++) { - if (!(memory = memories[mem_index++] = - memory_instantiate(module_inst, - module->memories[i].num_bytes_per_page, - module->memories[i].init_page_count, - module->memories[i].max_page_count, - heap_size, module->memories[i].flags, - error_buf, error_buf_size))) { + if (!(memory = memories[mem_index++] = memory_instantiate( + module_inst, module->memories[i].num_bytes_per_page, + module->memories[i].init_page_count, + module->memories[i].max_page_count, heap_size, + module->memories[i].flags, error_buf, error_buf_size))) { memories_deinstantiate(module_inst, memories, memory_count); return NULL; } @@ -427,8 +415,8 @@ memories_instantiate(const WASMModule *module, * for wasm code */ if (!(memory = memories[mem_index++] = - memory_instantiate(module_inst, 0, 0, 0, heap_size, 0, - error_buf, error_buf_size))) { + memory_instantiate(module_inst, 0, 0, 0, heap_size, 0, + error_buf, error_buf_size))) { memories_deinstantiate(module_inst, memories, memory_count); return NULL; } @@ -458,37 +446,37 @@ tables_deinstantiate(WASMTableInstance **tables, uint32 count) * Instantiate tables in a module. */ static WASMTableInstance ** -tables_instantiate(const WASMModule *module, - WASMModuleInstance *module_inst, +tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, char *error_buf, uint32 error_buf_size) { WASMImport *import; - uint32 table_index = 0, i, table_count = - module->import_table_count + module->table_count; - uint64 total_size = sizeof(WASMTableInstance*) * (uint64)table_count; + uint32 table_index = 0, i, + table_count = module->import_table_count + module->table_count; + uint64 total_size = sizeof(WASMTableInstance *) * (uint64)table_count; WASMTableInstance **tables, *table; - if (!(tables = runtime_malloc(total_size, - error_buf, error_buf_size))) { + if (!(tables = runtime_malloc(total_size, error_buf, error_buf_size))) { return NULL; } /* instantiate tables from import section */ import = module->import_tables; for (i = 0; i < module->import_table_count; i++, import++) { + uint32 max_size_fixed = 0; #if WASM_ENABLE_MULTI_MODULE != 0 WASMTableInstance *table_inst_linked = NULL; WASMModuleInstance *module_inst_linked = NULL; + if (import->u.table.import_module) { - if (!(module_inst_linked = - get_sub_module_inst(module_inst, import->u.table.import_module))) { + if (!(module_inst_linked = get_sub_module_inst( + module_inst, import->u.table.import_module))) { set_error_buf(error_buf, error_buf_size, "unknown table"); tables_deinstantiate(tables, table_count); return NULL; } - if (!(table_inst_linked = wasm_lookup_table(module_inst_linked, - import->u.table.field_name))) { + if (!(table_inst_linked = wasm_lookup_table( + module_inst_linked, import->u.table.field_name))) { set_error_buf(error_buf, error_buf_size, "unknown table"); tables_deinstantiate(tables, table_count); return NULL; @@ -499,22 +487,25 @@ tables_instantiate(const WASMModule *module, else #endif { + /* in order to save memory, alloc resource as few as possible */ + max_size_fixed = import->u.table.possible_grow + ? import->u.table.max_size + : import->u.table.init_size; + /* it is a built-in table, every module has its own */ total_size = offsetof(WASMTableInstance, base_addr); - total_size += - import->u.table.possible_grow - ? sizeof(uint32) * (uint64)import->u.table.max_size - : sizeof(uint32) * (uint64)import->u.table.init_size; + total_size += (uint64)max_size_fixed * sizeof(uint32); } - if (!(table = tables[table_index++] = runtime_malloc - (total_size, error_buf, error_buf_size))) { + if (!(table = tables[table_index++] = + runtime_malloc(total_size, error_buf, error_buf_size))) { tables_deinstantiate(tables, table_count); return NULL; } /* Set all elements to -1 to mark them as uninitialized elements */ memset(table, -1, (uint32)total_size); + #if WASM_ENABLE_MULTI_MODULE != 0 table->table_inst_linked = table_inst_linked; if (table_inst_linked != NULL) { @@ -527,23 +518,27 @@ tables_instantiate(const WASMModule *module, { table->elem_type = import->u.table.elem_type; table->cur_size = import->u.table.init_size; - table->max_size = import->u.table.max_size; + table->max_size = max_size_fixed; } } /* instantiate tables from table section */ for (i = 0; i < module->table_count; i++) { + uint32 max_size_fixed = 0; + total_size = offsetof(WASMTableInstance, base_addr); #if WASM_ENABLE_MULTI_MODULE != 0 /* in case, a module which imports this table will grow it */ - total_size += sizeof(uint32) * (uint64)module->tables[i].max_size; + max_size_fixed = module->tables[i].max_size; #else - total_size += module->tables[i].possible_grow - ? sizeof(uint32) * (uint64)module->tables[i].max_size - : sizeof(uint32) * (uint64)module->tables[i].init_size; + max_size_fixed = module->tables[i].possible_grow + ? module->tables[i].max_size + : module->tables[i].init_size; #endif - if (!(table = tables[table_index++] = runtime_malloc - (total_size, error_buf, error_buf_size))) { + total_size += sizeof(uint32) * (uint64)max_size_fixed; + + if (!(table = tables[table_index++] = + runtime_malloc(total_size, error_buf, error_buf_size))) { tables_deinstantiate(tables, table_count); return NULL; } @@ -552,7 +547,7 @@ tables_instantiate(const WASMModule *module, memset(table, -1, (uint32)total_size); table->elem_type = module->tables[i].elem_type; table->cur_size = module->tables[i].init_size; - table->max_size = module->tables[i].max_size; + table->max_size = max_size_fixed; #if WASM_ENABLE_MULTI_MODULE != 0 table->table_inst_linked = NULL; #endif @@ -578,18 +573,16 @@ functions_deinstantiate(WASMFunctionInstance *functions, uint32 count) * Instantiate functions in a module. */ static WASMFunctionInstance * -functions_instantiate(const WASMModule *module, - WASMModuleInstance *module_inst, +functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, char *error_buf, uint32 error_buf_size) { WASMImport *import; - uint32 i, function_count = - module->import_function_count + module->function_count; + uint32 i, + function_count = module->import_function_count + module->function_count; uint64 total_size = sizeof(WASMFunctionInstance) * (uint64)function_count; WASMFunctionInstance *functions, *function; - if (!(functions = runtime_malloc(total_size, - error_buf, error_buf_size))) { + if (!(functions = runtime_malloc(total_size, error_buf, error_buf_size))) { return NULL; } @@ -601,23 +594,21 @@ functions_instantiate(const WASMModule *module, #if WASM_ENABLE_MULTI_MODULE != 0 if (import->u.function.import_module) { - function->import_module_inst = - get_sub_module_inst(module_inst, - import->u.function.import_module); + function->import_module_inst = get_sub_module_inst( + module_inst, import->u.function.import_module); if (function->import_module_inst) { function->import_func_inst = - wasm_lookup_function(function->import_module_inst, - import->u.function.field_name, NULL); + wasm_lookup_function(function->import_module_inst, + import->u.function.field_name, NULL); } } #endif /* WASM_ENABLE_MULTI_MODULE */ function->u.func_import = &import->u.function; - function->param_cell_num = - import->u.function.func_type->param_cell_num; + function->param_cell_num = import->u.function.func_type->param_cell_num; function->ret_cell_num = import->u.function.func_type->ret_cell_num; function->param_count = - (uint16)function->u.func_import->func_type->param_count; + (uint16)function->u.func_import->func_type->param_count; function->param_types = function->u.func_import->func_type->types; function->local_cell_num = 0; function->local_count = 0; @@ -635,7 +626,8 @@ functions_instantiate(const WASMModule *module, function->ret_cell_num = function->u.func->ret_cell_num; function->local_cell_num = function->u.func->local_cell_num; - function->param_count = (uint16)function->u.func->func_type->param_count; + function->param_count = + (uint16)function->u.func->func_type->param_count; function->local_count = (uint16)function->u.func->local_count; function->param_types = function->u.func->func_type->types; function->local_types = function->u.func->local_types; @@ -669,8 +661,8 @@ check_global_init_expr(const WASMModule *module, uint32 global_index, char *error_buf, uint32 error_buf_size) { if (global_index >= module->import_global_count + module->global_count) { - set_error_buf_v(error_buf, error_buf_size, - "unknown global %d", global_index); + set_error_buf_v(error_buf, error_buf_size, "unknown global %d", + global_index); return false; } @@ -695,20 +687,17 @@ check_global_init_expr(const WASMModule *module, uint32 global_index, * Instantiate globals in a module. */ static WASMGlobalInstance * -globals_instantiate(const WASMModule *module, - WASMModuleInstance *module_inst, +globals_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, uint32 *p_global_data_size, char *error_buf, uint32 error_buf_size) { WASMImport *import; uint32 global_data_offset = 0; - uint32 i, global_count = - module->import_global_count + module->global_count; + uint32 i, global_count = module->import_global_count + module->global_count; uint64 total_size = sizeof(WASMGlobalInstance) * (uint64)global_count; WASMGlobalInstance *globals, *global; - if (!(globals = runtime_malloc(total_size, - error_buf, error_buf_size))) { + if (!(globals = runtime_malloc(total_size, error_buf, error_buf_size))) { return NULL; } @@ -722,13 +711,13 @@ globals_instantiate(const WASMModule *module, #if WASM_ENABLE_MULTI_MODULE != 0 if (global_import->import_module) { if (!(global->import_module_inst = get_sub_module_inst( - module_inst, global_import->import_module))) { + module_inst, global_import->import_module))) { set_error_buf(error_buf, error_buf_size, "unknown global"); return NULL; } if (!(global->import_global_inst = wasm_lookup_global( - global->import_module_inst, global_import->field_name))) { + global->import_module_inst, global_import->field_name))) { set_error_buf(error_buf, error_buf_size, "unknown global"); return NULL; } @@ -770,9 +759,9 @@ globals_instantiate(const WASMModule *module, } bh_memcpy_s( - &(global->initial_value), sizeof(WASMValue), - &(globals[init_expr->u.global_index].initial_value), - sizeof(globals[init_expr->u.global_index].initial_value)); + &(global->initial_value), sizeof(WASMValue), + &(globals[init_expr->u.global_index].initial_value), + sizeof(globals[init_expr->u.global_index].initial_value)); } #if WASM_ENABLE_REF_TYPES != 0 else if (init_expr->init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST) { @@ -801,7 +790,7 @@ get_export_count(const WASMModule *module, uint8 kind) WASMExport *export = module->exports; uint32 count = 0, i; - for (i = 0; i < module->export_count; i++, export++) + for (i = 0; i < module->export_count; i++, export ++) if (export->kind == kind) count++; @@ -821,23 +810,24 @@ export_functions_deinstantiate(WASMExportFuncInstance *functions) /** * Instantiate export functions in a module. */ -static WASMExportFuncInstance* +static WASMExportFuncInstance * export_functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, - uint32 export_func_count, - char *error_buf, uint32 error_buf_size) + uint32 export_func_count, char *error_buf, + uint32 error_buf_size) { WASMExportFuncInstance *export_funcs, *export_func; WASMExport *export = module->exports; uint32 i; - uint64 total_size = sizeof(WASMExportFuncInstance) * (uint64)export_func_count; + uint64 total_size = + sizeof(WASMExportFuncInstance) * (uint64)export_func_count; - if (!(export_func = export_funcs = runtime_malloc - (total_size, error_buf, error_buf_size))) { + if (!(export_func = export_funcs = + runtime_malloc(total_size, error_buf, error_buf_size))) { return NULL; } - for (i = 0; i < module->export_count; i++, export++) + for (i = 0; i < module->export_count; i++, export ++) if (export->kind == EXPORT_KIND_FUNC) { export_func->name = export->name; export_func->function = &module_inst->functions[export->index]; @@ -858,21 +848,22 @@ export_globals_deinstantiate(WASMExportGlobInstance *globals) static WASMExportGlobInstance * export_globals_instantiate(const WASMModule *module, - WASMModuleInstance *module_inst, - uint32 export_glob_count, char *error_buf, - uint32 error_buf_size) + WASMModuleInstance *module_inst, + uint32 export_glob_count, char *error_buf, + uint32 error_buf_size) { WASMExportGlobInstance *export_globals, *export_global; WASMExport *export = module->exports; uint32 i; - uint64 total_size = sizeof(WASMExportGlobInstance) * (uint64)export_glob_count; + uint64 total_size = + sizeof(WASMExportGlobInstance) * (uint64)export_glob_count; - if (!(export_global = export_globals = runtime_malloc - (total_size, error_buf, error_buf_size))) { + if (!(export_global = export_globals = + runtime_malloc(total_size, error_buf, error_buf_size))) { return NULL; } - for (i = 0; i < module->export_count; i++, export++) + for (i = 0; i < module->export_count; i++, export ++) if (export->kind == EXPORT_KIND_GLOBAL) { export_global->name = export->name; export_global->global = &module_inst->globals[export->index]; @@ -892,7 +883,8 @@ execute_post_inst_function(WASMModuleInstance *module_inst) uint32 i; for (i = 0; i < module_inst->export_func_count; i++) - if (!strcmp(module_inst->export_functions[i].name, "__post_instantiate")) { + if (!strcmp(module_inst->export_functions[i].name, + "__post_instantiate")) { post_inst_func = module_inst->export_functions[i].function; break; } @@ -920,7 +912,8 @@ execute_memory_init_function(WASMModuleInstance *module_inst) uint32 i; for (i = 0; i < module_inst->export_func_count; i++) - if (!strcmp(module_inst->export_functions[i].name, "__wasm_call_ctors")) { + if (!strcmp(module_inst->export_functions[i].name, + "__wasm_call_ctors")) { memory_init_func = module_inst->export_functions[i].function; break; } @@ -935,8 +928,7 @@ execute_memory_init_function(WASMModuleInstance *module_inst) /* Not a valid function type, ignore it */ return true; - return wasm_create_exec_env_and_call_function(module_inst, - memory_init_func, + return wasm_create_exec_env_and_call_function(module_inst, memory_init_func, 0, NULL); } #endif @@ -958,8 +950,8 @@ execute_start_function(WASMModuleInstance *module_inst) static bool execute_malloc_function(WASMModuleInstance *module_inst, WASMFunctionInstance *malloc_func, - WASMFunctionInstance *retain_func, - uint32 size, uint32 *p_result) + WASMFunctionInstance *retain_func, uint32 size, + uint32 *p_result) { uint32 argv[2], argc; bool ret; @@ -979,12 +971,12 @@ execute_malloc_function(WASMModuleInstance *module_inst, argc = 2; } - ret = wasm_create_exec_env_and_call_function - (module_inst, malloc_func, argc, argv); + ret = wasm_create_exec_env_and_call_function(module_inst, malloc_func, argc, + argv); if (retain_func && ret) { - ret = wasm_create_exec_env_and_call_function - (module_inst, retain_func, 1, argv); + ret = wasm_create_exec_env_and_call_function(module_inst, retain_func, + 1, argv); } if (ret) @@ -994,40 +986,39 @@ execute_malloc_function(WASMModuleInstance *module_inst, static bool execute_free_function(WASMModuleInstance *module_inst, - WASMFunctionInstance *free_func, - uint32 offset) + WASMFunctionInstance *free_func, uint32 offset) { uint32 argv[2]; argv[0] = offset; - return wasm_create_exec_env_and_call_function - (module_inst, free_func, 1, argv); + return wasm_create_exec_env_and_call_function(module_inst, free_func, 1, + argv); } #if WASM_ENABLE_MULTI_MODULE != 0 static bool sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst, - uint32 stack_size, uint32 heap_size, char *error_buf, - uint32 error_buf_size) + uint32 stack_size, uint32 heap_size, char *error_buf, + uint32 error_buf_size) { bh_list *sub_module_inst_list = module_inst->sub_module_inst_list; WASMRegisteredModule *sub_module_list_node = - bh_list_first_elem(module->import_module_list); + bh_list_first_elem(module->import_module_list); while (sub_module_list_node) { WASMSubModInstNode *sub_module_inst_list_node; - WASMModule *sub_module = (WASMModule*)sub_module_list_node->module; + WASMModule *sub_module = (WASMModule *)sub_module_list_node->module; WASMModuleInstance *sub_module_inst = - wasm_instantiate(sub_module, false, stack_size, heap_size, - error_buf, error_buf_size); + wasm_instantiate(sub_module, false, stack_size, heap_size, + error_buf, error_buf_size); if (!sub_module_inst) { LOG_DEBUG("instantiate %s failed", sub_module_list_node->module_name); return false; } - sub_module_inst_list_node = runtime_malloc - (sizeof(WASMSubModInstNode), error_buf, error_buf_size); + sub_module_inst_list_node = runtime_malloc(sizeof(WASMSubModInstNode), + error_buf, error_buf_size); if (!sub_module_inst_list_node) { LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d", sizeof(WASMSubModInstNode)); @@ -1037,9 +1028,9 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst, sub_module_inst_list_node->module_inst = sub_module_inst; sub_module_inst_list_node->module_name = - sub_module_list_node->module_name; + sub_module_list_node->module_name; bh_list_status ret = - bh_list_insert(sub_module_inst_list, sub_module_inst_list_node); + bh_list_insert(sub_module_inst_list, sub_module_inst_list_node); bh_assert(BH_LIST_SUCCESS == ret); (void)ret; @@ -1073,7 +1064,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, for (i = 0; i < module->import_function_count; i++) { WASMFunctionImport *func = - &((module->import_functions + i)->u.function); + &((module->import_functions + i)->u.function); if (!func->func_ptr_linked #if WASM_ENABLE_MULTI_MODULE != 0 && !func->import_func_linked @@ -1118,10 +1109,9 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf, /** * Instantiate module */ -WASMModuleInstance* -wasm_instantiate(WASMModule *module, bool is_sub_inst, - uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size) +WASMModuleInstance * +wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size, + uint32 heap_size, char *error_buf, uint32 error_buf_size) { WASMModuleInstance *module_inst; WASMGlobalInstance *globals = NULL, *global; @@ -1141,16 +1131,15 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, heap_size = APP_HEAP_SIZE_MAX; /* Allocate the memory */ - if (!(module_inst = runtime_malloc(sizeof(WASMModuleInstance), - error_buf, error_buf_size))) { + if (!(module_inst = runtime_malloc(sizeof(WASMModuleInstance), error_buf, + error_buf_size))) { return NULL; } module_inst->module = module; #if WASM_ENABLE_MULTI_MODULE != 0 - module_inst->sub_module_inst_list = - &module_inst->sub_module_inst_list_head; + module_inst->sub_module_inst_list = &module_inst->sub_module_inst_list_head; ret = sub_module_instantiate(module, module_inst, stack_size, heap_size, error_buf, error_buf_size); if (!ret) { @@ -1159,12 +1148,19 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, } #endif +#if WASM_ENABLE_DUMP_CALL_STACK != 0 + if (!(module_inst->frames = runtime_malloc((uint64)sizeof(Vector), + error_buf, error_buf_size))) { + goto fail; + } +#endif + /* Instantiate global firstly to get the mutable data size */ global_count = module->import_global_count + module->global_count; if (global_count - && !(globals = globals_instantiate(module, module_inst, - &global_data_size, - error_buf, error_buf_size))) { + && !(globals = + globals_instantiate(module, module_inst, &global_data_size, + error_buf, error_buf_size))) { goto fail; } module_inst->global_count = global_count; @@ -1172,8 +1168,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, module_inst->memory_count = module->import_memory_count + module->memory_count; - module_inst->table_count = - module->import_table_count + module->table_count; + module_inst->table_count = module->import_table_count + module->table_count; module_inst->function_count = module->import_function_count + module->function_count; @@ -1181,42 +1176,38 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, module_inst->export_func_count = get_export_count(module, EXPORT_KIND_FUNC); #if WASM_ENABLE_MULTI_MODULE != 0 module_inst->export_tab_count = get_export_count(module, EXPORT_KIND_TABLE); - module_inst->export_mem_count = get_export_count(module, EXPORT_KIND_MEMORY); - module_inst->export_glob_count = get_export_count(module, EXPORT_KIND_GLOBAL); + module_inst->export_mem_count = + get_export_count(module, EXPORT_KIND_MEMORY); + module_inst->export_glob_count = + get_export_count(module, EXPORT_KIND_GLOBAL); #endif if (global_count > 0) { - if (!(module_inst->global_data = runtime_malloc - (global_data_size, error_buf, error_buf_size))) { + if (!(module_inst->global_data = runtime_malloc( + global_data_size, error_buf, error_buf_size))) { goto fail; } } /* Instantiate memories/tables/functions */ if ((module_inst->memory_count > 0 - && !(module_inst->memories = - memories_instantiate(module, - module_inst, - heap_size, error_buf, error_buf_size))) + && !(module_inst->memories = memories_instantiate( + module, module_inst, heap_size, error_buf, error_buf_size))) || (module_inst->table_count > 0 - && !(module_inst->tables = - tables_instantiate(module, - module_inst, - error_buf, error_buf_size))) + && !(module_inst->tables = tables_instantiate( + module, module_inst, error_buf, error_buf_size))) || (module_inst->function_count > 0 - && !(module_inst->functions = - functions_instantiate(module, - module_inst, - error_buf, error_buf_size))) + && !(module_inst->functions = functions_instantiate( + module, module_inst, error_buf, error_buf_size))) || (module_inst->export_func_count > 0 && !(module_inst->export_functions = export_functions_instantiate( - module, module_inst, module_inst->export_func_count, - error_buf, error_buf_size))) + module, module_inst, module_inst->export_func_count, + error_buf, error_buf_size))) #if WASM_ENABLE_MULTI_MODULE != 0 || (module_inst->export_glob_count > 0 && !(module_inst->export_globals = export_globals_instantiate( - module, module_inst, module_inst->export_glob_count, - error_buf, error_buf_size))) + module, module_inst, module_inst->export_glob_count, + error_buf, error_buf_size))) #endif ) { goto fail; @@ -1235,12 +1226,13 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, case VALUE_TYPE_FUNCREF: case VALUE_TYPE_EXTERNREF: #endif - *(int32*)global_data = global->initial_value.i32; + *(int32 *)global_data = global->initial_value.i32; global_data += sizeof(int32); break; case VALUE_TYPE_I64: case VALUE_TYPE_F64: - bh_memcpy_s(global_data, (uint32)(global_data_end - global_data), + bh_memcpy_s(global_data, + (uint32)(global_data_end - global_data), &global->initial_value.i64, sizeof(int64)); global_data += sizeof(int64); break; @@ -1257,7 +1249,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, /* Initialize the memory data with data segment section */ module_inst->default_memory = - module_inst->memory_count ? module_inst->memories[0] : NULL; + module_inst->memory_count ? module_inst->memories[0] : NULL; for (i = 0; i < module->data_seg_count; i++) { WASMMemoryInstance *memory = NULL; @@ -1279,12 +1271,11 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, bh_assert(memory_data || memory_size == 0); bh_assert(data_seg->base_offset.init_expr_type - == INIT_EXPR_TYPE_I32_CONST + == INIT_EXPR_TYPE_I32_CONST || data_seg->base_offset.init_expr_type - == INIT_EXPR_TYPE_GET_GLOBAL); + == INIT_EXPR_TYPE_GET_GLOBAL); - if (data_seg->base_offset.init_expr_type - == INIT_EXPR_TYPE_GET_GLOBAL) { + if (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { if (!check_global_init_expr(module, data_seg->base_offset.u.global_index, error_buf, error_buf_size)) { @@ -1293,15 +1284,14 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, if (!globals || globals[data_seg->base_offset.u.global_index].type - != VALUE_TYPE_I32) { + != VALUE_TYPE_I32) { set_error_buf(error_buf, error_buf_size, "data segment does not fit"); goto fail; } data_seg->base_offset.u.i32 = - globals[data_seg->base_offset.u.global_index] - .initial_value.i32; + globals[data_seg->base_offset.u.global_index].initial_value.i32; } /* check offset */ @@ -1342,7 +1332,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, /* Initialize the table data with table segment section */ module_inst->default_table = - module_inst->table_count ? module_inst->tables[0] : NULL; + module_inst->table_count ? module_inst->tables[0] : NULL; /* in case there is no table */ for (i = 0; module_inst->table_count > 0 && i < module->table_seg_count; i++) { @@ -1363,8 +1353,8 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 *table_data = (uint32 *)table->base_addr; #if WASM_ENABLE_MULTI_MODULE != 0 table_data = table->table_inst_linked - ? (uint32 *)table->table_inst_linked->base_addr - : table_data; + ? (uint32 *)table->table_inst_linked->base_addr + : table_data; #endif bh_assert(table_data); @@ -1375,11 +1365,14 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, /* init vec(funcidx) or vec(expr) */ bh_assert( - table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST - || table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL + table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST + || table_seg->base_offset.init_expr_type + == INIT_EXPR_TYPE_GET_GLOBAL #if WASM_ENABLE_REF_TYPES != 0 - || table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST - || table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST + || table_seg->base_offset.init_expr_type + == INIT_EXPR_TYPE_FUNCREF_CONST + || table_seg->base_offset.init_expr_type + == INIT_EXPR_TYPE_REFNULL_CONST #endif ); @@ -1393,14 +1386,15 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, if (!globals || globals[table_seg->base_offset.u.global_index].type - != VALUE_TYPE_I32) { + != VALUE_TYPE_I32) { set_error_buf(error_buf, error_buf_size, "elements segment does not fit"); goto fail; } table_seg->base_offset.u.i32 = - globals[table_seg->base_offset.u.global_index].initial_value.i32; + globals[table_seg->base_offset.u.global_index] + .initial_value.i32; } /* check offset since length might negative */ @@ -1438,10 +1432,10 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, * so loader check is enough */ bh_memcpy_s( - table_data + table_seg->base_offset.u.i32, - (uint32)((table->cur_size - (uint32)table_seg->base_offset.u.i32) - * sizeof(uint32)), - table_seg->func_indexes, (uint32)(length * sizeof(uint32))); + table_data + table_seg->base_offset.u.i32, + (uint32)((table->cur_size - (uint32)table_seg->base_offset.u.i32) + * sizeof(uint32)), + table_seg->func_indexes, (uint32)(length * sizeof(uint32))); } /* module instance type */ @@ -1451,7 +1445,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, if (stack_size == 0) stack_size = DEFAULT_WASM_STACK_SIZE; #if WASM_ENABLE_SPEC_TEST != 0 - if (stack_size < 48 *1024) + if (stack_size < 48 * 1024) stack_size = 48 * 1024; #endif module_inst->default_wasm_stack_size = stack_size; @@ -1474,19 +1468,14 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, #if WASM_ENABLE_LIBC_WASI != 0 /* The sub-instance will get the wasi_ctx from main-instance */ if (!is_sub_inst) { - if (!wasm_runtime_init_wasi((WASMModuleInstanceCommon*)module_inst, - module->wasi_args.dir_list, - module->wasi_args.dir_count, - module->wasi_args.map_dir_list, - module->wasi_args.map_dir_count, - module->wasi_args.env, - module->wasi_args.env_count, - module->wasi_args.argv, - module->wasi_args.argc, - module->wasi_args.stdio[0], - module->wasi_args.stdio[1], - module->wasi_args.stdio[2], - error_buf, error_buf_size)) { + if (!wasm_runtime_init_wasi( + (WASMModuleInstanceCommon *)module_inst, + module->wasi_args.dir_list, module->wasi_args.dir_count, + module->wasi_args.map_dir_list, module->wasi_args.map_dir_count, + module->wasi_args.env, module->wasi_args.env_count, + module->wasi_args.argv, module->wasi_args.argc, + module->wasi_args.stdio[0], module->wasi_args.stdio[1], + module->wasi_args.stdio[2], error_buf, error_buf_size)) { goto fail; } } @@ -1502,8 +1491,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, /* Execute __post_instantiate function */ if (!execute_post_inst_function(module_inst) || !execute_start_function(module_inst)) { - set_error_buf(error_buf, error_buf_size, - module_inst->cur_exception); + set_error_buf(error_buf, error_buf_size, module_inst->cur_exception); goto fail; } @@ -1527,8 +1515,8 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, #endif #if WASM_ENABLE_MEMORY_TRACING != 0 - wasm_runtime_dump_module_inst_mem_consumption - ((WASMModuleInstanceCommon *)module_inst); + wasm_runtime_dump_module_inst_mem_consumption( + (WASMModuleInstanceCommon *)module_inst); #endif (void)global_data_end; return module_inst; @@ -1554,16 +1542,16 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) which may allocated from global heap. */ /* Only destroy wasi ctx in the main module instance */ if (!is_sub_inst) - wasm_runtime_destroy_wasi((WASMModuleInstanceCommon*)module_inst); + wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst); #endif if (module_inst->memory_count > 0) - memories_deinstantiate( - module_inst, - module_inst->memories, module_inst->memory_count); + memories_deinstantiate(module_inst, module_inst->memories, + module_inst->memory_count); tables_deinstantiate(module_inst->tables, module_inst->table_count); - functions_deinstantiate(module_inst->functions, module_inst->function_count); + functions_deinstantiate(module_inst->functions, + module_inst->function_count); globals_deinstantiate(module_inst->globals); export_functions_deinstantiate(module_inst->export_functions); #if WASM_ENABLE_MULTI_MODULE != 0 @@ -1574,18 +1562,26 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) wasm_runtime_free(module_inst->global_data); #if WASM_ENABLE_REF_TYPES != 0 - wasm_externref_cleanup((WASMModuleInstanceCommon*)module_inst); + wasm_externref_cleanup((WASMModuleInstanceCommon *)module_inst); #endif if (module_inst->exec_env_singleton) wasm_exec_env_destroy(module_inst->exec_env_singleton); +#if WASM_ENABLE_DUMP_CALL_STACK != 0 + if (module_inst->frames) { + bh_vector_destroy(module_inst->frames); + wasm_runtime_free(module_inst->frames); + module_inst->frames = NULL; + } +#endif + wasm_runtime_free(module_inst); } -WASMFunctionInstance* -wasm_lookup_function(const WASMModuleInstance *module_inst, - const char *name, const char *signature) +WASMFunctionInstance * +wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name, + const char *signature) { uint32 i; for (i = 0; i < module_inst->export_func_count; i++) @@ -1612,7 +1608,7 @@ wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name) /** * using a strong assumption that one module instance only has * one memory instance - */ + */ (void)module_inst->export_memories; return module_inst->memories[0]; } @@ -1648,11 +1644,11 @@ clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst) } bool -wasm_call_function(WASMExecEnv *exec_env, - WASMFunctionInstance *function, +wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, unsigned argc, uint32 argv[]) { - WASMModuleInstance *module_inst = (WASMModuleInstance*)exec_env->module_inst; + WASMModuleInstance *module_inst = + (WASMModuleInstance *)exec_env->module_inst; /* set thread handle and stack boundary */ wasm_exec_env_set_thread_info(exec_env); @@ -1673,13 +1669,12 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst, #if WASM_ENABLE_THREAD_MGR != 0 WASMExecEnv *existing_exec_env = NULL; - if (!(existing_exec_env = exec_env = - wasm_clusters_search_exec_env( - (WASMModuleInstanceCommon*)module_inst))) { + if (!(existing_exec_env = exec_env = wasm_clusters_search_exec_env( + (WASMModuleInstanceCommon *)module_inst))) { #endif - if (!(exec_env = wasm_exec_env_create( - (WASMModuleInstanceCommon*)module_inst, - module_inst->default_wasm_stack_size))) { + if (!(exec_env = + wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst, + module_inst->default_wasm_stack_size))) { wasm_set_exception(module_inst, "allocate memory failed"); return false; } @@ -1720,18 +1715,16 @@ wasm_create_exec_env_singleton(WASMModuleInstance *module_inst) } void -wasm_set_exception(WASMModuleInstance *module_inst, - const char *exception) +wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) { if (exception) - snprintf(module_inst->cur_exception, - sizeof(module_inst->cur_exception), + snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), "Exception: %s", exception); else module_inst->cur_exception[0] = '\0'; } -const char* +const char * wasm_get_exception(WASMModuleInstance *module_inst) { if (module_inst->cur_exception[0] == '\0') @@ -1772,13 +1765,16 @@ wasm_dump_perf_profiling(const WASMModuleInstance *module_inst) } if (func_name) - os_printf(" func %s, execution time: %.3f ms, execution count: %d times\n", - func_name, module_inst->functions[i].total_exec_time / 1000.0f, - module_inst->functions[i].total_exec_cnt); + os_printf(" func %s, execution time: %.3f ms, execution count: %d " + "times\n", + func_name, + module_inst->functions[i].total_exec_time / 1000.0f, + module_inst->functions[i].total_exec_cnt); else - os_printf(" func %d, execution time: %.3f ms, execution count: %d times\n", - i, module_inst->functions[i].total_exec_time / 1000.0f, - module_inst->functions[i].total_exec_cnt); + os_printf(" func %d, execution time: %.3f ms, execution count: %d " + "times\n", + i, module_inst->functions[i].total_exec_time / 1000.0f, + module_inst->functions[i].total_exec_cnt); } } #endif @@ -1799,16 +1795,30 @@ wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size, if (memory->heap_handle) { addr = mem_allocator_malloc(memory->heap_handle, size); } - else if (module_inst->malloc_function - && module_inst->free_function) { - if (!execute_malloc_function(module_inst, - module_inst->malloc_function, - module_inst->retain_function, - size, &offset)) { + else if (module_inst->malloc_function && module_inst->free_function) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + /* TODO: obviously, we can not create debug instance for + * module malloc here, so, just disable the engine here, + * it is strange, but we now are lack of ways to indicate + * which calls should not be debugged. And we have other + * execute_xxx_function may need to be taken care of + */ + bool active = wasm_debug_get_engine_active(); + wasm_debug_set_engine_active(false); +#endif + if (!execute_malloc_function(module_inst, module_inst->malloc_function, + module_inst->retain_function, size, + &offset)) { +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_debug_set_engine_active(active); +#endif return 0; } +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_debug_set_engine_active(active); +#endif /* If we use app's malloc function, - the default memory may be changed while memory growing */ + the default memory may be changed while memory growing */ memory = module_inst->default_memory; addr = offset ? memory->memory_data + offset : NULL; } @@ -1873,7 +1883,7 @@ wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr) { if (ptr) { WASMMemoryInstance *memory = module_inst->default_memory; - uint8* addr; + uint8 *addr; if (!memory) { return; @@ -1881,29 +1891,35 @@ wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr) addr = memory->memory_data + ptr; - if (memory->heap_handle - && memory->heap_data <= addr + if (memory->heap_handle && memory->heap_data <= addr && addr < memory->heap_data_end) { mem_allocator_free(memory->heap_handle, addr); } - else if (module_inst->malloc_function - && module_inst->free_function + else if (module_inst->malloc_function && module_inst->free_function && memory->memory_data <= addr && addr < memory->memory_data_end) { - execute_free_function(module_inst, - module_inst->free_function, - ptr); +#if WASM_ENABLE_DEBUG_INTERP != 0 + /*TODO: obviously, we can not create debug instance for module + malloc here, so, just disable the engine here, it is strange. the + wasm's call should be marshed to its own thread */ + bool active = wasm_debug_get_engine_active(); + wasm_debug_set_engine_active(false); +#endif + execute_free_function(module_inst, module_inst->free_function, ptr); +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_debug_set_engine_active(active); +#endif } } } uint32 -wasm_module_dup_data(WASMModuleInstance *module_inst, - const char *src, uint32 size) +wasm_module_dup_data(WASMModuleInstance *module_inst, const char *src, + uint32 size) { char *buffer; - uint32 buffer_offset = wasm_module_malloc(module_inst, size, - (void**)&buffer); + uint32 buffer_offset = + wasm_module_malloc(module_inst, size, (void **)&buffer); if (buffer_offset != 0) { buffer = wasm_addr_app_to_native(module_inst, buffer_offset); bh_memcpy_s(buffer, size, src, size); @@ -1912,8 +1928,8 @@ wasm_module_dup_data(WASMModuleInstance *module_inst, } bool -wasm_validate_app_addr(WASMModuleInstance *module_inst, - uint32 app_offset, uint32 size) +wasm_validate_app_addr(WASMModuleInstance *module_inst, uint32 app_offset, + uint32 size) { WASMMemoryInstance *memory = module_inst->default_memory; uint32 memory_data_size; @@ -1925,7 +1941,7 @@ wasm_validate_app_addr(WASMModuleInstance *module_inst, memory_data_size = memory->num_bytes_per_page * memory->cur_page_count; /* integer overflow check */ - if (app_offset + size < app_offset) { + if (app_offset > UINT32_MAX - size) { goto fail; } @@ -1938,8 +1954,8 @@ wasm_validate_app_addr(WASMModuleInstance *module_inst, } bool -wasm_validate_native_addr(WASMModuleInstance *module_inst, - void *native_ptr, uint32 size) +wasm_validate_native_addr(WASMModuleInstance *module_inst, void *native_ptr, + uint32 size) { WASMMemoryInstance *memory = module_inst->default_memory; uint8 *addr = (uint8 *)native_ptr; @@ -1949,12 +1965,11 @@ wasm_validate_native_addr(WASMModuleInstance *module_inst, } /* integer overflow check */ - if (addr + size < addr) { + if ((uintptr_t)addr > UINTPTR_MAX - size) { goto fail; } - if (memory->memory_data <= addr - && addr + size <= memory->memory_data_end) { + if (memory->memory_data <= addr && addr + size <= memory->memory_data_end) { return true; } fail: @@ -1963,8 +1978,7 @@ wasm_validate_native_addr(WASMModuleInstance *module_inst, } void * -wasm_addr_app_to_native(WASMModuleInstance *module_inst, - uint32 app_offset) +wasm_addr_app_to_native(WASMModuleInstance *module_inst, uint32 app_offset) { WASMMemoryInstance *memory = module_inst->default_memory; uint8 *addr; @@ -1974,15 +1988,13 @@ wasm_addr_app_to_native(WASMModuleInstance *module_inst, addr = memory->memory_data + app_offset; - if (memory->memory_data <= addr - && addr < memory->memory_data_end) + if (memory->memory_data <= addr && addr < memory->memory_data_end) return addr; return NULL; } uint32 -wasm_addr_native_to_app(WASMModuleInstance *module_inst, - void *native_ptr) +wasm_addr_native_to_app(WASMModuleInstance *module_inst, void *native_ptr) { WASMMemoryInstance *memory = module_inst->default_memory; uint8 *addr = (uint8 *)native_ptr; @@ -1990,17 +2002,14 @@ wasm_addr_native_to_app(WASMModuleInstance *module_inst, if (!memory) return 0; - if (memory->memory_data <= addr - && addr < memory->memory_data_end) + if (memory->memory_data <= addr && addr < memory->memory_data_end) return (uint32)(addr - memory->memory_data); return 0; } bool -wasm_get_app_addr_range(WASMModuleInstance *module_inst, - uint32 app_offset, - uint32 *p_app_start_offset, - uint32 *p_app_end_offset) +wasm_get_app_addr_range(WASMModuleInstance *module_inst, uint32 app_offset, + uint32 *p_app_start_offset, uint32 *p_app_end_offset) { WASMMemoryInstance *memory = module_inst->default_memory; uint32 memory_data_size; @@ -2021,8 +2030,7 @@ wasm_get_app_addr_range(WASMModuleInstance *module_inst, } bool -wasm_get_native_addr_range(WASMModuleInstance *module_inst, - uint8 *native_ptr, +wasm_get_native_addr_range(WASMModuleInstance *module_inst, uint8 *native_ptr, uint8 **p_native_start_addr, uint8 **p_native_end_addr) { @@ -2032,8 +2040,7 @@ wasm_get_native_addr_range(WASMModuleInstance *module_inst, if (!memory) return false; - if (memory->memory_data <= addr - && addr < memory->memory_data_end) { + if (memory->memory_data <= addr && addr < memory->memory_data_end) { if (p_native_start_addr) *p_native_start_addr = memory->memory_data; if (p_native_end_addr) @@ -2083,25 +2090,27 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) } #endif - if (!(new_memory_data = wasm_runtime_realloc(memory_data, (uint32)total_size))) { + if (!(new_memory_data = + wasm_runtime_realloc(memory_data, (uint32)total_size))) { if (!(new_memory_data = wasm_runtime_malloc((uint32)total_size))) { return false; } if (memory_data) { - bh_memcpy_s(new_memory_data, (uint32)total_size, - memory_data, total_size_old); + bh_memcpy_s(new_memory_data, (uint32)total_size, memory_data, + total_size_old); wasm_runtime_free(memory_data); } } - memset(new_memory_data + total_size_old, - 0, (uint32)total_size - total_size_old); + memset(new_memory_data + total_size_old, 0, + (uint32)total_size - total_size_old); if (heap_size > 0) { if (mem_allocator_migrate(memory->heap_handle, (char *)heap_data_old - + (new_memory_data - memory_data), - heap_size) != 0) { + + (new_memory_data - memory_data), + heap_size) + != 0) { return false; } } @@ -2110,17 +2119,16 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) memory->cur_page_count = total_page_count; memory->heap_data = heap_data_old + (new_memory_data - memory_data); memory->heap_data_end = memory->heap_data + heap_size; - memory->memory_data_end = memory->memory_data - + memory->num_bytes_per_page - * total_page_count; + memory->memory_data_end = + memory->memory_data + memory->num_bytes_per_page * total_page_count; return true; } #if WASM_ENABLE_REF_TYPES != 0 bool -wasm_enlarge_table(WASMModuleInstance *module_inst, - uint32 table_idx, uint32 inc_entries, uint32 init_val) +wasm_enlarge_table(WASMModuleInstance *module_inst, uint32 table_idx, + uint32 inc_entries, uint32 init_val) { uint32 entry_count, *new_table_data_start, i; WASMTableInstance *table_inst; @@ -2135,17 +2143,19 @@ wasm_enlarge_table(WASMModuleInstance *module_inst, return false; } + if (inc_entries > UINT32_MAX - table_inst->cur_size) { + return false; + } + entry_count = table_inst->cur_size + inc_entries; - /* prevent from integer overflow */ - if (entry_count < table_inst->cur_size - || entry_count > table_inst->max_size) { + if (entry_count > table_inst->max_size) { return false; } /* fill in */ new_table_data_start = - (uint32 *)((uint8 *)table_inst + offsetof(WASMTableInstance, base_addr)) - + table_inst->cur_size; + (uint32 *)((uint8 *)table_inst + offsetof(WASMTableInstance, base_addr)) + + table_inst->cur_size; for (i = 0; i < inc_entries; ++i) { new_table_data_start[i] = init_val; } @@ -2156,18 +2166,15 @@ wasm_enlarge_table(WASMModuleInstance *module_inst, #endif /* WASM_ENABLE_REF_TYPES != 0 */ bool -wasm_call_indirect(WASMExecEnv *exec_env, - uint32_t tbl_idx, - uint32_t element_indices, - uint32_t argc, uint32_t argv[]) +wasm_call_indirect(WASMExecEnv *exec_env, uint32_t tbl_idx, + uint32_t element_indices, uint32_t argc, uint32_t argv[]) { WASMModuleInstance *module_inst = NULL; WASMTableInstance *table_inst = NULL; uint32_t function_indices = 0; WASMFunctionInstance *function_inst = NULL; - module_inst = - (WASMModuleInstance*)exec_env->module_inst; + module_inst = (WASMModuleInstance *)exec_env->module_inst; bh_assert(module_inst); table_inst = module_inst->tables[tbl_idx]; @@ -2185,7 +2192,7 @@ wasm_call_indirect(WASMExecEnv *exec_env, * please be aware that table_inst->base_addr may point * to another module's table **/ - function_indices = ((uint32_t*)table_inst->base_addr)[element_indices]; + function_indices = ((uint32_t *)table_inst->base_addr)[element_indices]; if (function_indices == NULL_REF) { wasm_set_exception(module_inst, "uninitialized element"); goto got_exception; @@ -2212,16 +2219,14 @@ wasm_call_indirect(WASMExecEnv *exec_env, #if WASM_ENABLE_THREAD_MGR != 0 bool -wasm_set_aux_stack(WASMExecEnv *exec_env, - uint32 start_offset, uint32 size) +wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size) { WASMModuleInstance *module_inst = - (WASMModuleInstance*)exec_env->module_inst; + (WASMModuleInstance *)exec_env->module_inst; uint32 stack_top_idx = module_inst->module->aux_stack_top_global_index; uint32 data_end = module_inst->module->aux_data_end; uint32 stack_bottom = module_inst->module->aux_stack_bottom; - bool is_stack_before_data = - stack_bottom < data_end ? true : false; + bool is_stack_before_data = stack_bottom < data_end ? true : false; /* Check the aux stack space, currently we don't allocate space in heap */ if ((is_stack_before_data && (size > start_offset)) @@ -2231,10 +2236,9 @@ wasm_set_aux_stack(WASMExecEnv *exec_env, if (stack_top_idx != (uint32)-1) { /* The aux stack top is a wasm global, set the initial value for the global */ - uint8 *global_addr = - module_inst->global_data + - module_inst->globals[stack_top_idx].data_offset; - *(int32*)global_addr = start_offset; + uint8 *global_addr = module_inst->global_data + + module_inst->globals[stack_top_idx].data_offset; + *(int32 *)global_addr = start_offset; /* The aux stack boundary is a constant value, set the value to exec_env */ exec_env->aux_stack_boundary.boundary = start_offset - size; @@ -2246,18 +2250,15 @@ wasm_set_aux_stack(WASMExecEnv *exec_env, } bool -wasm_get_aux_stack(WASMExecEnv *exec_env, - uint32 *start_offset, uint32 *size) +wasm_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size) { WASMModuleInstance *module_inst = - (WASMModuleInstance*)exec_env->module_inst; + (WASMModuleInstance *)exec_env->module_inst; /* The aux stack information is resolved in loader and store in module */ - uint32 stack_bottom = - module_inst->module->aux_stack_bottom; - uint32 total_aux_stack_size = - module_inst->module->aux_stack_size; + uint32 stack_bottom = module_inst->module->aux_stack_bottom; + uint32 total_aux_stack_size = module_inst->module->aux_stack_size; if (stack_bottom != 0 && total_aux_stack_size != 0) { if (start_offset) @@ -2284,23 +2285,23 @@ wasm_get_module_mem_consumption(const WASMModule *module, mem_conspn->types_size = sizeof(WASMType *) * module->type_count; for (i = 0; i < module->type_count; i++) { WASMType *type = module->types[i]; - size = offsetof(WASMType, types) + - sizeof(uint8) * (type->param_count + type->result_count); + size = offsetof(WASMType, types) + + sizeof(uint8) * (type->param_count + type->result_count); mem_conspn->types_size += size; } mem_conspn->imports_size = sizeof(WASMImport) * module->import_count; - mem_conspn->functions_size = sizeof(WASMFunction *) - * module->function_count; + mem_conspn->functions_size = + sizeof(WASMFunction *) * module->function_count; for (i = 0; i < module->function_count; i++) { WASMFunction *func = module->functions[i]; WASMType *type = func->func_type; size = sizeof(WASMFunction) + func->local_count + sizeof(uint16) * (type->param_count + func->local_count); #if WASM_ENABLE_FAST_INTERP != 0 - size += func->code_compiled_size - + sizeof(uint32) * func->const_cell_num; + size += + func->code_compiled_size + sizeof(uint32) * func->const_cell_num; #endif mem_conspn->functions_size += size; } @@ -2310,16 +2311,14 @@ wasm_get_module_mem_consumption(const WASMModule *module, mem_conspn->globals_size = sizeof(WASMGlobal) * module->global_count; mem_conspn->exports_size = sizeof(WASMExport) * module->export_count; - mem_conspn->table_segs_size = sizeof(WASMTableSeg) - * module->table_seg_count; + mem_conspn->table_segs_size = + sizeof(WASMTableSeg) * module->table_seg_count; for (i = 0; i < module->table_seg_count; i++) { WASMTableSeg *table_seg = &module->table_segments[i]; - mem_conspn->tables_size += sizeof(uint32) - * table_seg->function_count; + mem_conspn->tables_size += sizeof(uint32) * table_seg->function_count; } - mem_conspn->data_segs_size = sizeof(WASMDataSeg*) - * module->data_seg_count; + mem_conspn->data_segs_size = sizeof(WASMDataSeg *) * module->data_seg_count; for (i = 0; i < module->data_seg_count; i++) { mem_conspn->data_segs_size += sizeof(WASMDataSeg); } @@ -2328,8 +2327,8 @@ wasm_get_module_mem_consumption(const WASMModule *module, StringNode *node = module->const_str_list, *node_next; while (node) { node_next = node->next; - mem_conspn->const_strs_size += sizeof(StringNode) - + strlen(node->str) + 1; + mem_conspn->const_strs_size += + sizeof(StringNode) + strlen(node->str) + 1; node = node_next; } } @@ -2360,22 +2359,20 @@ wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst, mem_conspn->module_inst_struct_size = sizeof(WASMModuleInstance); - mem_conspn->memories_size = sizeof(WASMMemoryInstance *) - * module_inst->memory_count; + mem_conspn->memories_size = + sizeof(WASMMemoryInstance *) * module_inst->memory_count; for (i = 0; i < module_inst->memory_count; i++) { WASMMemoryInstance *memory = module_inst->memories[i]; size = sizeof(WASMMemoryInstance) + memory->num_bytes_per_page * memory->cur_page_count; mem_conspn->memories_size += size; - mem_conspn->app_heap_size += memory->heap_data_end - - memory->heap_data; + mem_conspn->app_heap_size += memory->heap_data_end - memory->heap_data; /* size of app heap structure */ - mem_conspn->memories_size += - mem_allocator_get_heap_struct_size(); + mem_conspn->memories_size += mem_allocator_get_heap_struct_size(); } - mem_conspn->tables_size = sizeof(WASMTableInstance *) - * module_inst->table_count; + mem_conspn->tables_size = + sizeof(WASMTableInstance *) * module_inst->table_count; for (i = 0; i < module_inst->table_count; i++) { WASMTableInstance *table = module_inst->tables[i]; #if WASM_ENABLE_MULTI_MODULE != 0 @@ -2391,20 +2388,20 @@ wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst, mem_conspn->tables_size += size; } - mem_conspn->functions_size = sizeof(WASMFunctionInstance) - * module_inst->function_count; + mem_conspn->functions_size = + sizeof(WASMFunctionInstance) * module_inst->function_count; - mem_conspn->globals_size = sizeof(WASMGlobalInstance) - * module_inst->global_count; + mem_conspn->globals_size = + sizeof(WASMGlobalInstance) * module_inst->global_count; if (module_inst->global_count > 0) { WASMGlobalInstance *global = &module_inst->globals[module_inst->global_count - 1]; - mem_conspn->globals_size += global->data_offset - + wasm_value_type_size(global->type); + mem_conspn->globals_size += + global->data_offset + wasm_value_type_size(global->type); } - mem_conspn->exports_size = sizeof(WASMExportFuncInstance) - * module_inst->export_func_count; + mem_conspn->exports_size = + sizeof(WASMExportFuncInstance) * module_inst->export_func_count; mem_conspn->total_size += mem_conspn->module_inst_struct_size; mem_conspn->total_size += mem_conspn->memories_size; @@ -2413,7 +2410,7 @@ wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst, mem_conspn->total_size += mem_conspn->globals_size; mem_conspn->total_size += mem_conspn->exports_size; } -#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) +#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \ || (WASM_ENABLE_MEMORY_TRACING != 0) */ #if WASM_ENABLE_DUMP_CALL_STACK != 0 @@ -2422,18 +2419,53 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env) { WASMModuleInstance *module_inst = (WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env); - WASMInterpFrame *cur_frame = - wasm_exec_env_get_cur_frame(exec_env); - WASMFunctionInstance *func_inst; - WASMExportFuncInstance *export_func; - const char *func_name = NULL; - uint32 n, i; + WASMInterpFrame *first_frame, + *cur_frame = wasm_exec_env_get_cur_frame(exec_env); + uint32 n = 0; + /* count frames includes a function */ + first_frame = cur_frame; + while (cur_frame) { + if (cur_frame->function) { + n++; + } + cur_frame = cur_frame->prev_frame; + } + + /* release previous stack frames and create new ones */ + if (!bh_vector_destroy(module_inst->frames) + || !bh_vector_init(module_inst->frames, n, sizeof(WASMCApiFrame))) { + return; + } + + cur_frame = first_frame; + n = 0; os_printf("\n"); - for (n = 0; cur_frame && cur_frame->function; n++) { - func_name = NULL; - func_inst = cur_frame->function; + while (cur_frame) { + WASMCApiFrame frame = { 0 }; + WASMFunctionInstance *func_inst = cur_frame->function; + const char *func_name = NULL; + const uint8 *func_code_base = NULL; + + if (!func_inst) { + cur_frame = cur_frame->prev_frame; + continue; + } + + /* place holder, will overwrite it in wasm_c_api */ + frame.instance = module_inst; + frame.module_offset = 0; + frame.func_index = (uint32)(func_inst - module_inst->functions); + func_code_base = wasm_get_func_code(func_inst); + if (!cur_frame->ip || !func_code_base) { + frame.func_offset = 0; + } + else { + frame.func_offset = (uint32)(cur_frame->ip - func_code_base); + } + + /* look for the function name */ if (func_inst->is_import_func) { func_name = func_inst->u.func_import->field_name; } @@ -2444,8 +2476,10 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env) /* if custom name section is not generated, search symbols from export table */ if (!func_name) { + uint32 i; for (i = 0; i < module_inst->export_func_count; i++) { - export_func = module_inst->export_functions + i; + WASMExportFuncInstance *export_func = + module_inst->export_functions + i; if (export_func->function == func_inst) { func_name = export_func->name; break; @@ -2462,7 +2496,11 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env) os_printf("#%02d %s \n", n, func_name); } + /* keep print */ + bh_vector_append(module_inst->frames, &frame); + cur_frame = cur_frame->prev_frame; + n++; } os_printf("\n"); } diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 55c13c282d..56871b3652 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -209,6 +209,10 @@ struct WASMModuleInstance { /* The exception buffer of wasm interpreter for current thread. */ char cur_exception[128]; +#if WASM_ENABLE_DUMP_CALL_STACK != 0 + Vector *frames; +#endif + /* The custom data that can be set/get by * wasm_set_custom_data/wasm_get_custom_data */ void *custom_data; @@ -243,7 +247,7 @@ typedef struct WASMSubModInstNode { * * @return the code block of the function */ -static inline uint8* +static inline uint8 * wasm_get_func_code(WASMFunctionInstance *func) { #if WASM_ENABLE_FAST_INTERP == 0 @@ -260,34 +264,33 @@ wasm_get_func_code(WASMFunctionInstance *func) * * @return the code block end of the function */ -static inline uint8* +static inline uint8 * wasm_get_func_code_end(WASMFunctionInstance *func) { #if WASM_ENABLE_FAST_INTERP == 0 - return func->is_import_func - ? NULL : func->u.func->code + func->u.func->code_size; + return func->is_import_func ? NULL + : func->u.func->code + func->u.func->code_size; #else return func->is_import_func - ? NULL - : func->u.func->code_compiled + func->u.func->code_compiled_size; + ? NULL + : func->u.func->code_compiled + func->u.func->code_compiled_size; #endif } WASMModule * -wasm_load(const uint8 *buf, uint32 size, - char *error_buf, uint32 error_buf_size); +wasm_load(const uint8 *buf, uint32 size, char *error_buf, + uint32 error_buf_size); WASMModule * -wasm_load_from_sections(WASMSection *section_list, - char *error_buf, uint32_t error_buf_size); +wasm_load_from_sections(WASMSection *section_list, char *error_buf, + uint32_t error_buf_size); void wasm_unload(WASMModule *module); WASMModuleInstance * -wasm_instantiate(WASMModule *module, bool is_sub_inst, - uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size); +wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size, + uint32 heap_size, char *error_buf, uint32 error_buf_size); void wasm_dump_perf_profiling(const WASMModuleInstance *module_inst); @@ -296,8 +299,8 @@ void wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst); WASMFunctionInstance * -wasm_lookup_function(const WASMModuleInstance *module_inst, - const char *name, const char *signature); +wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name, + const char *signature); #if WASM_ENABLE_MULTI_MODULE != 0 WASMGlobalInstance * @@ -311,8 +314,7 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name); #endif bool -wasm_call_function(WASMExecEnv *exec_env, - WASMFunctionInstance *function, +wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, unsigned argc, uint32 argv[]); bool @@ -326,7 +328,7 @@ wasm_create_exec_env_singleton(WASMModuleInstance *module_inst); void wasm_set_exception(WASMModuleInstance *module, const char *exception); -const char* +const char * wasm_get_exception(WASMModuleInstance *module); uint32 @@ -341,38 +343,32 @@ void wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr); uint32 -wasm_module_dup_data(WASMModuleInstance *module_inst, - const char *src, uint32 size); +wasm_module_dup_data(WASMModuleInstance *module_inst, const char *src, + uint32 size); bool -wasm_validate_app_addr(WASMModuleInstance *module_inst, - uint32 app_offset, uint32 size); +wasm_validate_app_addr(WASMModuleInstance *module_inst, uint32 app_offset, + uint32 size); bool -wasm_validate_app_str_addr(WASMModuleInstance *module_inst, - uint32 app_offset); +wasm_validate_app_str_addr(WASMModuleInstance *module_inst, uint32 app_offset); bool -wasm_validate_native_addr(WASMModuleInstance *module_inst, - void *native_ptr, uint32 size); +wasm_validate_native_addr(WASMModuleInstance *module_inst, void *native_ptr, + uint32 size); void * -wasm_addr_app_to_native(WASMModuleInstance *module_inst, - uint32 app_offset); +wasm_addr_app_to_native(WASMModuleInstance *module_inst, uint32 app_offset); uint32 -wasm_addr_native_to_app(WASMModuleInstance *module_inst, - void *native_ptr); +wasm_addr_native_to_app(WASMModuleInstance *module_inst, void *native_ptr); bool -wasm_get_app_addr_range(WASMModuleInstance *module_inst, - uint32 app_offset, - uint32 *p_app_start_offset, - uint32 *p_app_end_offset); +wasm_get_app_addr_range(WASMModuleInstance *module_inst, uint32 app_offset, + uint32 *p_app_start_offset, uint32 *p_app_end_offset); bool -wasm_get_native_addr_range(WASMModuleInstance *module_inst, - uint8_t *native_ptr, +wasm_get_native_addr_range(WASMModuleInstance *module_inst, uint8_t *native_ptr, uint8_t **p_native_start_addr, uint8_t **p_native_end_addr); @@ -380,19 +376,15 @@ bool wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count); bool -wasm_call_indirect(WASMExecEnv *exec_env, - uint32_t tbl_idx, - uint32_t element_indices, - uint32_t argc, uint32_t argv[]); +wasm_call_indirect(WASMExecEnv *exec_env, uint32_t tbl_idx, + uint32_t element_indices, uint32_t argc, uint32_t argv[]); #if WASM_ENABLE_THREAD_MGR != 0 bool -wasm_set_aux_stack(WASMExecEnv *exec_env, - uint32 start_offset, uint32 size); +wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size); bool -wasm_get_aux_stack(WASMExecEnv *exec_env, - uint32 *start_offset, uint32 *size); +wasm_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size); #endif void @@ -423,13 +415,12 @@ wasm_elem_is_declarative(uint32 mode) } bool -wasm_enlarge_table(WASMModuleInstance *module_inst, - uint32 table_idx, uint32 inc_entries, uint32 init_val); +wasm_enlarge_table(WASMModuleInstance *module_inst, uint32 table_idx, + uint32 inc_entries, uint32 init_val); #endif /* WASM_ENABLE_REF_TYPES != 0 */ static inline WASMTableInstance * -wasm_get_table_inst(const WASMModuleInstance *module_inst, - const uint32 tbl_idx) +wasm_get_table_inst(const WASMModuleInstance *module_inst, const uint32 tbl_idx) { /* careful, it might be a table in another module */ WASMTableInstance *tbl_inst = module_inst->tables[tbl_idx]; @@ -452,4 +443,3 @@ wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env); #endif #endif /* end of _WASM_RUNTIME_H */ - diff --git a/core/iwasm/libraries/debug-engine/debug_engine.c b/core/iwasm/libraries/debug-engine/debug_engine.c new file mode 100644 index 0000000000..889e328dec --- /dev/null +++ b/core/iwasm/libraries/debug-engine/debug_engine.c @@ -0,0 +1,1069 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "debug_engine.h" + +#include "bh_log.h" +#include "gdbserver.h" +#include "platform_api_extension.h" +#include "wasm_interp.h" +#include "wasm_opcode.h" +#include "wasm_runtime.h" + +static uint8 break_instr[] = { DEBUG_OP_BREAK }; + +typedef struct WASMDebugEngine { + struct WASMDebugEngine *next; + WASMDebugControlThread *control_thread; + char ip_addr[128]; + int platform_port; + int process_base_port; + bh_list debug_instance_list; + bool active; +} WASMDebugEngine; + +static WASMDebugEngine *g_debug_engine; + +static bool +should_stop(WASMDebugControlThread *control_thread) +{ + return control_thread->status != RUNNING; +} + +static void * +control_thread_routine(void *arg) +{ + WASMDebugInstance *debug_inst = (WASMDebugInstance *)arg; + WASMDebugControlThread *control_thread = NULL; + WASMCluster *cluster = NULL; + WASMExecEnv *exec_env; + bh_assert(debug_inst); + + control_thread = debug_inst->control_thread; + bh_assert(control_thread); + + cluster = debug_inst->cluster; + bh_assert(cluster); + + exec_env = bh_list_first_elem(&cluster->exec_env_list); + bh_assert(exec_env); + + os_mutex_lock(&exec_env->wait_lock); + + control_thread->status = RUNNING; + + debug_inst->id = g_debug_engine->debug_instance_list.len + 1; + + control_thread->debug_engine = g_debug_engine; + control_thread->debug_instance = debug_inst; + strcpy(control_thread->ip_addr, g_debug_engine->ip_addr); + control_thread->port = g_debug_engine->process_base_port + debug_inst->id; + + LOG_WARNING("control thread of debug object %p start at %s:%d\n", + debug_inst, control_thread->ip_addr, control_thread->port); + + control_thread->server = + wasm_launch_gdbserver(control_thread->ip_addr, control_thread->port); + if (!control_thread->server) { + LOG_ERROR("Failed to create debug server\n"); + os_cond_signal(&exec_env->wait_cond); + os_mutex_unlock(&exec_env->wait_lock); + return NULL; + } + + control_thread->server->thread = control_thread; + + /* control thread ready, notify main thread */ + os_cond_signal(&exec_env->wait_cond); + os_mutex_unlock(&exec_env->wait_lock); + + while (true) { + os_mutex_lock(&control_thread->wait_lock); + if (!should_stop(control_thread)) { + if (!wasm_gdbserver_handle_packet(control_thread->server)) { + control_thread->status = STOPPED; + } + } + else { + os_mutex_unlock(&control_thread->wait_lock); + break; + } + os_mutex_unlock(&control_thread->wait_lock); + } + + LOG_VERBOSE("control thread of debug object %p stop\n", debug_inst); + return NULL; +} + +static WASMDebugControlThread * +wasm_debug_control_thread_create(WASMDebugInstance *debug_instance) +{ + WASMDebugControlThread *control_thread; + WASMCluster *cluster = debug_instance->cluster; + WASMExecEnv *exec_env; + bh_assert(cluster); + + exec_env = bh_list_first_elem(&cluster->exec_env_list); + bh_assert(exec_env); + + if (!(control_thread = + wasm_runtime_malloc(sizeof(WASMDebugControlThread)))) { + LOG_ERROR("WASM Debug Engine error: failed to allocate memory"); + return NULL; + } + memset(control_thread, 0, sizeof(WASMDebugControlThread)); + + if (os_mutex_init(&control_thread->wait_lock) != 0) + goto fail; + + debug_instance->control_thread = control_thread; + + os_mutex_lock(&exec_env->wait_lock); + + if (0 + != os_thread_create(&control_thread->tid, control_thread_routine, + debug_instance, APP_THREAD_STACK_SIZE_MAX)) { + os_mutex_unlock(&control_thread->wait_lock); + goto fail1; + } + + /* wait until the debug control thread ready */ + os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); + os_mutex_unlock(&exec_env->wait_lock); + if (!control_thread->server) + goto fail1; + + /* create control thread success, append debug instance to debug engine */ + bh_list_insert(&g_debug_engine->debug_instance_list, debug_instance); + wasm_cluster_send_signal_all(debug_instance->cluster, WAMR_SIG_STOP); + + return control_thread; + +fail1: + os_mutex_destroy(&control_thread->wait_lock); +fail: + wasm_runtime_free(control_thread); + return NULL; +} + +static void +wasm_debug_control_thread_destroy(WASMDebugInstance *debug_instance) +{ + WASMDebugControlThread *control_thread = debug_instance->control_thread; + LOG_VERBOSE("control thread of debug object %p stop at %s:%d\n", + debug_instance, control_thread->ip_addr, control_thread->port); + control_thread->status = STOPPED; + os_mutex_lock(&control_thread->wait_lock); + wasm_close_gdbserver(control_thread->server); + os_mutex_unlock(&control_thread->wait_lock); + os_thread_join(control_thread->tid, NULL); + wasm_runtime_free(control_thread->server); + + os_mutex_destroy(&control_thread->wait_lock); + wasm_runtime_free(control_thread); +} + +static WASMDebugEngine * +wasm_debug_engine_create() +{ + WASMDebugEngine *engine; + + if (!(engine = wasm_runtime_malloc(sizeof(WASMDebugEngine)))) { + LOG_ERROR("WASM Debug Engine error: failed to allocate memory"); + return NULL; + } + memset(engine, 0, sizeof(WASMDebugEngine)); + + /* TODO: support Wasm platform in LLDB */ + /* + engine->control_thread = + wasm_debug_control_thread_create((WASMDebugObject *)engine); + engine->control_thread->debug_engine = (WASMDebugObject *)engine; + engine->control_thread->debug_instance = NULL; + sprintf(engine->control_thread->ip_addr, "127.0.0.1"); + engine->control_thread->port = 1234; + */ + + bh_list_init(&engine->debug_instance_list); + return engine; +} + +bool +wasm_debug_engine_init(char *ip_addr, int platform_port, int process_port) +{ + if (g_debug_engine == NULL) + g_debug_engine = wasm_debug_engine_create(); + + if (g_debug_engine) { + process_port -= 1; + g_debug_engine->platform_port = + platform_port > 0 ? platform_port : 1234; + g_debug_engine->process_base_port = + process_port > 0 ? process_port : 6169; + if (ip_addr) + sprintf(g_debug_engine->ip_addr, "%s", ip_addr); + else + sprintf(g_debug_engine->ip_addr, "%s", "127.0.0.1"); + g_debug_engine->active = true; + } + + return g_debug_engine != NULL ? true : false; +} + +void +wasm_debug_set_engine_active(bool active) +{ + if (g_debug_engine) { + g_debug_engine->active = active; + } +} + +bool +wasm_debug_get_engine_active(void) +{ + if (g_debug_engine) { + return g_debug_engine->active; + } + return false; +} + +void +wasm_debug_engine_destroy() +{ + if (g_debug_engine) { + wasm_runtime_free(g_debug_engine); + g_debug_engine = NULL; + } +} + +/* A debug Instance is a debug "process" in gdb remote protocol + and bound to a runtime cluster */ +WASMDebugInstance * +wasm_debug_instance_create(WASMCluster *cluster) +{ + WASMDebugInstance *instance; + WASMExecEnv *exec_env; + + if (!g_debug_engine || !g_debug_engine->active) { + return NULL; + } + + if (!(instance = wasm_runtime_malloc(sizeof(WASMDebugInstance)))) { + LOG_ERROR("WASM Debug Engine error: failed to allocate memory"); + return NULL; + } + memset(instance, 0, sizeof(WASMDebugInstance)); + bh_list_init(&instance->break_point_list); + + instance->cluster = cluster; + exec_env = bh_list_first_elem(&cluster->exec_env_list); + bh_assert(exec_env); + + instance->current_tid = exec_env->handle; + + if (!wasm_debug_control_thread_create(instance)) { + LOG_ERROR("WASM Debug Engine error: failed to create control thread"); + wasm_runtime_free(instance); + return NULL; + } + + return instance; +} + +static WASMDebugInstance * +wasm_cluster_get_debug_instance(WASMDebugEngine *engine, WASMCluster *cluster) +{ + WASMDebugInstance *instance = + bh_list_first_elem(&engine->debug_instance_list); + while (instance) { + if (instance->cluster == cluster) + return instance; + instance = bh_list_elem_next(instance); + } + return instance; +} + +static void +wasm_debug_instance_destroy_breakpoints(WASMDebugInstance *instance) +{ + WASMDebugBreakPoint *breakpoint, *next_bp; + + breakpoint = bh_list_first_elem(&instance->break_point_list); + while (breakpoint) { + next_bp = bh_list_elem_next(breakpoint); + + bh_list_remove(&instance->break_point_list, breakpoint); + wasm_runtime_free(breakpoint); + + breakpoint = next_bp; + } +} + +void +wasm_debug_instance_destroy(WASMCluster *cluster) +{ + WASMDebugInstance *instance = NULL; + + if (!g_debug_engine) { + return; + } + + instance = wasm_cluster_get_debug_instance(g_debug_engine, cluster); + if (instance) { + /* destroy control thread */ + wasm_debug_control_thread_destroy(instance); + bh_list_remove(&g_debug_engine->debug_instance_list, instance); + + /* destroy all breakpoints */ + wasm_debug_instance_destroy_breakpoints(instance); + + wasm_runtime_free(instance); + } +} + +static WASMExecEnv * +wasm_debug_instance_get_current_env(WASMDebugInstance *instance) +{ + WASMExecEnv *exec_env = NULL; + + if (instance) { + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + while (exec_env) { + if (exec_env->handle == instance->current_tid) + break; + exec_env = bh_list_elem_next(exec_env); + } + } + return exec_env; +} + +#if WASM_ENABLE_LIBC_WASI != 0 +bool +wasm_debug_instance_get_current_object_name(WASMDebugInstance *instance, + char name_buffer[], int len) +{ + WASMExecEnv *exec_env; + WASIArguments *wasi_args; + WASMModuleInstance *module_inst; + + if (!instance) + return false; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + if (!exec_env) + return false; + + module_inst = (WASMModuleInstance *)exec_env->module_inst; + wasi_args = &module_inst->module->wasi_args; + if (wasi_args && wasi_args->argc > 0) { + char *argv_name = wasi_args->argv[0]; + int name_len = strlen(argv_name); + printf("the module name is %s\n", argv_name); + if (len - 1 >= name_len) + strcpy(name_buffer, argv_name); + else + strcpy(name_buffer, argv_name + (name_len + 1 - len)); + return true; + } + return false; +} +#endif + +uint64 +wasm_debug_instance_get_pid(WASMDebugInstance *instance) +{ + if (instance != NULL) { + return (uint64)instance->id; + } + return (uint64)0; +} + +uint64 +wasm_debug_instance_get_tid(WASMDebugInstance *instance) +{ + if (instance != NULL) { + return (uint64)instance->current_tid; + } + return (uint64)0; +} + +int +wasm_debug_instance_get_tids(WASMDebugInstance *instance, uint64 tids[], + int len) +{ + WASMExecEnv *exec_env; + int i = 0; + + if (!instance) + return 0; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + while (exec_env && i < len) { + tids[i++] = exec_env->handle; + exec_env = bh_list_elem_next(exec_env); + } + LOG_VERBOSE("find %d tids\n", i); + return i; +} + +uint64 +wasm_debug_instance_wait_thread(WASMDebugInstance *instance, uint64 tid, + uint32 *status) +{ + WASMExecEnv *exec_env; + WASMExecEnv *last_exec_env = NULL; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + while (exec_env) { + last_exec_env = exec_env; + if (instance->current_tid != 0 + && last_exec_env->handle == instance->current_tid) { + break; + } + exec_env = bh_list_elem_next(exec_env); + } + + if (last_exec_env) { + wasm_cluster_wait_thread_status(last_exec_env, status); + if (instance->current_tid == 0) + instance->current_tid = last_exec_env->handle; + return last_exec_env->handle; + } + else { + *status = ~0; + return 0; + } +} + +void +wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, uint64 tid) +{ + instance->current_tid = tid; +} + +uint64 +wasm_debug_instance_get_pc(WASMDebugInstance *instance) +{ + WASMExecEnv *exec_env; + + if (!instance) + return 0; + + exec_env = wasm_debug_instance_get_current_env(instance); + if ((exec_env->cur_frame != NULL) && (exec_env->cur_frame->ip != NULL)) { + WASMModuleInstance *module_inst = + (WASMModuleInstance *)exec_env->module_inst; + return WASM_ADDR( + WasmObj, instance->id, + (exec_env->cur_frame->ip - module_inst->module->load_addr)); + } + return 0; +} + +uint64 +wasm_debug_instance_get_load_addr(WASMDebugInstance *instance) +{ + WASMExecEnv *exec_env; + + if (!instance) + return WASM_ADDR(WasmInvalid, 0, 0); + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + if (exec_env) { + return WASM_ADDR(WasmObj, instance->id, 0); + } + + return WASM_ADDR(WasmInvalid, 0, 0); +} + +WASMDebugMemoryInfo * +wasm_debug_instance_get_memregion(WASMDebugInstance *instance, uint64 addr) +{ + WASMDebugMemoryInfo *mem_info; + WASMExecEnv *exec_env; + WASMModuleInstance *module_inst; + WASMMemoryInstance *memory; + uint32 num_bytes_per_page; + uint32 linear_mem_size = 0; + + if (!instance) + return NULL; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + if (!exec_env) + return NULL; + + if (!(mem_info = wasm_runtime_malloc(sizeof(WASMDebugMemoryInfo)))) { + LOG_ERROR("WASM Debug Engine error: failed to allocate memory"); + return NULL; + } + memset(mem_info, 0, sizeof(WASMDebugMemoryInfo)); + mem_info->start = WASM_ADDR(WasmInvalid, 0, 0); + mem_info->size = 0; + mem_info->name[0] = '\0'; + mem_info->permisson[0] = '\0'; + + module_inst = (WASMModuleInstance *)exec_env->module_inst; + + switch (WASM_ADDR_TYPE(addr)) { + case WasmObj: + if (WASM_ADDR_OFFSET(addr) < module_inst->module->load_size) { + mem_info->start = WASM_ADDR(WasmObj, instance->id, 0); + mem_info->size = module_inst->module->load_size; + sprintf(mem_info->name, "%s", "module"); + sprintf(mem_info->permisson, "%s", "rx"); + } + break; + case WasmMemory: + { + memory = module_inst->default_memory; + + if (memory) { + num_bytes_per_page = memory->num_bytes_per_page; + linear_mem_size = num_bytes_per_page * memory->cur_page_count; + } + if (WASM_ADDR_OFFSET(addr) < linear_mem_size) { + mem_info->start = WASM_ADDR(WasmMemory, instance->id, 0); + mem_info->size = linear_mem_size; + sprintf(mem_info->name, "%s", "memory"); + sprintf(mem_info->permisson, "%s", "rw"); + } + break; + } + default: + mem_info->start = WASM_ADDR(WasmInvalid, 0, 0); + mem_info->size = 0; + } + return mem_info; +} + +void +wasm_debug_instance_destroy_memregion(WASMDebugInstance *instance, + WASMDebugMemoryInfo *mem_info) +{ + wasm_runtime_free(mem_info); +} + +bool +wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 offset, + char *buf, uint64 *size) +{ + WASMExecEnv *exec_env; + WASMModuleInstance *module_inst; + + if (!instance) + return false; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + if (!exec_env) + return false; + + module_inst = (WASMModuleInstance *)exec_env->module_inst; + + if (offset + *size > module_inst->module->load_size) { + LOG_VERBOSE("wasm_debug_instance_get_data_mem size over flow!\n"); + *size = module_inst->module->load_size >= offset + ? module_inst->module->load_size - offset + : 0; + } + + bh_memcpy_s(buf, *size, module_inst->module->load_addr + offset, *size); + + WASMDebugBreakPoint *breakpoint = + bh_list_first_elem(&instance->break_point_list); + + while (breakpoint) { + if (offset <= breakpoint->addr && breakpoint->addr < offset + *size) { + bh_memcpy_s(buf + (breakpoint->addr - offset), sizeof(break_instr), + &breakpoint->orignal_data, sizeof(break_instr)); + } + breakpoint = bh_list_elem_next(breakpoint); + } + + WASMFastOPCodeNode *fast_opcode = + bh_list_first_elem(&module_inst->module->fast_opcode_list); + while (fast_opcode) { + if (offset <= fast_opcode->offset + && fast_opcode->offset < offset + *size) { + *(uint8 *)(buf + (fast_opcode->offset - offset)) = + fast_opcode->orig_op; + } + fast_opcode = bh_list_elem_next(fast_opcode); + } + + return true; +} + +bool +wasm_debug_instance_get_linear_mem(WASMDebugInstance *instance, uint64 offset, + char *buf, uint64 *size) +{ + WASMExecEnv *exec_env; + WASMModuleInstance *module_inst; + WASMMemoryInstance *memory; + uint32 num_bytes_per_page; + uint32 linear_mem_size; + + if (!instance) + return false; + + exec_env = wasm_debug_instance_get_current_env(instance); + if (!exec_env) + return false; + + module_inst = (WASMModuleInstance *)exec_env->module_inst; + memory = module_inst->default_memory; + if (memory) { + num_bytes_per_page = memory->num_bytes_per_page; + linear_mem_size = num_bytes_per_page * memory->cur_page_count; + if (offset + *size > linear_mem_size) { + LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n"); + *size = linear_mem_size >= offset ? linear_mem_size - offset : 0; + } + bh_memcpy_s(buf, *size, memory->memory_data + offset, *size); + return true; + } + return false; +} + +bool +wasm_debug_instance_set_linear_mem(WASMDebugInstance *instance, uint64 offset, + char *buf, uint64 *size) +{ + WASMExecEnv *exec_env; + WASMModuleInstance *module_inst; + WASMMemoryInstance *memory; + uint32 num_bytes_per_page; + uint32 linear_mem_size; + + if (!instance) + return false; + + exec_env = wasm_debug_instance_get_current_env(instance); + if (!exec_env) + return false; + + module_inst = (WASMModuleInstance *)exec_env->module_inst; + memory = module_inst->default_memory; + if (memory) { + num_bytes_per_page = memory->num_bytes_per_page; + linear_mem_size = num_bytes_per_page * memory->cur_page_count; + if (offset + *size > linear_mem_size) { + LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n"); + *size = linear_mem_size >= offset ? linear_mem_size - offset : 0; + } + bh_memcpy_s(memory->memory_data + offset, *size, buf, *size); + return true; + } + return false; +} + +bool +wasm_debug_instance_get_mem(WASMDebugInstance *instance, uint64 addr, char *buf, + uint64 *size) +{ + switch (WASM_ADDR_TYPE(addr)) { + case WasmMemory: + return wasm_debug_instance_get_linear_mem( + instance, WASM_ADDR_OFFSET(addr), buf, size); + break; + case WasmObj: + return wasm_debug_instance_get_obj_mem( + instance, WASM_ADDR_OFFSET(addr), buf, size); + break; + default: + return false; + } +} + +bool +wasm_debug_instance_set_mem(WASMDebugInstance *instance, uint64 addr, char *buf, + uint64 *size) +{ + switch (WASM_ADDR_TYPE(addr)) { + case WasmMemory: + return wasm_debug_instance_set_linear_mem( + instance, WASM_ADDR_OFFSET(addr), buf, size); + break; + case WasmObj: + default: + return false; + } +} + +WASMDebugInstance * +wasm_exec_env_get_instance(WASMExecEnv *exec_env) +{ + WASMDebugInstance *instance = NULL; + bh_assert(g_debug_engine); + + instance = bh_list_first_elem(&g_debug_engine->debug_instance_list); + while (instance) { + if (instance->cluster == exec_env->cluster) + break; + instance = bh_list_elem_next(instance); + } + return instance; +} + +int +wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance, uint64 tid, + uint64 buf[], uint64 size) +{ + WASMExecEnv *exec_env; + struct WASMInterpFrame *frame; + uint64 i = 0; + + if (!instance) + return 0; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + while (exec_env) { + if (exec_env->handle == tid) { + WASMModuleInstance *module_inst = + (WASMModuleInstance *)exec_env->module_inst; + frame = exec_env->cur_frame; + while (frame && i < size) { + if (frame->ip != NULL) { + buf[i++] = + WASM_ADDR(WasmObj, instance->id, + (frame->ip - module_inst->module->load_addr)); + } + frame = frame->prev_frame; + } + return i; + } + exec_env = bh_list_elem_next(exec_env); + } + return 0; +} + +bool +wasm_debug_instance_add_breakpoint(WASMDebugInstance *instance, uint64 addr, + uint64 length) +{ + WASMExecEnv *exec_env; + WASMModuleInstance *module_inst; + uint64 offset; + + if (!instance) + return false; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + if (!exec_env) + return false; + + module_inst = (WASMModuleInstance *)exec_env->module_inst; + if (WASM_ADDR_TYPE(addr) != WasmObj) + return false; + + offset = WASM_ADDR_OFFSET(addr); + + if (length >= sizeof(break_instr)) { + if (offset + sizeof(break_instr) <= module_inst->module->load_size) { + WASMDebugBreakPoint *breakpoint; + if (!(breakpoint = + wasm_runtime_malloc(sizeof(WASMDebugBreakPoint)))) { + LOG_ERROR("WASM Debug Engine error: failed to allocate memory"); + return false; + } + memset(breakpoint, 0, sizeof(WASMDebugBreakPoint)); + breakpoint->addr = offset; + /* TODO: how to if more than one breakpoints are set + at the same addr? */ + bh_memcpy_s(&breakpoint->orignal_data, (uint32)sizeof(break_instr), + module_inst->module->load_addr + offset, + (uint32)sizeof(break_instr)); + + bh_memcpy_s(module_inst->module->load_addr + offset, + (uint32)sizeof(break_instr), break_instr, + (uint32)sizeof(break_instr)); + + bh_list_insert(&instance->break_point_list, breakpoint); + return true; + } + } + return false; +} + +bool +wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr, + uint64 length) +{ + WASMExecEnv *exec_env; + WASMModuleInstance *module_inst; + uint64 offset; + + if (!instance) + return false; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + if (!exec_env) + return false; + + module_inst = (WASMModuleInstance *)exec_env->module_inst; + + if (WASM_ADDR_TYPE(addr) != WasmObj) + return false; + offset = WASM_ADDR_OFFSET(addr); + + if (length >= sizeof(break_instr)) { + if (offset + sizeof(break_instr) <= module_inst->module->load_size) { + WASMDebugBreakPoint *breakpoint = + bh_list_first_elem(&instance->break_point_list); + while (breakpoint) { + WASMDebugBreakPoint *next_break = bh_list_elem_next(breakpoint); + if (breakpoint->addr == offset) { + /* TODO: how to if more than one breakpoints are set + at the same addr? */ + bh_memcpy_s(module_inst->module->load_addr + offset, + (uint32)sizeof(break_instr), + &breakpoint->orignal_data, + (uint32)sizeof(break_instr)); + bh_list_remove(&instance->break_point_list, breakpoint); + wasm_runtime_free(breakpoint); + } + breakpoint = next_break; + } + } + } + return true; +} + +bool +wasm_debug_instance_continue(WASMDebugInstance *instance) +{ + WASMExecEnv *exec_env; + + if (!instance) + return false; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + if (!exec_env) + return false; + + while (exec_env) { + wasm_cluster_thread_continue(exec_env); + exec_env = bh_list_elem_next(exec_env); + } + return true; +} + +bool +wasm_debug_instance_kill(WASMDebugInstance *instance) +{ + WASMExecEnv *exec_env; + + if (!instance) + return false; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + if (!exec_env) + return false; + + while (exec_env) { + wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM); + exec_env = bh_list_elem_next(exec_env); + } + return true; +} + +bool +wasm_debug_instance_singlestep(WASMDebugInstance *instance, uint64 tid) +{ + WASMExecEnv *exec_env; + + if (!instance) + return false; + + exec_env = bh_list_first_elem(&instance->cluster->exec_env_list); + if (!exec_env) + return false; + + while (exec_env) { + if (exec_env->handle == tid || tid == (uint64)~0) { + wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_SINGSTEP); + wasm_cluster_thread_step(exec_env); + } + exec_env = bh_list_elem_next(exec_env); + } + return true; +} + +bool +wasm_debug_instance_get_local(WASMDebugInstance *instance, int frame_index, + int local_index, char buf[], int *size) +{ + WASMExecEnv *exec_env; + struct WASMInterpFrame *frame; + WASMFunctionInstance *cur_func; + uint8 local_type = 0xFF; + uint32 local_offset; + int param_count; + int fi = 0; + + if (!instance) + return false; + + exec_env = wasm_debug_instance_get_current_env(instance); + if (!exec_env) + return false; + + frame = exec_env->cur_frame; + while (frame && fi++ != frame_index) { + frame = frame->prev_frame; + } + + if (!frame) + return false; + cur_func = frame->function; + if (!cur_func) + return false; + + param_count = cur_func->param_count; + + if (local_index >= param_count + cur_func->local_count) + return false; + + local_offset = cur_func->local_offsets[local_index]; + if (local_index < param_count) + local_type = cur_func->param_types[local_index]; + else if (local_index < cur_func->local_count + param_count) + local_type = cur_func->local_types[local_index - param_count]; + + switch (local_type) { + case VALUE_TYPE_I32: + case VALUE_TYPE_F32: + *size = 4; + bh_memcpy_s(buf, 4, (char *)(frame->lp + local_offset), 4); + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + *size = 8; + bh_memcpy_s(buf, 8, (char *)(frame->lp + local_offset), 8); + break; + default: + *size = 0; + break; + } + return true; +} + +bool +wasm_debug_instance_get_global(WASMDebugInstance *instance, int frame_index, + int global_index, char buf[], int *size) +{ + WASMExecEnv *exec_env; + struct WASMInterpFrame *frame; + WASMModuleInstance *module_inst; + WASMGlobalInstance *globals, *global; + uint8 *global_addr; + uint8 global_type = 0xFF; + uint8 *global_data; + int fi = 0; + + if (!instance) + return false; + + exec_env = wasm_debug_instance_get_current_env(instance); + if (!exec_env) + return false; + + frame = exec_env->cur_frame; + while (frame && fi++ != frame_index) { + frame = frame->prev_frame; + } + + if (!frame) + return false; + + module_inst = (WASMModuleInstance *)exec_env->module_inst; + global_data = module_inst->global_data; + globals = module_inst->globals; + + if ((global_index < 0) + || ((uint32)global_index >= module_inst->global_count)) { + return false; + } + global = globals + global_index; + +#if WASM_ENABLE_MULTI_MODULE == 0 + global_addr = global_data + global->data_offset; +#else + global_addr = global->import_global_inst + ? global->import_module_inst->global_data + + global->import_global_inst->data_offset + : global_data + global->data_offset; +#endif + global_type = global->type; + + switch (global_type) { + case VALUE_TYPE_I32: + case VALUE_TYPE_F32: + *size = 4; + bh_memcpy_s(buf, 4, (char *)(global_addr), 4); + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + *size = 8; + bh_memcpy_s(buf, 8, (char *)(global_addr), 8); + break; + default: + *size = 0; + break; + } + return true; +} + +uint64 +wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size, int map_port) +{ + WASMExecEnv *exec_env; + WASMModuleInstance *module_inst; + uint32 offset; + void *native_addr; + (void)map_port; + + if (!instance) + return 0; + + exec_env = wasm_debug_instance_get_current_env(instance); + if (!exec_env) + return 0; + + module_inst = (WASMModuleInstance *)exec_env->module_inst; + + /* TODO: malloc in wasi libc maybe not be thread safe, we hope LLDB will + always ask for memory when threads stopped */ + offset = wasm_runtime_module_malloc((wasm_module_inst_t)module_inst, size, + &native_addr); + if (!offset) + LOG_WARNING("the memory may be not enough for debug, try use larger " + "--heap-size"); + return WASM_ADDR(WasmMemory, 0, offset); +} + +bool +wasm_debug_instance_ummap(WASMDebugInstance *instance, uint64 addr) +{ + WASMExecEnv *exec_env; + WASMModuleInstance *module_inst; + uint32 offset; + + if (!instance) + return false; + + exec_env = wasm_debug_instance_get_current_env(instance); + if (!exec_env) + return false; + + module_inst = (WASMModuleInstance *)exec_env->module_inst; + if (WASM_ADDR_TYPE(addr) == WasmMemory) { + offset = WASM_ADDR_OFFSET(addr); + wasm_runtime_module_free((wasm_module_inst_t)module_inst, offset); + return true; + } + return false; +} diff --git a/core/iwasm/libraries/debug-engine/debug_engine.cmake b/core/iwasm/libraries/debug-engine/debug_engine.cmake new file mode 100644 index 0000000000..914ddd6396 --- /dev/null +++ b/core/iwasm/libraries/debug-engine/debug_engine.cmake @@ -0,0 +1,12 @@ +# Copyright (C) 2021 Ant Group. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (DEBUG_ENGINE_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions (-DWASM_ENABLE_DEBUG_INTERP=1) + +include_directories(${DEBUG_ENGINE_DIR}) + +file (GLOB source_all ${DEBUG_ENGINE_DIR}/*.c) + +set (DEBUG_ENGINE_SOURCE ${source_all}) diff --git a/core/iwasm/libraries/debug-engine/debug_engine.h b/core/iwasm/libraries/debug-engine/debug_engine.h new file mode 100644 index 0000000000..91cdfc81f8 --- /dev/null +++ b/core/iwasm/libraries/debug-engine/debug_engine.h @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _DEBUG_ENGINE_H +#define _DEBUG_ENGINE_H + +#include "bh_list.h" +#include "gdbserver.h" +#include "thread_manager.h" + +typedef enum WASMDebugControlThreadStatus { + RUNNING, + STOPPED, +} WASMDebugControlThreadStatus; + +struct WASMDebugEngine; +struct WASMDebugInstance; + +typedef struct WASMDebugControlThread { + WASMGDBServer *server; + korp_tid tid; + korp_mutex wait_lock; + char ip_addr[128]; + int port; + WASMDebugControlThreadStatus status; + struct WASMDebugEngine *debug_engine; + struct WASMDebugInstance *debug_instance; +} WASMDebugControlThread; + +typedef struct WASMDebugBreakPoint { + struct WASMDebugBreakPoint *next; + uint64 addr; + uint64 orignal_data; +} WASMDebugBreakPoint; + +typedef struct WASMDebugInstance { + struct WASMDebugInstance *next; + WASMDebugControlThread *control_thread; + bh_list break_point_list; + WASMCluster *cluster; + uint32 id; + korp_tid current_tid; +} WASMDebugInstance; + +typedef enum WASMDebugEventKind { + BREAK_POINT_ADD, + BREAK_POINT_REMOVE +} WASMDebugEventKind; + +typedef struct WASMDebugEvent { + WASMDebugEventKind kind; + unsigned char metadata[0]; +} WASMDebugEvent; + +typedef struct WASMDebugMemoryInfo { + uint64 start; + uint64 size; + char name[128]; + char permisson[4]; +} WASMDebugMemoryInfo; + +typedef enum WasmAddressType { + WasmMemory = 0x00, + WasmObj = 0x01, + WasmInvalid = 0x03 +} WasmAddressType; + +#define WASM_ADDR(type, id, offset) \ + (((uint64)type << 62) | ((uint64)0 << 32) | ((uint64)offset << 0)) + +#define WASM_ADDR_TYPE(addr) (((addr)&0xC000000000000000) >> 62) +#define WASM_ADDR_OFFSET(addr) (((addr)&0x00000000FFFFFFFF)) + +#define INVALIED_ADDR (0xFFFFFFFFFFFFFFFF) + +WASMDebugInstance * +wasm_debug_instance_create(WASMCluster *cluster); + +void +wasm_debug_instance_destroy(WASMCluster *cluster); + +WASMDebugInstance * +wasm_exec_env_get_instance(WASMExecEnv *exec_env); + +bool +wasm_debug_engine_init(char *ip_addr, int platform_port, int process_port); + +void +wasm_debug_engine_destroy(); + +void +wasm_debug_set_engine_active(bool active); + +bool +wasm_debug_get_engine_active(void); + +uint64 +wasm_debug_instance_get_pid(WASMDebugInstance *instance); + +uint64 +wasm_debug_instance_get_tid(WASMDebugInstance *instance); + +int +wasm_debug_instance_get_tids(WASMDebugInstance *instance, uint64 tids[], + int len); + +void +wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, uint64 tid); + +uint64 +wasm_debug_instance_get_pc(WASMDebugInstance *instance); + +uint64 +wasm_debug_instance_get_load_addr(WASMDebugInstance *instance); + +WASMDebugMemoryInfo * +wasm_debug_instance_get_memregion(WASMDebugInstance *instance, uint64 addr); + +void +wasm_debug_instance_destroy_memregion(WASMDebugInstance *instance, + WASMDebugMemoryInfo *mem_info); + +bool +wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 addr, + char *buf, uint64 *size); + +bool +wasm_debug_instance_get_linear_mem(WASMDebugInstance *instance, uint64 addr, + char *buf, uint64 *size); + +bool +wasm_debug_instance_get_mem(WASMDebugInstance *instance, uint64 addr, char *buf, + uint64 *size); + +bool +wasm_debug_instance_set_mem(WASMDebugInstance *instance, uint64 addr, char *buf, + uint64 *size); + +int +wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance, uint64 tid, + uint64 buf[], uint64 size); + +bool +wasm_debug_instance_add_breakpoint(WASMDebugInstance *instance, uint64 addr, + uint64 length); + +bool +wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr, + uint64 length); + +bool +wasm_debug_instance_continue(WASMDebugInstance *instance); + +bool +wasm_debug_instance_kill(WASMDebugInstance *instance); + +uint64 +wasm_debug_instance_wait_thread(WASMDebugInstance *instance, uint64 tid, + uint32 *status); + +bool +wasm_debug_instance_singlestep(WASMDebugInstance *instance, uint64 tid); + +bool +wasm_debug_instance_get_local(WASMDebugInstance *instance, int frame_index, + int local_index, char buf[], int *size); + +bool +wasm_debug_instance_get_global(WASMDebugInstance *instance, int frame_index, + int global_index, char buf[], int *size); + +#if WASM_ENABLE_LIBC_WASI != 0 +bool +wasm_debug_instance_get_current_object_name(WASMDebugInstance *instance, + char name_buffer[], int len); +#endif + +uint64 +wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size, + int map_port); + +bool +wasm_debug_instance_ummap(WASMDebugInstance *instance, uint64 addr); +#endif diff --git a/core/iwasm/libraries/debug-engine/gdbserver.c b/core/iwasm/libraries/debug-engine/gdbserver.c new file mode 100644 index 0000000000..dedd366ad7 --- /dev/null +++ b/core/iwasm/libraries/debug-engine/gdbserver.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gdbserver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bh_log.h" +#include "handler.h" +#include "packets.h" +#include "utils.h" + +typedef void (*PacketHandler)(WASMGDBServer *server, char *payload); + +struct packet_handler_elem { + char request; + PacketHandler handler; +}; + +#define DEL_HANDLER(r, h) [r] = { .request = r, .handler = h } + +static struct packet_handler_elem packet_handler_table[255] = { + DEL_HANDLER('Q', handle_generay_set), + DEL_HANDLER('q', handle_generay_query), + DEL_HANDLER('v', handle_v_packet), + DEL_HANDLER('?', handle_threadstop_request), + DEL_HANDLER('H', handle_set_current_thread), + DEL_HANDLER('p', handle_get_register), + DEL_HANDLER('j', handle_get_json_request), + DEL_HANDLER('m', handle_get_read_memory), + DEL_HANDLER('M', handle_get_write_memory), + DEL_HANDLER('x', handle_get_read_binary_memory), + DEL_HANDLER('Z', handle_add_break), + DEL_HANDLER('z', handle_remove_break), + DEL_HANDLER('c', handle_continue_request), + DEL_HANDLER('k', handle_kill_request), + DEL_HANDLER('_', handle____request), +}; + +WASMGDBServer * +wasm_launch_gdbserver(char *host, int port) +{ + int listen_fd = -1; + const int one = 1; + struct sockaddr_in addr; + int ret; + int sockt_fd = 0; + + WASMGDBServer *server; + + if (!(server = wasm_runtime_malloc(sizeof(WASMGDBServer)))) { + LOG_ERROR("wasm gdb server error: failed to allocate memory"); + return NULL; + } + + memset(server, 0, sizeof(WASMGDBServer)); + + listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (listen_fd < 0) { + LOG_ERROR("wasm gdb server error: socket() failed"); + goto fail; + } + + ret = fcntl(listen_fd, F_SETFD, FD_CLOEXEC); + if (ret < 0) { + LOG_ERROR( + "wasm gdb server error: fcntl() failed on setting FD_CLOEXEC"); + goto fail; + } + + ret = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + if (ret < 0) { + LOG_ERROR("wasm gdb server error: setsockopt() failed"); + goto fail; + } + + LOG_VERBOSE("Listening on %s:%d\n", host, port); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(host); + addr.sin_port = htons(port); + + ret = bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) { + LOG_ERROR("wasm gdb server error: bind() failed"); + goto fail; + } + + ret = listen(listen_fd, 1); + if (ret < 0) { + LOG_ERROR("wasm gdb server error: listen() failed"); + goto fail; + } + + server->listen_fd = listen_fd; + + sockt_fd = accept(listen_fd, NULL, NULL); + if (sockt_fd < 0) { + LOG_ERROR("wasm gdb server error: accept() failed"); + goto fail; + } + LOG_VERBOSE("accept gdb client"); + server->socket_fd = sockt_fd; + server->noack = false; + return server; + +fail: + if (listen_fd >= 0) { + shutdown(listen_fd, SHUT_RDWR); + close(listen_fd); + } + if (server) + wasm_runtime_free(server); + return NULL; +} + +void +wasm_close_gdbserver(WASMGDBServer *server) +{ + if (server->socket_fd > 0) { + shutdown(server->socket_fd, SHUT_RDWR); + close(server->socket_fd); + } + if (server->listen_fd > 0) { + shutdown(server->listen_fd, SHUT_RDWR); + close(server->listen_fd); + } +} + +static inline void +handler_packet(WASMGDBServer *server, char request, char *payload) +{ + if (packet_handler_table[(int)request].handler != NULL) + packet_handler_table[(int)request].handler(server, payload); +} + +/** + * The packet layout is: + * '$' + payload + '#' + checksum(2bytes) + * ^ + * packetend_ptr + */ +static void +process_packet(WASMGDBServer *server) +{ + uint8_t *inbuf = server->pkt.buf; + int inbuf_size = server->pkt.size; + uint8_t *packetend_ptr = (uint8_t *)memchr(inbuf, '#', inbuf_size); + int packetend = packetend_ptr - inbuf; + char request = inbuf[1]; + char *payload = NULL; + uint8_t checksum = 0; + + if (packetend == 1) { + LOG_VERBOSE("receive empty request, ignore it\n"); + return; + } + + bh_assert('$' == inbuf[0]); + inbuf[packetend] = '\0'; + + for (int i = 1; i < packetend; i++) + checksum += inbuf[i]; + bh_assert(checksum + == (hex(inbuf[packetend + 1]) << 4 | hex(inbuf[packetend + 2]))); + + payload = (char *)&inbuf[2]; + + LOG_VERBOSE("receive request:%c %s\n", request, payload); + handler_packet(server, request, payload); + + inbuf_erase_head(server, packetend + 3); +} + +bool +wasm_gdbserver_handle_packet(WASMGDBServer *server) +{ + bool ret; + ret = read_packet(server); + if (ret) + process_packet(server); + return ret; +} diff --git a/core/iwasm/libraries/debug-engine/gdbserver.h b/core/iwasm/libraries/debug-engine/gdbserver.h new file mode 100644 index 0000000000..db90b0195f --- /dev/null +++ b/core/iwasm/libraries/debug-engine/gdbserver.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _GDB_SERVER_H +#define _GDB_SERVER_H + +#include + +#define PACKET_BUF_SIZE 0x8000 + +enum GDBStoppointType { + eStoppointInvalid = -1, + eBreakpointSoftware = 0, + eBreakpointHardware, + eWatchpointWrite, + eWatchpointRead, + eWatchpointReadWrite +}; +typedef struct WasmDebugPacket { + unsigned char buf[PACKET_BUF_SIZE]; + unsigned int size; +} WasmDebugPacket; + +struct WASMDebugControlThread; +typedef struct WASMGDBServer { + int listen_fd; + int socket_fd; + WasmDebugPacket pkt; + bool noack; + struct WASMDebugControlThread *thread; +} WASMGDBServer; + +WASMGDBServer * +wasm_launch_gdbserver(char *addr, int port); + +void +wasm_close_gdbserver(WASMGDBServer *server); + +bool +wasm_gdbserver_handle_packet(WASMGDBServer *server); +#endif diff --git a/core/iwasm/libraries/debug-engine/handler.c b/core/iwasm/libraries/debug-engine/handler.c new file mode 100644 index 0000000000..8347cd0b63 --- /dev/null +++ b/core/iwasm/libraries/debug-engine/handler.c @@ -0,0 +1,613 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include + +#include "debug_engine.h" +#include "packets.h" +#include "utils.h" +#include "wasm_runtime.h" + +#define MAX_PACKET_SIZE (0x20000) +static char tmpbuf[MAX_PACKET_SIZE]; + +void +handle_generay_set(WASMGDBServer *server, char *payload) +{ + const char *name; + char *args; + + args = strchr(payload, ':'); + if (args) + *args++ = '\0'; + + name = payload; + LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload); + + if (!strcmp(name, "StartNoAckMode")) { + server->noack = true; + write_packet(server, "OK"); + } + if (!strcmp(name, "ThreadSuffixSupported")) { + write_packet(server, ""); + } + if (!strcmp(name, "ListThreadsInStopReply")) { + write_packet(server, ""); + } + if (!strcmp(name, "EnableErrorStrings")) { + write_packet(server, "OK"); + } +} + +static void +process_xfer(WASMGDBServer *server, const char *name, char *args) +{ + const char *mode = args; + + args = strchr(args, ':'); + if (args) + *args++ = '\0'; + + if (!strcmp(name, "libraries") && !strcmp(mode, "read")) { + // TODO: how to get current wasm file name? + uint64_t addr = wasm_debug_instance_get_load_addr( + (WASMDebugInstance *)server->thread->debug_instance); +#if WASM_ENABLE_LIBC_WASI != 0 + char objname[128]; + wasm_debug_instance_get_current_object_name( + (WASMDebugInstance *)server->thread->debug_instance, objname, 128); + sprintf(tmpbuf, + "l
", + objname, addr); +#else + sprintf(tmpbuf, + "l
", + "nobody.wasm", addr); +#endif + write_packet(server, tmpbuf); + } +} + +void +porcess_wasm_local(WASMGDBServer *server, char *args) +{ + int frame_index; + int local_index; + char buf[16]; + int size = 16; + bool ret; + + sprintf(tmpbuf, "E01"); + if (sscanf(args, "%d;%d", &frame_index, &local_index) == 2) { + ret = wasm_debug_instance_get_local( + (WASMDebugInstance *)server->thread->debug_instance, frame_index, + local_index, buf, &size); + if (ret && size > 0) { + mem2hex(buf, tmpbuf, size); + } + } + write_packet(server, tmpbuf); +} + +void +porcess_wasm_global(WASMGDBServer *server, char *args) +{ + int frame_index; + int global_index; + char buf[16]; + int size = 16; + bool ret; + + sprintf(tmpbuf, "E01"); + if (sscanf(args, "%d;%d", &frame_index, &global_index) == 2) { + ret = wasm_debug_instance_get_global( + (WASMDebugInstance *)server->thread->debug_instance, frame_index, + global_index, buf, &size); + if (ret && size > 0) { + mem2hex(buf, tmpbuf, size); + } + } + write_packet(server, tmpbuf); +} + +void +handle_generay_query(WASMGDBServer *server, char *payload) +{ + const char *name; + char *args; + + args = strchr(payload, ':'); + if (args) + *args++ = '\0'; + name = payload; + LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload); + + if (!strcmp(name, "C")) { + uint64_t pid, tid; + pid = wasm_debug_instance_get_pid( + (WASMDebugInstance *)server->thread->debug_instance); + tid = wasm_debug_instance_get_tid( + (WASMDebugInstance *)server->thread->debug_instance); + snprintf(tmpbuf, sizeof(tmpbuf), "QCp%lx.%lx", pid, tid); + write_packet(server, tmpbuf); + } + if (!strcmp(name, "Supported")) { + sprintf(tmpbuf, "qXfer:libraries:read+;PacketSize=%x;", + MAX_PACKET_SIZE); + write_packet(server, tmpbuf); + } + + if (!strcmp(name, "Xfer")) { + name = args; + + if (!args) { + LOG_ERROR("payload parse error during handle_generay_query"); + return; + } + + args = strchr(args, ':'); + + if (args) { + *args++ = '\0'; + process_xfer(server, name, args); + } + } + + if (!strcmp(name, "HostInfo")) { + // Todo: change vendor to Intel for outside tree? + char triple[256]; + mem2hex("wasm32-Ant-wasi-wasm", triple, strlen("wasm32-Ant-wasi-wasm")); + sprintf(tmpbuf, + "vendor:Ant;ostype:wasi;arch:wasm32;" + "triple:%s;endian:little;ptrsize:4;", + triple); + + write_packet(server, tmpbuf); + } + if (!strcmp(name, "GetWorkingDir")) { + if (getcwd(tmpbuf, PATH_MAX)) + write_packet(server, tmpbuf); + } + if (!strcmp(name, "QueryGDBServer")) { + write_packet(server, ""); + } + if (!strcmp(name, "VAttachOrWaitSupported")) { + write_packet(server, ""); + } + if (!strcmp(name, "ProcessInfo")) { + // Todo: process id parent-pid + uint64_t pid; + pid = wasm_debug_instance_get_pid( + (WASMDebugInstance *)server->thread->debug_instance); + char triple[256]; + // arch-vendor-os-env(format) + mem2hex("wasm32-Ant-wasi-wasm", triple, strlen("wasm32-Ant-wasi-wasm")); + sprintf(tmpbuf, + "pid:%lx;parent-pid:%lx;vendor:Ant;ostype:wasi;arch:wasm32;" + "triple:%s;endian:little;ptrsize:4;", + pid, pid, triple); + + write_packet(server, tmpbuf); + } + if (!strcmp(name, "RegisterInfo0")) { + sprintf( + tmpbuf, + "name:pc;alt-name:pc;bitsize:64;offset:0;encoding:uint;format:hex;" + "set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;"); + write_packet(server, tmpbuf); + } + else if (!strncmp(name, "RegisterInfo", strlen("RegisterInfo"))) { + write_packet(server, "E45"); + } + if (!strcmp(name, "StructuredDataPlugins")) { + write_packet(server, ""); + } + + if (args && (!strcmp(name, "MemoryRegionInfo"))) { + uint64_t addr = strtol(args, NULL, 16); + WASMDebugMemoryInfo *mem_info = wasm_debug_instance_get_memregion( + (WASMDebugInstance *)server->thread->debug_instance, addr); + if (mem_info) { + char name[256]; + mem2hex(mem_info->name, name, strlen(mem_info->name)); + sprintf(tmpbuf, "start:%lx;size:%lx;permissions:%s;name:%s;", + (uint64)mem_info->start, mem_info->size, + mem_info->permisson, name); + write_packet(server, tmpbuf); + wasm_debug_instance_destroy_memregion( + (WASMDebugInstance *)server->thread->debug_instance, mem_info); + } + } + + if (!strcmp(name, "WasmData")) { + } + + if (!strcmp(name, "WasmMem")) { + } + + if (!strcmp(name, "Symbol")) { + write_packet(server, ""); + } + + if (args && (!strcmp(name, "WasmCallStack"))) { + uint64_t tid = strtol(args, NULL, 16); + uint64_t buf[1024 / sizeof(uint64_t)]; + uint64_t count = wasm_debug_instance_get_call_stack_pcs( + (WASMDebugInstance *)server->thread->debug_instance, tid, buf, + 1024 / sizeof(uint64_t)); + if (count > 0) { + mem2hex((char *)buf, tmpbuf, count * sizeof(uint64_t)); + write_packet(server, tmpbuf); + } + else + write_packet(server, ""); + } + + if (args && (!strcmp(name, "WasmLocal"))) { + porcess_wasm_local(server, args); + } + + if (args && (!strcmp(name, "WasmGlobal"))) { + porcess_wasm_global(server, args); + } +} + +static void +send_thread_stop_status(WASMGDBServer *server, uint32_t status, uint64_t tid) +{ + int tids_number, len = 0, i = 0; + uint64_t tids[20]; + char pc_string[17]; + uint32_t gdb_status = status; + + if (status == 0) { + sprintf(tmpbuf, "W%02x", status); + write_packet(server, tmpbuf); + return; + } + tids_number = wasm_debug_instance_get_tids( + (WASMDebugInstance *)server->thread->debug_instance, tids, 20); + uint64_t pc = wasm_debug_instance_get_pc( + (WASMDebugInstance *)server->thread->debug_instance); + + if (status == WAMR_SIG_SINGSTEP) { + gdb_status = WAMR_SIG_TRAP; + } + + // TODO: how name a wasm thread? + len += + sprintf(tmpbuf, "T%02xthread:%lx;name:%s;", gdb_status, tid, "nobody"); + if (tids_number > 0) { + len += sprintf(tmpbuf + len, "threads:"); + while (i < tids_number) { + if (i == tids_number - 1) + len += sprintf(tmpbuf + len, "%lx;", tids[i]); + else + len += sprintf(tmpbuf + len, "%lx,", tids[i]); + i++; + } + } + mem2hex((void *)&pc, pc_string, 8); + pc_string[8 * 2] = '\0'; + + if (status == WAMR_SIG_TRAP) { + len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc, + pc_string, "breakpoint"); + } + else if (status == WAMR_SIG_SINGSTEP) { + len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc, + pc_string, "trace"); + } + else if (status > 0) { + len += sprintf(tmpbuf + len, "thread-pcs:%lx;00:%s,reason:%s;", pc, + pc_string, "signal"); + } + write_packet(server, tmpbuf); +} + +void +handle_v_packet(WASMGDBServer *server, char *payload) +{ + const char *name; + char *args; + uint32_t status; + args = strchr(payload, ';'); + if (args) + *args++ = '\0'; + name = payload; + LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload); + + if (!strcmp("Cont?", name)) + write_packet(server, "vCont;c;C;s;S;"); + + if (!strcmp("Cont", name)) { + if (args && args[0] == 's') { + char *numstring = strchr(args, ':'); + if (numstring) { + *numstring++ = '\0'; + uint64_t tid = strtol(numstring, NULL, 16); + wasm_debug_instance_set_cur_thread( + (WASMDebugInstance *)server->thread->debug_instance, tid); + wasm_debug_instance_singlestep( + (WASMDebugInstance *)server->thread->debug_instance, tid); + tid = wasm_debug_instance_wait_thread( + (WASMDebugInstance *)server->thread->debug_instance, tid, + &status); + send_thread_stop_status(server, status, tid); + } + } + } +} + +void +handle_threadstop_request(WASMGDBServer *server, char *payload) +{ + uint64_t tid = wasm_debug_instance_get_tid( + (WASMDebugInstance *)server->thread->debug_instance); + uint32_t status; + + tid = wasm_debug_instance_wait_thread( + (WASMDebugInstance *)server->thread->debug_instance, tid, &status); + + send_thread_stop_status(server, status, tid); +} + +void +handle_set_current_thread(WASMGDBServer *server, char *payload) +{ + LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload, payload); + if ('g' == *payload++) { + uint64_t tid; + tid = strtol(payload, NULL, 16); + if (tid > 0) + wasm_debug_instance_set_cur_thread( + (WASMDebugInstance *)server->thread->debug_instance, tid); + } + write_packet(server, "OK"); +} + +void +handle_get_register(WASMGDBServer *server, char *payload) +{ + int i = strtol(payload, NULL, 16); + + if (i != 0) { + write_packet(server, "E01"); + return; + } + uint64_t regdata = wasm_debug_instance_get_pc( + (WASMDebugInstance *)server->thread->debug_instance); + mem2hex((void *)®data, tmpbuf, 8); + tmpbuf[8 * 2] = '\0'; + write_packet(server, tmpbuf); +} + +void +handle_get_json_request(WASMGDBServer *server, char *payload) +{ + char *args; + + args = strchr(payload, ':'); + if (args) + *args++ = '\0'; + write_packet(server, ""); +} + +void +handle_get_read_binary_memory(WASMGDBServer *server, char *payload) +{ + write_packet(server, ""); +} + +void +handle_get_read_memory(WASMGDBServer *server, char *payload) +{ + size_t maddr, mlen; + bool ret; + + sprintf(tmpbuf, "%s", ""); + if (sscanf(payload, "%zx,%zx", &maddr, &mlen) == 2) { + if (mlen * 2 > MAX_PACKET_SIZE) { + LOG_ERROR("Buffer overflow!"); + mlen = MAX_PACKET_SIZE / 2; + } + char *buff = wasm_runtime_malloc(mlen); + if (buff) { + ret = wasm_debug_instance_get_mem( + (WASMDebugInstance *)server->thread->debug_instance, maddr, + buff, &mlen); + if (ret) { + mem2hex(buff, tmpbuf, mlen); + } + wasm_runtime_free(buff); + } + } + write_packet(server, tmpbuf); +} + +void +handle_get_write_memory(WASMGDBServer *server, char *payload) +{ + size_t maddr, mlen, hex_len; + int offset, act_len; + char *buff; + bool ret; + + sprintf(tmpbuf, "%s", ""); + if (sscanf(payload, "%zx,%zx:%n", &maddr, &mlen, &offset) == 2) { + payload += offset; + hex_len = strlen(payload); + act_len = hex_len / 2 < mlen ? hex_len / 2 : mlen; + buff = wasm_runtime_malloc(act_len); + if (buff) { + hex2mem(payload, buff, act_len); + ret = wasm_debug_instance_set_mem( + (WASMDebugInstance *)server->thread->debug_instance, maddr, + buff, &mlen); + if (ret) { + sprintf(tmpbuf, "%s", "OK"); + } + wasm_runtime_free(buff); + } + } + write_packet(server, tmpbuf); +} + +void +handle_add_break(WASMGDBServer *server, char *payload) +{ + size_t type, addr, length; + + if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) { + if (type == eBreakpointSoftware) { + bool ret = wasm_debug_instance_add_breakpoint( + (WASMDebugInstance *)server->thread->debug_instance, addr, + length); + if (ret) + write_packet(server, "OK"); + else + write_packet(server, "E01"); + return; + } + } + write_packet(server, ""); +} + +void +handle_remove_break(WASMGDBServer *server, char *payload) +{ + size_t type, addr, length; + + if (sscanf(payload, "%zx,%zx,%zx", &type, &addr, &length) == 3) { + if (type == eBreakpointSoftware) { + bool ret = wasm_debug_instance_remove_breakpoint( + (WASMDebugInstance *)server->thread->debug_instance, addr, + length); + if (ret) + write_packet(server, "OK"); + else + write_packet(server, "E01"); + return; + } + } + write_packet(server, ""); +} + +void +handle_continue_request(WASMGDBServer *server, char *payload) +{ + uint64_t tid; + uint32_t status; + + wasm_debug_instance_continue( + (WASMDebugInstance *)server->thread->debug_instance); + + tid = wasm_debug_instance_get_tid( + (WASMDebugInstance *)server->thread->debug_instance); + + tid = wasm_debug_instance_wait_thread( + (WASMDebugInstance *)server->thread->debug_instance, tid, &status); + + send_thread_stop_status(server, status, tid); +} + +void +handle_kill_request(WASMGDBServer *server, char *payload) +{ + uint64_t tid; + uint32_t status; + + wasm_debug_instance_kill( + (WASMDebugInstance *)server->thread->debug_instance); + + tid = wasm_debug_instance_get_tid( + (WASMDebugInstance *)server->thread->debug_instance); + + tid = wasm_debug_instance_wait_thread( + (WASMDebugInstance *)server->thread->debug_instance, tid, &status); + + send_thread_stop_status(server, status, tid); +} + +static void +handle_malloc(WASMGDBServer *server, char *payload) +{ + char *args; + uint64_t size; + int map_port = MMAP_PROT_NONE; + uint64_t addr; + + sprintf(tmpbuf, "%s", "E03"); + + args = strstr(payload, ","); + if (args) { + *args++ = '\0'; + } + else { + LOG_ERROR("Payload parse error during handle malloc"); + return; + } + + size = strtol(payload, NULL, 16); + if (size > 0) { + while (*args) { + if (*args == 'r') { + map_port |= MMAP_PROT_READ; + } + if (*args == 'w') { + map_port |= MMAP_PROT_WRITE; + } + if (*args == 'x') { + map_port |= MMAP_PROT_EXEC; + } + args++; + } + addr = wasm_debug_instance_mmap( + (WASMDebugInstance *)server->thread->debug_instance, size, + map_port); + if (addr) { + sprintf(tmpbuf, "%lx", addr); + } + } + write_packet(server, tmpbuf); +} + +static void +handle_free(WASMGDBServer *server, char *payload) +{ + uint64_t addr; + bool ret; + + sprintf(tmpbuf, "%s", "E03"); + addr = strtol(payload, NULL, 16); + + ret = wasm_debug_instance_ummap( + (WASMDebugInstance *)server->thread->debug_instance, addr); + if (ret) { + sprintf(tmpbuf, "%s", "OK"); + } + write_packet(server, tmpbuf); +} + +void +handle____request(WASMGDBServer *server, char *payload) +{ + char *args; + + if (payload[0] == 'M') { + args = payload + 1; + handle_malloc(server, args); + } + if (payload[0] == 'm') { + args = payload + 1; + handle_free(server, args); + } +} diff --git a/core/iwasm/libraries/debug-engine/handler.h b/core/iwasm/libraries/debug-engine/handler.h new file mode 100644 index 0000000000..90525a982d --- /dev/null +++ b/core/iwasm/libraries/debug-engine/handler.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef HANDLER_H +#define HANDLER_H + +#include "gdbserver.h" + +void +handle_generay_set(WASMGDBServer *server, char *payload); + +void +handle_generay_query(WASMGDBServer *server, char *payload); + +void +handle_v_packet(WASMGDBServer *server, char *payload); + +void +handle_threadstop_request(WASMGDBServer *server, char *payload); + +void +handle_set_current_thread(WASMGDBServer *server, char *payload); + +void +handle_get_register(WASMGDBServer *server, char *payload); + +void +handle_get_json_request(WASMGDBServer *server, char *payload); + +void +handle_get_read_binary_memory(WASMGDBServer *server, char *payload); + +void +handle_get_read_memory(WASMGDBServer *server, char *payload); + +void +handle_get_write_memory(WASMGDBServer *server, char *payload); + +void +handle_add_break(WASMGDBServer *server, char *payload); + +void +handle_remove_break(WASMGDBServer *server, char *payload); + +void +handle_continue_request(WASMGDBServer *server, char *payload); + +void +handle_kill_request(WASMGDBServer *server, char *payload); + +void +handle____request(WASMGDBServer *server, char *payload); +#endif diff --git a/core/iwasm/libraries/debug-engine/packets.c b/core/iwasm/libraries/debug-engine/packets.c new file mode 100644 index 0000000000..d937912048 --- /dev/null +++ b/core/iwasm/libraries/debug-engine/packets.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "packets.h" + +#include + +#include "bh_log.h" +#include "gdbserver.h" + +void +pktbuf_insert(WASMGDBServer *gdbserver, const uint8_t *buf, ssize_t len) +{ + WasmDebugPacket *pkt = &gdbserver->pkt; + + if ((unsigned long)(pkt->size + len) >= sizeof(pkt->buf)) { + LOG_ERROR("Packet buffer overflow"); + exit(-2); + } + + memcpy(pkt->buf + pkt->size, buf, len); + pkt->size += len; +} + +void +pktbuf_erase_head(WASMGDBServer *gdbserver, ssize_t index) +{ + WasmDebugPacket *pkt = &gdbserver->pkt; + memmove(pkt->buf, pkt->buf + index, pkt->size - index); + pkt->size -= index; +} + +void +inbuf_erase_head(WASMGDBServer *gdbserver, ssize_t index) +{ + pktbuf_erase_head(gdbserver, index); +} + +void +pktbuf_clear(WASMGDBServer *gdbserver) +{ + WasmDebugPacket *pkt = &gdbserver->pkt; + pkt->size = 0; +} + +int +read_data_once(WASMGDBServer *gdbserver) +{ + ssize_t nread; + uint8_t buf[4096]; + + nread = read(gdbserver->socket_fd, buf, sizeof(buf)); + if (nread <= 0) { + LOG_ERROR("Connection closed"); + return -1; + } + pktbuf_insert(gdbserver, buf, nread); + return nread; +} + +void +write_data_raw(WASMGDBServer *gdbserver, const uint8_t *data, ssize_t len) +{ + ssize_t nwritten; + + nwritten = write(gdbserver->socket_fd, data, len); + if (nwritten < 0) { + LOG_ERROR("Write error\n"); + exit(-2); + } +} + +void +write_hex(WASMGDBServer *gdbserver, unsigned long hex) +{ + char buf[32]; + size_t len; + + len = snprintf(buf, sizeof(buf) - 1, "%02lx", hex); + write_data_raw(gdbserver, (uint8_t *)buf, len); +} + +void +write_packet_bytes(WASMGDBServer *gdbserver, const uint8_t *data, + size_t num_bytes) +{ + uint8_t checksum; + size_t i; + + write_data_raw(gdbserver, (uint8_t *)"$", 1); + for (i = 0, checksum = 0; i < num_bytes; ++i) + checksum += data[i]; + write_data_raw(gdbserver, (uint8_t *)data, num_bytes); + write_data_raw(gdbserver, (uint8_t *)"#", 1); + write_hex(gdbserver, checksum); +} + +void +write_packet(WASMGDBServer *gdbserver, const char *data) +{ + LOG_VERBOSE("send replay:%s", data); + write_packet_bytes(gdbserver, (const uint8_t *)data, strlen(data)); +} + +void +write_binary_packet(WASMGDBServer *gdbserver, const char *pfx, + const uint8_t *data, ssize_t num_bytes) +{ + uint8_t *buf; + ssize_t pfx_num_chars = strlen(pfx); + ssize_t buf_num_bytes = 0, total_size; + int i; + + total_size = 2 * num_bytes + pfx_num_chars; + buf = wasm_runtime_malloc(total_size); + if (!buf) { + LOG_ERROR("Failed to allocate memory for binary packet"); + return; + } + + memset(buf, 0, total_size); + memcpy(buf, pfx, pfx_num_chars); + buf_num_bytes += pfx_num_chars; + + for (i = 0; i < num_bytes; ++i) { + uint8_t b = data[i]; + switch (b) { + case '#': + case '$': + case '}': + case '*': + buf[buf_num_bytes++] = '}'; + buf[buf_num_bytes++] = b ^ 0x20; + break; + default: + buf[buf_num_bytes++] = b; + break; + } + } + write_packet_bytes(gdbserver, buf, buf_num_bytes); + wasm_runtime_free(buf); +} + +bool +skip_to_packet_start(WASMGDBServer *gdbserver) +{ + ssize_t start_index = -1, i; + + for (i = 0; i < gdbserver->pkt.size; ++i) { + if (gdbserver->pkt.buf[i] == '$') { + start_index = i; + break; + } + } + + if (start_index < 0) { + pktbuf_clear(gdbserver); + return false; + } + + pktbuf_erase_head(gdbserver, start_index); + + bh_assert(1 <= gdbserver->pkt.size); + bh_assert('$' == gdbserver->pkt.buf[0]); + + return true; +} + +bool +read_packet(WASMGDBServer *gdbserver) +{ + while (!skip_to_packet_start(gdbserver)) { + if (read_data_once(gdbserver) < 0) + return false; + } + if (!gdbserver->noack) + write_data_raw(gdbserver, (uint8_t *)"+", 1); + return true; +} diff --git a/core/iwasm/libraries/debug-engine/packets.h b/core/iwasm/libraries/debug-engine/packets.h new file mode 100644 index 0000000000..ecc6978ce7 --- /dev/null +++ b/core/iwasm/libraries/debug-engine/packets.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef PACKETS_H +#define PACKETS_H + +#include +#include +#include "gdbserver.h" + +bool +read_packet(WASMGDBServer *gdbserver); + +void +write_packet(WASMGDBServer *gdbserver, const char *data); + +void +inbuf_erase_head(WASMGDBServer *gdbserver, ssize_t end); + +#endif diff --git a/core/iwasm/libraries/debug-engine/utils.c b/core/iwasm/libraries/debug-engine/utils.c new file mode 100644 index 0000000000..497dbd2d1f --- /dev/null +++ b/core/iwasm/libraries/debug-engine/utils.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "utils.h" + +int +hex(char ch) +{ + if ((ch >= 'a') && (ch <= 'f')) + return (ch - 'a' + 10); + if ((ch >= '0') && (ch <= '9')) + return (ch - '0'); + if ((ch >= 'A') && (ch <= 'F')) + return (ch - 'A' + 10); + return (-1); +} + +char * +mem2hex(char *mem, char *buf, int count) +{ + unsigned char ch; + + for (int i = 0; i < count; i++) { + ch = *(mem++); + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch % 16]; + } + *buf = 0; + return (buf); +} + +char * +hex2mem(char *buf, char *mem, int count) +{ + unsigned char ch; + + for (int i = 0; i < count; i++) { + ch = hex(*buf++) << 4; + ch = ch + hex(*buf++); + *(mem++) = ch; + } + return (mem); +} diff --git a/core/iwasm/libraries/debug-engine/utils.h b/core/iwasm/libraries/debug-engine/utils.h new file mode 100644 index 0000000000..cbf5819e71 --- /dev/null +++ b/core/iwasm/libraries/debug-engine/utils.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Ant Group. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef UTILS_H +#define UTILS_H + +static const char hexchars[] = "0123456789abcdef"; + +int +hex(char ch); + +char * +mem2hex(char *mem, char *buf, int count); + +char * +hex2mem(char *buf, char *mem, int count); + +int +unescape(char *msg, int len); + +#endif /* UTILS_H */ diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index 0eaed87bcd..6bc2074267 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -12,13 +12,14 @@ #define WAMR_PTHREAD_KEYS_MAX 32 +/* clang-format off */ #define get_module(exec_env) \ wasm_exec_env_get_module(exec_env) #define get_module_inst(exec_env) \ wasm_runtime_get_module_inst(exec_env) -#define get_thread_arg(exec_env) \ +#define get_thread_arg(exec_env) \ wasm_exec_env_get_thread_arg(exec_env) #define get_wasi_ctx(module_inst) \ @@ -35,10 +36,10 @@ #define addr_native_to_app(ptr) \ wasm_runtime_addr_native_to_app(module_inst, ptr) +/* clang-format on */ extern bool -wasm_runtime_call_indirect(wasm_exec_env_t exec_env, - uint32 element_indices, +wasm_runtime_call_indirect(wasm_exec_env_t exec_env, uint32 element_indices, uint32 argc, uint32 argv[]); enum { @@ -95,7 +96,7 @@ typedef struct ThreadInfoNode { /* type can be [THREAD | MUTEX | CONDITION] */ uint32 type; /* Thread status, this variable should be volatile - as its value may be changed in different threads */ + as its value may be changed in different threads */ volatile uint32 status; bool joinable; union { @@ -112,7 +113,7 @@ typedef struct { /* table elem index of the app's entry function */ uint32 elem_index; /* arg of the app's entry function */ - void *arg; + uint32 arg; wasm_module_inst_t module_inst; } ThreadRoutineArgs; @@ -161,8 +162,7 @@ lib_pthread_init() if (0 != os_mutex_init(&thread_global_lock)) return false; bh_list_init(&cluster_info_list); - if (!wasm_cluster_register_destroy_callback( - lib_pthread_destroy_callback)) { + if (!wasm_cluster_register_destroy_callback(lib_pthread_destroy_callback)) { os_mutex_destroy(&thread_global_lock); return false; } @@ -175,7 +175,7 @@ lib_pthread_destroy() os_mutex_destroy(&thread_global_lock); } -static ClusterInfoNode* +static ClusterInfoNode * get_cluster_info(WASMCluster *cluster) { ClusterInfoNode *node; @@ -195,30 +195,30 @@ get_cluster_info(WASMCluster *cluster) return NULL; } -static KeyData* +static KeyData * key_data_list_lookup(wasm_exec_env_t exec_env, int32 key) { ClusterInfoNode *node; - WASMCluster *cluster = - wasm_exec_env_get_cluster(exec_env); + WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); if ((node = get_cluster_info(cluster))) { return (key >= 0 && key < WAMR_PTHREAD_KEYS_MAX && node->key_data_list[key].is_created) - ? &(node->key_data_list[key]) : NULL; + ? &(node->key_data_list[key]) + : NULL; } return NULL; } -/* Lookup the thread key value node for a thread, - create a new one if failed - This design will reduce the memory usage. If the thread doesn't use - the local storage, it will not occupy memory space -*/ -static int32* -key_value_list_lookup_or_create(wasm_exec_env_t exec_env, - ClusterInfoNode *info, int32 key) +/** + * Lookup the thread key value node for a thread, create a new one if failed + * This design will reduce the memory usage. If the thread doesn't use the + * local storage, it will not occupy memory space. + */ +static int32 * +key_value_list_lookup_or_create(wasm_exec_env_t exec_env, ClusterInfoNode *info, + int32 key) { KeyData *key_node; ThreadKeyValueNode *data; @@ -296,9 +296,7 @@ call_key_destructor(wasm_exec_env_t exec_env) uint32 argv[1]; argv[0] = value; - wasm_runtime_call_indirect(exec_env, - destructor_index, - 1, argv); + wasm_runtime_call_indirect(exec_env, destructor_index, 1, argv); } } } @@ -325,7 +323,7 @@ destroy_thread_key_value_list(bh_list *list) } } -static ClusterInfoNode* +static ClusterInfoNode * create_cluster_info(WASMCluster *cluster) { ClusterInfoNode *node; @@ -346,12 +344,9 @@ create_cluster_info(WASMCluster *cluster) } node->cluster = cluster; - if (!(node->thread_info_map = - bh_hash_map_create(32, true, - (HashFunc)thread_handle_hash, - (KeyEqualFunc)thread_handle_equal, - NULL, - thread_info_destroy))) { + if (!(node->thread_info_map = bh_hash_map_create( + 32, true, (HashFunc)thread_handle_hash, + (KeyEqualFunc)thread_handle_equal, NULL, thread_info_destroy))) { os_mutex_destroy(&node->key_data_list_lock); wasm_runtime_free(node); return NULL; @@ -395,13 +390,12 @@ delete_thread_info_node(ThreadInfoNode *thread_info) { ClusterInfoNode *node; bool ret; - WASMCluster *cluster = - wasm_exec_env_get_cluster(thread_info->exec_env); + WASMCluster *cluster = wasm_exec_env_get_cluster(thread_info->exec_env); if ((node = get_cluster_info(cluster))) { ret = bh_hash_map_remove(node->thread_info_map, - (void *)(uintptr_t)thread_info->handle, - NULL, NULL); + (void *)(uintptr_t)thread_info->handle, NULL, + NULL); (void)ret; } @@ -412,8 +406,7 @@ static bool append_thread_info_node(ThreadInfoNode *thread_info) { ClusterInfoNode *node; - WASMCluster *cluster = - wasm_exec_env_get_cluster(thread_info->exec_env); + WASMCluster *cluster = wasm_exec_env_get_cluster(thread_info->exec_env); if (!(node = get_cluster_info(cluster))) { if (!(node = create_cluster_info(cluster))) { @@ -430,7 +423,7 @@ append_thread_info_node(ThreadInfoNode *thread_info) return true; } -static ThreadInfoNode* +static ThreadInfoNode * get_thread_info(wasm_exec_env_t exec_env, uint32 handle) { WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); @@ -453,7 +446,7 @@ allocate_handle() return id; } -static void* +static void * pthread_start_routine(void *arg) { wasm_exec_env_t exec_env = (wasm_exec_env_t)arg; @@ -479,21 +472,11 @@ pthread_start_routine(void *arg) os_cond_signal(&parent_exec_env->wait_cond); os_mutex_unlock(&parent_exec_env->wait_lock); - if (!validate_native_addr(routine_args->arg, sizeof(uint32))) { - /* If there are exceptions, copy the exception to - all other instance in this cluster */ - wasm_cluster_spread_exception(exec_env); - wasm_runtime_deinstantiate_internal(module_inst, true); - delete_thread_info_node(info_node); - return NULL; - } - wasm_exec_env_set_thread_info(exec_env); - argv[0] = addr_native_to_app(routine_args->arg); + argv[0] = routine_args->arg; - if(!wasm_runtime_call_indirect(exec_env, - routine_args->elem_index, - 1, argv)) { + if (!wasm_runtime_call_indirect(exec_env, routine_args->elem_index, 1, + argv)) { if (wasm_runtime_get_exception(module_inst)) wasm_cluster_spread_exception(exec_env); } @@ -507,8 +490,8 @@ pthread_start_routine(void *arg) wasm_runtime_free(routine_args); /* if the thread is joinable, store the result in its info node, - if the other threads join this thread after exited, then we - can return the stored result */ + if the other threads join this thread after exited, then we + can return the stored result */ if (!info_node->joinable) { delete_thread_info_node(info_node); } @@ -529,10 +512,10 @@ pthread_start_routine(void *arg) static int pthread_create_wrapper(wasm_exec_env_t exec_env, - uint32 *thread, /* thread_handle */ - const void *attr, /* not supported */ - uint32 elem_index, /* entry function */ - void *arg) /* arguments buffer */ + uint32 *thread, /* thread_handle */ + const void *attr, /* not supported */ + uint32 elem_index, /* entry function */ + uint32 arg) /* arguments buffer */ { wasm_module_t module = get_module(exec_env); wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -548,15 +531,13 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, bh_assert(module); bh_assert(module_inst); - if (!(new_module_inst = - wasm_runtime_instantiate_internal(module, true, 8192, 0, - NULL, 0))) + if (!(new_module_inst = wasm_runtime_instantiate_internal( + module, true, 8192, 0, NULL, 0))) return -1; /* Set custom_data to new module instance */ wasm_runtime_set_custom_data_internal( - new_module_inst, - wasm_runtime_get_custom_data(module_inst)); + new_module_inst, wasm_runtime_get_custom_data(module_inst)); #if WASM_ENABLE_LIBC_WASI != 0 wasi_ctx = get_wasi_ctx(module_inst); @@ -584,17 +565,16 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, routine_args->module_inst = new_module_inst; os_mutex_lock(&exec_env->wait_lock); - ret = wasm_cluster_create_thread(exec_env, new_module_inst, - pthread_start_routine, - (void *)routine_args); + ret = wasm_cluster_create_thread( + exec_env, new_module_inst, pthread_start_routine, (void *)routine_args); if (ret != 0) { os_mutex_unlock(&exec_env->wait_lock); goto fail; } /* Wait for the thread routine to assign the exec_env to - thread_info_node, otherwise the exec_env in the thread - info node may be NULL in the next pthread API call */ + thread_info_node, otherwise the exec_env in the thread + info node may be NULL in the next pthread API call */ os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); os_mutex_unlock(&exec_env->wait_lock); @@ -627,10 +607,10 @@ pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread, module_inst = get_module_inst(exec_env); /* validate addr, we can use current thread's - module instance here as the memory is shared */ + module instance here as the memory is shared */ if (!validate_app_addr(retval_offset, sizeof(int32))) { /* Join failed, but we don't want to terminate all threads, - do not spread exception here */ + do not spread exception here */ wasm_runtime_set_exception(module_inst, NULL); return -1; } @@ -654,14 +634,14 @@ pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread, /* if the thread has exited, return stored results */ /* this thread must be joinable, otherwise the - info_node should be destroyed once exit */ + info_node should be destroyed once exit */ bh_assert(node->joinable); join_ret = 0; ret = node->u.ret; } if (retval_offset != 0) - *(uint32*)retval = (uint32)(uintptr_t)ret; + *(uint32 *)retval = (uint32)(uintptr_t)ret; return join_ret; } @@ -708,7 +688,7 @@ pthread_self_wrapper(wasm_exec_env_t exec_env) { ThreadRoutineArgs *args = get_thread_arg(exec_env); /* If thread_arg is NULL, it's the exec_env of the main thread, - return id 0 to app */ + return id 0 to app */ if (!args) return 0; @@ -726,8 +706,8 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset) #if defined(OS_ENABLE_HW_BOUND_CHECK) && !defined(BH_PLATFORM_WINDOWS) /* If hardware bound check enabled, don't deinstantiate module inst - and thread info node here for AoT module, as they will be freed - in pthread_start_routine */ + and thread info node here for AoT module, as they will be freed + in pthread_start_routine */ if (exec_env->jmpbuf_stack_top) { wasm_cluster_exit_thread(exec_env, (void *)(uintptr_t)retval_offset); } @@ -782,7 +762,7 @@ pthread_mutex_init_wrapper(wasm_exec_env_t exec_env, uint32 *mutex, void *attr) /* Return the mutex handle to app */ if (mutex) - *(uint32*)mutex = info_node->handle; + *(uint32 *)mutex = info_node->handle; return 0; @@ -799,7 +779,7 @@ pthread_mutex_init_wrapper(wasm_exec_env_t exec_env, uint32 *mutex, void *attr) static int32 pthread_mutex_lock_wrapper(wasm_exec_env_t exec_env, uint32 *mutex) { - ThreadInfoNode* info_node = get_thread_info(exec_env, *mutex); + ThreadInfoNode *info_node = get_thread_info(exec_env, *mutex); if (!info_node || info_node->type != T_MUTEX) return -1; @@ -809,7 +789,7 @@ pthread_mutex_lock_wrapper(wasm_exec_env_t exec_env, uint32 *mutex) static int32 pthread_mutex_unlock_wrapper(wasm_exec_env_t exec_env, uint32 *mutex) { - ThreadInfoNode* info_node = get_thread_info(exec_env, *mutex); + ThreadInfoNode *info_node = get_thread_info(exec_env, *mutex); if (!info_node || info_node->type != T_MUTEX) return -1; @@ -820,7 +800,7 @@ static int32 pthread_mutex_destroy_wrapper(wasm_exec_env_t exec_env, uint32 *mutex) { int32 ret_val; - ThreadInfoNode* info_node = get_thread_info(exec_env, *mutex); + ThreadInfoNode *info_node = get_thread_info(exec_env, *mutex); if (!info_node || info_node->type != T_MUTEX) return -1; @@ -861,7 +841,7 @@ pthread_cond_init_wrapper(wasm_exec_env_t exec_env, uint32 *cond, void *attr) /* Return the cond handle to app */ if (cond) - *(uint32*)cond = info_node->handle; + *(uint32 *)cond = info_node->handle; return 0; @@ -891,9 +871,10 @@ pthread_cond_wait_wrapper(wasm_exec_env_t exec_env, uint32 *cond, uint32 *mutex) return os_cond_wait(cond_info_node->u.cond, mutex_info_node->u.mutex); } -/* Currently we don't support struct timespec in built-in libc, - so the pthread_cond_timedwait use useconds instead -*/ +/** + * Currently we don't support struct timespec in built-in libc, + * so the pthread_cond_timedwait use useconds instead + */ static int32 pthread_cond_timedwait_wrapper(wasm_exec_env_t exec_env, uint32 *cond, uint32 *mutex, uint64 useconds) @@ -915,7 +896,7 @@ pthread_cond_timedwait_wrapper(wasm_exec_env_t exec_env, uint32 *cond, static int32 pthread_cond_signal_wrapper(wasm_exec_env_t exec_env, uint32 *cond) { - ThreadInfoNode* info_node = get_thread_info(exec_env, *cond); + ThreadInfoNode *info_node = get_thread_info(exec_env, *cond); if (!info_node || info_node->type != T_COND) return -1; @@ -926,7 +907,7 @@ static int32 pthread_cond_destroy_wrapper(wasm_exec_env_t exec_env, uint32 *cond) { int32 ret_val; - ThreadInfoNode* info_node = get_thread_info(exec_env, *cond); + ThreadInfoNode *info_node = get_thread_info(exec_env, *cond); if (!info_node || info_node->type != T_COND) return -1; @@ -948,7 +929,7 @@ pthread_key_create_wrapper(wasm_exec_env_t exec_env, int32 *key, if (!info) { /* The user may call pthread_key_create in main thread, - in this case the cluster info hasn't been created */ + in this case the cluster info hasn't been created */ if (!(info = create_cluster_info(cluster))) { return -1; } @@ -1046,46 +1027,50 @@ pthread_key_delete_wrapper(wasm_exec_env_t exec_env, int32 key) return 0; } -/* Currently the memory allocator doesn't support alloc specific aligned - space, we wrap posix_memalign to simply malloc memory */ +/** + * Currently the memory allocator doesn't support alloc specific aligned + * space, we wrap posix_memalign to simply malloc memory + */ static int32 -posix_memalign_wrapper(wasm_exec_env_t exec_env, - void **memptr, int32 align, int32 size) +posix_memalign_wrapper(wasm_exec_env_t exec_env, void **memptr, int32 align, + int32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); void *p = NULL; - *((int32 *)memptr) = module_malloc(size, (void**)&p); + *((int32 *)memptr) = module_malloc(size, (void **)&p); if (!p) return -1; return 0; } -#define REG_NATIVE_FUNC(func_name, signature) \ +/* clang-format off */ +#define REG_NATIVE_FUNC(func_name, signature) \ { #func_name, func_name##_wrapper, signature, NULL } +/* clang-format on */ static NativeSymbol native_symbols_lib_pthread[] = { - REG_NATIVE_FUNC(pthread_create, "(**i*)i"), - REG_NATIVE_FUNC(pthread_join, "(ii)i"), - REG_NATIVE_FUNC(pthread_detach, "(i)i"), - REG_NATIVE_FUNC(pthread_cancel, "(i)i"), - REG_NATIVE_FUNC(pthread_self, "()i"), - REG_NATIVE_FUNC(pthread_exit, "(i)"), - REG_NATIVE_FUNC(pthread_mutex_init, "(**)i"), - REG_NATIVE_FUNC(pthread_mutex_lock, "(*)i"), - REG_NATIVE_FUNC(pthread_mutex_unlock, "(*)i"), - REG_NATIVE_FUNC(pthread_mutex_destroy, "(*)i"), - REG_NATIVE_FUNC(pthread_cond_init, "(**)i"), - REG_NATIVE_FUNC(pthread_cond_wait, "(**)i"), + REG_NATIVE_FUNC(pthread_create, "(**ii)i"), + REG_NATIVE_FUNC(pthread_join, "(ii)i"), + REG_NATIVE_FUNC(pthread_detach, "(i)i"), + REG_NATIVE_FUNC(pthread_cancel, "(i)i"), + REG_NATIVE_FUNC(pthread_self, "()i"), + REG_NATIVE_FUNC(pthread_exit, "(i)"), + REG_NATIVE_FUNC(pthread_mutex_init, "(**)i"), + REG_NATIVE_FUNC(pthread_mutex_lock, "(*)i"), + REG_NATIVE_FUNC(pthread_mutex_unlock, "(*)i"), + REG_NATIVE_FUNC(pthread_mutex_destroy, "(*)i"), + REG_NATIVE_FUNC(pthread_cond_init, "(**)i"), + REG_NATIVE_FUNC(pthread_cond_wait, "(**)i"), REG_NATIVE_FUNC(pthread_cond_timedwait, "(**I)i"), - REG_NATIVE_FUNC(pthread_cond_signal, "(*)i"), - REG_NATIVE_FUNC(pthread_cond_destroy, "(*)i"), - REG_NATIVE_FUNC(pthread_key_create, "(*i)i"), - REG_NATIVE_FUNC(pthread_setspecific, "(ii)i"), - REG_NATIVE_FUNC(pthread_getspecific, "(i)i"), - REG_NATIVE_FUNC(pthread_key_delete, "(i)i"), - REG_NATIVE_FUNC(posix_memalign, "(*ii)i"), + REG_NATIVE_FUNC(pthread_cond_signal, "(*)i"), + REG_NATIVE_FUNC(pthread_cond_destroy, "(*)i"), + REG_NATIVE_FUNC(pthread_key_create, "(*i)i"), + REG_NATIVE_FUNC(pthread_setspecific, "(ii)i"), + REG_NATIVE_FUNC(pthread_getspecific, "(i)i"), + REG_NATIVE_FUNC(pthread_key_delete, "(i)i"), + REG_NATIVE_FUNC(posix_memalign, "(*ii)i"), }; uint32 diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index cb21bac771..979e6e6cd4 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c @@ -29,9 +29,10 @@ void wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack); uint32 -wasm_runtime_module_realloc(wasm_module_inst_t module, uint32 ptr, - uint32 size, void **p_native_addr); +wasm_runtime_module_realloc(wasm_module_inst_t module, uint32 ptr, uint32 size, + void **p_native_addr); +/* clang-format off */ #define get_module_inst(exec_env) \ wasm_runtime_get_module_inst(exec_env) @@ -55,6 +56,7 @@ wasm_runtime_module_realloc(wasm_module_inst_t module, uint32 ptr, #define module_free(offset) \ wasm_runtime_module_free(module_inst, offset) +/* clang-format on */ typedef int (*out_func_t)(int c, void *ctx); @@ -66,15 +68,14 @@ enum pad_type { }; typedef char *_va_list; -#define _INTSIZEOF(n) \ - (((uint32)sizeof(n) + 3) & (uint32)~3) -#define _va_arg(ap, t) \ - (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))) +#define _INTSIZEOF(n) (((uint32)sizeof(n) + 3) & (uint32)~3) +#define _va_arg(ap, t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))) -#define CHECK_VA_ARG(ap, t) do { \ - if ((uint8*)ap + _INTSIZEOF(t) > native_end_addr) \ - goto fail; \ -} while (0) +#define CHECK_VA_ARG(ap, t) \ + do { \ + if ((uint8 *)ap + _INTSIZEOF(t) > native_end_addr) \ + goto fail; \ + } while (0) /** * @brief Output an unsigned int in hex format @@ -86,10 +87,8 @@ typedef char *_va_list; * @return N/A */ static void -_printf_hex_uint(out_func_t out, void *ctx, - const uint64 num, bool is_u64, - enum pad_type padding, - int min_width) +_printf_hex_uint(out_func_t out, void *ctx, const uint64 num, bool is_u64, + enum pad_type padding, int min_width) { int shift = sizeof(num) * 8; int found_largest_digit = 0; @@ -97,14 +96,14 @@ _printf_hex_uint(out_func_t out, void *ctx, int digits = 0; char nibble; - while (shift >= 4) { - shift -= 4; - nibble = (num >> shift) & 0xf; + while (shift >= 4) { + shift -= 4; + nibble = (num >> shift) & 0xf; if (nibble || found_largest_digit || shift == 0) { found_largest_digit = 1; nibble = (char)(nibble + (nibble > 9 ? 87 : 48)); - out((int) nibble, ctx); + out((int)nibble, ctx); digits++; continue; } @@ -112,7 +111,8 @@ _printf_hex_uint(out_func_t out, void *ctx, if (remaining-- <= min_width) { if (padding == PAD_ZERO_BEFORE) { out('0', ctx); - } else if (padding == PAD_SPACE_BEFORE) { + } + else if (padding == PAD_SPACE_BEFORE) { out(' ', ctx); } } @@ -136,10 +136,8 @@ _printf_hex_uint(out_func_t out, void *ctx, * @return N/A */ static void -_printf_dec_uint(out_func_t out, void *ctx, - const uint32 num, - enum pad_type padding, - int min_width) +_printf_dec_uint(out_func_t out, void *ctx, const uint32 num, + enum pad_type padding, int min_width) { uint32 pos = 999999999; uint32 remainder = num; @@ -155,17 +153,18 @@ _printf_dec_uint(out_func_t out, void *ctx, while (pos >= 9) { if (found_largest_digit || remainder > pos) { found_largest_digit = 1; - out((int) ((remainder / (pos + 1)) + 48), ctx); + out((int)((remainder / (pos + 1)) + 48), ctx); digits++; - } else if (remaining <= min_width && padding < PAD_SPACE_AFTER) { - out((int) (padding == PAD_ZERO_BEFORE ? '0' : ' '), ctx); + } + else if (remaining <= min_width && padding < PAD_SPACE_AFTER) { + out((int)(padding == PAD_ZERO_BEFORE ? '0' : ' '), ctx); digits++; } remaining--; remainder %= (pos + 1); pos /= 10; } - out((int) (remainder + 48), ctx); + out((int)(remainder + 48), ctx); if (padding == PAD_SPACE_AFTER) { remaining = min_width - digits; @@ -193,8 +192,8 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, int long_ctr = 0; uint8 *native_end_addr; - if (!wasm_runtime_get_native_addr_range(module_inst, (uint8*)ap, - NULL, &native_end_addr)) + if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)ap, NULL, + &native_end_addr)) goto fail; /* fmt has already been adjusted if needed */ @@ -202,7 +201,7 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, while (*fmt) { if (!might_format) { if (*fmt != '%') { - out((int) *fmt, ctx); + out((int)*fmt, ctx); } else { might_format = 1; @@ -213,179 +212,188 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, } else { switch (*fmt) { - case '-': - padding = PAD_SPACE_AFTER; - goto still_might_format; - - case '0': - if (min_width < 0 && padding == PAD_NONE) { - padding = PAD_ZERO_BEFORE; + case '-': + padding = PAD_SPACE_AFTER; goto still_might_format; - } - goto handle_1_to_9; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': -handle_1_to_9: - if (min_width < 0) { - min_width = *fmt - '0'; - } else { - min_width = 10 * min_width + *fmt - '0'; - } - if (padding == PAD_NONE) { - padding = PAD_SPACE_BEFORE; - } - goto still_might_format; + case '0': + if (min_width < 0 && padding == PAD_NONE) { + padding = PAD_ZERO_BEFORE; + goto still_might_format; + } + goto handle_1_to_9; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + handle_1_to_9: + if (min_width < 0) { + min_width = *fmt - '0'; + } + else { + min_width = 10 * min_width + *fmt - '0'; + } - case 'l': - long_ctr++; - /* Fall through */ - case 'z': - case 'h': - /* FIXME: do nothing for these modifiers */ - goto still_might_format; + if (padding == PAD_NONE) { + padding = PAD_SPACE_BEFORE; + } + goto still_might_format; - case 'd': - case 'i': { - int32 d; + case 'l': + long_ctr++; + /* Fall through */ + case 'z': + case 'h': + /* FIXME: do nothing for these modifiers */ + goto still_might_format; - if (long_ctr < 2) { - CHECK_VA_ARG(ap, int32); - d = _va_arg(ap, int32); - } - else { - int64 lld; - CHECK_VA_ARG(ap, int64); - lld = _va_arg(ap, int64); - if (lld > INT32_MAX || lld < INT32_MIN) { - print_err(out, ctx); - break; + case 'd': + case 'i': + { + int32 d; + + if (long_ctr < 2) { + CHECK_VA_ARG(ap, int32); + d = _va_arg(ap, int32); + } + else { + int64 lld; + CHECK_VA_ARG(ap, int64); + lld = _va_arg(ap, int64); + if (lld > INT32_MAX || lld < INT32_MIN) { + print_err(out, ctx); + break; + } + d = (int32)lld; } - d = (int32)lld; - } - if (d < 0) { - out((int)'-', ctx); - d = -d; - min_width--; + if (d < 0) { + out((int)'-', ctx); + d = -d; + min_width--; + } + _printf_dec_uint(out, ctx, (uint32)d, padding, min_width); + break; } - _printf_dec_uint(out, ctx, (uint32)d, padding, min_width); - break; - } - case 'u': { - uint32 u; + case 'u': + { + uint32 u; - if (long_ctr < 2) { - CHECK_VA_ARG(ap, uint32); - u = _va_arg(ap, uint32); - } - else { - uint64 llu; - CHECK_VA_ARG(ap, uint64); - llu = _va_arg(ap, uint64); - if (llu > INT32_MAX) { - print_err(out, ctx); - break; + if (long_ctr < 2) { + CHECK_VA_ARG(ap, uint32); + u = _va_arg(ap, uint32); } - u = (uint32)llu; + else { + uint64 llu; + CHECK_VA_ARG(ap, uint64); + llu = _va_arg(ap, uint64); + if (llu > INT32_MAX) { + print_err(out, ctx); + break; + } + u = (uint32)llu; + } + _printf_dec_uint(out, ctx, u, padding, min_width); + break; } - _printf_dec_uint(out, ctx, u, padding, min_width); - break; - } - case 'p': - out('0', ctx); - out('x', ctx); - /* left-pad pointers with zeros */ - padding = PAD_ZERO_BEFORE; - min_width = 8; - /* Fall through */ - case 'x': - case 'X': { - uint64 x; - bool is_ptr = (*fmt == 'p') ? true : false; - - if (long_ctr < 2) { - CHECK_VA_ARG(ap, uint32); - x = _va_arg(ap, uint32); - } else { - CHECK_VA_ARG(ap, uint64); - x = _va_arg(ap, uint64); + case 'p': + out('0', ctx); + out('x', ctx); + /* left-pad pointers with zeros */ + padding = PAD_ZERO_BEFORE; + min_width = 8; + /* Fall through */ + case 'x': + case 'X': + { + uint64 x; + bool is_ptr = (*fmt == 'p') ? true : false; + + if (long_ctr < 2) { + CHECK_VA_ARG(ap, uint32); + x = _va_arg(ap, uint32); + } + else { + CHECK_VA_ARG(ap, uint64); + x = _va_arg(ap, uint64); + } + _printf_hex_uint(out, ctx, x, !is_ptr, padding, min_width); + break; } - _printf_hex_uint(out, ctx, x, !is_ptr, padding, min_width); - break; - } - case 's': { - char *s; - char *start; - uint32 s_offset; + case 's': + { + char *s; + char *start; + uint32 s_offset; - CHECK_VA_ARG(ap, int32); - s_offset = _va_arg(ap, uint32); + CHECK_VA_ARG(ap, int32); + s_offset = _va_arg(ap, uint32); - if (!validate_app_str_addr(s_offset)) { - return false; - } + if (!validate_app_str_addr(s_offset)) { + return false; + } - s = start = addr_app_to_native(s_offset); + s = start = addr_app_to_native(s_offset); - while (*s) - out((int) (*s++), ctx); + while (*s) + out((int)(*s++), ctx); - if (padding == PAD_SPACE_AFTER) { - int remaining = min_width - (int32)(s - start); - while (remaining-- > 0) { - out(' ', ctx); + if (padding == PAD_SPACE_AFTER) { + int remaining = min_width - (int32)(s - start); + while (remaining-- > 0) { + out(' ', ctx); + } } + break; } - break; - } - case 'c': { - int c; - CHECK_VA_ARG(ap, int); - c = _va_arg(ap, int); - out(c, ctx); - break; - } + case 'c': + { + int c; + CHECK_VA_ARG(ap, int); + c = _va_arg(ap, int); + out(c, ctx); + break; + } - case '%': { - out((int) '%', ctx); - break; - } + case '%': + { + out((int)'%', ctx); + break; + } - case 'f': { - float64 f64; - char buf[16], *s; - - /* Make 8-byte aligned */ - ap = (_va_list)(((uintptr_t)ap + 7) & ~(uintptr_t)7); - CHECK_VA_ARG(ap, float64); - f64 = _va_arg(ap, float64); - snprintf(buf, sizeof(buf), "%f", f64); - s = buf; - while (*s) - out((int) (*s++), ctx); - break; - } + case 'f': + { + float64 f64; + char buf[16], *s; + + /* Make 8-byte aligned */ + ap = (_va_list)(((uintptr_t)ap + 7) & ~(uintptr_t)7); + CHECK_VA_ARG(ap, float64); + f64 = _va_arg(ap, float64); + snprintf(buf, sizeof(buf), "%f", f64); + s = buf; + while (*s) + out((int)(*s++), ctx); + break; + } - default: - out((int) '%', ctx); - out((int) *fmt, ctx); - break; + default: + out((int)'%', ctx); + out((int)*fmt, ctx); + break; } might_format = 0; } -still_might_format: + still_might_format: ++fmt; } return true; @@ -411,7 +419,8 @@ sprintf_out(int c, struct str_context *ctx) if (ctx->count == ctx->max - 1) { ctx->str[ctx->count++] = '\0'; - } else { + } + else { ctx->str[ctx->count++] = (char)c; } @@ -453,8 +462,7 @@ printf_out(int c, struct str_context *ctx) #endif static int -printf_wrapper(wasm_exec_env_t exec_env, - const char * format, _va_list va_args) +printf_wrapper(wasm_exec_env_t exec_env, const char *format, _va_list va_args) { wasm_module_inst_t module_inst = get_module_inst(exec_env); struct str_context ctx = { NULL, 0, 0 }; @@ -463,15 +471,16 @@ printf_wrapper(wasm_exec_env_t exec_env, if (!validate_native_addr(va_args, sizeof(int32))) return 0; - if (!_vprintf_wa((out_func_t)printf_out, &ctx, format, va_args, module_inst)) + if (!_vprintf_wa((out_func_t)printf_out, &ctx, format, va_args, + module_inst)) return 0; return (int)ctx.count; } static int -sprintf_wrapper(wasm_exec_env_t exec_env, - char *str, const char *format, _va_list va_args) +sprintf_wrapper(wasm_exec_env_t exec_env, char *str, const char *format, + _va_list va_args) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint8 *native_end_offset; @@ -481,17 +490,18 @@ sprintf_wrapper(wasm_exec_env_t exec_env, if (!validate_native_addr(va_args, sizeof(uint32))) return 0; - if (!wasm_runtime_get_native_addr_range(module_inst, (uint8*)str, - NULL, &native_end_offset)) { + if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)str, NULL, + &native_end_offset)) { wasm_runtime_set_exception(module_inst, "out of bounds memory access"); return false; } ctx.str = str; - ctx.max = (uint32)(native_end_offset - (uint8*)str); + ctx.max = (uint32)(native_end_offset - (uint8 *)str); ctx.count = 0; - if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args, module_inst)) + if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args, + module_inst)) return 0; if (ctx.count < ctx.max) { @@ -516,7 +526,8 @@ snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size, ctx.max = size; ctx.count = 0; - if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args, module_inst)) + if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args, + module_inst)) return 0; if (ctx.count < ctx.max) { @@ -551,7 +562,7 @@ strdup_wrapper(wasm_exec_env_t exec_env, const char *str) if (str) { len = (uint32)strlen(str) + 1; - str_ret_offset = module_malloc(len, (void**)&str_ret); + str_ret_offset = module_malloc(len, (void **)&str_ret); if (str_ret_offset) { bh_memcpy_s(str_ret, len, str, len); } @@ -567,21 +578,21 @@ _strdup_wrapper(wasm_exec_env_t exec_env, const char *str) } static int32 -memcmp_wrapper(wasm_exec_env_t exec_env, - const void *s1, const void *s2, uint32 size) +memcmp_wrapper(wasm_exec_env_t exec_env, const void *s1, const void *s2, + uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); /* s2 has been checked by runtime */ - if (!validate_native_addr((void*)s1, size)) + if (!validate_native_addr((void *)s1, size)) return 0; return memcmp(s1, s2, size); } static uint32 -memcpy_wrapper(wasm_exec_env_t exec_env, - void *dst, const void *src, uint32 size) +memcpy_wrapper(wasm_exec_env_t exec_env, void *dst, const void *src, + uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 dst_offset = addr_native_to_app(dst); @@ -598,8 +609,7 @@ memcpy_wrapper(wasm_exec_env_t exec_env, } static uint32 -memmove_wrapper(wasm_exec_env_t exec_env, - void *dst, void *src, uint32 size) +memmove_wrapper(wasm_exec_env_t exec_env, void *dst, void *src, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 dst_offset = addr_native_to_app(dst); @@ -616,8 +626,7 @@ memmove_wrapper(wasm_exec_env_t exec_env, } static uint32 -memset_wrapper(wasm_exec_env_t exec_env, - void *s, int32 c, uint32 size) +memset_wrapper(wasm_exec_env_t exec_env, void *s, int32 c, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 s_offset = addr_native_to_app(s); @@ -630,8 +639,7 @@ memset_wrapper(wasm_exec_env_t exec_env, } static uint32 -strchr_wrapper(wasm_exec_env_t exec_env, - const char *s, int32 c) +strchr_wrapper(wasm_exec_env_t exec_env, const char *s, int32 c) { wasm_module_inst_t module_inst = get_module_inst(exec_env); char *ret; @@ -642,21 +650,20 @@ strchr_wrapper(wasm_exec_env_t exec_env, } static int32 -strcmp_wrapper(wasm_exec_env_t exec_env, - const char *s1, const char *s2) +strcmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2) { /* s1 and s2 have been checked by runtime */ return strcmp(s1, s2); } static int32 -strncmp_wrapper(wasm_exec_env_t exec_env, - const char *s1, const char *s2, uint32 size) +strncmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2, + uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); /* s2 has been checked by runtime */ - if (!validate_native_addr((void*)s1, size)) + if (!validate_native_addr((void *)s1, size)) return 0; return strncmp(s1, s2, size); @@ -681,8 +688,8 @@ strcpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src) } static uint32 -strncpy_wrapper(wasm_exec_env_t exec_env, - char *dst, const char *src, uint32 size) +strncpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src, + uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -716,14 +723,14 @@ static uint32 calloc_wrapper(wasm_exec_env_t exec_env, uint32 nmemb, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); - uint64 total_size = (uint64) nmemb * (uint64) size; + uint64 total_size = (uint64)nmemb * (uint64)size; uint32 ret_offset = 0; uint8 *ret_ptr; if (total_size >= UINT32_MAX) return 0; - ret_offset = module_malloc((uint32)total_size, (void**)&ret_ptr); + ret_offset = module_malloc((uint32)total_size, (void **)&ret_ptr); if (ret_offset) { memset(ret_ptr, 0, (uint32)total_size); } @@ -767,8 +774,8 @@ exit_wrapper(wasm_exec_env_t exec_env, int32 status) } static int32 -strtol_wrapper(wasm_exec_env_t exec_env, - const char *nptr, char **endptr, int32 base) +strtol_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr, + int32 base) { wasm_module_inst_t module_inst = get_module_inst(exec_env); int32 num = 0; @@ -778,14 +785,14 @@ strtol_wrapper(wasm_exec_env_t exec_env, return 0; num = (int32)strtol(nptr, endptr, base); - *(uint32*)endptr = addr_native_to_app(*endptr); + *(uint32 *)endptr = addr_native_to_app(*endptr); return num; } static uint32 -strtoul_wrapper(wasm_exec_env_t exec_env, - const char *nptr, char **endptr, int32 base) +strtoul_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr, + int32 base) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 num = 0; @@ -801,13 +808,12 @@ strtoul_wrapper(wasm_exec_env_t exec_env, } static uint32 -memchr_wrapper(wasm_exec_env_t exec_env, - const void *s, int32 c, uint32 n) +memchr_wrapper(wasm_exec_env_t exec_env, const void *s, int32 c, uint32 n) { wasm_module_inst_t module_inst = get_module_inst(exec_env); void *res; - if (!validate_native_addr((void*)s, n)) + if (!validate_native_addr((void *)s, n)) return 0; res = memchr(s, c, n); @@ -815,32 +821,29 @@ memchr_wrapper(wasm_exec_env_t exec_env, } static int32 -strncasecmp_wrapper(wasm_exec_env_t exec_env, - const char *s1, const char *s2, uint32 n) +strncasecmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2, + uint32 n) { /* s1 and s2 have been checked by runtime */ return strncasecmp(s1, s2, n); } static uint32 -strspn_wrapper(wasm_exec_env_t exec_env, - const char *s, const char *accept) +strspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *accept) { /* s and accept have been checked by runtime */ return (uint32)strspn(s, accept); } static uint32 -strcspn_wrapper(wasm_exec_env_t exec_env, - const char *s, const char *reject) +strcspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *reject) { /* s and reject have been checked by runtime */ return (uint32)strcspn(s, reject); } static uint32 -strstr_wrapper(wasm_exec_env_t exec_env, - const char *s, const char *find) +strstr_wrapper(wasm_exec_env_t exec_env, const char *s, const char *find) { wasm_module_inst_t module_inst = get_module_inst(exec_env); /* s and find have been checked by runtime */ @@ -925,24 +928,19 @@ getTempRet0_wrapper(wasm_exec_env_t exec_env) static uint32 llvm_bswap_i16_wrapper(wasm_exec_env_t exec_env, uint32 data) { - return (data & 0xFFFF0000) - | ((data & 0xFF) << 8) - | ((data & 0xFF00) >> 8); + return (data & 0xFFFF0000) | ((data & 0xFF) << 8) | ((data & 0xFF00) >> 8); } static uint32 llvm_bswap_i32_wrapper(wasm_exec_env_t exec_env, uint32 data) { - return ((data & 0xFF) << 24) - | ((data & 0xFF00) << 8) - | ((data & 0xFF0000) >> 8) - | ((data & 0xFF000000) >> 24); + return ((data & 0xFF) << 24) | ((data & 0xFF00) << 8) + | ((data & 0xFF0000) >> 8) | ((data & 0xFF000000) >> 24); } static uint32 -bitshift64Lshr_wrapper(wasm_exec_env_t exec_env, - uint32 uint64_part0, uint32 uint64_part1, - uint32 bits) +bitshift64Lshr_wrapper(wasm_exec_env_t exec_env, uint32 uint64_part0, + uint32 uint64_part1, uint32 bits) { wasm_module_inst_t module_inst = get_module_inst(exec_env); union { @@ -955,14 +953,13 @@ bitshift64Lshr_wrapper(wasm_exec_env_t exec_env, u.value >>= bits; /* return low 32bit and save high 32bit to temp ret */ - wasm_runtime_set_temp_ret(module_inst, (uint32) (u.value >> 32)); - return (uint32) u.value; + wasm_runtime_set_temp_ret(module_inst, (uint32)(u.value >> 32)); + return (uint32)u.value; } static uint32 -bitshift64Shl_wrapper(wasm_exec_env_t exec_env, - uint32 int64_part0, uint32 int64_part1, - uint32 bits) +bitshift64Shl_wrapper(wasm_exec_env_t exec_env, uint32 int64_part0, + uint32 int64_part1, uint32 bits) { wasm_module_inst_t module_inst = get_module_inst(exec_env); union { @@ -975,8 +972,8 @@ bitshift64Shl_wrapper(wasm_exec_env_t exec_env, u.value <<= bits; /* return low 32bit and save high 32bit to temp ret */ - wasm_runtime_set_temp_ret(module_inst, (uint32) (u.value >> 32)); - return (uint32) u.value; + wasm_runtime_set_temp_ret(module_inst, (uint32)(u.value >> 32)); + return (uint32)u.value; } static void @@ -996,8 +993,8 @@ llvm_stacksave_wrapper(wasm_exec_env_t exec_env) } static uint32 -emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, - void *dst, const void *src, uint32 size) +emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, void *dst, + const void *src, uint32 size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 dst_offset = addr_native_to_app(dst); @@ -1038,8 +1035,7 @@ nullFunc_X_wrapper(wasm_exec_env_t exec_env, int32 code) } static uint32 -__cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, - uint32 thrown_size) +__cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, uint32 thrown_size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 exception = module_malloc(thrown_size, NULL); @@ -1050,16 +1046,12 @@ __cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, } static void -__cxa_begin_catch_wrapper(wasm_exec_env_t exec_env, - void *exception_object) -{ -} +__cxa_begin_catch_wrapper(wasm_exec_env_t exec_env, void *exception_object) +{} static void -__cxa_throw_wrapper(wasm_exec_env_t exec_env, - void *thrown_exception, - void *tinfo, - uint32 table_elem_idx) +__cxa_throw_wrapper(wasm_exec_env_t exec_env, void *thrown_exception, + void *tinfo, uint32 table_elem_idx) { wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; @@ -1068,12 +1060,41 @@ __cxa_throw_wrapper(wasm_exec_env_t exec_env, wasm_runtime_set_exception(module_inst, buf); } +struct timespec_app { + int64 tv_sec; + int32 tv_nsec; +}; + +static uint32 +clock_gettime_wrapper(wasm_exec_env_t exec_env, uint32 clk_id, + struct timespec_app *ts_app) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + uint64 time; + + if (!validate_native_addr(ts_app, sizeof(struct timespec_app))) + return (uint32)-1; + + time = os_time_get_boot_microsecond(); + ts_app->tv_sec = time / 1000000; + ts_app->tv_nsec = (time % 1000000) * 1000; + + return (uint32)0; +} + +static uint64 +clock_wrapper(wasm_exec_env_t exec_env) +{ + /* Convert to nano seconds as CLOCKS_PER_SEC in wasi-sdk */ + + return os_time_get_boot_microsecond() * 1000; +} + #if WASM_ENABLE_SPEC_TEST != 0 static void print_wrapper(wasm_exec_env_t exec_env) { os_printf("in specttest.print()\n"); - } static void @@ -1107,8 +1128,10 @@ print_f64_wrapper(wasm_exec_env_t exec_env, double f64) } #endif /* WASM_ENABLE_SPEC_TEST */ -#define REG_NATIVE_FUNC(func_name, signature) \ - { #func_name, func_name##_wrapper, signature, NULL } +#define REG_NATIVE_FUNC(func_name, signature) \ + { \ +#func_name, func_name##_wrapper, signature, NULL \ + } static NativeSymbol native_symbols_libc_builtin[] = { REG_NATIVE_FUNC(printf, "($*)i"), @@ -1167,6 +1190,8 @@ static NativeSymbol native_symbols_libc_builtin[] = { REG_NATIVE_FUNC(__cxa_allocate_exception, "(i)i"), REG_NATIVE_FUNC(__cxa_begin_catch, "(*)"), REG_NATIVE_FUNC(__cxa_throw, "(**i)"), + REG_NATIVE_FUNC(clock_gettime, "(i*)i"), + REG_NATIVE_FUNC(clock, "()I"), }; #if WASM_ENABLE_SPEC_TEST != 0 @@ -1249,4 +1274,3 @@ wasm_native_lookup_libc_builtin_global(const char *module_name, return false; } - diff --git a/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c b/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c index 545bfe6a5b..e35f3908d1 100644 --- a/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c +++ b/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c @@ -11,6 +11,7 @@ #include "sys/syscall.h" #endif +/* clang-format off */ #define get_module_inst(exec_env) \ wasm_runtime_get_module_inst(exec_env) @@ -34,15 +35,15 @@ #define module_free(offset) \ wasm_runtime_module_free(module_inst, offset) +/* clang-format on */ extern bool -wasm_runtime_call_indirect(wasm_exec_env_t exec_env, - uint32 element_idx, +wasm_runtime_call_indirect(wasm_exec_env_t exec_env, uint32 element_idx, uint32 argc, uint32 argv[]); static void -invoke_viiii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, - int arg0, int arg1, int arg2, int arg3) +invoke_viiii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0, + int arg1, int arg2, int arg3) { uint32 argv[4]; bool ret; @@ -56,8 +57,8 @@ invoke_viiii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, } static void -invoke_viii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, - int arg0, int arg1, int arg2) +invoke_viii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0, + int arg1, int arg2) { uint32 argv[4]; bool ret; @@ -70,8 +71,8 @@ invoke_viii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, } static void -invoke_vii_wrapper(wasm_exec_env_t exec_env, - uint32 elem_idx, int arg0, int arg1) +invoke_vii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0, + int arg1) { uint32 argv[4]; bool ret; @@ -83,8 +84,7 @@ invoke_vii_wrapper(wasm_exec_env_t exec_env, } static void -invoke_vi_wrapper(wasm_exec_env_t exec_env, - uint32 elem_idx, int arg0) +invoke_vi_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0) { uint32 argv[4]; bool ret; @@ -95,8 +95,8 @@ invoke_vi_wrapper(wasm_exec_env_t exec_env, } static int -invoke_iii_wrapper(wasm_exec_env_t exec_env, - uint32 elem_idx, int arg0, int arg1) +invoke_iii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0, + int arg1) { uint32 argv[4]; bool ret; @@ -108,8 +108,7 @@ invoke_iii_wrapper(wasm_exec_env_t exec_env, } static int -invoke_ii_wrapper(wasm_exec_env_t exec_env, - uint32 elem_idx, int arg0) +invoke_ii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0) { uint32 argv[4]; bool ret; @@ -144,8 +143,8 @@ struct stat_emcc { }; static int -open_wrapper(wasm_exec_env_t exec_env, const char *pathname, - int flags, int mode) +open_wrapper(wasm_exec_env_t exec_env, const char *pathname, int flags, + int mode) { if (pathname == NULL) return -1; @@ -153,8 +152,7 @@ open_wrapper(wasm_exec_env_t exec_env, const char *pathname, } static int -__sys_read_wrapper(wasm_exec_env_t exec_env, - int fd, void *buf, uint32 count) +__sys_read_wrapper(wasm_exec_env_t exec_env, int fd, void *buf, uint32 count) { return read(fd, buf, count); } @@ -183,15 +181,14 @@ statbuf_native2app(const struct stat *statbuf_native, } static int -__sys_stat64_wrapper(wasm_exec_env_t exec_env, - const char *pathname, +__sys_stat64_wrapper(wasm_exec_env_t exec_env, const char *pathname, struct stat_emcc *statbuf_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); int ret; struct stat statbuf; - if (!validate_native_addr((void*)statbuf_app, sizeof(struct stat_emcc))) + if (!validate_native_addr((void *)statbuf_app, sizeof(struct stat_emcc))) return -1; if (pathname == NULL) @@ -204,14 +201,14 @@ __sys_stat64_wrapper(wasm_exec_env_t exec_env, } static int -__sys_fstat64_wrapper(wasm_exec_env_t exec_env, - int fd, struct stat_emcc *statbuf_app) +__sys_fstat64_wrapper(wasm_exec_env_t exec_env, int fd, + struct stat_emcc *statbuf_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); int ret; struct stat statbuf; - if (!validate_native_addr((void*)statbuf_app, sizeof(struct stat_emcc))) + if (!validate_native_addr((void *)statbuf_app, sizeof(struct stat_emcc))) return -1; if (fd <= 0) @@ -224,16 +221,15 @@ __sys_fstat64_wrapper(wasm_exec_env_t exec_env, } static int -mmap_wrapper(wasm_exec_env_t exec_env, - void *addr, int length, int prot, int flags, - int fd, int64 offset) +mmap_wrapper(wasm_exec_env_t exec_env, void *addr, int length, int prot, + int flags, int fd, int64 offset) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 buf_offset; char *buf; int size_read; - buf_offset = module_malloc(length, (void**)&buf); + buf_offset = module_malloc(length, (void **)&buf); if (buf_offset == 0) return -1; @@ -275,16 +271,14 @@ getentropy_wrapper(wasm_exec_env_t exec_env, void *buffer, uint32 length) } static int -setjmp_wrapper(wasm_exec_env_t exec_env, - void *jmp_buf) +setjmp_wrapper(wasm_exec_env_t exec_env, void *jmp_buf) { os_printf("setjmp() called\n"); return 0; } static void -longjmp_wrapper(wasm_exec_env_t exec_env, - void *jmp_buf, int val) +longjmp_wrapper(wasm_exec_env_t exec_env, void *jmp_buf, int val) { os_printf("longjmp() called\n"); } @@ -305,9 +299,7 @@ get_free_file_slot() } static int -fopen_wrapper(wasm_exec_env_t exec_env, - const char *pathname, - const char *mode) +fopen_wrapper(wasm_exec_env_t exec_env, const char *pathname, const char *mode) { FILE *file; int file_id; @@ -327,8 +319,8 @@ fopen_wrapper(wasm_exec_env_t exec_env, } static uint32 -fread_wrapper(wasm_exec_env_t exec_env, - void *ptr, uint32 size, uint32 nmemb, int file_id) +fread_wrapper(wasm_exec_env_t exec_env, void *ptr, uint32 size, uint32 nmemb, + int file_id) { FILE *file; @@ -343,8 +335,7 @@ fread_wrapper(wasm_exec_env_t exec_env, } static int -fseeko_wrapper(wasm_exec_env_t exec_env, - int file_id, int64 offset, int whence) +fseeko_wrapper(wasm_exec_env_t exec_env, int file_id, int64 offset, int whence) { FILE *file; @@ -359,9 +350,8 @@ fseeko_wrapper(wasm_exec_env_t exec_env, } static uint32 -emcc_fwrite_wrapper(wasm_exec_env_t exec_env, - const void *ptr, uint32 size, uint32 nmemb, - int file_id) +emcc_fwrite_wrapper(wasm_exec_env_t exec_env, const void *ptr, uint32 size, + uint32 nmemb, int file_id) { FILE *file; @@ -403,8 +393,7 @@ fclose_wrapper(wasm_exec_env_t exec_env, int file_id) } static int -__sys_mkdir_wrapper(wasm_exec_env_t exec_env, - const char *pathname, int mode) +__sys_mkdir_wrapper(wasm_exec_env_t exec_env, const char *pathname, int mode) { if (!pathname) return -1; @@ -522,8 +511,10 @@ emscripten_thread_sleep_wrapper(wasm_exec_env_t exec_env, double timeout_ms) #endif /* end of BH_PLATFORM_LINUX_SGX */ -#define REG_NATIVE_FUNC(func_name, signature) \ +/* clang-format off */ +#define REG_NATIVE_FUNC(func_name, signature) \ { #func_name, func_name##_wrapper, signature, NULL } +/* clang-format off */ static NativeSymbol native_symbols_libc_emcc[] = { REG_NATIVE_FUNC(invoke_viiii, "(iiiii)"), diff --git a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c index af6e0de3db..e292984e7d 100644 --- a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c +++ b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c @@ -7,6 +7,7 @@ #include "bh_platform.h" #include "wasm_export.h" +/* clang-format off */ #define get_module_inst(exec_env) \ wasm_runtime_get_module_inst(exec_env) @@ -30,6 +31,7 @@ #define module_free(offset) \ wasm_runtime_module_free(module_inst, offset) +/* clang-format on */ #define wasi_errno_t uvwasi_errno_t #define wasi_fd_t uvwasi_fd_t @@ -117,8 +119,8 @@ wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf) } static wasi_errno_t -wasi_args_sizes_get(wasm_exec_env_t exec_env, - uint32 *argc_app, uint32 *argv_buf_size_app) +wasi_args_sizes_get(wasm_exec_env_t exec_env, uint32 *argc_app, + uint32 *argv_buf_size_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -132,7 +134,6 @@ wasi_args_sizes_get(wasm_exec_env_t exec_env, || !validate_native_addr(argv_buf_size_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = uvwasi_args_sizes_get(uvwasi, &argc, &argv_buf_size); if (err) return err; @@ -143,8 +144,7 @@ wasi_args_sizes_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_clock_res_get(wasm_exec_env_t exec_env, - wasi_clockid_t clock_id, +wasi_clock_res_get(wasm_exec_env_t exec_env, wasi_clockid_t clock_id, wasi_timestamp_t *resolution) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -157,10 +157,8 @@ wasi_clock_res_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_clock_time_get(wasm_exec_env_t exec_env, - wasi_clockid_t clock_id, - wasi_timestamp_t precision, - wasi_timestamp_t *time) +wasi_clock_time_get(wasm_exec_env_t exec_env, wasi_clockid_t clock_id, + wasi_timestamp_t precision, wasi_timestamp_t *time) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -172,8 +170,8 @@ wasi_clock_time_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_environ_get(wasm_exec_env_t exec_env, - uint32 *environ_offsets, char *environ_buf) +wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets, + char *environ_buf) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -217,8 +215,8 @@ wasi_environ_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_environ_sizes_get(wasm_exec_env_t exec_env, - uint32 *environ_count_app, uint32 *environ_buf_size_app) +wasi_environ_sizes_get(wasm_exec_env_t exec_env, uint32 *environ_count_app, + uint32 *environ_buf_size_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -242,8 +240,8 @@ wasi_environ_sizes_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_prestat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_prestat_app_t *prestat_app) +wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_prestat_app_t *prestat_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -266,8 +264,8 @@ wasi_fd_prestat_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, - wasi_fd_t fd, char *path, uint32 path_len) +wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, wasi_fd_t fd, char *path, + uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -303,9 +301,8 @@ wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd) } static wasi_errno_t -wasi_fd_pread(wasm_exec_env_t exec_env, - wasi_fd_t fd, iovec_app_t *iovec_app, uint32 iovs_len, - wasi_filesize_t offset, uint32 *nread_app) +wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app, + uint32 iovs_len, wasi_filesize_t offset, uint32 *nread_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -335,12 +332,11 @@ wasi_fd_pread(wasm_exec_env_t exec_env, err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void*)addr_app_to_native(iovec_app->buf_offset); + iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset); iovec->buf_len = iovec_app->buf_len; } - err = uvwasi_fd_pread(uvwasi, fd, iovec_begin, - iovs_len, offset, &nread); + err = uvwasi_fd_pread(uvwasi, fd, iovec_begin, iovs_len, offset, &nread); if (err) goto fail; @@ -355,8 +351,8 @@ wasi_fd_pread(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_pwrite(wasm_exec_env_t exec_env, - wasi_fd_t fd, const iovec_app_t *iovec_app, uint32 iovs_len, +wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, + const iovec_app_t *iovec_app, uint32 iovs_len, wasi_filesize_t offset, uint32 *nwritten_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -373,7 +369,7 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, total_size = sizeof(iovec_app_t) * (uint64)iovs_len; if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void*)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, (uint32)total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; @@ -387,12 +383,12 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char*)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset); ciovec->buf_len = iovec_app->buf_len; } - err = uvwasi_fd_pwrite(uvwasi, fd, ciovec_begin, - iovs_len, offset, &nwritten); + err = + uvwasi_fd_pwrite(uvwasi, fd, ciovec_begin, iovs_len, offset, &nwritten); if (err) goto fail; @@ -407,9 +403,8 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_read(wasm_exec_env_t exec_env, - wasi_fd_t fd, const iovec_app_t *iovec_app, uint32 iovs_len, - uint32 *nread_app) +wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, + const iovec_app_t *iovec_app, uint32 iovs_len, uint32 *nread_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -425,7 +420,7 @@ wasi_fd_read(wasm_exec_env_t exec_env, total_size = sizeof(iovec_app_t) * (uint64)iovs_len; if (!validate_native_addr(nread_app, (uint32)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void*)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, (uint32)total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; @@ -439,12 +434,11 @@ wasi_fd_read(wasm_exec_env_t exec_env, err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void*)addr_app_to_native(iovec_app->buf_offset); + iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset); iovec->buf_len = iovec_app->buf_len; } - err = uvwasi_fd_read(uvwasi, fd, - iovec_begin, iovs_len, &nread); + err = uvwasi_fd_read(uvwasi, fd, iovec_begin, iovs_len, &nread); if (err) goto fail; @@ -471,9 +465,8 @@ wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to) } static wasi_errno_t -wasi_fd_seek(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_filedelta_t offset, wasi_whence_t whence, - wasi_filesize_t *newoffset) +wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset, + wasi_whence_t whence, wasi_filesize_t *newoffset) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -488,8 +481,7 @@ wasi_fd_seek(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_tell(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_filesize_t *newoffset) +wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -504,8 +496,8 @@ wasi_fd_tell(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_fdstat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_fdstat_t *fdstat_app) +wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_fdstat_t *fdstat_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -527,8 +519,8 @@ wasi_fd_fdstat_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_fdflags_t flags) +wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_fdflags_t flags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -540,8 +532,7 @@ wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, - wasi_fd_t fd, +wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_rights_t fs_rights_base, wasi_rights_t fs_rights_inheriting) { @@ -551,8 +542,8 @@ wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, if (!uvwasi) return (wasi_errno_t)-1; - return uvwasi_fd_fdstat_set_rights(uvwasi, fd, - fs_rights_base, fs_rights_inheriting); + return uvwasi_fd_fdstat_set_rights(uvwasi, fd, fs_rights_base, + fs_rights_inheriting); } static wasi_errno_t @@ -586,7 +577,7 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, total_size = sizeof(iovec_app_t) * (uint64)iovs_len; if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void*)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, (uint32)total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; @@ -600,7 +591,7 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char*)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset); ciovec->buf_len = iovec_app->buf_len; } @@ -643,11 +634,8 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, } static wasi_errno_t -wasi_fd_advise(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_filesize_t offset, - wasi_filesize_t len, - wasi_advice_t advice) +wasi_fd_advise(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, + wasi_filesize_t len, wasi_advice_t advice) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -659,9 +647,7 @@ wasi_fd_advise(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_allocate(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_filesize_t offset, +wasi_fd_allocate(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, wasi_filesize_t len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -674,8 +660,8 @@ wasi_fd_allocate(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_create_directory(wasm_exec_env_t exec_env, - wasi_fd_t fd, const char *path, uint32 path_len) +wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, + const char *path, uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -687,12 +673,10 @@ wasi_path_create_directory(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_link(wasm_exec_env_t exec_env, - wasi_fd_t old_fd, - wasi_lookupflags_t old_flags, - const char *old_path, uint32 old_path_len, - wasi_fd_t new_fd, - const char *new_path, uint32 new_path_len) +wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd, + wasi_lookupflags_t old_flags, const char *old_path, + uint32 old_path_len, wasi_fd_t new_fd, const char *new_path, + uint32 new_path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -700,20 +684,15 @@ wasi_path_link(wasm_exec_env_t exec_env, if (!uvwasi) return (wasi_errno_t)-1; - return uvwasi_path_link(uvwasi, - old_fd, old_flags, old_path, old_path_len, + return uvwasi_path_link(uvwasi, old_fd, old_flags, old_path, old_path_len, new_fd, new_path, new_path_len); } static wasi_errno_t -wasi_path_open(wasm_exec_env_t exec_env, - wasi_fd_t dirfd, - wasi_lookupflags_t dirflags, - const char *path, uint32 path_len, - wasi_oflags_t oflags, - wasi_rights_t fs_rights_base, - wasi_rights_t fs_rights_inheriting, - wasi_fdflags_t fs_flags, +wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd, + wasi_lookupflags_t dirflags, const char *path, uint32 path_len, + wasi_oflags_t oflags, wasi_rights_t fs_rights_base, + wasi_rights_t fs_rights_inheriting, wasi_fdflags_t fs_flags, wasi_fd_t *fd_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -727,25 +706,16 @@ wasi_path_open(wasm_exec_env_t exec_env, if (!validate_native_addr(fd_app, sizeof(wasi_fd_t))) return (wasi_errno_t)-1; - err = uvwasi_path_open(uvwasi, - dirfd, dirflags, - path, path_len, - oflags, - fs_rights_base, - fs_rights_inheriting, - fs_flags, - &fd); + err = uvwasi_path_open(uvwasi, dirfd, dirflags, path, path_len, oflags, + fs_rights_base, fs_rights_inheriting, fs_flags, &fd); *fd_app = fd; return err; } static wasi_errno_t -wasi_fd_readdir(wasm_exec_env_t exec_env, - wasi_fd_t fd, - void *buf, uint32 buf_len, - wasi_dircookie_t cookie, - uint32 *bufused_app) +wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf, + uint32 buf_len, wasi_dircookie_t cookie, uint32 *bufused_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -758,8 +728,7 @@ wasi_fd_readdir(wasm_exec_env_t exec_env, if (!validate_native_addr(bufused_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = uvwasi_fd_readdir(uvwasi, fd, - buf, buf_len, cookie, &bufused); + err = uvwasi_fd_readdir(uvwasi, fd, buf, buf_len, cookie, &bufused); if (err) return err; @@ -768,10 +737,8 @@ wasi_fd_readdir(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_readlink(wasm_exec_env_t exec_env, - wasi_fd_t fd, - const char *path, uint32 path_len, - char *buf, uint32 buf_len, +wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, + uint32 path_len, char *buf, uint32 buf_len, uint32 *bufused_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -785,9 +752,8 @@ wasi_path_readlink(wasm_exec_env_t exec_env, if (!validate_native_addr(bufused_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = uvwasi_path_readlink(uvwasi, fd, - path, path_len, - buf, buf_len, &bufused); + err = uvwasi_path_readlink(uvwasi, fd, path, path_len, buf, buf_len, + &bufused); if (err) return err; @@ -796,9 +762,9 @@ wasi_path_readlink(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_rename(wasm_exec_env_t exec_env, - wasi_fd_t old_fd, const char *old_path, uint32 old_path_len, - wasi_fd_t new_fd, const char *new_path, uint32 new_path_len) +wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd, + const char *old_path, uint32 old_path_len, wasi_fd_t new_fd, + const char *new_path, uint32 new_path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -806,14 +772,13 @@ wasi_path_rename(wasm_exec_env_t exec_env, if (!uvwasi) return (wasi_errno_t)-1; - return uvwasi_path_rename(uvwasi, - old_fd, old_path, old_path_len, - new_fd, new_path, new_path_len); + return uvwasi_path_rename(uvwasi, old_fd, old_path, old_path_len, new_fd, + new_path, new_path_len); } static wasi_errno_t -wasi_fd_filestat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_filestat_t *filestat) +wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_filestat_t *filestat) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -828,10 +793,8 @@ wasi_fd_filestat_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_timestamp_t st_atim, - wasi_timestamp_t st_mtim, +wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_timestamp_t st_atim, wasi_timestamp_t st_mtim, wasi_fstflags_t fstflags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -840,13 +803,11 @@ wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, if (!uvwasi) return (wasi_errno_t)-1; - return uvwasi_fd_filestat_set_times(uvwasi, fd, - st_atim, st_mtim, fstflags); + return uvwasi_fd_filestat_set_times(uvwasi, fd, st_atim, st_mtim, fstflags); } static wasi_errno_t -wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, - wasi_fd_t fd, +wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t st_size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -859,11 +820,9 @@ wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_filestat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_lookupflags_t flags, - const char *path, uint32 path_len, - wasi_filestat_t *filestat) +wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_lookupflags_t flags, const char *path, + uint32 path_len, wasi_filestat_t *filestat) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -874,18 +833,15 @@ wasi_path_filestat_get(wasm_exec_env_t exec_env, if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; - return uvwasi_path_filestat_get(uvwasi, fd, - flags, path, path_len, filestat); + return uvwasi_path_filestat_get(uvwasi, fd, flags, path, path_len, + filestat); } static wasi_errno_t -wasi_path_filestat_set_times(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_lookupflags_t flags, - const char *path, uint32 path_len, - wasi_timestamp_t st_atim, - wasi_timestamp_t st_mtim, - wasi_fstflags_t fstflags) +wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_lookupflags_t flags, const char *path, + uint32 path_len, wasi_timestamp_t st_atim, + wasi_timestamp_t st_mtim, wasi_fstflags_t fstflags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -893,15 +849,14 @@ wasi_path_filestat_set_times(wasm_exec_env_t exec_env, if (!uvwasi) return (wasi_errno_t)-1; - return uvwasi_path_filestat_set_times(uvwasi, fd, - flags, path, path_len, + return uvwasi_path_filestat_set_times(uvwasi, fd, flags, path, path_len, st_atim, st_mtim, fstflags); } static wasi_errno_t -wasi_path_symlink(wasm_exec_env_t exec_env, - const char *old_path, uint32 old_path_len, - wasi_fd_t fd, const char *new_path, uint32 new_path_len) +wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path, + uint32 old_path_len, wasi_fd_t fd, const char *new_path, + uint32 new_path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -909,14 +864,13 @@ wasi_path_symlink(wasm_exec_env_t exec_env, if (!uvwasi) return (wasi_errno_t)-1; - return uvwasi_path_symlink(uvwasi, - old_path, old_path_len, fd, - new_path, new_path_len); + return uvwasi_path_symlink(uvwasi, old_path, old_path_len, fd, new_path, + new_path_len); } static wasi_errno_t -wasi_path_unlink_file(wasm_exec_env_t exec_env, - wasi_fd_t fd, const char *path, uint32 path_len) +wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, + uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -928,8 +882,8 @@ wasi_path_unlink_file(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_remove_directory(wasm_exec_env_t exec_env, - wasi_fd_t fd, const char *path, uint32 path_len) +wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, + const char *path, uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -941,9 +895,8 @@ wasi_path_remove_directory(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_poll_oneoff(wasm_exec_env_t exec_env, - const wasi_subscription_t *in, wasi_event_t *out, - uint32 nsubscriptions, uint32 *nevents_app) +wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, + wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -953,13 +906,12 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, if (!uvwasi) return (wasi_errno_t)-1; - if (!validate_native_addr((void*)in, sizeof(wasi_subscription_t)) + if (!validate_native_addr((void *)in, sizeof(wasi_subscription_t)) || !validate_native_addr(out, sizeof(wasi_event_t)) || !validate_native_addr(nevents_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = uvwasi_poll_oneoff(uvwasi, in, out, - nsubscriptions, &nevents); + err = uvwasi_poll_oneoff(uvwasi, in, out, nsubscriptions, &nevents); if (err) return err; @@ -997,12 +949,9 @@ wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len) } static wasi_errno_t -wasi_sock_recv(wasm_exec_env_t exec_env, - wasi_fd_t sock, - iovec_app_t *ri_data, uint32 ri_data_len, - wasi_riflags_t ri_flags, - uint32 *ro_datalen_app, - wasi_roflags_t *ro_flags) +wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data, + uint32 ri_data_len, wasi_riflags_t ri_flags, + uint32 *ro_datalen_app, wasi_roflags_t *ro_flags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -1033,18 +982,16 @@ wasi_sock_recv(wasm_exec_env_t exec_env, err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void*)addr_app_to_native(ri_data->buf_offset); + iovec->buf = (void *)addr_app_to_native(ri_data->buf_offset); iovec->buf_len = ri_data->buf_len; } - err = uvwasi_sock_recv(uvwasi, sock, - iovec_begin, ri_data_len, - ri_flags, &ro_datalen, - ro_flags); + err = uvwasi_sock_recv(uvwasi, sock, iovec_begin, ri_data_len, ri_flags, + &ro_datalen, ro_flags); if (err) goto fail; - *(uint32*)ro_datalen_app = (uint32)ro_datalen; + *(uint32 *)ro_datalen_app = (uint32)ro_datalen; /* success */ err = 0; @@ -1055,11 +1002,9 @@ wasi_sock_recv(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_sock_send(wasm_exec_env_t exec_env, - wasi_fd_t sock, +wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, const iovec_app_t *si_data, uint32 si_data_len, - wasi_siflags_t si_flags, - uint32 *so_datalen_app) + wasi_siflags_t si_flags, uint32 *so_datalen_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -1075,7 +1020,7 @@ wasi_sock_send(wasm_exec_env_t exec_env, total_size = sizeof(iovec_app_t) * (uint64)si_data_len; if (!validate_native_addr(so_datalen_app, sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void*)si_data, (uint32)total_size)) + || !validate_native_addr((void *)si_data, (uint32)total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)si_data_len; @@ -1089,13 +1034,12 @@ wasi_sock_send(wasm_exec_env_t exec_env, err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char*)addr_app_to_native(si_data->buf_offset); + ciovec->buf = (char *)addr_app_to_native(si_data->buf_offset); ciovec->buf_len = si_data->buf_len; } - err = uvwasi_sock_send(uvwasi, sock, - ciovec_begin, si_data_len, - si_flags, &so_datalen); + err = uvwasi_sock_send(uvwasi, sock, ciovec_begin, si_data_len, si_flags, + &so_datalen); if (err) goto fail; @@ -1110,8 +1054,7 @@ wasi_sock_send(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_sock_shutdown(wasm_exec_env_t exec_env, - wasi_fd_t sock, wasi_sdflags_t how) +wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how) { wasm_module_inst_t module_inst = get_module_inst(exec_env); uvwasi_t *uvwasi = get_wasi_ctx(module_inst); @@ -1131,8 +1074,10 @@ wasi_sched_yield(wasm_exec_env_t exec_env) return uvwasi_sched_yield(uvwasi); } -#define REG_NATIVE_FUNC(func_name, signature) \ +/* clang-format off */ +#define REG_NATIVE_FUNC(func_name, signature) \ { #func_name, wasi_##func_name, signature, NULL } +/* clang-format on */ static NativeSymbol native_symbols_libc_wasi[] = { REG_NATIVE_FUNC(args_get, "(**)i"), @@ -1188,4 +1133,3 @@ get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis) *p_libc_wasi_apis = native_symbols_libc_wasi; return sizeof(native_symbols_libc_wasi) / sizeof(NativeSymbol); } - diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index 467a9e2ce2..a8ecb234d2 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -10,6 +10,7 @@ void wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); +/* clang-format off */ #define get_module_inst(exec_env) \ wasm_runtime_get_module_inst(exec_env) @@ -33,6 +34,7 @@ wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); #define module_free(offset) \ wasm_runtime_module_free(module_inst, offset) +/* clang-format on */ typedef struct wasi_prestat_app { wasi_preopentype_t pr_type; @@ -52,14 +54,13 @@ typedef struct WASIContext { char **argv_list; char *env_buf; char **env_list; -} *wasi_ctx_t; +} * wasi_ctx_t; wasi_ctx_t wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst); static inline struct fd_table * -wasi_ctx_get_curfds(wasm_module_inst_t module_inst, - wasi_ctx_t wasi_ctx) +wasi_ctx_get_curfds(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) { if (!wasi_ctx) return NULL; @@ -67,8 +68,7 @@ wasi_ctx_get_curfds(wasm_module_inst_t module_inst, } static inline struct argv_environ_values * -wasi_ctx_get_argv_environ(wasm_module_inst_t module_inst, - wasi_ctx_t wasi_ctx) +wasi_ctx_get_argv_environ(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) { if (!wasi_ctx) return NULL; @@ -76,8 +76,7 @@ wasi_ctx_get_argv_environ(wasm_module_inst_t module_inst, } static inline struct fd_prestats * -wasi_ctx_get_prestats(wasm_module_inst_t module_inst, - wasi_ctx_t wasi_ctx) +wasi_ctx_get_prestats(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) { if (!wasi_ctx) return NULL; @@ -90,7 +89,7 @@ wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf) wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); struct argv_environ_values *argv_environ = - wasi_ctx_get_argv_environ(module_inst, wasi_ctx); + wasi_ctx_get_argv_environ(module_inst, wasi_ctx); size_t argc, argv_buf_size, i; char **argv; uint64 total_size; @@ -110,7 +109,7 @@ wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf) || !validate_native_addr(argv_buf, (uint32)argv_buf_size)) return (wasi_errno_t)-1; - total_size = sizeof(char*) * ((uint64)argc + 1); + total_size = sizeof(char *) * ((uint64)argc + 1); if (total_size >= UINT32_MAX || !(argv = wasm_runtime_malloc((uint32)total_size))) return (wasi_errno_t)-1; @@ -130,8 +129,8 @@ wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf) } static wasi_errno_t -wasi_args_sizes_get(wasm_exec_env_t exec_env, - uint32 *argc_app, uint32 *argv_buf_size_app) +wasi_args_sizes_get(wasm_exec_env_t exec_env, uint32 *argc_app, + uint32 *argv_buf_size_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -148,8 +147,7 @@ wasi_args_sizes_get(wasm_exec_env_t exec_env, argv_environ = wasi_ctx->argv_environ; - err = wasmtime_ssp_args_sizes_get(argv_environ, - &argc, &argv_buf_size); + err = wasmtime_ssp_args_sizes_get(argv_environ, &argc, &argv_buf_size); if (err) return err; @@ -173,7 +171,7 @@ wasi_clock_res_get(wasm_exec_env_t exec_env, static wasi_errno_t wasi_clock_time_get(wasm_exec_env_t exec_env, - wasi_clockid_t clock_id, /* uint32 clock_id */ + wasi_clockid_t clock_id, /* uint32 clock_id */ wasi_timestamp_t precision, /* uint64 precision */ wasi_timestamp_t *time /* uint64 *time */) { @@ -186,13 +184,13 @@ wasi_clock_time_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_environ_get(wasm_exec_env_t exec_env, - uint32 *environ_offsets, char *environ_buf) +wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets, + char *environ_buf) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); struct argv_environ_values *argv_environ = - wasi_ctx_get_argv_environ(module_inst, wasi_ctx); + wasi_ctx_get_argv_environ(module_inst, wasi_ctx); size_t environ_count, environ_buf_size, i; uint64 total_size; char **environs; @@ -201,8 +199,8 @@ wasi_environ_get(wasm_exec_env_t exec_env, if (!wasi_ctx) return (wasi_errno_t)-1; - err = wasmtime_ssp_environ_sizes_get(argv_environ, - &environ_count, &environ_buf_size); + err = wasmtime_ssp_environ_sizes_get(argv_environ, &environ_count, + &environ_buf_size); if (err) return err; @@ -213,7 +211,7 @@ wasi_environ_get(wasm_exec_env_t exec_env, || !validate_native_addr(environ_buf, (uint32)environ_buf_size)) return (wasi_errno_t)-1; - total_size = sizeof(char*) * (((uint64)environ_count + 1)); + total_size = sizeof(char *) * (((uint64)environ_count + 1)); if (total_size >= UINT32_MAX || !(environs = wasm_runtime_malloc((uint32)total_size))) @@ -234,13 +232,13 @@ wasi_environ_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_environ_sizes_get(wasm_exec_env_t exec_env, - uint32 *environ_count_app, uint32 *environ_buf_size_app) +wasi_environ_sizes_get(wasm_exec_env_t exec_env, uint32 *environ_count_app, + uint32 *environ_buf_size_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); struct argv_environ_values *argv_environ = - wasi_ctx_get_argv_environ(module_inst, wasi_ctx); + wasi_ctx_get_argv_environ(module_inst, wasi_ctx); size_t environ_count, environ_buf_size; wasi_errno_t err; @@ -251,8 +249,8 @@ wasi_environ_sizes_get(wasm_exec_env_t exec_env, || !validate_native_addr(environ_buf_size_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = wasmtime_ssp_environ_sizes_get(argv_environ, - &environ_count, &environ_buf_size); + err = wasmtime_ssp_environ_sizes_get(argv_environ, &environ_count, + &environ_buf_size); if (err) return err; @@ -263,8 +261,8 @@ wasi_environ_sizes_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_prestat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_prestat_app_t *prestat_app) +wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_prestat_app_t *prestat_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -288,8 +286,8 @@ wasi_fd_prestat_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, - wasi_fd_t fd, char *path, uint32 path_len) +wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, wasi_fd_t fd, char *path, + uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -298,8 +296,7 @@ wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_prestat_dir_name(prestats, - fd, path, path_len); + return wasmtime_ssp_fd_prestat_dir_name(prestats, fd, path, path_len); } static wasi_errno_t @@ -330,9 +327,8 @@ wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd) } static wasi_errno_t -wasi_fd_pread(wasm_exec_env_t exec_env, - wasi_fd_t fd, iovec_app_t *iovec_app, uint32 iovs_len, - wasi_filesize_t offset, uint32 *nread_app) +wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app, + uint32 iovs_len, wasi_filesize_t offset, uint32 *nread_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -364,12 +360,12 @@ wasi_fd_pread(wasm_exec_env_t exec_env, err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void*)addr_app_to_native(iovec_app->buf_offset); + iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset); iovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_pread(curfds, fd, iovec_begin, - iovs_len, offset, &nread); + err = wasmtime_ssp_fd_pread(curfds, fd, iovec_begin, iovs_len, offset, + &nread); if (err) goto fail; @@ -384,8 +380,8 @@ wasi_fd_pread(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_pwrite(wasm_exec_env_t exec_env, - wasi_fd_t fd, const iovec_app_t *iovec_app, uint32 iovs_len, +wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, + const iovec_app_t *iovec_app, uint32 iovs_len, wasi_filesize_t offset, uint32 *nwritten_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -403,7 +399,7 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, total_size = sizeof(iovec_app_t) * (uint64)iovs_len; if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void*)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, (uint32)total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; @@ -418,12 +414,12 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char*)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset); ciovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_pwrite(curfds, fd, ciovec_begin, - iovs_len, offset, &nwritten); + err = wasmtime_ssp_fd_pwrite(curfds, fd, ciovec_begin, iovs_len, offset, + &nwritten); if (err) goto fail; @@ -438,9 +434,8 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_read(wasm_exec_env_t exec_env, - wasi_fd_t fd, const iovec_app_t *iovec_app, uint32 iovs_len, - uint32 *nread_app) +wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, + const iovec_app_t *iovec_app, uint32 iovs_len, uint32 *nread_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -457,7 +452,7 @@ wasi_fd_read(wasm_exec_env_t exec_env, total_size = sizeof(iovec_app_t) * (uint64)iovs_len; if (!validate_native_addr(nread_app, (uint32)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void*)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, (uint32)total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; @@ -472,12 +467,11 @@ wasi_fd_read(wasm_exec_env_t exec_env, err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void*)addr_app_to_native(iovec_app->buf_offset); + iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset); iovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_read(curfds, fd, - iovec_begin, iovs_len, &nread); + err = wasmtime_ssp_fd_read(curfds, fd, iovec_begin, iovs_len, &nread); if (err) goto fail; @@ -506,9 +500,8 @@ wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to) } static wasi_errno_t -wasi_fd_seek(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_filedelta_t offset, wasi_whence_t whence, - wasi_filesize_t *newoffset) +wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset, + wasi_whence_t whence, wasi_filesize_t *newoffset) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -524,8 +517,7 @@ wasi_fd_seek(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_tell(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_filesize_t *newoffset) +wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -541,8 +533,8 @@ wasi_fd_tell(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_fdstat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_fdstat_t *fdstat_app) +wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_fdstat_t *fdstat_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -565,8 +557,8 @@ wasi_fd_fdstat_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_fdflags_t flags) +wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_fdflags_t flags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -579,8 +571,7 @@ wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, - wasi_fd_t fd, +wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_rights_t fs_rights_base, wasi_rights_t fs_rights_inheriting) { @@ -591,8 +582,8 @@ wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_fdstat_set_rights(curfds, fd, - fs_rights_base, fs_rights_inheriting); + return wasmtime_ssp_fd_fdstat_set_rights(curfds, fd, fs_rights_base, + fs_rights_inheriting); } static wasi_errno_t @@ -628,7 +619,7 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, total_size = sizeof(iovec_app_t) * (uint64)iovs_len; if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void*)iovec_app, (uint32)total_size)) + || !validate_native_addr((void *)iovec_app, (uint32)total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; @@ -643,12 +634,11 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char*)addr_app_to_native(iovec_app->buf_offset); + ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset); ciovec->buf_len = iovec_app->buf_len; } - err = wasmtime_ssp_fd_write(curfds, fd, - ciovec_begin, iovs_len, &nwritten); + err = wasmtime_ssp_fd_write(curfds, fd, ciovec_begin, iovs_len, &nwritten); if (err) goto fail; @@ -663,11 +653,8 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, } static wasi_errno_t -wasi_fd_advise(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_filesize_t offset, - wasi_filesize_t len, - wasi_advice_t advice) +wasi_fd_advise(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, + wasi_filesize_t len, wasi_advice_t advice) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -680,9 +667,7 @@ wasi_fd_advise(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_allocate(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_filesize_t offset, +wasi_fd_allocate(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, wasi_filesize_t len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -696,8 +681,8 @@ wasi_fd_allocate(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_create_directory(wasm_exec_env_t exec_env, - wasi_fd_t fd, const char *path, uint32 path_len) +wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, + const char *path, uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -706,17 +691,14 @@ wasi_path_create_directory(wasm_exec_env_t exec_env, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_create_directory(curfds, fd, - path, path_len); + return wasmtime_ssp_path_create_directory(curfds, fd, path, path_len); } static wasi_errno_t -wasi_path_link(wasm_exec_env_t exec_env, - wasi_fd_t old_fd, - wasi_lookupflags_t old_flags, - const char *old_path, uint32 old_path_len, - wasi_fd_t new_fd, - const char *new_path, uint32 new_path_len) +wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd, + wasi_lookupflags_t old_flags, const char *old_path, + uint32 old_path_len, wasi_fd_t new_fd, const char *new_path, + uint32 new_path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -726,20 +708,15 @@ wasi_path_link(wasm_exec_env_t exec_env, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_link(curfds, prestats, - old_fd, old_flags, old_path, old_path_len, - new_fd, new_path, new_path_len); + return wasmtime_ssp_path_link(curfds, prestats, old_fd, old_flags, old_path, + old_path_len, new_fd, new_path, new_path_len); } static wasi_errno_t -wasi_path_open(wasm_exec_env_t exec_env, - wasi_fd_t dirfd, - wasi_lookupflags_t dirflags, - const char *path, uint32 path_len, - wasi_oflags_t oflags, - wasi_rights_t fs_rights_base, - wasi_rights_t fs_rights_inheriting, - wasi_fdflags_t fs_flags, +wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd, + wasi_lookupflags_t dirflags, const char *path, uint32 path_len, + wasi_oflags_t oflags, wasi_rights_t fs_rights_base, + wasi_rights_t fs_rights_inheriting, wasi_fdflags_t fs_flags, wasi_fd_t *fd_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -754,25 +731,17 @@ wasi_path_open(wasm_exec_env_t exec_env, if (!validate_native_addr(fd_app, sizeof(wasi_fd_t))) return (wasi_errno_t)-1; - err = wasmtime_ssp_path_open(curfds, - dirfd, dirflags, - path, path_len, - oflags, - fs_rights_base, - fs_rights_inheriting, - fs_flags, - &fd); + err = wasmtime_ssp_path_open(curfds, dirfd, dirflags, path, path_len, + oflags, fs_rights_base, fs_rights_inheriting, + fs_flags, &fd); *fd_app = fd; return err; } static wasi_errno_t -wasi_fd_readdir(wasm_exec_env_t exec_env, - wasi_fd_t fd, - void *buf, uint32 buf_len, - wasi_dircookie_t cookie, - uint32 *bufused_app) +wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf, + uint32 buf_len, wasi_dircookie_t cookie, uint32 *bufused_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -786,8 +755,7 @@ wasi_fd_readdir(wasm_exec_env_t exec_env, if (!validate_native_addr(bufused_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = wasmtime_ssp_fd_readdir(curfds, fd, - buf, buf_len, cookie, &bufused); + err = wasmtime_ssp_fd_readdir(curfds, fd, buf, buf_len, cookie, &bufused); if (err) return err; @@ -796,10 +764,8 @@ wasi_fd_readdir(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_readlink(wasm_exec_env_t exec_env, - wasi_fd_t fd, - const char *path, uint32 path_len, - char *buf, uint32 buf_len, +wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, + uint32 path_len, char *buf, uint32 buf_len, uint32 *bufused_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -814,9 +780,8 @@ wasi_path_readlink(wasm_exec_env_t exec_env, if (!validate_native_addr(bufused_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = wasmtime_ssp_path_readlink(curfds, fd, - path, path_len, - buf, buf_len, &bufused); + err = wasmtime_ssp_path_readlink(curfds, fd, path, path_len, buf, buf_len, + &bufused); if (err) return err; @@ -825,9 +790,9 @@ wasi_path_readlink(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_rename(wasm_exec_env_t exec_env, - wasi_fd_t old_fd, const char *old_path, uint32 old_path_len, - wasi_fd_t new_fd, const char *new_path, uint32 new_path_len) +wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd, + const char *old_path, uint32 old_path_len, wasi_fd_t new_fd, + const char *new_path, uint32 new_path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -836,14 +801,13 @@ wasi_path_rename(wasm_exec_env_t exec_env, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_rename(curfds, - old_fd, old_path, old_path_len, + return wasmtime_ssp_path_rename(curfds, old_fd, old_path, old_path_len, new_fd, new_path, new_path_len); } static wasi_errno_t -wasi_fd_filestat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, wasi_filestat_t *filestat) +wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_filestat_t *filestat) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -859,10 +823,8 @@ wasi_fd_filestat_get(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_timestamp_t st_atim, - wasi_timestamp_t st_mtim, +wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_timestamp_t st_atim, wasi_timestamp_t st_mtim, wasi_fstflags_t fstflags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -872,13 +834,12 @@ wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_fd_filestat_set_times(curfds, fd, - st_atim, st_mtim, fstflags); + return wasmtime_ssp_fd_filestat_set_times(curfds, fd, st_atim, st_mtim, + fstflags); } static wasi_errno_t -wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, - wasi_fd_t fd, +wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t st_size) { wasm_module_inst_t module_inst = get_module_inst(exec_env); @@ -892,11 +853,9 @@ wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_filestat_get(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_lookupflags_t flags, - const char *path, uint32 path_len, - wasi_filestat_t *filestat) +wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_lookupflags_t flags, const char *path, + uint32 path_len, wasi_filestat_t *filestat) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -908,18 +867,15 @@ wasi_path_filestat_get(wasm_exec_env_t exec_env, if (!validate_native_addr(filestat, sizeof(wasi_filestat_t))) return (wasi_errno_t)-1; - return wasmtime_ssp_path_filestat_get(curfds, fd, - flags, path, path_len, filestat); + return wasmtime_ssp_path_filestat_get(curfds, fd, flags, path, path_len, + filestat); } static wasi_errno_t -wasi_path_filestat_set_times(wasm_exec_env_t exec_env, - wasi_fd_t fd, - wasi_lookupflags_t flags, - const char *path, uint32 path_len, - wasi_timestamp_t st_atim, - wasi_timestamp_t st_mtim, - wasi_fstflags_t fstflags) +wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, + wasi_lookupflags_t flags, const char *path, + uint32 path_len, wasi_timestamp_t st_atim, + wasi_timestamp_t st_mtim, wasi_fstflags_t fstflags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -928,15 +884,14 @@ wasi_path_filestat_set_times(wasm_exec_env_t exec_env, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_filestat_set_times(curfds, fd, - flags, path, path_len, - st_atim, st_mtim, fstflags); + return wasmtime_ssp_path_filestat_set_times( + curfds, fd, flags, path, path_len, st_atim, st_mtim, fstflags); } static wasi_errno_t -wasi_path_symlink(wasm_exec_env_t exec_env, - const char *old_path, uint32 old_path_len, - wasi_fd_t fd, const char *new_path, uint32 new_path_len) +wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path, + uint32 old_path_len, wasi_fd_t fd, const char *new_path, + uint32 new_path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -946,14 +901,13 @@ wasi_path_symlink(wasm_exec_env_t exec_env, if (!wasi_ctx) return (wasi_errno_t)-1; - return wasmtime_ssp_path_symlink(curfds, prestats, - old_path, old_path_len, fd, - new_path, new_path_len); + return wasmtime_ssp_path_symlink(curfds, prestats, old_path, old_path_len, + fd, new_path, new_path_len); } static wasi_errno_t -wasi_path_unlink_file(wasm_exec_env_t exec_env, - wasi_fd_t fd, const char *path, uint32 path_len) +wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, + uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -966,8 +920,8 @@ wasi_path_unlink_file(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_path_remove_directory(wasm_exec_env_t exec_env, - wasi_fd_t fd, const char *path, uint32 path_len) +wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, + const char *path, uint32 path_len) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -980,9 +934,8 @@ wasi_path_remove_directory(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_poll_oneoff(wasm_exec_env_t exec_env, - const wasi_subscription_t *in, wasi_event_t *out, - uint32 nsubscriptions, uint32 *nevents_app) +wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, + wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -993,13 +946,12 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, if (!wasi_ctx) return (wasi_errno_t)-1; - if (!validate_native_addr((void*)in, sizeof(wasi_subscription_t)) + if (!validate_native_addr((void *)in, sizeof(wasi_subscription_t)) || !validate_native_addr(out, sizeof(wasi_event_t)) || !validate_native_addr(nevents_app, sizeof(uint32))) return (wasi_errno_t)-1; - err = wasmtime_ssp_poll_oneoff(curfds, in, out, - nsubscriptions, &nevents); + err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents); if (err) return err; @@ -1035,12 +987,9 @@ wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len) } static wasi_errno_t -wasi_sock_recv(wasm_exec_env_t exec_env, - wasi_fd_t sock, - iovec_app_t *ri_data, uint32 ri_data_len, - wasi_riflags_t ri_flags, - uint32 *ro_datalen_app, - wasi_roflags_t *ro_flags) +wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data, + uint32 ri_data_len, wasi_riflags_t ri_flags, + uint32 *ro_datalen_app, wasi_roflags_t *ro_flags) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -1073,18 +1022,16 @@ wasi_sock_recv(wasm_exec_env_t exec_env, err = (wasi_errno_t)-1; goto fail; } - iovec->buf = (void*)addr_app_to_native(ri_data->buf_offset); + iovec->buf = (void *)addr_app_to_native(ri_data->buf_offset); iovec->buf_len = ri_data->buf_len; } - err = wasmtime_ssp_sock_recv(curfds, sock, - iovec_begin, ri_data_len, - ri_flags, &ro_datalen, - ro_flags); + err = wasmtime_ssp_sock_recv(curfds, sock, iovec_begin, ri_data_len, + ri_flags, &ro_datalen, ro_flags); if (err) goto fail; - *(uint32*)ro_datalen_app = (uint32)ro_datalen; + *(uint32 *)ro_datalen_app = (uint32)ro_datalen; /* success */ err = 0; @@ -1095,11 +1042,9 @@ wasi_sock_recv(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_sock_send(wasm_exec_env_t exec_env, - wasi_fd_t sock, +wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, const iovec_app_t *si_data, uint32 si_data_len, - wasi_siflags_t si_flags, - uint32 *so_datalen_app) + wasi_siflags_t si_flags, uint32 *so_datalen_app) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -1116,7 +1061,7 @@ wasi_sock_send(wasm_exec_env_t exec_env, total_size = sizeof(iovec_app_t) * (uint64)si_data_len; if (!validate_native_addr(so_datalen_app, sizeof(uint32)) || total_size >= UINT32_MAX - || !validate_native_addr((void*)si_data, (uint32)total_size)) + || !validate_native_addr((void *)si_data, (uint32)total_size)) return (wasi_errno_t)-1; total_size = sizeof(wasi_ciovec_t) * (uint64)si_data_len; @@ -1131,12 +1076,11 @@ wasi_sock_send(wasm_exec_env_t exec_env, err = (wasi_errno_t)-1; goto fail; } - ciovec->buf = (char*)addr_app_to_native(si_data->buf_offset); + ciovec->buf = (char *)addr_app_to_native(si_data->buf_offset); ciovec->buf_len = si_data->buf_len; } - err = wasmtime_ssp_sock_send(curfds, sock, - ciovec_begin, si_data_len, + err = wasmtime_ssp_sock_send(curfds, sock, ciovec_begin, si_data_len, si_flags, &so_datalen); if (err) goto fail; @@ -1152,8 +1096,7 @@ wasi_sock_send(wasm_exec_env_t exec_env, } static wasi_errno_t -wasi_sock_shutdown(wasm_exec_env_t exec_env, - wasi_fd_t sock, wasi_sdflags_t how) +wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); @@ -1171,8 +1114,10 @@ wasi_sched_yield(wasm_exec_env_t exec_env) return wasmtime_ssp_sched_yield(); } -#define REG_NATIVE_FUNC(func_name, signature) \ +/* clang-format off */ +#define REG_NATIVE_FUNC(func_name, signature) \ { #func_name, wasi_##func_name, signature, NULL } +/* clang-format on */ static NativeSymbol native_symbols_libc_wasi[] = { REG_NATIVE_FUNC(args_get, "(**)i"), @@ -1228,4 +1173,3 @@ get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis) *p_libc_wasi_apis = native_symbols_libc_wasi; return sizeof(native_symbols_libc_wasi) / sizeof(NativeSymbol); } - diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h index c8473bdf4c..7c241d8806 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -1,6 +1,8 @@ /* - * Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. - * See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. + * Part of the Wasmtime Project, under the Apache License v2.0 with + * LLVM Exceptions. See + * https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE + * for license information. * * This file declares an interface similar to WASI, but augmented to expose * some implementation details such as the curfds arguments that we pass @@ -13,6 +15,8 @@ #include #include +/* clang-format off */ + #ifdef __cplusplus #ifndef _Static_assert #define _Static_assert static_assert @@ -28,7 +32,6 @@ extern "C" { #endif - _Static_assert(_Alignof(int8_t) == 1, "non-wasi data layout"); _Static_assert(_Alignof(uint8_t) == 1, "non-wasi data layout"); _Static_assert(_Alignof(int16_t) == 2, "non-wasi data layout"); @@ -891,5 +894,6 @@ __wasi_errno_t wasmtime_ssp_sched_yield(void) #undef WASMTIME_SSP_SYSCALL_NAME -#endif +/* clang-format on */ +#endif /* end of WASMTIME_SSP_H */ diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h index 490f9a10a4..40b064b813 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -32,13 +34,13 @@ #define LOCKS_SHARED(...) LOCK_ANNOTATE(shared_lock_function(__VA_ARGS__)) #define TRYLOCKS_EXCLUSIVE(...) \ - LOCK_ANNOTATE(exclusive_trylock_function(__VA_ARGS__)) + LOCK_ANNOTATE(exclusive_trylock_function(__VA_ARGS__)) #define TRYLOCKS_SHARED(...) LOCK_ANNOTATE(shared_trylock_function(__VA_ARGS__)) #define UNLOCKS(...) LOCK_ANNOTATE(unlock_function(__VA_ARGS__)) #define REQUIRES_EXCLUSIVE(...) \ - LOCK_ANNOTATE(exclusive_locks_required(__VA_ARGS__)) + LOCK_ANNOTATE(exclusive_locks_required(__VA_ARGS__)) #define REQUIRES_SHARED(...) LOCK_ANNOTATE(shared_locks_required(__VA_ARGS__)) #define REQUIRES_UNLOCKED(...) LOCK_ANNOTATE(locks_excluded(__VA_ARGS__)) @@ -50,8 +52,10 @@ struct LOCKABLE mutex { pthread_mutex_t object; }; +/* clang-format off */ #define MUTEX_INITIALIZER \ - { PTHREAD_MUTEX_INITIALIZER } + { PTHREAD_MUTEX_INITIALIZER } +/* clang-format on */ static inline bool mutex_init(struct mutex *lock) REQUIRES_UNLOCKED(*lock) @@ -117,14 +121,15 @@ rwlock_destroy(struct rwlock *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS struct LOCKABLE cond { pthread_cond_t object; -#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK || \ - !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP +#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \ + || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP clockid_t clock; #endif }; static inline bool -cond_init_monotonic(struct cond *cond) { +cond_init_monotonic(struct cond *cond) +{ bool ret = false; #if CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK pthread_condattr_t attr; @@ -147,8 +152,8 @@ cond_init_monotonic(struct cond *cond) { ret = true; #endif -#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK || \ - !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP +#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \ + || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP cond->clock = CLOCK_MONOTONIC; #endif return ret; @@ -159,28 +164,29 @@ cond_init_realtime(struct cond *cond) { if (pthread_cond_init(&cond->object, NULL) != 0) return false; -#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK || \ - !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP +#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \ + || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP cond->clock = CLOCK_REALTIME; #endif return true; } static inline void -cond_destroy(struct cond *cond) { +cond_destroy(struct cond *cond) +{ pthread_cond_destroy(&cond->object); } static inline void -cond_signal(struct cond *cond) { +cond_signal(struct cond *cond) +{ pthread_cond_signal(&cond->object); } #if !CONFIG_HAS_CLOCK_NANOSLEEP static inline bool -cond_timedwait(struct cond *cond, struct mutex *lock, - uint64_t timeout, bool abstime) - REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS +cond_timedwait(struct cond *cond, struct mutex *lock, uint64_t timeout, + bool abstime) REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS { int ret; struct timespec ts = { @@ -220,8 +226,8 @@ cond_timedwait(struct cond *cond, struct mutex *lock, else { #if CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP /* Implementation supports relative timeouts. */ - ret = pthread_cond_timedwait_relative_np(&cond->object, - &lock->object, &ts); + ret = pthread_cond_timedwait_relative_np(&cond->object, &lock->object, + &ts); bh_assert((ret == 0 || ret == ETIMEDOUT) && "pthread_cond_timedwait_relative_np() failed"); return ret == ETIMEDOUT; diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h index 2b815271e8..233f3733b6 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -12,29 +14,29 @@ #ifndef COMMON_LIMITS_H #define COMMON_LIMITS_H -#define NUMERIC_MIN(t) \ - _Generic((t)0, char \ - : CHAR_MIN, signed char \ - : SCHAR_MIN, unsigned char : 0, short \ - : SHRT_MIN, unsigned short : 0, int \ - : INT_MIN, unsigned int : 0, long \ - : LONG_MIN, unsigned long : 0, long long \ - : LLONG_MIN, unsigned long long : 0, default \ - : (void)0) +#define NUMERIC_MIN(t) \ + _Generic((t)0, char \ + : CHAR_MIN, signed char \ + : SCHAR_MIN, unsigned char : 0, short \ + : SHRT_MIN, unsigned short : 0, int \ + : INT_MIN, unsigned int : 0, long \ + : LONG_MIN, unsigned long : 0, long long \ + : LLONG_MIN, unsigned long long : 0, default \ + : (void)0) -#define NUMERIC_MAX(t) \ - _Generic((t)0, char \ - : CHAR_MAX, signed char \ - : SCHAR_MAX, unsigned char \ - : UCHAR_MAX, short \ - : SHRT_MAX, unsigned short \ - : USHRT_MAX, int \ - : INT_MAX, unsigned int \ - : UINT_MAX, long \ - : LONG_MAX, unsigned long \ - : ULONG_MAX, long long \ - : LLONG_MAX, unsigned long long \ - : ULLONG_MAX, default \ - : (void)0) +#define NUMERIC_MAX(t) \ + _Generic((t)0, char \ + : CHAR_MAX, signed char \ + : SCHAR_MAX, unsigned char \ + : UCHAR_MAX, short \ + : SHRT_MAX, unsigned short \ + : USHRT_MAX, int \ + : INT_MAX, unsigned int \ + : UINT_MAX, long \ + : LONG_MAX, unsigned long \ + : ULONG_MAX, long long \ + : LLONG_MAX, unsigned long long \ + : ULLONG_MAX, default \ + : (void)0) #endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 6b4cbe20aa..94eb0024cb 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -61,1355 +63,1347 @@ static __thread struct argv_environ_values *argv_environ; #endif // Converts a POSIX error code to a CloudABI error code. -static __wasi_errno_t convert_errno(int error) { - static const __wasi_errno_t errors[] = { +static __wasi_errno_t +convert_errno(int error) +{ + static const __wasi_errno_t errors[] = { #define X(v) [v] = __WASI_##v - X(E2BIG), - X(EACCES), - X(EADDRINUSE), - X(EADDRNOTAVAIL), - X(EAFNOSUPPORT), - X(EAGAIN), - X(EALREADY), - X(EBADF), - X(EBADMSG), - X(EBUSY), - X(ECANCELED), - X(ECHILD), - X(ECONNABORTED), - X(ECONNREFUSED), - X(ECONNRESET), - X(EDEADLK), - X(EDESTADDRREQ), - X(EDOM), - X(EDQUOT), - X(EEXIST), - X(EFAULT), - X(EFBIG), - X(EHOSTUNREACH), - X(EIDRM), - X(EILSEQ), - X(EINPROGRESS), - X(EINTR), - X(EINVAL), - X(EIO), - X(EISCONN), - X(EISDIR), - X(ELOOP), - X(EMFILE), - X(EMLINK), - X(EMSGSIZE), - X(EMULTIHOP), - X(ENAMETOOLONG), - X(ENETDOWN), - X(ENETRESET), - X(ENETUNREACH), - X(ENFILE), - X(ENOBUFS), - X(ENODEV), - X(ENOENT), - X(ENOEXEC), - X(ENOLCK), - X(ENOLINK), - X(ENOMEM), - X(ENOMSG), - X(ENOPROTOOPT), - X(ENOSPC), - X(ENOSYS), + X(E2BIG), + X(EACCES), + X(EADDRINUSE), + X(EADDRNOTAVAIL), + X(EAFNOSUPPORT), + X(EAGAIN), + X(EALREADY), + X(EBADF), + X(EBADMSG), + X(EBUSY), + X(ECANCELED), + X(ECHILD), + X(ECONNABORTED), + X(ECONNREFUSED), + X(ECONNRESET), + X(EDEADLK), + X(EDESTADDRREQ), + X(EDOM), + X(EDQUOT), + X(EEXIST), + X(EFAULT), + X(EFBIG), + X(EHOSTUNREACH), + X(EIDRM), + X(EILSEQ), + X(EINPROGRESS), + X(EINTR), + X(EINVAL), + X(EIO), + X(EISCONN), + X(EISDIR), + X(ELOOP), + X(EMFILE), + X(EMLINK), + X(EMSGSIZE), + X(EMULTIHOP), + X(ENAMETOOLONG), + X(ENETDOWN), + X(ENETRESET), + X(ENETUNREACH), + X(ENFILE), + X(ENOBUFS), + X(ENODEV), + X(ENOENT), + X(ENOEXEC), + X(ENOLCK), + X(ENOLINK), + X(ENOMEM), + X(ENOMSG), + X(ENOPROTOOPT), + X(ENOSPC), + X(ENOSYS), #ifdef ENOTCAPABLE - X(ENOTCAPABLE), -#endif - X(ENOTCONN), - X(ENOTDIR), - X(ENOTEMPTY), - X(ENOTRECOVERABLE), - X(ENOTSOCK), - X(ENOTSUP), - X(ENOTTY), - X(ENXIO), - X(EOVERFLOW), - X(EOWNERDEAD), - X(EPERM), - X(EPIPE), - X(EPROTO), - X(EPROTONOSUPPORT), - X(EPROTOTYPE), - X(ERANGE), - X(EROFS), - X(ESPIPE), - X(ESRCH), - X(ESTALE), - X(ETIMEDOUT), - X(ETXTBSY), - X(EXDEV), + X(ENOTCAPABLE), +#endif + X(ENOTCONN), + X(ENOTDIR), + X(ENOTEMPTY), + X(ENOTRECOVERABLE), + X(ENOTSOCK), + X(ENOTSUP), + X(ENOTTY), + X(ENXIO), + X(EOVERFLOW), + X(EOWNERDEAD), + X(EPERM), + X(EPIPE), + X(EPROTO), + X(EPROTONOSUPPORT), + X(EPROTOTYPE), + X(ERANGE), + X(EROFS), + X(ESPIPE), + X(ESRCH), + X(ESTALE), + X(ETIMEDOUT), + X(ETXTBSY), + X(EXDEV), #undef X #if EOPNOTSUPP != ENOTSUP - [EOPNOTSUPP] = __WASI_ENOTSUP, + [EOPNOTSUPP] = __WASI_ENOTSUP, #endif #if EWOULDBLOCK != EAGAIN - [EWOULDBLOCK] = __WASI_EAGAIN, + [EWOULDBLOCK] = __WASI_EAGAIN, #endif - }; - if (error < 0 || (size_t)error >= sizeof(errors) / sizeof(errors[0]) || - errors[error] == 0) - return __WASI_ENOSYS; - return errors[error]; + }; + if (error < 0 || (size_t)error >= sizeof(errors) / sizeof(errors[0]) + || errors[error] == 0) + return __WASI_ENOSYS; + return errors[error]; } // Converts a POSIX timespec to a CloudABI timestamp. -static __wasi_timestamp_t convert_timespec( - const struct timespec *ts -) { - if (ts->tv_sec < 0) - return 0; - if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000) - return UINT64_MAX; - return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + (__wasi_timestamp_t)ts->tv_nsec; +static __wasi_timestamp_t +convert_timespec(const struct timespec *ts) +{ + if (ts->tv_sec < 0) + return 0; + if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000) + return UINT64_MAX; + return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + + (__wasi_timestamp_t)ts->tv_nsec; } // Converts a CloudABI clock identifier to a POSIX clock identifier. -static bool convert_clockid( - __wasi_clockid_t in, - clockid_t *out -) { - switch (in) { - case __WASI_CLOCK_MONOTONIC: - *out = CLOCK_MONOTONIC; - return true; - case __WASI_CLOCK_PROCESS_CPUTIME_ID: - *out = CLOCK_PROCESS_CPUTIME_ID; - return true; - case __WASI_CLOCK_REALTIME: - *out = CLOCK_REALTIME; - return true; - case __WASI_CLOCK_THREAD_CPUTIME_ID: - *out = CLOCK_THREAD_CPUTIME_ID; - return true; - default: - return false; - } -} - -__wasi_errno_t wasmtime_ssp_clock_res_get( - __wasi_clockid_t clock_id, - __wasi_timestamp_t *resolution -) { - clockid_t nclock_id; - if (!convert_clockid(clock_id, &nclock_id)) - return __WASI_EINVAL; - struct timespec ts; - if (clock_getres(nclock_id, &ts) < 0) - return convert_errno(errno); - *resolution = convert_timespec(&ts); - return 0; -} - -__wasi_errno_t wasmtime_ssp_clock_time_get( - __wasi_clockid_t clock_id, - __wasi_timestamp_t precision, - __wasi_timestamp_t *time -) { - clockid_t nclock_id; - if (!convert_clockid(clock_id, &nclock_id)) - return __WASI_EINVAL; - struct timespec ts; - if (clock_gettime(nclock_id, &ts) < 0) - return convert_errno(errno); - *time = convert_timespec(&ts); - return 0; +static bool +convert_clockid(__wasi_clockid_t in, clockid_t *out) +{ + switch (in) { + case __WASI_CLOCK_MONOTONIC: + *out = CLOCK_MONOTONIC; + return true; + case __WASI_CLOCK_PROCESS_CPUTIME_ID: + *out = CLOCK_PROCESS_CPUTIME_ID; + return true; + case __WASI_CLOCK_REALTIME: + *out = CLOCK_REALTIME; + return true; + case __WASI_CLOCK_THREAD_CPUTIME_ID: + *out = CLOCK_THREAD_CPUTIME_ID; + return true; + default: + return false; + } +} + +__wasi_errno_t +wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id, + __wasi_timestamp_t *resolution) +{ + clockid_t nclock_id; + if (!convert_clockid(clock_id, &nclock_id)) + return __WASI_EINVAL; + struct timespec ts; + if (clock_getres(nclock_id, &ts) < 0) + return convert_errno(errno); + *resolution = convert_timespec(&ts); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_clock_time_get(__wasi_clockid_t clock_id, + __wasi_timestamp_t precision, + __wasi_timestamp_t *time) +{ + clockid_t nclock_id; + if (!convert_clockid(clock_id, &nclock_id)) + return __WASI_EINVAL; + struct timespec ts; + if (clock_gettime(nclock_id, &ts) < 0) + return convert_errno(errno); + *time = convert_timespec(&ts); + return 0; } struct fd_prestat { - const char *dir; + const char *dir; }; -bool fd_prestats_init( - struct fd_prestats *pt -) { - if (!rwlock_init(&pt->lock)) - return false; - pt->prestats = NULL; - pt->size = 0; - pt->used = 0; +bool +fd_prestats_init(struct fd_prestats *pt) +{ + if (!rwlock_init(&pt->lock)) + return false; + pt->prestats = NULL; + pt->size = 0; + pt->used = 0; #if defined(WASMTIME_SSP_STATIC_CURFDS) - prestats = pt; + prestats = pt; #endif - return true; + return true; } // Grows the preopened resource table to a required lower bound and a // minimum number of free preopened resource table entries. -static bool fd_prestats_grow( - struct fd_prestats *pt, - size_t min, - size_t incr -) REQUIRES_EXCLUSIVE(pt->lock) { - if (pt->size <= min || pt->size < (pt->used + incr) * 2) { - // Keep on doubling the table size until we've met our constraints. - size_t size = pt->size == 0 ? 1 : pt->size; - while (size <= min || size < (pt->used + incr) * 2) - size *= 2; - - // Grow the file descriptor table's allocation. - struct fd_prestat *prestats = wasm_runtime_malloc((uint32)(sizeof(*prestats) * size)); - if (prestats == NULL) - return false; - - if (pt->prestats && pt->size > 0) { - bh_memcpy_s(prestats, (uint32)(sizeof(*prestats) * size), - pt->prestats, (uint32)(sizeof(*prestats) * pt->size)); - } - - if (pt->prestats) - wasm_runtime_free(pt->prestats); - - // Mark all new file descriptors as unused. - for (size_t i = pt->size; i < size; ++i) - prestats[i].dir = NULL; - pt->prestats = prestats; - pt->size = size; - } - return true; +static bool +fd_prestats_grow(struct fd_prestats *pt, size_t min, size_t incr) + REQUIRES_EXCLUSIVE(pt->lock) +{ + if (pt->size <= min || pt->size < (pt->used + incr) * 2) { + // Keep on doubling the table size until we've met our constraints. + size_t size = pt->size == 0 ? 1 : pt->size; + while (size <= min || size < (pt->used + incr) * 2) + size *= 2; + + // Grow the file descriptor table's allocation. + struct fd_prestat *prestats = + wasm_runtime_malloc((uint32)(sizeof(*prestats) * size)); + if (prestats == NULL) + return false; + + if (pt->prestats && pt->size > 0) { + bh_memcpy_s(prestats, (uint32)(sizeof(*prestats) * size), + pt->prestats, (uint32)(sizeof(*prestats) * pt->size)); + } + + if (pt->prestats) + wasm_runtime_free(pt->prestats); + + // Mark all new file descriptors as unused. + for (size_t i = pt->size; i < size; ++i) + prestats[i].dir = NULL; + pt->prestats = prestats; + pt->size = size; + } + return true; } // Inserts a preopened resource record into the preopened resource table. -bool fd_prestats_insert( - struct fd_prestats *pt, - const char *dir, - __wasi_fd_t fd -) { - // Grow the preopened resource table if needed. - rwlock_wrlock(&pt->lock); - if (!fd_prestats_grow(pt, fd, 1)) { - rwlock_unlock(&pt->lock); - return false; - } +bool +fd_prestats_insert(struct fd_prestats *pt, const char *dir, __wasi_fd_t fd) +{ + // Grow the preopened resource table if needed. + rwlock_wrlock(&pt->lock); + if (!fd_prestats_grow(pt, fd, 1)) { + rwlock_unlock(&pt->lock); + return false; + } - pt->prestats[fd].dir = bh_strdup(dir); - rwlock_unlock(&pt->lock); + pt->prestats[fd].dir = bh_strdup(dir); + rwlock_unlock(&pt->lock); - if (pt->prestats[fd].dir == NULL) - return false; + if (pt->prestats[fd].dir == NULL) + return false; - return true; + return true; } // Looks up a preopened resource table entry by number. -static __wasi_errno_t fd_prestats_get_entry( - struct fd_prestats *pt, - __wasi_fd_t fd, - struct fd_prestat **ret -) REQUIRES_SHARED(pt->lock) { - // Test for file descriptor existence. - if (fd >= pt->size) - return __WASI_EBADF; - struct fd_prestat *prestat = &pt->prestats[fd]; - if (prestat->dir == NULL) - return __WASI_EBADF; - - *ret = prestat; - return 0; +static __wasi_errno_t +fd_prestats_get_entry(struct fd_prestats *pt, __wasi_fd_t fd, + struct fd_prestat **ret) REQUIRES_SHARED(pt->lock) +{ + // Test for file descriptor existence. + if (fd >= pt->size) + return __WASI_EBADF; + struct fd_prestat *prestat = &pt->prestats[fd]; + if (prestat->dir == NULL) + return __WASI_EBADF; + + *ret = prestat; + return 0; } struct fd_object { - struct refcount refcount; - __wasi_filetype_t type; - int number; - - union { - // Data associated with directory file descriptors. - struct { - struct mutex lock; // Lock to protect members below. - DIR *handle; // Directory handle. - __wasi_dircookie_t offset; // Offset of the directory. - } directory; - }; + struct refcount refcount; + __wasi_filetype_t type; + int number; + + union { + // Data associated with directory file descriptors. + struct { + struct mutex lock; // Lock to protect members below. + DIR *handle; // Directory handle. + __wasi_dircookie_t offset; // Offset of the directory. + } directory; + }; }; struct fd_entry { - struct fd_object *object; - __wasi_rights_t rights_base; - __wasi_rights_t rights_inheriting; + struct fd_object *object; + __wasi_rights_t rights_base; + __wasi_rights_t rights_inheriting; }; -bool fd_table_init( - struct fd_table *ft -) { - if (!rwlock_init(&ft->lock)) - return false; - ft->entries = NULL; - ft->size = 0; - ft->used = 0; +bool +fd_table_init(struct fd_table *ft) +{ + if (!rwlock_init(&ft->lock)) + return false; + ft->entries = NULL; + ft->size = 0; + ft->used = 0; #if defined(WASMTIME_SSP_STATIC_CURFDS) - curfds = ft; + curfds = ft; #endif - return true; + return true; } // Looks up a file descriptor table entry by number and required rights. -static __wasi_errno_t fd_table_get_entry( - struct fd_table *ft, - __wasi_fd_t fd, - __wasi_rights_t rights_base, - __wasi_rights_t rights_inheriting, - struct fd_entry **ret -) REQUIRES_SHARED(ft->lock) { - // Test for file descriptor existence. - if (fd >= ft->size) - return __WASI_EBADF; - struct fd_entry *fe = &ft->entries[fd]; - if (fe->object == NULL) - return __WASI_EBADF; - - // Validate rights. - if ((~fe->rights_base & rights_base) != 0 || - (~fe->rights_inheriting & rights_inheriting) != 0) - return __WASI_ENOTCAPABLE; - *ret = fe; - return 0; +static __wasi_errno_t +fd_table_get_entry(struct fd_table *ft, __wasi_fd_t fd, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, struct fd_entry **ret) + REQUIRES_SHARED(ft->lock) +{ + // Test for file descriptor existence. + if (fd >= ft->size) + return __WASI_EBADF; + struct fd_entry *fe = &ft->entries[fd]; + if (fe->object == NULL) + return __WASI_EBADF; + + // Validate rights. + if ((~fe->rights_base & rights_base) != 0 + || (~fe->rights_inheriting & rights_inheriting) != 0) + return __WASI_ENOTCAPABLE; + *ret = fe; + return 0; } // Grows the file descriptor table to a required lower bound and a // minimum number of free file descriptor table entries. -static bool fd_table_grow( - struct fd_table *ft, - size_t min, - size_t incr -) REQUIRES_EXCLUSIVE(ft->lock) { - if (ft->size <= min || ft->size < (ft->used + incr) * 2) { - // Keep on doubling the table size until we've met our constraints. - size_t size = ft->size == 0 ? 1 : ft->size; - while (size <= min || size < (ft->used + incr) * 2) - size *= 2; - - // Grow the file descriptor table's allocation. - struct fd_entry *entries = wasm_runtime_malloc((uint32)(sizeof(*entries) * size)); - if (entries == NULL) - return false; - - if (ft->entries && ft->size > 0) { - bh_memcpy_s(entries, (uint32)(sizeof(*entries) * size), - ft->entries, (uint32)(sizeof(*entries) * ft->size)); - } - - if (ft->entries) - wasm_runtime_free(ft->entries); - - // Mark all new file descriptors as unused. - for (size_t i = ft->size; i < size; ++i) - entries[i].object = NULL; - ft->entries = entries; - ft->size = size; - } - return true; +static bool +fd_table_grow(struct fd_table *ft, size_t min, size_t incr) + REQUIRES_EXCLUSIVE(ft->lock) +{ + if (ft->size <= min || ft->size < (ft->used + incr) * 2) { + // Keep on doubling the table size until we've met our constraints. + size_t size = ft->size == 0 ? 1 : ft->size; + while (size <= min || size < (ft->used + incr) * 2) + size *= 2; + + // Grow the file descriptor table's allocation. + struct fd_entry *entries = + wasm_runtime_malloc((uint32)(sizeof(*entries) * size)); + if (entries == NULL) + return false; + + if (ft->entries && ft->size > 0) { + bh_memcpy_s(entries, (uint32)(sizeof(*entries) * size), ft->entries, + (uint32)(sizeof(*entries) * ft->size)); + } + + if (ft->entries) + wasm_runtime_free(ft->entries); + + // Mark all new file descriptors as unused. + for (size_t i = ft->size; i < size; ++i) + entries[i].object = NULL; + ft->entries = entries; + ft->size = size; + } + return true; } // Allocates a new file descriptor object. -static __wasi_errno_t fd_object_new( - __wasi_filetype_t type, - struct fd_object **fo -) TRYLOCKS_SHARED(0, (*fo)->refcount) { - *fo = wasm_runtime_malloc(sizeof(**fo)); - if (*fo == NULL) - return __WASI_ENOMEM; - refcount_init(&(*fo)->refcount, 1); - (*fo)->type = type; - (*fo)->number = -1; - return 0; +static __wasi_errno_t +fd_object_new(__wasi_filetype_t type, struct fd_object **fo) + TRYLOCKS_SHARED(0, (*fo)->refcount) +{ + *fo = wasm_runtime_malloc(sizeof(**fo)); + if (*fo == NULL) + return __WASI_ENOMEM; + refcount_init(&(*fo)->refcount, 1); + (*fo)->type = type; + (*fo)->number = -1; + return 0; } // Attaches a file descriptor to the file descriptor table. -static void fd_table_attach( - struct fd_table *ft, - __wasi_fd_t fd, - struct fd_object *fo, - __wasi_rights_t rights_base, - __wasi_rights_t rights_inheriting -) REQUIRES_EXCLUSIVE(ft->lock) CONSUMES(fo->refcount) { - assert(ft->size > fd && "File descriptor table too small"); - struct fd_entry *fe = &ft->entries[fd]; - assert(fe->object == NULL && "Attempted to overwrite an existing descriptor"); - fe->object = fo; - fe->rights_base = rights_base; - fe->rights_inheriting = rights_inheriting; - ++ft->used; - assert(ft->size >= ft->used * 2 && "File descriptor too full"); +static void +fd_table_attach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object *fo, + __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting) + REQUIRES_EXCLUSIVE(ft->lock) CONSUMES(fo->refcount) +{ + assert(ft->size > fd && "File descriptor table too small"); + struct fd_entry *fe = &ft->entries[fd]; + assert(fe->object == NULL + && "Attempted to overwrite an existing descriptor"); + fe->object = fo; + fe->rights_base = rights_base; + fe->rights_inheriting = rights_inheriting; + ++ft->used; + assert(ft->size >= ft->used * 2 && "File descriptor too full"); } // Detaches a file descriptor from the file descriptor table. -static void fd_table_detach( - struct fd_table *ft, - __wasi_fd_t fd, - struct fd_object **fo -) REQUIRES_EXCLUSIVE(ft->lock) PRODUCES((*fo)->refcount) { - assert(ft->size > fd && "File descriptor table too small"); - struct fd_entry *fe = &ft->entries[fd]; - *fo = fe->object; - assert(*fo != NULL && "Attempted to detach nonexistent descriptor"); - fe->object = NULL; - assert(ft->used > 0 && "Reference count mismatch"); - --ft->used; +static void +fd_table_detach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object **fo) + REQUIRES_EXCLUSIVE(ft->lock) PRODUCES((*fo)->refcount) +{ + assert(ft->size > fd && "File descriptor table too small"); + struct fd_entry *fe = &ft->entries[fd]; + *fo = fe->object; + assert(*fo != NULL && "Attempted to detach nonexistent descriptor"); + fe->object = NULL; + assert(ft->used > 0 && "Reference count mismatch"); + --ft->used; } // Determines the type of a file descriptor and its maximum set of // rights that should be attached to it. -static __wasi_errno_t fd_determine_type_rights( - int fd, - __wasi_filetype_t *type, - __wasi_rights_t *rights_base, - __wasi_rights_t *rights_inheriting -) { - struct stat sb; - if (fstat(fd, &sb) < 0) - return convert_errno(errno); - if (S_ISBLK(sb.st_mode)) { - *type = __WASI_FILETYPE_BLOCK_DEVICE; - *rights_base = RIGHTS_BLOCK_DEVICE_BASE; - *rights_inheriting = RIGHTS_BLOCK_DEVICE_INHERITING; - } else if (S_ISCHR(sb.st_mode)) { - *type = __WASI_FILETYPE_CHARACTER_DEVICE; +static __wasi_errno_t +fd_determine_type_rights(int fd, __wasi_filetype_t *type, + __wasi_rights_t *rights_base, + __wasi_rights_t *rights_inheriting) +{ + struct stat sb; + if (fstat(fd, &sb) < 0) + return convert_errno(errno); + if (S_ISBLK(sb.st_mode)) { + *type = __WASI_FILETYPE_BLOCK_DEVICE; + *rights_base = RIGHTS_BLOCK_DEVICE_BASE; + *rights_inheriting = RIGHTS_BLOCK_DEVICE_INHERITING; + } + else if (S_ISCHR(sb.st_mode)) { + *type = __WASI_FILETYPE_CHARACTER_DEVICE; #if CONFIG_HAS_ISATTY - if (isatty(fd)) { - *rights_base = RIGHTS_TTY_BASE; - *rights_inheriting = RIGHTS_TTY_INHERITING; - } else + if (isatty(fd)) { + *rights_base = RIGHTS_TTY_BASE; + *rights_inheriting = RIGHTS_TTY_INHERITING; + } + else #endif - { - *rights_base = RIGHTS_CHARACTER_DEVICE_BASE; - *rights_inheriting = RIGHTS_CHARACTER_DEVICE_INHERITING; - } - } else if (S_ISDIR(sb.st_mode)) { - *type = __WASI_FILETYPE_DIRECTORY; - *rights_base = RIGHTS_DIRECTORY_BASE; - *rights_inheriting = RIGHTS_DIRECTORY_INHERITING; - } else if (S_ISREG(sb.st_mode)) { - *type = __WASI_FILETYPE_REGULAR_FILE; - *rights_base = RIGHTS_REGULAR_FILE_BASE; - *rights_inheriting = RIGHTS_REGULAR_FILE_INHERITING; - } else if (S_ISSOCK(sb.st_mode)) { - int socktype; - socklen_t socktypelen = sizeof(socktype); - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &socktype, &socktypelen) < 0) - return convert_errno(errno); - switch (socktype) { - case SOCK_DGRAM: - *type = __WASI_FILETYPE_SOCKET_DGRAM; - break; - case SOCK_STREAM: + { + *rights_base = RIGHTS_CHARACTER_DEVICE_BASE; + *rights_inheriting = RIGHTS_CHARACTER_DEVICE_INHERITING; + } + } + else if (S_ISDIR(sb.st_mode)) { + *type = __WASI_FILETYPE_DIRECTORY; + *rights_base = RIGHTS_DIRECTORY_BASE; + *rights_inheriting = RIGHTS_DIRECTORY_INHERITING; + } + else if (S_ISREG(sb.st_mode)) { + *type = __WASI_FILETYPE_REGULAR_FILE; + *rights_base = RIGHTS_REGULAR_FILE_BASE; + *rights_inheriting = RIGHTS_REGULAR_FILE_INHERITING; + } + else if (S_ISSOCK(sb.st_mode)) { + int socktype; + socklen_t socktypelen = sizeof(socktype); + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &socktype, &socktypelen) < 0) + return convert_errno(errno); + switch (socktype) { + case SOCK_DGRAM: + *type = __WASI_FILETYPE_SOCKET_DGRAM; + break; + case SOCK_STREAM: + *type = __WASI_FILETYPE_SOCKET_STREAM; + break; + default: + return __WASI_EINVAL; + } + *rights_base = RIGHTS_SOCKET_BASE; + *rights_inheriting = RIGHTS_SOCKET_INHERITING; + } + else if (S_ISFIFO(sb.st_mode)) { *type = __WASI_FILETYPE_SOCKET_STREAM; - break; - default: + *rights_base = RIGHTS_SOCKET_BASE; + *rights_inheriting = RIGHTS_SOCKET_INHERITING; + } + else { return __WASI_EINVAL; } - *rights_base = RIGHTS_SOCKET_BASE; - *rights_inheriting = RIGHTS_SOCKET_INHERITING; - } else if (S_ISFIFO(sb.st_mode)) { - *type = __WASI_FILETYPE_SOCKET_STREAM; - *rights_base = RIGHTS_SOCKET_BASE; - *rights_inheriting = RIGHTS_SOCKET_INHERITING; - } else { - return __WASI_EINVAL; - } - - // Strip off read/write bits based on the access mode. - switch (fcntl(fd, F_GETFL) & O_ACCMODE) { - case O_RDONLY: - *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_WRITE; - break; - case O_WRONLY: - *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_READ; - break; - } - return 0; + + // Strip off read/write bits based on the access mode. + switch (fcntl(fd, F_GETFL) & O_ACCMODE) { + case O_RDONLY: + *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_WRITE; + break; + case O_WRONLY: + *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_READ; + break; + } + return 0; } // Returns the underlying file descriptor number of a file descriptor // object. This function can only be applied to objects that have an // underlying file descriptor number. -static int fd_number( - const struct fd_object *fo -) { - int number = fo->number; - assert(number >= 0 && "fd_number() called on virtual file descriptor"); - return number; +static int +fd_number(const struct fd_object *fo) +{ + int number = fo->number; + assert(number >= 0 && "fd_number() called on virtual file descriptor"); + return number; } -#define CLOSE_NON_STD_FD(fd) do { \ - if (fd > 2) \ - close(fd); \ - } while (0) +#define CLOSE_NON_STD_FD(fd) \ + do { \ + if (fd > 2) \ + close(fd); \ + } while (0) // Lowers the reference count on a file descriptor object. When the // reference count reaches zero, its resources are cleaned up. -static void fd_object_release( - struct fd_object *fo -) UNLOCKS(fo->refcount) { - if (refcount_release(&fo->refcount)) { - switch (fo->type) { - case __WASI_FILETYPE_DIRECTORY: - // For directories we may keep track of a DIR object. Calling - // closedir() on it also closes the underlying file descriptor. - mutex_destroy(&fo->directory.lock); - if (fo->directory.handle == NULL) { - CLOSE_NON_STD_FD(fd_number(fo)); - } else { - closedir(fo->directory.handle); +static void +fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount) +{ + if (refcount_release(&fo->refcount)) { + switch (fo->type) { + case __WASI_FILETYPE_DIRECTORY: + // For directories we may keep track of a DIR object. Calling + // closedir() on it also closes the underlying file descriptor. + mutex_destroy(&fo->directory.lock); + if (fo->directory.handle == NULL) { + CLOSE_NON_STD_FD(fd_number(fo)); + } + else { + closedir(fo->directory.handle); + } + break; + default: + CLOSE_NON_STD_FD(fd_number(fo)); + break; } - break; - default: - CLOSE_NON_STD_FD(fd_number(fo)); - break; + wasm_runtime_free(fo); } - wasm_runtime_free(fo); - } } // Inserts an already existing file descriptor into the file descriptor // table. -bool fd_table_insert_existing( - struct fd_table *ft, - __wasi_fd_t in, - int out -) { - __wasi_filetype_t type; - __wasi_rights_t rights_base, rights_inheriting; - struct fd_object *fo; - __wasi_errno_t error; +bool +fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out) +{ + __wasi_filetype_t type; + __wasi_rights_t rights_base, rights_inheriting; + struct fd_object *fo; + __wasi_errno_t error; + + if (fd_determine_type_rights(out, &type, &rights_base, &rights_inheriting) + != 0) + return false; + + error = fd_object_new(type, &fo); + if (error != 0) + return false; + fo->number = out; + if (type == __WASI_FILETYPE_DIRECTORY) { + if (!mutex_init(&fo->directory.lock)) { + fd_object_release(fo); + return false; + } + fo->directory.handle = NULL; + } - if (fd_determine_type_rights(out, &type, &rights_base, - &rights_inheriting) != 0) - return false; + // Grow the file descriptor table if needed. + rwlock_wrlock(&ft->lock); + if (!fd_table_grow(ft, in, 1)) { + rwlock_unlock(&ft->lock); + fd_object_release(fo); + return false; + } - error = fd_object_new(type, &fo); - if (error != 0) - return false; - fo->number = out; - if (type == __WASI_FILETYPE_DIRECTORY) { - if (!mutex_init(&fo->directory.lock)) { - fd_object_release(fo); - return false; - } - fo->directory.handle = NULL; - } - - // Grow the file descriptor table if needed. - rwlock_wrlock(&ft->lock); - if (!fd_table_grow(ft, in, 1)) { + fd_table_attach(ft, in, fo, rights_base, rights_inheriting); rwlock_unlock(&ft->lock); - fd_object_release(fo); - return false; - } - - fd_table_attach(ft, in, fo, rights_base, rights_inheriting); - rwlock_unlock(&ft->lock); - return true; + return true; } // Picks an unused slot from the file descriptor table. -static __wasi_fd_t fd_table_unused( - struct fd_table *ft -) REQUIRES_SHARED(ft->lock) { - assert(ft->size > ft->used && "File descriptor table has no free slots"); - for (;;) { - __wasi_fd_t fd = (__wasi_fd_t)random_uniform(ft->size); - if (ft->entries[fd].object == NULL) - return fd; - } +static __wasi_fd_t +fd_table_unused(struct fd_table *ft) REQUIRES_SHARED(ft->lock) +{ + assert(ft->size > ft->used && "File descriptor table has no free slots"); + for (;;) { + __wasi_fd_t fd = (__wasi_fd_t)random_uniform(ft->size); + if (ft->entries[fd].object == NULL) + return fd; + } } // Inserts a file descriptor object into an unused slot of the file // descriptor table. -static __wasi_errno_t fd_table_insert( - struct fd_table *ft, - struct fd_object *fo, - __wasi_rights_t rights_base, - __wasi_rights_t rights_inheriting, - __wasi_fd_t *out -) REQUIRES_UNLOCKED(ft->lock) UNLOCKS(fo->refcount) { - // Grow the file descriptor table if needed. - rwlock_wrlock(&ft->lock); - if (!fd_table_grow(ft, 0, 1)) { - rwlock_unlock(&ft->lock); - fd_object_release(fo); - return convert_errno(errno); - } +static __wasi_errno_t +fd_table_insert(struct fd_table *ft, struct fd_object *fo, + __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting, + __wasi_fd_t *out) REQUIRES_UNLOCKED(ft->lock) + UNLOCKS(fo->refcount) +{ + // Grow the file descriptor table if needed. + rwlock_wrlock(&ft->lock); + if (!fd_table_grow(ft, 0, 1)) { + rwlock_unlock(&ft->lock); + fd_object_release(fo); + return convert_errno(errno); + } - *out = fd_table_unused(ft); - fd_table_attach(ft, *out, fo, rights_base, rights_inheriting); - rwlock_unlock(&ft->lock); - return 0; + *out = fd_table_unused(ft); + fd_table_attach(ft, *out, fo, rights_base, rights_inheriting); + rwlock_unlock(&ft->lock); + return 0; } // Inserts a numerical file descriptor into the file descriptor table. -static __wasi_errno_t fd_table_insert_fd( - struct fd_table *ft, - int in, - __wasi_filetype_t type, - __wasi_rights_t rights_base, - __wasi_rights_t rights_inheriting, - __wasi_fd_t *out -) REQUIRES_UNLOCKED(ft->lock) { - struct fd_object *fo; - __wasi_errno_t error = fd_object_new(type, &fo); - - if (error != 0) { - close(in); - return error; - } - fo->number = in; - if (type == __WASI_FILETYPE_DIRECTORY) { - if (!mutex_init(&fo->directory.lock)) { - fd_object_release(fo); - return (__wasi_errno_t)-1; +static __wasi_errno_t +fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, __wasi_fd_t *out) + REQUIRES_UNLOCKED(ft->lock) +{ + struct fd_object *fo; + __wasi_errno_t error = fd_object_new(type, &fo); + + if (error != 0) { + close(in); + return error; } - fo->directory.handle = NULL; - } - return fd_table_insert(ft, fo, rights_base, rights_inheriting, out); + fo->number = in; + if (type == __WASI_FILETYPE_DIRECTORY) { + if (!mutex_init(&fo->directory.lock)) { + fd_object_release(fo); + return (__wasi_errno_t)-1; + } + fo->directory.handle = NULL; + } + return fd_table_insert(ft, fo, rights_base, rights_inheriting, out); } -__wasi_errno_t wasmtime_ssp_fd_prestat_get( +__wasi_errno_t +wasmtime_ssp_fd_prestat_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_prestats *prestats, #endif - __wasi_fd_t fd, - __wasi_prestat_t *buf -) { - rwlock_rdlock(&prestats->lock); - struct fd_prestat *prestat; - __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); - if (error != 0) { - rwlock_unlock(&prestats->lock); - return error; - } + __wasi_fd_t fd, __wasi_prestat_t *buf) +{ + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); + if (error != 0) { + rwlock_unlock(&prestats->lock); + return error; + } - *buf = (__wasi_prestat_t) { - .pr_type = __WASI_PREOPENTYPE_DIR, - }; + *buf = (__wasi_prestat_t){ + .pr_type = __WASI_PREOPENTYPE_DIR, + }; - buf->u.dir.pr_name_len = strlen(prestat->dir); + buf->u.dir.pr_name_len = strlen(prestat->dir); - rwlock_unlock(&prestats->lock); + rwlock_unlock(&prestats->lock); - return 0; + return 0; } -__wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( +__wasi_errno_t +wasmtime_ssp_fd_prestat_dir_name( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_prestats *prestats, #endif - __wasi_fd_t fd, - char *path, - size_t path_len -) { - rwlock_rdlock(&prestats->lock); - struct fd_prestat *prestat; - __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); - if (error != 0) { - rwlock_unlock(&prestats->lock); - return error; - } - if (path_len != strlen(prestat->dir)) { - rwlock_unlock(&prestats->lock); - return EINVAL; - } + __wasi_fd_t fd, char *path, size_t path_len) +{ + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); + if (error != 0) { + rwlock_unlock(&prestats->lock); + return error; + } + if (path_len != strlen(prestat->dir)) { + rwlock_unlock(&prestats->lock); + return EINVAL; + } - bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)path_len); + bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)path_len); - rwlock_unlock(&prestats->lock); + rwlock_unlock(&prestats->lock); - return 0; + return 0; } -__wasi_errno_t wasmtime_ssp_fd_close( +__wasi_errno_t +wasmtime_ssp_fd_close( #if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, - struct fd_prestats *prestats, + struct fd_table *curfds, struct fd_prestats *prestats, #endif - __wasi_fd_t fd -) { - // Don't allow closing a pre-opened resource. - // TODO: Eventually, we do want to permit this, once libpreopen in - // userspace is capable of removing entries from its tables as well. - { - rwlock_rdlock(&prestats->lock); - struct fd_prestat *prestat; - __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); - rwlock_unlock(&prestats->lock); - if (error == 0) { - return __WASI_ENOTSUP; + __wasi_fd_t fd) +{ + // Don't allow closing a pre-opened resource. + // TODO: Eventually, we do want to permit this, once libpreopen in + // userspace is capable of removing entries from its tables as well. + { + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); + rwlock_unlock(&prestats->lock); + if (error == 0) { + return __WASI_ENOTSUP; + } } - } - // Validate the file descriptor. - struct fd_table *ft = curfds; - rwlock_wrlock(&ft->lock); - struct fd_entry *fe; - __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); - if (error != 0) { - rwlock_unlock(&ft->lock); - return error; - } + // Validate the file descriptor. + struct fd_table *ft = curfds; + rwlock_wrlock(&ft->lock); + struct fd_entry *fe; + __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } - // Remove it from the file descriptor table. - struct fd_object *fo; - fd_table_detach(ft, fd, &fo); - rwlock_unlock(&ft->lock); - fd_object_release(fo); - return 0; + // Remove it from the file descriptor table. + struct fd_object *fo; + fd_table_detach(ft, fd, &fo); + rwlock_unlock(&ft->lock); + fd_object_release(fo); + return 0; } // Look up a file descriptor object in a locked file descriptor table // and increases its reference count. -static __wasi_errno_t fd_object_get_locked( - struct fd_object **fo, - struct fd_table *ft, - __wasi_fd_t fd, - __wasi_rights_t rights_base, - __wasi_rights_t rights_inheriting -) TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount) REQUIRES_EXCLUSIVE(ft->lock) { - // Test whether the file descriptor number is valid. - struct fd_entry *fe; - __wasi_errno_t error = - fd_table_get_entry(ft, fd, rights_base, rights_inheriting, &fe); - if (error != 0) - return error; - - // Increase the reference count on the file descriptor object. A copy - // of the rights are also stored, so callers can still access those if - // needed. - *fo = fe->object; - refcount_acquire(&(*fo)->refcount); - return 0; +static __wasi_errno_t +fd_object_get_locked(struct fd_object **fo, struct fd_table *ft, __wasi_fd_t fd, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting) + TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount) REQUIRES_EXCLUSIVE(ft->lock) +{ + // Test whether the file descriptor number is valid. + struct fd_entry *fe; + __wasi_errno_t error = + fd_table_get_entry(ft, fd, rights_base, rights_inheriting, &fe); + if (error != 0) + return error; + + // Increase the reference count on the file descriptor object. A copy + // of the rights are also stored, so callers can still access those if + // needed. + *fo = fe->object; + refcount_acquire(&(*fo)->refcount); + return 0; } // Temporarily locks the file descriptor table to look up a file // descriptor object, increases its reference count and drops the lock. -static __wasi_errno_t fd_object_get( - struct fd_table *curfds, - struct fd_object **fo, - __wasi_fd_t fd, - __wasi_rights_t rights_base, - __wasi_rights_t rights_inheriting -) TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount) { - struct fd_table *ft = curfds; - rwlock_rdlock(&ft->lock); - __wasi_errno_t error = - fd_object_get_locked(fo, ft, fd, rights_base, rights_inheriting); - rwlock_unlock(&ft->lock); - return error; -} - -__wasi_errno_t wasmtime_ssp_fd_datasync( +static __wasi_errno_t +fd_object_get(struct fd_table *curfds, struct fd_object **fo, __wasi_fd_t fd, + __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting) + TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount) +{ + struct fd_table *ft = curfds; + rwlock_rdlock(&ft->lock); + __wasi_errno_t error = + fd_object_get_locked(fo, ft, fd, rights_base, rights_inheriting); + rwlock_unlock(&ft->lock); + return error; +} + +__wasi_errno_t +wasmtime_ssp_fd_datasync( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd -) { - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_DATASYNC, 0); - if (error != 0) - return error; + __wasi_fd_t fd) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_DATASYNC, 0); + if (error != 0) + return error; #if CONFIG_HAS_FDATASYNC - int ret = fdatasync(fd_number(fo)); + int ret = fdatasync(fd_number(fo)); #else - int ret = fsync(fd_number(fo)); + int ret = fsync(fd_number(fo)); #endif - fd_object_release(fo); - if (ret < 0) - return convert_errno(errno); - return 0; + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; } -__wasi_errno_t wasmtime_ssp_fd_pread( +__wasi_errno_t +wasmtime_ssp_fd_pread( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - const __wasi_iovec_t *iov, - size_t iovcnt, - __wasi_filesize_t offset, - size_t *nread -) { - if (iovcnt == 0) - return __WASI_EINVAL; + __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, + __wasi_filesize_t offset, size_t *nread) +{ + if (iovcnt == 0) + return __WASI_EINVAL; - struct fd_object *fo; - __wasi_errno_t error = fd_object_get(curfds, - &fo, fd, __WASI_RIGHT_FD_READ, 0); - if (error != 0) - return error; + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READ, 0); + if (error != 0) + return error; #if CONFIG_HAS_PREADV - ssize_t len = - preadv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, (off_t)offset); - fd_object_release(fo); - if (len < 0) - return convert_errno(errno); - *nread = (size_t)len; - return 0; -#else - if (iovcnt == 1) { - ssize_t len = pread(fd_number(fo), iov->buf, iov->buf_len, offset); + ssize_t len = preadv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, + (off_t)offset); fd_object_release(fo); if (len < 0) - return convert_errno(errno); - *nread = len; - return 0; - } else { - // Allocate a single buffer to fit all data. - size_t totalsize = 0; - for (size_t i = 0; i < iovcnt; ++i) - totalsize += iov[i].buf_len; - char *buf = wasm_runtime_malloc(totalsize); - if (buf == NULL) { - fd_object_release(fo); - return __WASI_ENOMEM; - } - - // Perform a single read operation. - ssize_t len = pread(fd_number(fo), buf, totalsize, offset); - fd_object_release(fo); - if (len < 0) { - wasm_runtime_free(buf); - return convert_errno(errno); - } - - // Copy data back to vectors. - size_t bufoff = 0; - for (size_t i = 0; i < iovcnt; ++i) { - if (bufoff + iov[i].buf_len < len) { - bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff, iov[i].buf_len); - bufoff += iov[i].buf_len; - } else { - bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff, len - bufoff); - break; - } - } - wasm_runtime_free(buf); - *nread = len; + return convert_errno(errno); + *nread = (size_t)len; return 0; - } +#else + if (iovcnt == 1) { + ssize_t len = pread(fd_number(fo), iov->buf, iov->buf_len, offset); + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nread = len; + return 0; + } + else { + // Allocate a single buffer to fit all data. + size_t totalsize = 0; + for (size_t i = 0; i < iovcnt; ++i) + totalsize += iov[i].buf_len; + char *buf = wasm_runtime_malloc(totalsize); + if (buf == NULL) { + fd_object_release(fo); + return __WASI_ENOMEM; + } + + // Perform a single read operation. + ssize_t len = pread(fd_number(fo), buf, totalsize, offset); + fd_object_release(fo); + if (len < 0) { + wasm_runtime_free(buf); + return convert_errno(errno); + } + + // Copy data back to vectors. + size_t bufoff = 0; + for (size_t i = 0; i < iovcnt; ++i) { + if (bufoff + iov[i].buf_len < len) { + bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff, + iov[i].buf_len); + bufoff += iov[i].buf_len; + } + else { + bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff, + len - bufoff); + break; + } + } + wasm_runtime_free(buf); + *nread = len; + return 0; + } #endif } -__wasi_errno_t wasmtime_ssp_fd_pwrite( +__wasi_errno_t +wasmtime_ssp_fd_pwrite( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - const __wasi_ciovec_t *iov, - size_t iovcnt, - __wasi_filesize_t offset, - size_t *nwritten -) { - if (iovcnt == 0) - return __WASI_EINVAL; + __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, + __wasi_filesize_t offset, size_t *nwritten) +{ + if (iovcnt == 0) + return __WASI_EINVAL; - struct fd_object *fo; - __wasi_errno_t error = fd_object_get(curfds, - &fo, fd, __WASI_RIGHT_FD_WRITE, 0); - if (error != 0) - return error; + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0); + if (error != 0) + return error; - ssize_t len; + ssize_t len; #if CONFIG_HAS_PWRITEV - len = pwritev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, (off_t)offset); + len = pwritev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, + (off_t)offset); #else - if (iovcnt == 1) { - len = pwrite(fd_number(fo), iov->buf, iov->buf_len, offset); - } else { - // Allocate a single buffer to fit all data. - size_t totalsize = 0; - for (size_t i = 0; i < iovcnt; ++i) - totalsize += iov[i].buf_len; - char *buf = wasm_runtime_malloc(totalsize); - if (buf == NULL) { - fd_object_release(fo); - return __WASI_ENOMEM; - } - size_t bufoff = 0; - for (size_t i = 0; i < iovcnt; ++i) { - bh_memcpy_s(buf + bufoff, totalsize - bufoff, - iov[i].buf, iov[i].buf_len); - bufoff += iov[i].buf_len; - } - - // Perform a single write operation. - len = pwrite(fd_number(fo), buf, totalsize, offset); - wasm_runtime_free(buf); - } -#endif - fd_object_release(fo); - if (len < 0) - return convert_errno(errno); - *nwritten = (size_t)len; - return 0; -} - -__wasi_errno_t wasmtime_ssp_fd_read( + if (iovcnt == 1) { + len = pwrite(fd_number(fo), iov->buf, iov->buf_len, offset); + } + else { + // Allocate a single buffer to fit all data. + size_t totalsize = 0; + for (size_t i = 0; i < iovcnt; ++i) + totalsize += iov[i].buf_len; + char *buf = wasm_runtime_malloc(totalsize); + if (buf == NULL) { + fd_object_release(fo); + return __WASI_ENOMEM; + } + size_t bufoff = 0; + for (size_t i = 0; i < iovcnt; ++i) { + bh_memcpy_s(buf + bufoff, totalsize - bufoff, iov[i].buf, + iov[i].buf_len); + bufoff += iov[i].buf_len; + } + + // Perform a single write operation. + len = pwrite(fd_number(fo), buf, totalsize, offset); + wasm_runtime_free(buf); + } +#endif + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nwritten = (size_t)len; + return 0; +} + +__wasi_errno_t +wasmtime_ssp_fd_read( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - const __wasi_iovec_t *iov, - size_t iovcnt, - size_t *nread -) { - struct fd_object *fo; - __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READ, 0); - if (error != 0) - return error; + __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, size_t *nread) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READ, 0); + if (error != 0) + return error; - ssize_t len = readv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); - fd_object_release(fo); - if (len < 0) - return convert_errno(errno); - *nread = (size_t)len; - return 0; + ssize_t len = readv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nread = (size_t)len; + return 0; } -__wasi_errno_t wasmtime_ssp_fd_renumber( +__wasi_errno_t +wasmtime_ssp_fd_renumber( #if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, - struct fd_prestats *prestats, + struct fd_table *curfds, struct fd_prestats *prestats, #endif - __wasi_fd_t from, - __wasi_fd_t to -) { - // Don't allow renumbering over a pre-opened resource. - // TODO: Eventually, we do want to permit this, once libpreopen in - // userspace is capable of removing entries from its tables as well. - { - rwlock_rdlock(&prestats->lock); - struct fd_prestat *prestat; - __wasi_errno_t error = fd_prestats_get_entry(prestats, to, &prestat); + __wasi_fd_t from, __wasi_fd_t to) +{ + // Don't allow renumbering over a pre-opened resource. + // TODO: Eventually, we do want to permit this, once libpreopen in + // userspace is capable of removing entries from its tables as well. + { + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, to, &prestat); + if (error != 0) { + error = fd_prestats_get_entry(prestats, from, &prestat); + } + rwlock_unlock(&prestats->lock); + if (error == 0) { + return __WASI_ENOTSUP; + } + } + + struct fd_table *ft = curfds; + rwlock_wrlock(&ft->lock); + struct fd_entry *fe_from; + __wasi_errno_t error = fd_table_get_entry(ft, from, 0, 0, &fe_from); if (error != 0) { - error = fd_prestats_get_entry(prestats, from, &prestat); + rwlock_unlock(&ft->lock); + return error; } - rwlock_unlock(&prestats->lock); - if (error == 0) { - return __WASI_ENOTSUP; + struct fd_entry *fe_to; + error = fd_table_get_entry(ft, to, 0, 0, &fe_to); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; } - } - struct fd_table *ft = curfds; - rwlock_wrlock(&ft->lock); - struct fd_entry *fe_from; - __wasi_errno_t error = fd_table_get_entry(ft, from, 0, 0, &fe_from); - if (error != 0) { - rwlock_unlock(&ft->lock); - return error; - } - struct fd_entry *fe_to; - error = fd_table_get_entry(ft, to, 0, 0, &fe_to); - if (error != 0) { - rwlock_unlock(&ft->lock); - return error; - } - - struct fd_object *fo; - fd_table_detach(ft, to, &fo); - refcount_acquire(&fe_from->object->refcount); - fd_table_attach(ft, to, fe_from->object, fe_from->rights_base, - fe_from->rights_inheriting); - fd_object_release(fo); + struct fd_object *fo; + fd_table_detach(ft, to, &fo); + refcount_acquire(&fe_from->object->refcount); + fd_table_attach(ft, to, fe_from->object, fe_from->rights_base, + fe_from->rights_inheriting); + fd_object_release(fo); - // Remove the old fd from the file descriptor table. - fd_table_detach(ft, from, &fo); - fd_object_release(fo); - --ft->used; + // Remove the old fd from the file descriptor table. + fd_table_detach(ft, from, &fo); + fd_object_release(fo); + --ft->used; - rwlock_unlock(&ft->lock); - return 0; + rwlock_unlock(&ft->lock); + return 0; } -__wasi_errno_t wasmtime_ssp_fd_seek( +__wasi_errno_t +wasmtime_ssp_fd_seek( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_filedelta_t offset, - __wasi_whence_t whence, - __wasi_filesize_t *newoffset -) { - int nwhence; - switch (whence) { - case __WASI_WHENCE_CUR: - nwhence = SEEK_CUR; - break; - case __WASI_WHENCE_END: - nwhence = SEEK_END; - break; - case __WASI_WHENCE_SET: - nwhence = SEEK_SET; - break; - default: - return __WASI_EINVAL; - } - - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, - offset == 0 && whence == __WASI_WHENCE_CUR - ? __WASI_RIGHT_FD_TELL - : __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_TELL, - 0); - if (error != 0) - return error; + __wasi_fd_t fd, __wasi_filedelta_t offset, __wasi_whence_t whence, + __wasi_filesize_t *newoffset) +{ + int nwhence; + switch (whence) { + case __WASI_WHENCE_CUR: + nwhence = SEEK_CUR; + break; + case __WASI_WHENCE_END: + nwhence = SEEK_END; + break; + case __WASI_WHENCE_SET: + nwhence = SEEK_SET; + break; + default: + return __WASI_EINVAL; + } - off_t ret = lseek(fd_number(fo), offset, nwhence); - fd_object_release(fo); - if (ret < 0) - return convert_errno(errno); - *newoffset = (__wasi_filesize_t)ret; - return 0; + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, + offset == 0 && whence == __WASI_WHENCE_CUR + ? __WASI_RIGHT_FD_TELL + : __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_TELL, + 0); + if (error != 0) + return error; + + off_t ret = lseek(fd_number(fo), offset, nwhence); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + *newoffset = (__wasi_filesize_t)ret; + return 0; } -__wasi_errno_t wasmtime_ssp_fd_tell( +__wasi_errno_t +wasmtime_ssp_fd_tell( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_filesize_t *newoffset -) { - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_TELL, 0); - if (error != 0) - return error; + __wasi_fd_t fd, __wasi_filesize_t *newoffset) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_TELL, 0); + if (error != 0) + return error; - off_t ret = lseek(fd_number(fo), 0, SEEK_CUR); - fd_object_release(fo); - if (ret < 0) - return convert_errno(errno); - *newoffset = (__wasi_filesize_t)ret; - return 0; + off_t ret = lseek(fd_number(fo), 0, SEEK_CUR); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + *newoffset = (__wasi_filesize_t)ret; + return 0; } -__wasi_errno_t wasmtime_ssp_fd_fdstat_get( +__wasi_errno_t +wasmtime_ssp_fd_fdstat_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_fdstat_t *buf -) { - struct fd_table *ft = curfds; - rwlock_rdlock(&ft->lock); - struct fd_entry *fe; - __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); - if (error != 0) { + __wasi_fd_t fd, __wasi_fdstat_t *buf) +{ + struct fd_table *ft = curfds; + rwlock_rdlock(&ft->lock); + struct fd_entry *fe; + __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } + + // Extract file descriptor type and rights. + struct fd_object *fo = fe->object; + *buf = (__wasi_fdstat_t){ + .fs_filetype = fo->type, + .fs_rights_base = fe->rights_base, + .fs_rights_inheriting = fe->rights_inheriting, + }; + + // Fetch file descriptor flags. + int ret; + switch (fo->type) { + default: + ret = fcntl(fd_number(fo), F_GETFL); + break; + } rwlock_unlock(&ft->lock); - return error; - } - - // Extract file descriptor type and rights. - struct fd_object *fo = fe->object; - *buf = (__wasi_fdstat_t){ - .fs_filetype = fo->type, - .fs_rights_base = fe->rights_base, - .fs_rights_inheriting = fe->rights_inheriting, - }; - - // Fetch file descriptor flags. - int ret; - switch (fo->type) { - default: - ret = fcntl(fd_number(fo), F_GETFL); - break; - } - rwlock_unlock(&ft->lock); - if (ret < 0) - return convert_errno(errno); - - if ((ret & O_APPEND) != 0) - buf->fs_flags |= __WASI_FDFLAG_APPEND; + if (ret < 0) + return convert_errno(errno); + + if ((ret & O_APPEND) != 0) + buf->fs_flags |= __WASI_FDFLAG_APPEND; #ifdef O_DSYNC - if ((ret & O_DSYNC) != 0) - buf->fs_flags |= __WASI_FDFLAG_DSYNC; + if ((ret & O_DSYNC) != 0) + buf->fs_flags |= __WASI_FDFLAG_DSYNC; #endif - if ((ret & O_NONBLOCK) != 0) - buf->fs_flags |= __WASI_FDFLAG_NONBLOCK; + if ((ret & O_NONBLOCK) != 0) + buf->fs_flags |= __WASI_FDFLAG_NONBLOCK; #ifdef O_RSYNC - if ((ret & O_RSYNC) != 0) - buf->fs_flags |= __WASI_FDFLAG_RSYNC; + if ((ret & O_RSYNC) != 0) + buf->fs_flags |= __WASI_FDFLAG_RSYNC; #endif - if ((ret & O_SYNC) != 0) - buf->fs_flags |= __WASI_FDFLAG_SYNC; - return 0; + if ((ret & O_SYNC) != 0) + buf->fs_flags |= __WASI_FDFLAG_SYNC; + return 0; } -__wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags( +__wasi_errno_t +wasmtime_ssp_fd_fdstat_set_flags( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_fdflags_t fs_flags -) { - int noflags = 0; - if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) - noflags |= O_APPEND; - if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) + __wasi_fd_t fd, __wasi_fdflags_t fs_flags) +{ + int noflags = 0; + if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) + noflags |= O_APPEND; + if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) #ifdef O_DSYNC - noflags |= O_DSYNC; + noflags |= O_DSYNC; #else - noflags |= O_SYNC; + noflags |= O_SYNC; #endif - if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) - noflags |= O_NONBLOCK; - if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) + if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) + noflags |= O_NONBLOCK; + if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) #ifdef O_RSYNC - noflags |= O_RSYNC; + noflags |= O_RSYNC; #else - noflags |= O_SYNC; + noflags |= O_SYNC; #endif - if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) - noflags |= O_SYNC; + if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) + noflags |= O_SYNC; - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FDSTAT_SET_FLAGS, 0); - if (error != 0) - return error; + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FDSTAT_SET_FLAGS, 0); + if (error != 0) + return error; - int ret = fcntl(fd_number(fo), F_SETFL, noflags); - fd_object_release(fo); - if (ret < 0) - return convert_errno(errno); - return 0; + int ret = fcntl(fd_number(fo), F_SETFL, noflags); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; } -__wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights( +__wasi_errno_t +wasmtime_ssp_fd_fdstat_set_rights( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_rights_t fs_rights_base, - __wasi_rights_t fs_rights_inheriting -) { - struct fd_table *ft = curfds; - rwlock_wrlock(&ft->lock); - struct fd_entry *fe; - __wasi_errno_t error = - fd_table_get_entry(ft, fd, fs_rights_base, fs_rights_inheriting, &fe); - if (error != 0) { - rwlock_unlock(&ft->lock); - return error; - } + __wasi_fd_t fd, __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting) +{ + struct fd_table *ft = curfds; + rwlock_wrlock(&ft->lock); + struct fd_entry *fe; + __wasi_errno_t error = + fd_table_get_entry(ft, fd, fs_rights_base, fs_rights_inheriting, &fe); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } - // Restrict the rights on the file descriptor. - fe->rights_base = fs_rights_base; - fe->rights_inheriting = fs_rights_inheriting; - rwlock_unlock(&ft->lock); - return 0; + // Restrict the rights on the file descriptor. + fe->rights_base = fs_rights_base; + fe->rights_inheriting = fs_rights_inheriting; + rwlock_unlock(&ft->lock); + return 0; } -__wasi_errno_t wasmtime_ssp_fd_sync( +__wasi_errno_t +wasmtime_ssp_fd_sync( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd -) { - struct fd_object *fo; - __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_SYNC, 0); - if (error != 0) - return error; + __wasi_fd_t fd) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_SYNC, 0); + if (error != 0) + return error; - int ret = fsync(fd_number(fo)); - fd_object_release(fo); - if (ret < 0) - return convert_errno(errno); - return 0; + int ret = fsync(fd_number(fo)); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; } -__wasi_errno_t wasmtime_ssp_fd_write( +__wasi_errno_t +wasmtime_ssp_fd_write( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - const __wasi_ciovec_t *iov, - size_t iovcnt, - size_t *nwritten -) { - struct fd_object *fo; - __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0); - if (error != 0) - return error; + __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, size_t *nwritten) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0); + if (error != 0) + return error; #ifndef BH_VPRINTF - ssize_t len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); + ssize_t len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); #else - ssize_t len = 0; - /* redirect stdout/stderr output to BH_VPRINTF function */ - if (fd_number(fo) == 1 || fd_number(fo) == 2) { - int i; - const struct iovec *iov1 = (const struct iovec *)iov; - - for (i = 0; i < (int)iovcnt; i++, iov1++) { - if (iov1->iov_len > 0 && iov1->iov_base) { - char format[16]; - - /* make up format string "%.ns" */ - snprintf(format, sizeof(format), "%%.%ds", (int)iov1->iov_len); - len += (ssize_t)os_printf(format, iov1->iov_base); - } - } - } - else { - len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); - } + ssize_t len = 0; + /* redirect stdout/stderr output to BH_VPRINTF function */ + if (fd_number(fo) == 1 || fd_number(fo) == 2) { + int i; + const struct iovec *iov1 = (const struct iovec *)iov; + + for (i = 0; i < (int)iovcnt; i++, iov1++) { + if (iov1->iov_len > 0 && iov1->iov_base) { + char format[16]; + + /* make up format string "%.ns" */ + snprintf(format, sizeof(format), "%%.%ds", (int)iov1->iov_len); + len += (ssize_t)os_printf(format, iov1->iov_base); + } + } + } + else { + len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); + } #endif /* end of BH_VPRINTF */ - fd_object_release(fo); - if (len < 0) - return convert_errno(errno); - *nwritten = (size_t)len; - return 0; + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nwritten = (size_t)len; + return 0; } -__wasi_errno_t wasmtime_ssp_fd_advise( +__wasi_errno_t +wasmtime_ssp_fd_advise( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_filesize_t offset, - __wasi_filesize_t len, - __wasi_advice_t advice -) { + __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len, + __wasi_advice_t advice) +{ #ifdef POSIX_FADV_NORMAL - int nadvice; - switch (advice) { - case __WASI_ADVICE_DONTNEED: - nadvice = POSIX_FADV_DONTNEED; - break; - case __WASI_ADVICE_NOREUSE: - nadvice = POSIX_FADV_NOREUSE; - break; - case __WASI_ADVICE_NORMAL: - nadvice = POSIX_FADV_NORMAL; - break; - case __WASI_ADVICE_RANDOM: - nadvice = POSIX_FADV_RANDOM; - break; - case __WASI_ADVICE_SEQUENTIAL: - nadvice = POSIX_FADV_SEQUENTIAL; - break; - case __WASI_ADVICE_WILLNEED: - nadvice = POSIX_FADV_WILLNEED; - break; - default: - return __WASI_EINVAL; - } - - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ADVISE, 0); - if (error != 0) - return error; + int nadvice; + switch (advice) { + case __WASI_ADVICE_DONTNEED: + nadvice = POSIX_FADV_DONTNEED; + break; + case __WASI_ADVICE_NOREUSE: + nadvice = POSIX_FADV_NOREUSE; + break; + case __WASI_ADVICE_NORMAL: + nadvice = POSIX_FADV_NORMAL; + break; + case __WASI_ADVICE_RANDOM: + nadvice = POSIX_FADV_RANDOM; + break; + case __WASI_ADVICE_SEQUENTIAL: + nadvice = POSIX_FADV_SEQUENTIAL; + break; + case __WASI_ADVICE_WILLNEED: + nadvice = POSIX_FADV_WILLNEED; + break; + default: + return __WASI_EINVAL; + } + + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ADVISE, 0); + if (error != 0) + return error; - int ret = posix_fadvise(fd_number(fo), (off_t)offset, (off_t)len, nadvice); - fd_object_release(fo); - if (ret != 0) - return convert_errno(ret); - return 0; + int ret = posix_fadvise(fd_number(fo), (off_t)offset, (off_t)len, nadvice); + fd_object_release(fo); + if (ret != 0) + return convert_errno(ret); + return 0; #else - // Advisory information can safely be ignored if unsupported. - switch (advice) { - case __WASI_ADVICE_DONTNEED: - case __WASI_ADVICE_NOREUSE: - case __WASI_ADVICE_NORMAL: - case __WASI_ADVICE_RANDOM: - case __WASI_ADVICE_SEQUENTIAL: - case __WASI_ADVICE_WILLNEED: - break; - default: - return __WASI_EINVAL; - } - - // At least check for file descriptor existence. - struct fd_table *ft = curfds; - rwlock_rdlock(&ft->lock); - struct fd_entry *fe; - __wasi_errno_t error = - fd_table_get_entry(ft, fd, __WASI_RIGHT_FD_ADVISE, 0, &fe); - rwlock_unlock(&ft->lock); - return error; -#endif -} - -__wasi_errno_t wasmtime_ssp_fd_allocate( + // Advisory information can safely be ignored if unsupported. + switch (advice) { + case __WASI_ADVICE_DONTNEED: + case __WASI_ADVICE_NOREUSE: + case __WASI_ADVICE_NORMAL: + case __WASI_ADVICE_RANDOM: + case __WASI_ADVICE_SEQUENTIAL: + case __WASI_ADVICE_WILLNEED: + break; + default: + return __WASI_EINVAL; + } + + // At least check for file descriptor existence. + struct fd_table *ft = curfds; + rwlock_rdlock(&ft->lock); + struct fd_entry *fe; + __wasi_errno_t error = + fd_table_get_entry(ft, fd, __WASI_RIGHT_FD_ADVISE, 0, &fe); + rwlock_unlock(&ft->lock); + return error; +#endif +} + +__wasi_errno_t +wasmtime_ssp_fd_allocate( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_filesize_t offset, - __wasi_filesize_t len -) { - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ALLOCATE, 0); - if (error != 0) - return error; + __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ALLOCATE, 0); + if (error != 0) + return error; #if CONFIG_HAS_POSIX_FALLOCATE - int ret = posix_fallocate(fd_number(fo), (off_t)offset, (off_t)len); + int ret = posix_fallocate(fd_number(fo), (off_t)offset, (off_t)len); #else - // At least ensure that the file is grown to the right size. - // TODO(ed): See if this can somehow be implemented without any race - // conditions. We may end up shrinking the file right now. - struct stat sb; - int ret = fstat(fd_number(fo), &sb); - if (ret == 0 && sb.st_size < offset + len) - ret = ftruncate(fd_number(fo), offset + len); + // At least ensure that the file is grown to the right size. + // TODO(ed): See if this can somehow be implemented without any race + // conditions. We may end up shrinking the file right now. + struct stat sb; + int ret = fstat(fd_number(fo), &sb); + if (ret == 0 && sb.st_size < offset + len) + ret = ftruncate(fd_number(fo), offset + len); #endif - fd_object_release(fo); - if (ret != 0) - return convert_errno(ret); - return 0; + fd_object_release(fo); + if (ret != 0) + return convert_errno(ret); + return 0; } // Reads the entire contents of a symbolic link, returning the contents // in an allocated buffer. The allocated buffer is large enough to fit // at least one extra byte, so the caller may append a trailing slash to // it. This is needed by path_get(). -static char *readlinkat_dup( - int fd, - const char *path, - size_t *p_len -) { - char *buf = NULL; - size_t len = 32; - size_t len_org = len; +static char * +readlinkat_dup(int fd, const char *path, size_t *p_len) +{ + char *buf = NULL; + size_t len = 32; + size_t len_org = len; - for (;;) { - char *newbuf = wasm_runtime_malloc((uint32)len); + for (;;) { + char *newbuf = wasm_runtime_malloc((uint32)len); - if (newbuf == NULL) { - if (buf) - wasm_runtime_free(buf); - return NULL; - } + if (newbuf == NULL) { + if (buf) + wasm_runtime_free(buf); + return NULL; + } - if (buf != NULL) { - bh_memcpy_s(newbuf, (uint32)len, buf, (uint32)len_org); - wasm_runtime_free(buf); - } + if (buf != NULL) { + bh_memcpy_s(newbuf, (uint32)len, buf, (uint32)len_org); + wasm_runtime_free(buf); + } - buf = newbuf; - ssize_t ret = readlinkat(fd, path, buf, len); - if (ret < 0) { - wasm_runtime_free(buf); - return NULL; - } - if ((size_t)ret + 1 < len) { - buf[ret] = '\0'; - *p_len = len; - return buf; + buf = newbuf; + ssize_t ret = readlinkat(fd, path, buf, len); + if (ret < 0) { + wasm_runtime_free(buf); + return NULL; + } + if ((size_t)ret + 1 < len) { + buf[ret] = '\0'; + *p_len = len; + return buf; + } + len_org = len; + len *= 2; } - len_org = len; - len *= 2; - } } // Lease to a directory, so a path underneath it can be accessed. @@ -1419,288 +1413,286 @@ static char *readlinkat_dup( // descriptor representing the directory where the lookup needs to start // and the actual pathname string. struct path_access { - int fd; // Directory file descriptor. - const char *path; // Pathname. - bool follow; // Whether symbolic links should be followed. - char *path_start; // Internal: pathname to free. - struct fd_object *fd_object; // Internal: directory file descriptor object. + int fd; // Directory file descriptor. + const char *path; // Pathname. + bool follow; // Whether symbolic links should be followed. + char *path_start; // Internal: pathname to free. + struct fd_object *fd_object; // Internal: directory file descriptor object. }; // Creates a lease to a file descriptor and pathname pair. If the // operating system does not implement Capsicum, it also normalizes the // pathname to ensure the target path is placed underneath the // directory. -static __wasi_errno_t path_get( - struct fd_table *curfds, - struct path_access *pa, - __wasi_fd_t fd, - __wasi_lookupflags_t flags, - const char *upath, - size_t upathlen, - __wasi_rights_t rights_base, - __wasi_rights_t rights_inheriting, - bool needs_final_component -) TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount) { - char *path = str_nullterminate(upath, upathlen); - if (path == NULL) - return convert_errno(errno); - - // Fetch the directory file descriptor. - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, rights_base, rights_inheriting); - if (error != 0) { - wasm_runtime_free(path); - return error; - } +static __wasi_errno_t +path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd, + __wasi_lookupflags_t flags, const char *upath, size_t upathlen, + __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting, + bool needs_final_component) + TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount) +{ + char *path = str_nullterminate(upath, upathlen); + if (path == NULL) + return convert_errno(errno); + + // Fetch the directory file descriptor. + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, rights_base, rights_inheriting); + if (error != 0) { + wasm_runtime_free(path); + return error; + } #if CONFIG_HAS_CAP_ENTER - // Rely on the kernel to constrain access to automatically constrain - // access to files stored underneath this directory. - pa->fd = fd_number(fo); - pa->path = pa->path_start = path; - pa->follow = (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0; - pa->fd_object = fo; - return 0; + // Rely on the kernel to constrain access to automatically constrain + // access to files stored underneath this directory. + pa->fd = fd_number(fo); + pa->path = pa->path_start = path; + pa->follow = (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0; + pa->fd_object = fo; + return 0; #else - // The implementation provides no mechanism to constrain lookups to a - // directory automatically. Emulate this logic by resolving the - // pathname manually. - - // Stack of directory file descriptors. Index 0 always corresponds - // with the directory provided to this function. Entering a directory - // causes a file descriptor to be pushed, while handling ".." entries - // causes an entry to be popped. Index 0 cannot be popped, as this - // would imply escaping the base directory. - int fds[128]; - fds[0] = fd_number(fo); - size_t curfd = 0; - - // Stack of pathname strings used for symlink expansion. By using a - // stack, there is no need to concatenate any pathname strings while - // expanding symlinks. - char *paths[32]; - char *paths_start[32]; - paths[0] = paths_start[0] = path; - size_t curpath = 0; - size_t expansions = 0; - char *symlink; - size_t symlink_len; - - for (;;) { - // Extract the next pathname component from 'paths[curpath]', null - // terminate it and store it in 'file'. 'ends_with_slashes' stores - // whether the pathname component is followed by one or more - // trailing slashes, as this requires it to be a directory. - char *file = paths[curpath]; - char *file_end = file + strcspn(file, "/"); - paths[curpath] = file_end + strspn(file_end, "/"); - bool ends_with_slashes = *file_end == '/'; - *file_end = '\0'; - - // Test for empty pathname strings and absolute paths. - if (file == file_end) { - error = ends_with_slashes ? __WASI_ENOTCAPABLE : __WASI_ENOENT; - goto fail; - } - - if (strcmp(file, ".") == 0) { - // Skip component. - } else if (strcmp(file, "..") == 0) { - // Pop a directory off the stack. - if (curfd == 0) { - // Attempted to go to parent directory of the directory file - // descriptor. - error = __WASI_ENOTCAPABLE; - goto fail; - } - close(fds[curfd--]); - } else if (curpath > 0 || *paths[curpath] != '\0' || - (ends_with_slashes && !needs_final_component)) { - // A pathname component whose name we're not interested in that is - // followed by a slash or is followed by other pathname - // components. In other words, a pathname component that must be a - // directory. First attempt to obtain a directory file descriptor - // for it. - int newdir = + // The implementation provides no mechanism to constrain lookups to a + // directory automatically. Emulate this logic by resolving the + // pathname manually. + + // Stack of directory file descriptors. Index 0 always corresponds + // with the directory provided to this function. Entering a directory + // causes a file descriptor to be pushed, while handling ".." entries + // causes an entry to be popped. Index 0 cannot be popped, as this + // would imply escaping the base directory. + int fds[128]; + fds[0] = fd_number(fo); + size_t curfd = 0; + + // Stack of pathname strings used for symlink expansion. By using a + // stack, there is no need to concatenate any pathname strings while + // expanding symlinks. + char *paths[32]; + char *paths_start[32]; + paths[0] = paths_start[0] = path; + size_t curpath = 0; + size_t expansions = 0; + char *symlink; + size_t symlink_len; + + for (;;) { + // Extract the next pathname component from 'paths[curpath]', null + // terminate it and store it in 'file'. 'ends_with_slashes' stores + // whether the pathname component is followed by one or more + // trailing slashes, as this requires it to be a directory. + char *file = paths[curpath]; + char *file_end = file + strcspn(file, "/"); + paths[curpath] = file_end + strspn(file_end, "/"); + bool ends_with_slashes = *file_end == '/'; + *file_end = '\0'; + + // Test for empty pathname strings and absolute paths. + if (file == file_end) { + error = ends_with_slashes ? __WASI_ENOTCAPABLE : __WASI_ENOENT; + goto fail; + } + + if (strcmp(file, ".") == 0) { + // Skip component. + } + else if (strcmp(file, "..") == 0) { + // Pop a directory off the stack. + if (curfd == 0) { + // Attempted to go to parent directory of the directory file + // descriptor. + error = __WASI_ENOTCAPABLE; + goto fail; + } + close(fds[curfd--]); + } + else if (curpath > 0 || *paths[curpath] != '\0' + || (ends_with_slashes && !needs_final_component)) { + // A pathname component whose name we're not interested in that is + // followed by a slash or is followed by other pathname + // components. In other words, a pathname component that must be a + // directory. First attempt to obtain a directory file descriptor + // for it. + int newdir = #ifdef O_SEARCH - openat(fds[curfd], file, O_SEARCH | O_DIRECTORY | O_NOFOLLOW); + openat(fds[curfd], file, O_SEARCH | O_DIRECTORY | O_NOFOLLOW); #else - openat(fds[curfd], file, O_RDONLY | O_DIRECTORY | O_NOFOLLOW); -#endif - if (newdir != -1) { - // Success. Push it onto the directory stack. - if (curfd + 1 == sizeof(fds) / sizeof(fds[0])) { - close(newdir); - error = __WASI_ENAMETOOLONG; - goto fail; + openat(fds[curfd], file, O_RDONLY | O_DIRECTORY | O_NOFOLLOW); +#endif + if (newdir != -1) { + // Success. Push it onto the directory stack. + if (curfd + 1 == sizeof(fds) / sizeof(fds[0])) { + close(newdir); + error = __WASI_ENAMETOOLONG; + goto fail; + } + fds[++curfd] = newdir; + } + else { + // Failed to open it. Attempt symlink expansion. + if (errno != ELOOP && errno != EMLINK && errno != ENOTDIR) { + error = convert_errno(errno); + goto fail; + } + symlink = readlinkat_dup(fds[curfd], file, &symlink_len); + if (symlink != NULL) + goto push_symlink; + + // readlink returns EINVAL if the path isn't a symlink. In that + // case, it's more informative to return ENOTDIR. + if (errno == EINVAL) + errno = ENOTDIR; + + error = convert_errno(errno); + goto fail; + } } - fds[++curfd] = newdir; - } else { - // Failed to open it. Attempt symlink expansion. - if (errno != ELOOP && errno != EMLINK && errno != ENOTDIR) { - error = convert_errno(errno); - goto fail; + else { + // The final pathname component. Depending on whether it ends with + // a slash or the symlink-follow flag is set, perform symlink + // expansion. + if (ends_with_slashes + || (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0) { + symlink = readlinkat_dup(fds[curfd], file, &symlink_len); + if (symlink != NULL) + goto push_symlink; + if (errno != EINVAL && errno != ENOENT) { + error = convert_errno(errno); + goto fail; + } + } + + // Not a symlink, meaning we're done. Return the filename, + // together with the directory containing this file. + // + // If the file was followed by a trailing slash, we must retain + // it, to ensure system calls properly return ENOTDIR. + // Unfortunately, this opens up a race condition, because this + // means that users of path_get() will perform symlink expansion a + // second time. There is nothing we can do to mitigate this, as + // far as I know. + if (ends_with_slashes) + *file_end = '/'; + pa->path = file; + pa->path_start = paths_start[0]; + goto success; } - symlink = readlinkat_dup(fds[curfd], file, &symlink_len); - if (symlink != NULL) - goto push_symlink; - // readlink returns EINVAL if the path isn't a symlink. In that case, - // it's more informative to return ENOTDIR. - if (errno == EINVAL) - errno = ENOTDIR; + if (*paths[curpath] == '\0') { + if (curpath == 0) { + // No further pathname components to process. We may end up here + // when called on paths like ".", "a/..", but also if the path + // had trailing slashes and the caller is not interested in the + // name of the pathname component. + wasm_runtime_free(paths_start[0]); + pa->path = "."; + pa->path_start = NULL; + goto success; + } - error = convert_errno(errno); - goto fail; - } - } else { - // The final pathname component. Depending on whether it ends with - // a slash or the symlink-follow flag is set, perform symlink - // expansion. - if (ends_with_slashes || - (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0) { - symlink = readlinkat_dup(fds[curfd], file, &symlink_len); - if (symlink != NULL) - goto push_symlink; - if (errno != EINVAL && errno != ENOENT) { - error = convert_errno(errno); - goto fail; + // Finished expanding symlink. Continue processing along the + // original path. + wasm_runtime_free(paths_start[curpath--]); + } + continue; + + push_symlink: + // Prevent infinite loops by placing an upper limit on the number of + // symlink expansions. + if (++expansions == 128) { + wasm_runtime_free(symlink); + error = __WASI_ELOOP; + goto fail; + } + + if (*paths[curpath] == '\0') { + // The original path already finished processing. Replace it by + // this symlink entirely. + wasm_runtime_free(paths_start[curpath]); + } + else if (curpath + 1 == sizeof(paths) / sizeof(paths[0])) { + // Too many nested symlinks. Stop processing. + wasm_runtime_free(symlink); + error = __WASI_ELOOP; + goto fail; + } + else { + // The original path still has components left. Retain the + // components that remain, so we can process them afterwards. + ++curpath; } - } - - // Not a symlink, meaning we're done. Return the filename, - // together with the directory containing this file. - // - // If the file was followed by a trailing slash, we must retain - // it, to ensure system calls properly return ENOTDIR. - // Unfortunately, this opens up a race condition, because this - // means that users of path_get() will perform symlink expansion a - // second time. There is nothing we can do to mitigate this, as - // far as I know. - if (ends_with_slashes) - *file_end = '/'; - pa->path = file; - pa->path_start = paths_start[0]; - goto success; - } - - if (*paths[curpath] == '\0') { - if (curpath == 0) { - // No further pathname components to process. We may end up here - // when called on paths like ".", "a/..", but also if the path - // had trailing slashes and the caller is not interested in the - // name of the pathname component. - wasm_runtime_free(paths_start[0]); - pa->path = "."; - pa->path_start = NULL; - goto success; - } - - // Finished expanding symlink. Continue processing along the - // original path. - wasm_runtime_free(paths_start[curpath--]); - } - continue; - - push_symlink: - // Prevent infinite loops by placing an upper limit on the number of - // symlink expansions. - if (++expansions == 128) { - wasm_runtime_free(symlink); - error = __WASI_ELOOP; - goto fail; - } - - if (*paths[curpath] == '\0') { - // The original path already finished processing. Replace it by - // this symlink entirely. - wasm_runtime_free(paths_start[curpath]); - } else if (curpath + 1 == sizeof(paths) / sizeof(paths[0])) { - // Too many nested symlinks. Stop processing. - wasm_runtime_free(symlink); - error = __WASI_ELOOP; - goto fail; - } else { - // The original path still has components left. Retain the - // components that remain, so we can process them afterwards. - ++curpath; - } - - // Append a trailing slash to the symlink if the path leading up to - // it also contained one. Otherwise we would not throw ENOTDIR if - // the target is not a directory. - if (ends_with_slashes) - bh_strcat_s(symlink, (uint32)symlink_len, "/"); - paths[curpath] = paths_start[curpath] = symlink; - } + + // Append a trailing slash to the symlink if the path leading up to + // it also contained one. Otherwise we would not throw ENOTDIR if + // the target is not a directory. + if (ends_with_slashes) + bh_strcat_s(symlink, (uint32)symlink_len, "/"); + paths[curpath] = paths_start[curpath] = symlink; + } success: - // Return the lease. Close all directories, except the one the caller - // needs to use. - for (size_t i = 1; i < curfd; ++i) - close(fds[i]); - pa->fd = fds[curfd]; - pa->follow = false; - pa->fd_object = fo; - return 0; + // Return the lease. Close all directories, except the one the caller + // needs to use. + for (size_t i = 1; i < curfd; ++i) + close(fds[i]); + pa->fd = fds[curfd]; + pa->follow = false; + pa->fd_object = fo; + return 0; fail: - // Failure. Free all resources. - for (size_t i = 1; i <= curfd; ++i) - close(fds[i]); - for (size_t i = 0; i <= curpath; ++i) - wasm_runtime_free(paths_start[i]); - fd_object_release(fo); - return error; + // Failure. Free all resources. + for (size_t i = 1; i <= curfd; ++i) + close(fds[i]); + for (size_t i = 0; i <= curpath; ++i) + wasm_runtime_free(paths_start[i]); + fd_object_release(fo); + return error; #endif } -static __wasi_errno_t path_get_nofollow( - struct fd_table *curfds, - struct path_access *pa, - __wasi_fd_t fd, - const char *path, - size_t pathlen, - __wasi_rights_t rights_base, - __wasi_rights_t rights_inheriting, - bool needs_final_component -) TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount) { - __wasi_lookupflags_t flags = 0; - return path_get(curfds, pa, fd, flags, path, pathlen, rights_base, rights_inheriting, - needs_final_component); -} - -static void path_put( - struct path_access *pa -) UNLOCKS(pa->fd_object->refcount) { - if (pa->path_start) - wasm_runtime_free(pa->path_start); - if (fd_number(pa->fd_object) != pa->fd) - close(pa->fd); - fd_object_release(pa->fd_object); -} - -__wasi_errno_t wasmtime_ssp_path_create_directory( +static __wasi_errno_t +path_get_nofollow(struct fd_table *curfds, struct path_access *pa, + __wasi_fd_t fd, const char *path, size_t pathlen, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, bool needs_final_component) + TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount) +{ + __wasi_lookupflags_t flags = 0; + return path_get(curfds, pa, fd, flags, path, pathlen, rights_base, + rights_inheriting, needs_final_component); +} + +static void +path_put(struct path_access *pa) UNLOCKS(pa->fd_object->refcount) +{ + if (pa->path_start) + wasm_runtime_free(pa->path_start); + if (fd_number(pa->fd_object) != pa->fd) + close(pa->fd); + fd_object_release(pa->fd_object); +} + +__wasi_errno_t +wasmtime_ssp_path_create_directory( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - const char *path, - size_t pathlen -) { - struct path_access pa; - __wasi_errno_t error = - path_get_nofollow(curfds, &pa, fd, path, pathlen, - __WASI_RIGHT_PATH_CREATE_DIRECTORY, 0, true); - if (error != 0) - return error; - - int ret = mkdirat(pa.fd, pa.path, 0777); - path_put(&pa); - if (ret < 0) - return convert_errno(errno); - return 0; + __wasi_fd_t fd, const char *path, size_t pathlen) +{ + struct path_access pa; + __wasi_errno_t error = + path_get_nofollow(curfds, &pa, fd, path, pathlen, + __WASI_RIGHT_PATH_CREATE_DIRECTORY, 0, true); + if (error != 0) + return error; + + int ret = mkdirat(pa.fd, pa.path, 0777); + path_put(&pa); + if (ret < 0) + return convert_errno(errno); + return 0; } static bool @@ -1719,8 +1711,8 @@ validate_path(const char *path, struct fd_prestats *pt) for (i = 0; i < pt->size; i++) { if (pt->prestats[i].dir) { - if (!(prestat_dir_real = realpath(pt->prestats[i].dir, - prestat_dir_resolved))) + if (!(prestat_dir_real = + realpath(pt->prestats[i].dir, prestat_dir_resolved))) return false; if (!strncmp(path_real, prestat_dir_real, strlen(prestat_dir_real))) return true; @@ -1730,939 +1722,945 @@ validate_path(const char *path, struct fd_prestats *pt) return false; } -__wasi_errno_t wasmtime_ssp_path_link( +__wasi_errno_t +wasmtime_ssp_path_link( #if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, - struct fd_prestats *prestats, + struct fd_table *curfds, struct fd_prestats *prestats, #endif - __wasi_fd_t old_fd, - __wasi_lookupflags_t old_flags, - const char *old_path, - size_t old_path_len, - __wasi_fd_t new_fd, - const char *new_path, - size_t new_path_len -) { - struct path_access old_pa; - __wasi_errno_t error = path_get(curfds, &old_pa, old_fd, old_flags, old_path, old_path_len, - __WASI_RIGHT_PATH_LINK_SOURCE, 0, false); - if (error != 0) - return error; + __wasi_fd_t old_fd, __wasi_lookupflags_t old_flags, const char *old_path, + size_t old_path_len, __wasi_fd_t new_fd, const char *new_path, + size_t new_path_len) +{ + struct path_access old_pa; + __wasi_errno_t error = + path_get(curfds, &old_pa, old_fd, old_flags, old_path, old_path_len, + __WASI_RIGHT_PATH_LINK_SOURCE, 0, false); + if (error != 0) + return error; + + struct path_access new_pa; + error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len, + __WASI_RIGHT_PATH_LINK_TARGET, 0, true); + if (error != 0) { + path_put(&old_pa); + return error; + } + + rwlock_rdlock(&prestats->lock); + if (!validate_path(old_pa.path, prestats) + || !validate_path(new_pa.path, prestats)) { + rwlock_unlock(&prestats->lock); + return __WASI_EBADF; + } + rwlock_unlock(&prestats->lock); - struct path_access new_pa; - error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len, - __WASI_RIGHT_PATH_LINK_TARGET, 0, true); - if (error != 0) { + int ret = linkat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path, + old_pa.follow ? AT_SYMLINK_FOLLOW : 0); + if (ret < 0 && errno == ENOTSUP && !old_pa.follow) { + // OS X doesn't allow creating hardlinks to symbolic links. + // Duplicate the symbolic link instead. + size_t target_len; + char *target = readlinkat_dup(old_pa.fd, old_pa.path, &target_len); + if (target != NULL) { + bh_assert(target[target_len] == '\0'); + rwlock_rdlock(&prestats->lock); + if (!validate_path(target, prestats)) { + rwlock_unlock(&prestats->lock); + wasm_runtime_free(target); + return __WASI_EBADF; + } + rwlock_unlock(&prestats->lock); + ret = symlinkat(target, new_pa.fd, new_pa.path); + wasm_runtime_free(target); + } + } path_put(&old_pa); - return error; - } - - rwlock_rdlock(&prestats->lock); - if (!validate_path(old_pa.path, prestats) - || !validate_path(new_pa.path, prestats)) { - rwlock_unlock(&prestats->lock); - return __WASI_EBADF; - } - rwlock_unlock(&prestats->lock); - - int ret = linkat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path, - old_pa.follow ? AT_SYMLINK_FOLLOW : 0); - if (ret < 0 && errno == ENOTSUP && !old_pa.follow) { - // OS X doesn't allow creating hardlinks to symbolic links. - // Duplicate the symbolic link instead. - size_t target_len; - char *target = readlinkat_dup(old_pa.fd, old_pa.path, &target_len); - if (target != NULL) { - bh_assert(target[target_len] == '\0'); - rwlock_rdlock(&prestats->lock); - if (!validate_path(target, prestats)) { - rwlock_unlock(&prestats->lock); - wasm_runtime_free(target); - return __WASI_EBADF; - } - rwlock_unlock(&prestats->lock); - ret = symlinkat(target, new_pa.fd, new_pa.path); - wasm_runtime_free(target); - } - } - path_put(&old_pa); - path_put(&new_pa); - if (ret < 0) - return convert_errno(errno); - return 0; -} - -__wasi_errno_t wasmtime_ssp_path_open( + path_put(&new_pa); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t +wasmtime_ssp_path_open( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t dirfd, - __wasi_lookupflags_t dirflags, - const char *path, - size_t pathlen, - __wasi_oflags_t oflags, - __wasi_rights_t fs_rights_base, - __wasi_rights_t fs_rights_inheriting, - __wasi_fdflags_t fs_flags, - __wasi_fd_t *fd -) { - // Rights that should be installed on the new file descriptor. - __wasi_rights_t rights_base = fs_rights_base; - __wasi_rights_t rights_inheriting = fs_rights_inheriting; - - // Which open() mode should be used to satisfy the needed rights. - bool read = - (rights_base & (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_READDIR)) != 0; - bool write = - (rights_base & (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_WRITE | - __WASI_RIGHT_FD_ALLOCATE | - __WASI_RIGHT_FD_FILESTAT_SET_SIZE)) != 0; - int noflags = write ? read ? O_RDWR : O_WRONLY : O_RDONLY; - - // Which rights are needed on the directory file descriptor. - __wasi_rights_t needed_base = __WASI_RIGHT_PATH_OPEN; - __wasi_rights_t needed_inheriting = rights_base | rights_inheriting; - - // Convert open flags. - if ((oflags & __WASI_O_CREAT) != 0) { - noflags |= O_CREAT; - needed_base |= __WASI_RIGHT_PATH_CREATE_FILE; - } - if ((oflags & __WASI_O_DIRECTORY) != 0) - noflags |= O_DIRECTORY; - if ((oflags & __WASI_O_EXCL) != 0) - noflags |= O_EXCL; - if ((oflags & __WASI_O_TRUNC) != 0) { - noflags |= O_TRUNC; - needed_base |= __WASI_RIGHT_PATH_FILESTAT_SET_SIZE; - } - - // Convert file descriptor flags. - if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) - noflags |= O_APPEND; - if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) { + __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, const char *path, + size_t pathlen, __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting, __wasi_fdflags_t fs_flags, + __wasi_fd_t *fd) +{ + // Rights that should be installed on the new file descriptor. + __wasi_rights_t rights_base = fs_rights_base; + __wasi_rights_t rights_inheriting = fs_rights_inheriting; + + // Which open() mode should be used to satisfy the needed rights. + bool read = + (rights_base & (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_READDIR)) != 0; + bool write = + (rights_base + & (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_WRITE + | __WASI_RIGHT_FD_ALLOCATE | __WASI_RIGHT_FD_FILESTAT_SET_SIZE)) + != 0; + int noflags = write ? read ? O_RDWR : O_WRONLY : O_RDONLY; + + // Which rights are needed on the directory file descriptor. + __wasi_rights_t needed_base = __WASI_RIGHT_PATH_OPEN; + __wasi_rights_t needed_inheriting = rights_base | rights_inheriting; + + // Convert open flags. + if ((oflags & __WASI_O_CREAT) != 0) { + noflags |= O_CREAT; + needed_base |= __WASI_RIGHT_PATH_CREATE_FILE; + } + if ((oflags & __WASI_O_DIRECTORY) != 0) + noflags |= O_DIRECTORY; + if ((oflags & __WASI_O_EXCL) != 0) + noflags |= O_EXCL; + if ((oflags & __WASI_O_TRUNC) != 0) { + noflags |= O_TRUNC; + needed_base |= __WASI_RIGHT_PATH_FILESTAT_SET_SIZE; + } + + // Convert file descriptor flags. + if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) + noflags |= O_APPEND; + if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) { #ifdef O_DSYNC - noflags |= O_DSYNC; + noflags |= O_DSYNC; #else - noflags |= O_SYNC; + noflags |= O_SYNC; #endif - needed_inheriting |= __WASI_RIGHT_FD_DATASYNC; - } - if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) - noflags |= O_NONBLOCK; - if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) { + needed_inheriting |= __WASI_RIGHT_FD_DATASYNC; + } + if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) + noflags |= O_NONBLOCK; + if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) { #ifdef O_RSYNC - noflags |= O_RSYNC; + noflags |= O_RSYNC; #else - noflags |= O_SYNC; -#endif - needed_inheriting |= __WASI_RIGHT_FD_SYNC; - } - if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) { - noflags |= O_SYNC; - needed_inheriting |= __WASI_RIGHT_FD_SYNC; - } - if (write && (noflags & (O_APPEND | O_TRUNC)) == 0) - needed_inheriting |= __WASI_RIGHT_FD_SEEK; - - struct path_access pa; - __wasi_errno_t error = - path_get(curfds, &pa, dirfd, dirflags, path, pathlen, needed_base, needed_inheriting, - (oflags & __WASI_O_CREAT) != 0); - if (error != 0) - return error; - if (!pa.follow) - noflags |= O_NOFOLLOW; - - int nfd = openat(pa.fd, pa.path, noflags, 0666); - if (nfd < 0) { - int openat_errno = errno; - // Linux returns ENXIO instead of EOPNOTSUPP when opening a socket. - if (openat_errno == ENXIO) { - struct stat sb; - int ret = - fstatat(pa.fd, pa.path, &sb, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); - path_put(&pa); - return ret == 0 && S_ISSOCK(sb.st_mode) ? __WASI_ENOTSUP - : __WASI_ENXIO; - } - // Linux returns ENOTDIR instead of ELOOP when using O_NOFOLLOW|O_DIRECTORY - // on a symlink. - if (openat_errno == ENOTDIR && (noflags & (O_NOFOLLOW | O_DIRECTORY)) != 0) { - struct stat sb; - int ret = fstatat(pa.fd, pa.path, &sb, AT_SYMLINK_NOFOLLOW); - if (S_ISLNK(sb.st_mode)) { + noflags |= O_SYNC; +#endif + needed_inheriting |= __WASI_RIGHT_FD_SYNC; + } + if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) { + noflags |= O_SYNC; + needed_inheriting |= __WASI_RIGHT_FD_SYNC; + } + if (write && (noflags & (O_APPEND | O_TRUNC)) == 0) + needed_inheriting |= __WASI_RIGHT_FD_SEEK; + + struct path_access pa; + __wasi_errno_t error = + path_get(curfds, &pa, dirfd, dirflags, path, pathlen, needed_base, + needed_inheriting, (oflags & __WASI_O_CREAT) != 0); + if (error != 0) + return error; + if (!pa.follow) + noflags |= O_NOFOLLOW; + + int nfd = openat(pa.fd, pa.path, noflags, 0666); + if (nfd < 0) { + int openat_errno = errno; + // Linux returns ENXIO instead of EOPNOTSUPP when opening a socket. + if (openat_errno == ENXIO) { + struct stat sb; + int ret = fstatat(pa.fd, pa.path, &sb, + pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); + path_put(&pa); + return ret == 0 && S_ISSOCK(sb.st_mode) ? __WASI_ENOTSUP + : __WASI_ENXIO; + } + // Linux returns ENOTDIR instead of ELOOP when using + // O_NOFOLLOW|O_DIRECTORY on a symlink. + if (openat_errno == ENOTDIR + && (noflags & (O_NOFOLLOW | O_DIRECTORY)) != 0) { + struct stat sb; + int ret = fstatat(pa.fd, pa.path, &sb, AT_SYMLINK_NOFOLLOW); + if (S_ISLNK(sb.st_mode)) { + path_put(&pa); + return __WASI_ELOOP; + } + (void)ret; + } path_put(&pa); - return __WASI_ELOOP; - } - (void)ret; + // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on + // a symlink. + if (!pa.follow && openat_errno == EMLINK) + return __WASI_ELOOP; + return convert_errno(openat_errno); } path_put(&pa); - // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on - // a symlink. - if (!pa.follow && openat_errno == EMLINK) - return __WASI_ELOOP; - return convert_errno(openat_errno); - } - path_put(&pa); - - // Determine the type of the new file descriptor and which rights - // contradict with this type. - __wasi_filetype_t type; - __wasi_rights_t max_base, max_inheriting; - error = fd_determine_type_rights(nfd, &type, &max_base, &max_inheriting); - if (error != 0) { - close(nfd); - return error; - } - - { - struct stat sb; - if (fstat(nfd, &sb) < 0) { - close(nfd); - return convert_errno(errno); + // Determine the type of the new file descriptor and which rights + // contradict with this type. + __wasi_filetype_t type; + __wasi_rights_t max_base, max_inheriting; + error = fd_determine_type_rights(nfd, &type, &max_base, &max_inheriting); + if (error != 0) { + close(nfd); + return error; } - if (S_ISDIR(sb.st_mode)) - rights_base |= (__wasi_rights_t)RIGHTS_DIRECTORY_BASE; - else if (S_ISREG(sb.st_mode)) - rights_base |= (__wasi_rights_t)RIGHTS_REGULAR_FILE_BASE; - } + { + struct stat sb; + + if (fstat(nfd, &sb) < 0) { + close(nfd); + return convert_errno(errno); + } + + if (S_ISDIR(sb.st_mode)) + rights_base |= (__wasi_rights_t)RIGHTS_DIRECTORY_BASE; + else if (S_ISREG(sb.st_mode)) + rights_base |= (__wasi_rights_t)RIGHTS_REGULAR_FILE_BASE; + } - return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base, - rights_inheriting & max_inheriting, fd); + return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base, + rights_inheriting & max_inheriting, fd); } // Copies out directory entry metadata or filename, potentially // truncating it in the process. -static void fd_readdir_put( - void *buf, - size_t bufsize, - size_t *bufused, - const void *elem, - size_t elemsize -) { - size_t bufavail = bufsize - *bufused; - if (elemsize > bufavail) - elemsize = bufavail; - bh_memcpy_s((char *)buf + *bufused, (uint32)bufavail, elem, (uint32)elemsize); - *bufused += elemsize; +static void +fd_readdir_put(void *buf, size_t bufsize, size_t *bufused, const void *elem, + size_t elemsize) +{ + size_t bufavail = bufsize - *bufused; + if (elemsize > bufavail) + elemsize = bufavail; + bh_memcpy_s((char *)buf + *bufused, (uint32)bufavail, elem, + (uint32)elemsize); + *bufused += elemsize; } -__wasi_errno_t wasmtime_ssp_fd_readdir( +__wasi_errno_t +wasmtime_ssp_fd_readdir( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - void *buf, - size_t nbyte, - __wasi_dircookie_t cookie, - size_t *bufused -) { - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READDIR, 0); - if (error != 0) { - return error; - } + __wasi_fd_t fd, void *buf, size_t nbyte, __wasi_dircookie_t cookie, + size_t *bufused) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READDIR, 0); + if (error != 0) { + return error; + } - // Create a directory handle if none has been opened yet. - mutex_lock(&fo->directory.lock); - DIR *dp = fo->directory.handle; - if (dp == NULL) { - dp = fdopendir(fd_number(fo)); + // Create a directory handle if none has been opened yet. + mutex_lock(&fo->directory.lock); + DIR *dp = fo->directory.handle; if (dp == NULL) { - mutex_unlock(&fo->directory.lock); - fd_object_release(fo); - return convert_errno(errno); - } - fo->directory.handle = dp; - fo->directory.offset = __WASI_DIRCOOKIE_START; - } - - // Seek to the right position if the requested offset does not match - // the current offset. - if (fo->directory.offset != cookie) { - if (cookie == __WASI_DIRCOOKIE_START) - rewinddir(dp); - else - seekdir(dp, (long)cookie); - fo->directory.offset = cookie; - } - - *bufused = 0; - while (*bufused < nbyte) { - // Read the next directory entry. - errno = 0; - struct dirent *de = readdir(dp); - if (de == NULL) { - mutex_unlock(&fo->directory.lock); - fd_object_release(fo); - return errno == 0 || *bufused > 0 ? 0 : convert_errno(errno); - } - fo->directory.offset = (__wasi_dircookie_t)telldir(dp); - - // Craft a directory entry and copy that back. - size_t namlen = strlen(de->d_name); - __wasi_dirent_t cde = { - .d_next = fo->directory.offset, - .d_ino = de->d_ino, - .d_namlen = (uint32)namlen, - }; - switch (de->d_type) { - case DT_BLK: - cde.d_type = __WASI_FILETYPE_BLOCK_DEVICE; - break; - case DT_CHR: - cde.d_type = __WASI_FILETYPE_CHARACTER_DEVICE; - break; - case DT_DIR: - cde.d_type = __WASI_FILETYPE_DIRECTORY; - break; - case DT_FIFO: - cde.d_type = __WASI_FILETYPE_SOCKET_STREAM; - break; - case DT_LNK: - cde.d_type = __WASI_FILETYPE_SYMBOLIC_LINK; - break; - case DT_REG: - cde.d_type = __WASI_FILETYPE_REGULAR_FILE; - break; + dp = fdopendir(fd_number(fo)); + if (dp == NULL) { + mutex_unlock(&fo->directory.lock); + fd_object_release(fo); + return convert_errno(errno); + } + fo->directory.handle = dp; + fo->directory.offset = __WASI_DIRCOOKIE_START; + } + + // Seek to the right position if the requested offset does not match + // the current offset. + if (fo->directory.offset != cookie) { + if (cookie == __WASI_DIRCOOKIE_START) + rewinddir(dp); + else + seekdir(dp, (long)cookie); + fo->directory.offset = cookie; + } + + *bufused = 0; + while (*bufused < nbyte) { + // Read the next directory entry. + errno = 0; + struct dirent *de = readdir(dp); + if (de == NULL) { + mutex_unlock(&fo->directory.lock); + fd_object_release(fo); + return errno == 0 || *bufused > 0 ? 0 : convert_errno(errno); + } + fo->directory.offset = (__wasi_dircookie_t)telldir(dp); + + // Craft a directory entry and copy that back. + size_t namlen = strlen(de->d_name); + __wasi_dirent_t cde = { + .d_next = fo->directory.offset, + .d_ino = de->d_ino, + .d_namlen = (uint32)namlen, + }; + switch (de->d_type) { + case DT_BLK: + cde.d_type = __WASI_FILETYPE_BLOCK_DEVICE; + break; + case DT_CHR: + cde.d_type = __WASI_FILETYPE_CHARACTER_DEVICE; + break; + case DT_DIR: + cde.d_type = __WASI_FILETYPE_DIRECTORY; + break; + case DT_FIFO: + cde.d_type = __WASI_FILETYPE_SOCKET_STREAM; + break; + case DT_LNK: + cde.d_type = __WASI_FILETYPE_SYMBOLIC_LINK; + break; + case DT_REG: + cde.d_type = __WASI_FILETYPE_REGULAR_FILE; + break; #ifdef DT_SOCK - case DT_SOCK: - // Technically not correct, but good enough. - cde.d_type = __WASI_FILETYPE_SOCKET_STREAM; - break; -#endif - default: - cde.d_type = __WASI_FILETYPE_UNKNOWN; - break; + case DT_SOCK: + // Technically not correct, but good enough. + cde.d_type = __WASI_FILETYPE_SOCKET_STREAM; + break; +#endif + default: + cde.d_type = __WASI_FILETYPE_UNKNOWN; + break; + } + fd_readdir_put(buf, nbyte, bufused, &cde, sizeof(cde)); + fd_readdir_put(buf, nbyte, bufused, de->d_name, namlen); } - fd_readdir_put(buf, nbyte, bufused, &cde, sizeof(cde)); - fd_readdir_put(buf, nbyte, bufused, de->d_name, namlen); - } - mutex_unlock(&fo->directory.lock); - fd_object_release(fo); - return 0; + mutex_unlock(&fo->directory.lock); + fd_object_release(fo); + return 0; } -__wasi_errno_t wasmtime_ssp_path_readlink( +__wasi_errno_t +wasmtime_ssp_path_readlink( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - const char *path, - size_t pathlen, - char *buf, - size_t bufsize, - size_t *bufused -) { - struct path_access pa; - __wasi_errno_t error = path_get_nofollow(curfds, - &pa, fd, path, pathlen, __WASI_RIGHT_PATH_READLINK, 0, false); - if (error != 0) - return error; - - // Linux requires that the buffer size is positive. whereas POSIX does - // not. Use a fake buffer to store the results if the size is zero. - char fakebuf[1]; - ssize_t len = readlinkat(pa.fd, pa.path, bufsize == 0 ? fakebuf : buf, - bufsize == 0 ? sizeof(fakebuf) : bufsize); - path_put(&pa); - if (len < 0) - return convert_errno(errno); - *bufused = (size_t)len < bufsize ? (size_t)len : bufsize; - return 0; + __wasi_fd_t fd, const char *path, size_t pathlen, char *buf, size_t bufsize, + size_t *bufused) +{ + struct path_access pa; + __wasi_errno_t error = path_get_nofollow( + curfds, &pa, fd, path, pathlen, __WASI_RIGHT_PATH_READLINK, 0, false); + if (error != 0) + return error; + + // Linux requires that the buffer size is positive. whereas POSIX does + // not. Use a fake buffer to store the results if the size is zero. + char fakebuf[1]; + ssize_t len = readlinkat(pa.fd, pa.path, bufsize == 0 ? fakebuf : buf, + bufsize == 0 ? sizeof(fakebuf) : bufsize); + path_put(&pa); + if (len < 0) + return convert_errno(errno); + *bufused = (size_t)len < bufsize ? (size_t)len : bufsize; + return 0; } -__wasi_errno_t wasmtime_ssp_path_rename( +__wasi_errno_t +wasmtime_ssp_path_rename( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t old_fd, - const char *old_path, - size_t old_path_len, - __wasi_fd_t new_fd, - const char *new_path, - size_t new_path_len -) { - struct path_access old_pa; - __wasi_errno_t error = path_get_nofollow(curfds, &old_pa, old_fd, old_path, old_path_len, - __WASI_RIGHT_PATH_RENAME_SOURCE, 0, true); - if (error != 0) - return error; + __wasi_fd_t old_fd, const char *old_path, size_t old_path_len, + __wasi_fd_t new_fd, const char *new_path, size_t new_path_len) +{ + struct path_access old_pa; + __wasi_errno_t error = + path_get_nofollow(curfds, &old_pa, old_fd, old_path, old_path_len, + __WASI_RIGHT_PATH_RENAME_SOURCE, 0, true); + if (error != 0) + return error; + + struct path_access new_pa; + error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len, + __WASI_RIGHT_PATH_RENAME_TARGET, 0, true); + if (error != 0) { + path_put(&old_pa); + return error; + } - struct path_access new_pa; - error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len, - __WASI_RIGHT_PATH_RENAME_TARGET, 0, true); - if (error != 0) { + int ret = renameat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path); path_put(&old_pa); - return error; - } - - int ret = renameat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path); - path_put(&old_pa); - path_put(&new_pa); - if (ret < 0) { - return convert_errno(errno); - } - return 0; + path_put(&new_pa); + if (ret < 0) { + return convert_errno(errno); + } + return 0; } // Converts a POSIX stat structure to a CloudABI filestat structure. -static void convert_stat( - const struct stat *in, - __wasi_filestat_t *out -) { - *out = (__wasi_filestat_t){ - .st_dev = in->st_dev, - .st_ino = in->st_ino, - .st_nlink = (__wasi_linkcount_t)in->st_nlink, - .st_size = (__wasi_filesize_t)in->st_size, - .st_atim = convert_timespec(&in->st_atim), - .st_mtim = convert_timespec(&in->st_mtim), - .st_ctim = convert_timespec(&in->st_ctim), - }; -} - -__wasi_errno_t wasmtime_ssp_fd_filestat_get( +static void +convert_stat(const struct stat *in, __wasi_filestat_t *out) +{ + *out = (__wasi_filestat_t){ + .st_dev = in->st_dev, + .st_ino = in->st_ino, + .st_nlink = (__wasi_linkcount_t)in->st_nlink, + .st_size = (__wasi_filesize_t)in->st_size, + .st_atim = convert_timespec(&in->st_atim), + .st_mtim = convert_timespec(&in->st_mtim), + .st_ctim = convert_timespec(&in->st_ctim), + }; +} + +__wasi_errno_t +wasmtime_ssp_fd_filestat_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_filestat_t *buf -) { - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_GET, 0); - if (error != 0) - return error; + __wasi_fd_t fd, __wasi_filestat_t *buf) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_GET, 0); + if (error != 0) + return error; - int ret; - switch (fo->type) { - default: { - struct stat sb; - ret = fstat(fd_number(fo), &sb); - convert_stat(&sb, buf); - break; - } - } - buf->st_filetype = fo->type; - fd_object_release(fo); - if (ret < 0) - return convert_errno(errno); - return 0; -} - -static void convert_timestamp( - __wasi_timestamp_t in, - struct timespec *out -) { - // Store sub-second remainder. -#ifndef __APPLE__ - out->tv_nsec = (__syscall_slong_t)(in % 1000000000); + int ret; + switch (fo->type) { + default: + { + struct stat sb; + ret = fstat(fd_number(fo), &sb); + convert_stat(&sb, buf); + break; + } + } + buf->st_filetype = fo->type; + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +static void +convert_timestamp(__wasi_timestamp_t in, struct timespec *out) +{ + // Store sub-second remainder. +#if defined(__SYSCALL_SLONG_TYPE) + out->tv_nsec = (__SYSCALL_SLONG_TYPE)(in % 1000000000); #else - out->tv_nsec = (long)(in % 1000000000); + out->tv_nsec = (long)(in % 1000000000); #endif - in /= 1000000000; + in /= 1000000000; - // Clamp to the maximum in case it would overflow our system's time_t. - out->tv_sec = (time_t)in < NUMERIC_MAX(time_t) ? (time_t)in : NUMERIC_MAX(time_t); + // Clamp to the maximum in case it would overflow our system's time_t. + out->tv_sec = + (time_t)in < NUMERIC_MAX(time_t) ? (time_t)in : NUMERIC_MAX(time_t); } // Converts the provided timestamps and flags to a set of arguments for // futimens() and utimensat(). -static void convert_utimens_arguments( - __wasi_timestamp_t st_atim, - __wasi_timestamp_t st_mtim, - __wasi_fstflags_t fstflags, - struct timespec *ts -) { - if ((fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) { - ts[0].tv_nsec = UTIME_NOW; - } else if ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0) { - convert_timestamp(st_atim, &ts[0]); - } else { - ts[0].tv_nsec = UTIME_OMIT; - } - - if ((fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0) { - ts[1].tv_nsec = UTIME_NOW; - } else if ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0) { - convert_timestamp(st_mtim, &ts[1]); - } else { - ts[1].tv_nsec = UTIME_OMIT; - } -} - -__wasi_errno_t wasmtime_ssp_fd_filestat_set_size( +static void +convert_utimens_arguments(__wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags, struct timespec *ts) +{ + if ((fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) { + ts[0].tv_nsec = UTIME_NOW; + } + else if ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0) { + convert_timestamp(st_atim, &ts[0]); + } + else { + ts[0].tv_nsec = UTIME_OMIT; + } + + if ((fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0) { + ts[1].tv_nsec = UTIME_NOW; + } + else if ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0) { + convert_timestamp(st_mtim, &ts[1]); + } + else { + ts[1].tv_nsec = UTIME_OMIT; + } +} + +__wasi_errno_t +wasmtime_ssp_fd_filestat_set_size( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_filesize_t st_size -) { - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_SIZE, 0); - if (error != 0) - return error; + __wasi_fd_t fd, __wasi_filesize_t st_size) +{ + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_SIZE, 0); + if (error != 0) + return error; - int ret = ftruncate(fd_number(fo), (off_t)st_size); - fd_object_release(fo); - if (ret < 0) - return convert_errno(errno); - return 0; + int ret = ftruncate(fd_number(fo), (off_t)st_size); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; } -__wasi_errno_t wasmtime_ssp_fd_filestat_set_times( +__wasi_errno_t +wasmtime_ssp_fd_filestat_set_times( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_timestamp_t st_atim, - __wasi_timestamp_t st_mtim, - __wasi_fstflags_t fstflags -) { - if ((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW | - __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) != 0) - return __WASI_EINVAL; - - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_TIMES, 0); - if (error != 0) - return error; + __wasi_fd_t fd, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags) +{ + if ((fstflags + & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW + | __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) + != 0) + return __WASI_EINVAL; - struct timespec ts[2]; - convert_utimens_arguments(st_atim, st_mtim, fstflags, ts); - int ret = futimens(fd_number(fo), ts); + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_TIMES, 0); + if (error != 0) + return error; - fd_object_release(fo); - if (ret < 0) - return convert_errno(errno); - return 0; + struct timespec ts[2]; + convert_utimens_arguments(st_atim, st_mtim, fstflags, ts); + int ret = futimens(fd_number(fo), ts); + + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; } -__wasi_errno_t wasmtime_ssp_path_filestat_get( +__wasi_errno_t +wasmtime_ssp_path_filestat_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_lookupflags_t flags, - const char *path, - size_t pathlen, - __wasi_filestat_t *buf -) { - struct path_access pa; - __wasi_errno_t error = - path_get(curfds, &pa, fd, flags, path, pathlen, __WASI_RIGHT_PATH_FILESTAT_GET, 0, false); - if (error != 0) - return error; + __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, + size_t pathlen, __wasi_filestat_t *buf) +{ + struct path_access pa; + __wasi_errno_t error = path_get(curfds, &pa, fd, flags, path, pathlen, + __WASI_RIGHT_PATH_FILESTAT_GET, 0, false); + if (error != 0) + return error; + + struct stat sb; + int ret = fstatat(pa.fd, pa.path, &sb, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); + path_put(&pa); + if (ret < 0) + return convert_errno(errno); + convert_stat(&sb, buf); + + // Convert the file type. In the case of sockets there is no way we + // can easily determine the exact socket type. + if (S_ISBLK(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_BLOCK_DEVICE; + else if (S_ISCHR(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_CHARACTER_DEVICE; + else if (S_ISDIR(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_DIRECTORY; + else if (S_ISFIFO(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; + else if (S_ISLNK(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_SYMBOLIC_LINK; + else if (S_ISREG(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_REGULAR_FILE; + else if (S_ISSOCK(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; + return 0; +} - struct stat sb; - int ret = fstatat(pa.fd, pa.path, &sb, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); - path_put(&pa); - if (ret < 0) - return convert_errno(errno); - convert_stat(&sb, buf); - - // Convert the file type. In the case of sockets there is no way we - // can easily determine the exact socket type. - if (S_ISBLK(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_BLOCK_DEVICE; - else if (S_ISCHR(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_CHARACTER_DEVICE; - else if (S_ISDIR(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_DIRECTORY; - else if (S_ISFIFO(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; - else if (S_ISLNK(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_SYMBOLIC_LINK; - else if (S_ISREG(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_REGULAR_FILE; - else if (S_ISSOCK(sb.st_mode)) - buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; - return 0; -} - -__wasi_errno_t wasmtime_ssp_path_filestat_set_times( +__wasi_errno_t +wasmtime_ssp_path_filestat_set_times( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - __wasi_lookupflags_t flags, - const char *path, - size_t pathlen, - __wasi_timestamp_t st_atim, - __wasi_timestamp_t st_mtim, - __wasi_fstflags_t fstflags -) { - if (((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW | - __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) != 0) - /* ATIM & ATIM_NOW can't be set at the same time */ - || ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0 - && (fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) - /* MTIM & MTIM_NOW can't be set at the same time */ - || ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0 - && (fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0)) - return __WASI_EINVAL; - - struct path_access pa; - __wasi_errno_t error = path_get(curfds, - &pa, fd, flags, path, pathlen, __WASI_RIGHT_PATH_FILESTAT_SET_TIMES, 0, false); - if (error != 0) - return error; + __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path, + size_t pathlen, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags) +{ + if (((fstflags + & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW + | __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) + != 0) + /* ATIM & ATIM_NOW can't be set at the same time */ + || ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0 + && (fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) + /* MTIM & MTIM_NOW can't be set at the same time */ + || ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0 + && (fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0)) + return __WASI_EINVAL; - struct timespec ts[2]; - convert_utimens_arguments(st_atim, st_mtim, fstflags, ts); - int ret = utimensat(pa.fd, pa.path, ts, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); + struct path_access pa; + __wasi_errno_t error = + path_get(curfds, &pa, fd, flags, path, pathlen, + __WASI_RIGHT_PATH_FILESTAT_SET_TIMES, 0, false); + if (error != 0) + return error; - path_put(&pa); - if (ret < 0) - return convert_errno(errno); - return 0; + struct timespec ts[2]; + convert_utimens_arguments(st_atim, st_mtim, fstflags, ts); + int ret = + utimensat(pa.fd, pa.path, ts, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); + + path_put(&pa); + if (ret < 0) + return convert_errno(errno); + return 0; } -__wasi_errno_t wasmtime_ssp_path_symlink( +__wasi_errno_t +wasmtime_ssp_path_symlink( #if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct fd_table *curfds, - struct fd_prestats *prestats, + struct fd_table *curfds, struct fd_prestats *prestats, #endif - const char *old_path, - size_t old_path_len, - __wasi_fd_t fd, - const char *new_path, - size_t new_path_len -) { - char *target = str_nullterminate(old_path, old_path_len); - if (target == NULL) - return convert_errno(errno); - - struct path_access pa; - __wasi_errno_t error = path_get_nofollow(curfds, - &pa, fd, new_path, new_path_len, __WASI_RIGHT_PATH_SYMLINK, 0, true); - if (error != 0) { - wasm_runtime_free(target); - return error; - } + const char *old_path, size_t old_path_len, __wasi_fd_t fd, + const char *new_path, size_t new_path_len) +{ + char *target = str_nullterminate(old_path, old_path_len); + if (target == NULL) + return convert_errno(errno); + + struct path_access pa; + __wasi_errno_t error = + path_get_nofollow(curfds, &pa, fd, new_path, new_path_len, + __WASI_RIGHT_PATH_SYMLINK, 0, true); + if (error != 0) { + wasm_runtime_free(target); + return error; + } - rwlock_rdlock(&prestats->lock); - if (!validate_path(target, prestats)) { - rwlock_unlock(&prestats->lock); - wasm_runtime_free(target); - return __WASI_EBADF; - } - rwlock_unlock(&prestats->lock); + rwlock_rdlock(&prestats->lock); + if (!validate_path(target, prestats)) { + rwlock_unlock(&prestats->lock); + wasm_runtime_free(target); + return __WASI_EBADF; + } + rwlock_unlock(&prestats->lock); - int ret = symlinkat(target, pa.fd, pa.path); - path_put(&pa); - wasm_runtime_free(target); - if (ret < 0) - return convert_errno(errno); - return 0; + int ret = symlinkat(target, pa.fd, pa.path); + path_put(&pa); + wasm_runtime_free(target); + if (ret < 0) + return convert_errno(errno); + return 0; } -__wasi_errno_t wasmtime_ssp_path_unlink_file( +__wasi_errno_t +wasmtime_ssp_path_unlink_file( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - const char *path, - size_t pathlen -) { - struct path_access pa; - __wasi_errno_t error = path_get_nofollow(curfds, - &pa, fd, path, pathlen, __WASI_RIGHT_PATH_UNLINK_FILE, 0, true); - if (error != 0) - return error; + __wasi_fd_t fd, const char *path, size_t pathlen) +{ + struct path_access pa; + __wasi_errno_t error = path_get_nofollow( + curfds, &pa, fd, path, pathlen, __WASI_RIGHT_PATH_UNLINK_FILE, 0, true); + if (error != 0) + return error; - int ret = unlinkat(pa.fd, pa.path, 0); + int ret = unlinkat(pa.fd, pa.path, 0); #ifndef __linux__ - // Non-Linux implementations may return EPERM when attempting to remove a - // directory without REMOVEDIR. While that's what POSIX specifies, it's - // less useful. Adjust this to EISDIR. It doesn't matter that this is not - // atomic with the unlinkat, because if the file is removed and a directory - // is created before fstatat sees it, we're racing with that change anyway - // and unlinkat could have legitimately seen the directory if the race had - // turned out differently. - if (ret < 0 && errno == EPERM) { - struct stat statbuf; - if (fstatat(pa.fd, pa.path, &statbuf, AT_SYMLINK_NOFOLLOW) == 0 && - S_ISDIR(statbuf.st_mode)) { - errno = EISDIR; - } - } -#endif - path_put(&pa); - if (ret < 0) { - return convert_errno(errno); - } - return 0; -} - -__wasi_errno_t wasmtime_ssp_path_remove_directory( + // Non-Linux implementations may return EPERM when attempting to remove a + // directory without REMOVEDIR. While that's what POSIX specifies, it's + // less useful. Adjust this to EISDIR. It doesn't matter that this is not + // atomic with the unlinkat, because if the file is removed and a directory + // is created before fstatat sees it, we're racing with that change anyway + // and unlinkat could have legitimately seen the directory if the race had + // turned out differently. + if (ret < 0 && errno == EPERM) { + struct stat statbuf; + if (fstatat(pa.fd, pa.path, &statbuf, AT_SYMLINK_NOFOLLOW) == 0 + && S_ISDIR(statbuf.st_mode)) { + errno = EISDIR; + } + } +#endif + path_put(&pa); + if (ret < 0) { + return convert_errno(errno); + } + return 0; +} + +__wasi_errno_t +wasmtime_ssp_path_remove_directory( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t fd, - const char *path, - size_t pathlen -) { - struct path_access pa; - __wasi_errno_t error = path_get_nofollow(curfds, - &pa, fd, path, pathlen, __WASI_RIGHT_PATH_REMOVE_DIRECTORY, 0, true); - if (error != 0) - return error; - - int ret = unlinkat(pa.fd, pa.path, AT_REMOVEDIR); + __wasi_fd_t fd, const char *path, size_t pathlen) +{ + struct path_access pa; + __wasi_errno_t error = + path_get_nofollow(curfds, &pa, fd, path, pathlen, + __WASI_RIGHT_PATH_REMOVE_DIRECTORY, 0, true); + if (error != 0) + return error; + + int ret = unlinkat(pa.fd, pa.path, AT_REMOVEDIR); #ifndef __linux__ - // POSIX permits either EEXIST or ENOTEMPTY when the directory is not empty. - // Map it to ENOTEMPTY. - if (ret < 0 && errno == EEXIST) { - errno = ENOTEMPTY; - } + // POSIX permits either EEXIST or ENOTEMPTY when the directory is not empty. + // Map it to ENOTEMPTY. + if (ret < 0 && errno == EEXIST) { + errno = ENOTEMPTY; + } #endif - path_put(&pa); - if (ret < 0) { - return convert_errno(errno); - } - return 0; + path_put(&pa); + if (ret < 0) { + return convert_errno(errno); + } + return 0; } -__wasi_errno_t wasmtime_ssp_poll_oneoff( +__wasi_errno_t +wasmtime_ssp_poll_oneoff( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - const __wasi_subscription_t *in, - __wasi_event_t *out, - size_t nsubscriptions, - size_t *nevents -) NO_LOCK_ANALYSIS { - // Sleeping. - if (nsubscriptions == 1 && in[0].type == __WASI_EVENTTYPE_CLOCK) { - out[0] = (__wasi_event_t){ - .userdata = in[0].userdata, - .type = in[0].type, - }; + const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions, + size_t *nevents) NO_LOCK_ANALYSIS +{ + // Sleeping. + if (nsubscriptions == 1 && in[0].type == __WASI_EVENTTYPE_CLOCK) { + out[0] = (__wasi_event_t){ + .userdata = in[0].userdata, + .type = in[0].type, + }; #if CONFIG_HAS_CLOCK_NANOSLEEP - clockid_t clock_id; - if (convert_clockid(in[0].u.clock.clock_id, &clock_id)) { - struct timespec ts; - convert_timestamp(in[0].u.clock.timeout, &ts); - int ret = clock_nanosleep( - clock_id, - (in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0 - ? TIMER_ABSTIME - : 0, - &ts, NULL); - if (ret != 0) - out[0].error = convert_errno(ret); - } else { - out[0].error = __WASI_ENOTSUP; - } -#else - switch (in[0].u.clock.clock_id) { - case __WASI_CLOCK_MONOTONIC: - if ((in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0) { - // TODO(ed): Implement. - fputs("Unimplemented absolute sleep on monotonic clock\n", stderr); - out[0].error = __WASI_ENOSYS; - } else { - // Perform relative sleeps on the monotonic clock also using - // nanosleep(). This is incorrect, but good enough for now. - struct timespec ts; - convert_timestamp(in[0].u.clock.timeout, &ts); - nanosleep(&ts, NULL); + clockid_t clock_id; + if (convert_clockid(in[0].u.clock.clock_id, &clock_id)) { + struct timespec ts; + convert_timestamp(in[0].u.clock.timeout, &ts); + int ret = clock_nanosleep( + clock_id, + (in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0 + ? TIMER_ABSTIME + : 0, + &ts, NULL); + if (ret != 0) + out[0].error = convert_errno(ret); } - break; - case __WASI_CLOCK_REALTIME: - if ((in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0) { - // Sleeping to an absolute point in time can only be done - // by waiting on a condition variable. - struct mutex mutex; - struct cond cond; - - if (!mutex_init(&mutex)) - return -1; - if (!cond_init_realtime(&cond)) { - mutex_destroy(&mutex); - return -1; - } - mutex_lock(&mutex); - cond_timedwait(&cond, &mutex, in[0].u.clock.timeout, true); - mutex_unlock(&mutex); - mutex_destroy(&mutex); - cond_destroy(&cond); - } else { - // Relative sleeps can be done using nanosleep(). - struct timespec ts; - convert_timestamp(in[0].u.clock.timeout, &ts); - nanosleep(&ts, NULL); + else { + out[0].error = __WASI_ENOTSUP; } - break; - default: - out[0].error = __WASI_ENOTSUP; - break; - } -#endif - *nevents = 1; - return 0; - } - - // Last option: call into poll(). This can only be done in case all - // subscriptions consist of __WASI_EVENTTYPE_FD_READ and - // __WASI_EVENTTYPE_FD_WRITE entries. There may be up to one - // __WASI_EVENTTYPE_CLOCK entry to act as a timeout. These are also - // the subscriptions generate by cloudlibc's poll() and select(). - struct fd_object **fos = wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*fos))); - if (fos == NULL) - return __WASI_ENOMEM; - struct pollfd *pfds = wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*pfds))); - if (pfds == NULL) { - wasm_runtime_free(fos); - return __WASI_ENOMEM; - } - - // Convert subscriptions to pollfd entries. Increase the reference - // count on the file descriptors to ensure they remain valid across - // the call to poll(). - struct fd_table *ft = curfds; - rwlock_rdlock(&ft->lock); - *nevents = 0; - const __wasi_subscription_t *clock_subscription = NULL; - for (size_t i = 0; i < nsubscriptions; ++i) { - const __wasi_subscription_t *s = &in[i]; - switch (s->type) { - case __WASI_EVENTTYPE_FD_READ: - case __WASI_EVENTTYPE_FD_WRITE: { - __wasi_errno_t error = - fd_object_get_locked(&fos[i], ft, s->u.fd_readwrite.fd, - __WASI_RIGHT_POLL_FD_READWRITE, 0); - if (error == 0) { - // Proper file descriptor on which we can poll(). - pfds[i] = (struct pollfd){ - .fd = fd_number(fos[i]), - .events = s->type == __WASI_EVENTTYPE_FD_READ ? POLLRDNORM - : POLLWRNORM, - }; - } else { - // Invalid file descriptor or rights missing. - fos[i] = NULL; - pfds[i] = (struct pollfd){.fd = -1}; - out[(*nevents)++] = (__wasi_event_t){ - .userdata = s->userdata, - .error = error, - .type = s->type, - }; +#else + switch (in[0].u.clock.clock_id) { + case __WASI_CLOCK_MONOTONIC: + if ((in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) + != 0) { + // TODO(ed): Implement. + fputs("Unimplemented absolute sleep on monotonic clock\n", + stderr); + out[0].error = __WASI_ENOSYS; + } + else { + // Perform relative sleeps on the monotonic clock also using + // nanosleep(). This is incorrect, but good enough for now. + struct timespec ts; + convert_timestamp(in[0].u.clock.timeout, &ts); + nanosleep(&ts, NULL); + } + break; + case __WASI_CLOCK_REALTIME: + if ((in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) + != 0) { + // Sleeping to an absolute point in time can only be done + // by waiting on a condition variable. + struct mutex mutex; + struct cond cond; + + if (!mutex_init(&mutex)) + return -1; + if (!cond_init_realtime(&cond)) { + mutex_destroy(&mutex); + return -1; + } + mutex_lock(&mutex); + cond_timedwait(&cond, &mutex, in[0].u.clock.timeout, true); + mutex_unlock(&mutex); + mutex_destroy(&mutex); + cond_destroy(&cond); + } + else { + // Relative sleeps can be done using nanosleep(). + struct timespec ts; + convert_timestamp(in[0].u.clock.timeout, &ts); + nanosleep(&ts, NULL); + } + break; + default: + out[0].error = __WASI_ENOTSUP; + break; } - break; - } - case __WASI_EVENTTYPE_CLOCK: - if (clock_subscription == NULL && - (s->u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) == 0) { - // Relative timeout. - fos[i] = NULL; - pfds[i] = (struct pollfd){.fd = -1}; - clock_subscription = s; - break; +#endif + *nevents = 1; + return 0; + } + + // Last option: call into poll(). This can only be done in case all + // subscriptions consist of __WASI_EVENTTYPE_FD_READ and + // __WASI_EVENTTYPE_FD_WRITE entries. There may be up to one + // __WASI_EVENTTYPE_CLOCK entry to act as a timeout. These are also + // the subscriptions generate by cloudlibc's poll() and select(). + struct fd_object **fos = + wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*fos))); + if (fos == NULL) + return __WASI_ENOMEM; + struct pollfd *pfds = + wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*pfds))); + if (pfds == NULL) { + wasm_runtime_free(fos); + return __WASI_ENOMEM; + } + + // Convert subscriptions to pollfd entries. Increase the reference + // count on the file descriptors to ensure they remain valid across + // the call to poll(). + struct fd_table *ft = curfds; + rwlock_rdlock(&ft->lock); + *nevents = 0; + const __wasi_subscription_t *clock_subscription = NULL; + for (size_t i = 0; i < nsubscriptions; ++i) { + const __wasi_subscription_t *s = &in[i]; + switch (s->type) { + case __WASI_EVENTTYPE_FD_READ: + case __WASI_EVENTTYPE_FD_WRITE: + { + __wasi_errno_t error = + fd_object_get_locked(&fos[i], ft, s->u.fd_readwrite.fd, + __WASI_RIGHT_POLL_FD_READWRITE, 0); + if (error == 0) { + // Proper file descriptor on which we can poll(). + pfds[i] = (struct pollfd){ + .fd = fd_number(fos[i]), + .events = s->type == __WASI_EVENTTYPE_FD_READ + ? POLLRDNORM + : POLLWRNORM, + }; + } + else { + // Invalid file descriptor or rights missing. + fos[i] = NULL; + pfds[i] = (struct pollfd){ .fd = -1 }; + out[(*nevents)++] = (__wasi_event_t){ + .userdata = s->userdata, + .error = error, + .type = s->type, + }; + } + break; + } + case __WASI_EVENTTYPE_CLOCK: + if (clock_subscription == NULL + && (s->u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) + == 0) { + // Relative timeout. + fos[i] = NULL; + pfds[i] = (struct pollfd){ .fd = -1 }; + clock_subscription = s; + break; + } + // Fallthrough. + default: + // Unsupported event. + fos[i] = NULL; + pfds[i] = (struct pollfd){ .fd = -1 }; + out[(*nevents)++] = (__wasi_event_t){ + .userdata = s->userdata, + .error = __WASI_ENOSYS, + .type = s->type, + }; + break; } - // Fallthrough. - default: - // Unsupported event. - fos[i] = NULL; - pfds[i] = (struct pollfd){.fd = -1}; + } + rwlock_unlock(&ft->lock); + + // Use a zero-second timeout in case we've already generated events in + // the loop above. + int timeout; + if (*nevents != 0) { + timeout = 0; + } + else if (clock_subscription != NULL) { + __wasi_timestamp_t ts = clock_subscription->u.clock.timeout / 1000000; + timeout = ts > INT_MAX ? -1 : (int)ts; + } + else { + timeout = -1; + } + int ret = poll(pfds, nsubscriptions, timeout); + + __wasi_errno_t error = 0; + if (ret == -1) { + error = convert_errno(errno); + } + else if (ret == 0 && *nevents == 0 && clock_subscription != NULL) { + // No events triggered. Trigger the clock event. out[(*nevents)++] = (__wasi_event_t){ - .userdata = s->userdata, - .error = __WASI_ENOSYS, - .type = s->type, + .userdata = clock_subscription->userdata, + .type = __WASI_EVENTTYPE_CLOCK, }; - break; - } - } - rwlock_unlock(&ft->lock); - - // Use a zero-second timeout in case we've already generated events in - // the loop above. - int timeout; - if (*nevents != 0) { - timeout = 0; - } else if (clock_subscription != NULL) { - __wasi_timestamp_t ts = clock_subscription->u.clock.timeout / 1000000; - timeout = ts > INT_MAX ? -1 : (int)ts; - } else { - timeout = -1; - } - int ret = poll(pfds, nsubscriptions, timeout); - - __wasi_errno_t error = 0; - if (ret == -1) { - error = convert_errno(errno); - } else if (ret == 0 && *nevents == 0 && clock_subscription != NULL) { - // No events triggered. Trigger the clock event. - out[(*nevents)++] = (__wasi_event_t){ - .userdata = clock_subscription->userdata, - .type = __WASI_EVENTTYPE_CLOCK, - }; - } else { - // Events got triggered. Don't trigger the clock event. - for (size_t i = 0; i < nsubscriptions; ++i) { - if (pfds[i].fd >= 0) { - __wasi_filesize_t nbytes = 0; - if (in[i].type == __WASI_EVENTTYPE_FD_READ) { - int l; - if (ioctl(fd_number(fos[i]), FIONREAD, &l) == 0) - nbytes = (__wasi_filesize_t)l; - } - if ((pfds[i].revents & POLLNVAL) != 0) { - // Bad file descriptor. This normally cannot occur, as - // referencing the file descriptor object will always ensure - // the descriptor is valid. Still, macOS may sometimes return - // this on FIFOs when reaching end-of-file. - out[(*nevents)++] = (__wasi_event_t){ - .userdata = in[i].userdata, + } + else { + // Events got triggered. Don't trigger the clock event. + for (size_t i = 0; i < nsubscriptions; ++i) { + if (pfds[i].fd >= 0) { + __wasi_filesize_t nbytes = 0; + if (in[i].type == __WASI_EVENTTYPE_FD_READ) { + int l; + if (ioctl(fd_number(fos[i]), FIONREAD, &l) == 0) + nbytes = (__wasi_filesize_t)l; + } + if ((pfds[i].revents & POLLNVAL) != 0) { + // Bad file descriptor. This normally cannot occur, as + // referencing the file descriptor object will always ensure + // the descriptor is valid. Still, macOS may sometimes + // return this on FIFOs when reaching end-of-file. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, #ifdef __APPLE__ - .u.fd_readwrite.nbytes = nbytes, - .u.fd_readwrite.flags = __WASI_EVENT_FD_READWRITE_HANGUP, + .u.fd_readwrite.nbytes = nbytes, + .u.fd_readwrite.flags = + __WASI_EVENT_FD_READWRITE_HANGUP, #else - .error = __WASI_EBADF, -#endif - .type = in[i].type, - }; - } else if ((pfds[i].revents & POLLERR) != 0) { - // File descriptor is in an error state. - out[(*nevents)++] = (__wasi_event_t){ - .userdata = in[i].userdata, - .error = __WASI_EIO, - .type = in[i].type, - }; - } else if ((pfds[i].revents & POLLHUP) != 0) { - // End-of-file. - out[(*nevents)++] = (__wasi_event_t){ - .userdata = in[i].userdata, - .type = in[i].type, - .u.fd_readwrite.nbytes = nbytes, - .u.fd_readwrite.flags = __WASI_EVENT_FD_READWRITE_HANGUP, - }; - } else if ((pfds[i].revents & (POLLRDNORM | POLLWRNORM)) != 0) { - // Read or write possible. - out[(*nevents)++] = (__wasi_event_t){ - .userdata = in[i].userdata, - .type = in[i].type, - .u.fd_readwrite.nbytes = nbytes, - }; + .error = __WASI_EBADF, +#endif + .type = in[i].type, + }; + } + else if ((pfds[i].revents & POLLERR) != 0) { + // File descriptor is in an error state. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, + .error = __WASI_EIO, + .type = in[i].type, + }; + } + else if ((pfds[i].revents & POLLHUP) != 0) { + // End-of-file. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, + .type = in[i].type, + .u.fd_readwrite.nbytes = nbytes, + .u.fd_readwrite.flags = + __WASI_EVENT_FD_READWRITE_HANGUP, + }; + } + else if ((pfds[i].revents & (POLLRDNORM | POLLWRNORM)) != 0) { + // Read or write possible. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, + .type = in[i].type, + .u.fd_readwrite.nbytes = nbytes, + }; + } + } } - } } - } - for (size_t i = 0; i < nsubscriptions; ++i) - if (fos[i] != NULL) - fd_object_release(fos[i]); - wasm_runtime_free(fos); - wasm_runtime_free(pfds); - return error; + for (size_t i = 0; i < nsubscriptions; ++i) + if (fos[i] != NULL) + fd_object_release(fos[i]); + wasm_runtime_free(fos); + wasm_runtime_free(pfds); + return error; } #if 0 @@ -2677,227 +2675,228 @@ void wasmtime_ssp_proc_exit( } #endif -__wasi_errno_t wasmtime_ssp_proc_raise( - __wasi_signal_t sig -) { - static const int signals[] = { +__wasi_errno_t +wasmtime_ssp_proc_raise(__wasi_signal_t sig) +{ + static const int signals[] = { #define X(v) [__WASI_##v] = v - X(SIGABRT), X(SIGALRM), X(SIGBUS), X(SIGCHLD), X(SIGCONT), X(SIGFPE), - X(SIGHUP), X(SIGILL), X(SIGINT), X(SIGKILL), X(SIGPIPE), X(SIGQUIT), - X(SIGSEGV), X(SIGSTOP), X(SIGSYS), X(SIGTERM), X(SIGTRAP), X(SIGTSTP), - X(SIGTTIN), X(SIGTTOU), X(SIGURG), X(SIGUSR1), X(SIGUSR2), X(SIGVTALRM), - X(SIGXCPU), X(SIGXFSZ), + X(SIGABRT), X(SIGALRM), X(SIGBUS), X(SIGCHLD), X(SIGCONT), X(SIGFPE), + X(SIGHUP), X(SIGILL), X(SIGINT), X(SIGKILL), X(SIGPIPE), X(SIGQUIT), + X(SIGSEGV), X(SIGSTOP), X(SIGSYS), X(SIGTERM), X(SIGTRAP), X(SIGTSTP), + X(SIGTTIN), X(SIGTTOU), X(SIGURG), X(SIGUSR1), X(SIGUSR2), X(SIGVTALRM), + X(SIGXCPU), X(SIGXFSZ), #undef X - }; - if (sig >= sizeof(signals) / sizeof(signals[0]) || signals[sig] == 0) - return __WASI_EINVAL; + }; + if (sig >= sizeof(signals) / sizeof(signals[0]) || signals[sig] == 0) + return __WASI_EINVAL; #if CONFIG_TLS_USE_GSBASE - // TLS on OS X depends on installing a SIGSEGV handler. Reset SIGSEGV - // to the default action before raising. - if (sig == __WASI_SIGSEGV) { - struct sigaction sa = { - .sa_handler = SIG_DFL, - }; - sigemptyset(&sa.sa_mask); - sigaction(SIGSEGV, &sa, NULL); - } + // TLS on OS X depends on installing a SIGSEGV handler. Reset SIGSEGV + // to the default action before raising. + if (sig == __WASI_SIGSEGV) { + struct sigaction sa = { + .sa_handler = SIG_DFL, + }; + sigemptyset(&sa.sa_mask); + sigaction(SIGSEGV, &sa, NULL); + } #endif - if (raise(signals[sig]) < 0) - return convert_errno(errno); - return 0; + if (raise(signals[sig]) < 0) + return convert_errno(errno); + return 0; } -__wasi_errno_t wasmtime_ssp_random_get( - void *buf, - size_t nbyte -) { - random_buf(buf, nbyte); - return 0; +__wasi_errno_t +wasmtime_ssp_random_get(void *buf, size_t nbyte) +{ + random_buf(buf, nbyte); + return 0; } -__wasi_errno_t wasmtime_ssp_sock_recv( +__wasi_errno_t +wasmtime_ssp_sock_recv( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t sock, - const __wasi_iovec_t *ri_data, - size_t ri_data_len, - __wasi_riflags_t ri_flags, - size_t *ro_datalen, - __wasi_roflags_t *ro_flags -) { - // Convert input to msghdr. - struct msghdr hdr = { - .msg_iov = (struct iovec *)ri_data, - .msg_iovlen = ri_data_len, - }; - int nflags = 0; - if ((ri_flags & __WASI_SOCK_RECV_PEEK) != 0) - nflags |= MSG_PEEK; - if ((ri_flags & __WASI_SOCK_RECV_WAITALL) != 0) - nflags |= MSG_WAITALL; - - struct fd_object *fo; - __wasi_errno_t error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0); - if (error != 0) { - return error; - } - - ssize_t datalen = recvmsg(fd_number(fo), &hdr, nflags); - fd_object_release(fo); - if (datalen < 0) { - return convert_errno(errno); - } + __wasi_fd_t sock, const __wasi_iovec_t *ri_data, size_t ri_data_len, + __wasi_riflags_t ri_flags, size_t *ro_datalen, __wasi_roflags_t *ro_flags) +{ + // Convert input to msghdr. + struct msghdr hdr = { + .msg_iov = (struct iovec *)ri_data, + .msg_iovlen = ri_data_len, + }; + int nflags = 0; + if ((ri_flags & __WASI_SOCK_RECV_PEEK) != 0) + nflags |= MSG_PEEK; + if ((ri_flags & __WASI_SOCK_RECV_WAITALL) != 0) + nflags |= MSG_WAITALL; + + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0); + if (error != 0) { + return error; + } + ssize_t datalen = recvmsg(fd_number(fo), &hdr, nflags); + fd_object_release(fo); + if (datalen < 0) { + return convert_errno(errno); + } - // Convert msghdr to output. - *ro_datalen = (size_t)datalen; - *ro_flags = 0; - if ((hdr.msg_flags & MSG_TRUNC) != 0) - *ro_flags |= __WASI_SOCK_RECV_DATA_TRUNCATED; - return 0; + // Convert msghdr to output. + *ro_datalen = (size_t)datalen; + *ro_flags = 0; + if ((hdr.msg_flags & MSG_TRUNC) != 0) + *ro_flags |= __WASI_SOCK_RECV_DATA_TRUNCATED; + return 0; } -__wasi_errno_t wasmtime_ssp_sock_send( +__wasi_errno_t +wasmtime_ssp_sock_send( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t sock, - const __wasi_ciovec_t *si_data, - size_t si_data_len, - __wasi_siflags_t si_flags, - size_t *so_datalen -) NO_LOCK_ANALYSIS { - // Convert input to msghdr. - struct msghdr hdr = { - .msg_iov = (struct iovec *)si_data, - .msg_iovlen = si_data_len, - }; - - // Attach file descriptors if present. - __wasi_errno_t error; - - // Send message. - struct fd_object *fo; - error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0); - if (error != 0) - goto out; - ssize_t len = sendmsg(fd_number(fo), &hdr, 0); - fd_object_release(fo); - if (len < 0) { - error = convert_errno(errno); - } else { - *so_datalen = (size_t)len; - } + __wasi_fd_t sock, const __wasi_ciovec_t *si_data, size_t si_data_len, + __wasi_siflags_t si_flags, size_t *so_datalen) NO_LOCK_ANALYSIS +{ + // Convert input to msghdr. + struct msghdr hdr = { + .msg_iov = (struct iovec *)si_data, + .msg_iovlen = si_data_len, + }; + + // Attach file descriptors if present. + __wasi_errno_t error; + + // Send message. + struct fd_object *fo; + error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0); + if (error != 0) + goto out; + ssize_t len = sendmsg(fd_number(fo), &hdr, 0); + fd_object_release(fo); + if (len < 0) { + error = convert_errno(errno); + } + else { + *so_datalen = (size_t)len; + } out: - return error; + return error; } -__wasi_errno_t wasmtime_ssp_sock_shutdown( +__wasi_errno_t +wasmtime_ssp_sock_shutdown( #if !defined(WASMTIME_SSP_STATIC_CURFDS) struct fd_table *curfds, #endif - __wasi_fd_t sock, - __wasi_sdflags_t how -) { - int nhow; - switch (how) { - case __WASI_SHUT_RD: - nhow = SHUT_RD; - break; - case __WASI_SHUT_WR: - nhow = SHUT_WR; - break; - case __WASI_SHUT_RD | __WASI_SHUT_WR: - nhow = SHUT_RDWR; - break; - default: - return __WASI_EINVAL; - } - - struct fd_object *fo; - __wasi_errno_t error = - fd_object_get(curfds, &fo, sock, __WASI_RIGHT_SOCK_SHUTDOWN, 0); - if (error != 0) - return error; + __wasi_fd_t sock, __wasi_sdflags_t how) +{ + int nhow; + switch (how) { + case __WASI_SHUT_RD: + nhow = SHUT_RD; + break; + case __WASI_SHUT_WR: + nhow = SHUT_WR; + break; + case __WASI_SHUT_RD | __WASI_SHUT_WR: + nhow = SHUT_RDWR; + break; + default: + return __WASI_EINVAL; + } + + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, sock, __WASI_RIGHT_SOCK_SHUTDOWN, 0); + if (error != 0) + return error; - int ret = shutdown(fd_number(fo), nhow); - fd_object_release(fo); - if (ret < 0) - return convert_errno(errno); - return 0; + int ret = shutdown(fd_number(fo), nhow); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; } -__wasi_errno_t wasmtime_ssp_sched_yield(void) { - if (sched_yield() < 0) - return convert_errno(errno); - return 0; +__wasi_errno_t +wasmtime_ssp_sched_yield(void) +{ + if (sched_yield() < 0) + return convert_errno(errno); + return 0; } -__wasi_errno_t wasmtime_ssp_args_get( +__wasi_errno_t +wasmtime_ssp_args_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, + struct argv_environ_values *argv_environ, #endif - char **argv, - char *argv_buf -) { - for (size_t i = 0; i < argv_environ->argc; ++i) { - argv[i] = argv_buf + (argv_environ->argv_list[i] - argv_environ->argv_buf); - } - argv[argv_environ->argc] = NULL; - bh_memcpy_s(argv_buf, (uint32)argv_environ->argv_buf_size, - argv_environ->argv_buf, (uint32)argv_environ->argv_buf_size); - return __WASI_ESUCCESS; + char **argv, char *argv_buf) +{ + for (size_t i = 0; i < argv_environ->argc; ++i) { + argv[i] = + argv_buf + (argv_environ->argv_list[i] - argv_environ->argv_buf); + } + argv[argv_environ->argc] = NULL; + bh_memcpy_s(argv_buf, (uint32)argv_environ->argv_buf_size, + argv_environ->argv_buf, (uint32)argv_environ->argv_buf_size); + return __WASI_ESUCCESS; } -__wasi_errno_t wasmtime_ssp_args_sizes_get( +__wasi_errno_t +wasmtime_ssp_args_sizes_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, + struct argv_environ_values *argv_environ, #endif - size_t *argc, - size_t *argv_buf_size -) { - *argc = argv_environ->argc; - *argv_buf_size = argv_environ->argv_buf_size; - return __WASI_ESUCCESS; + size_t *argc, size_t *argv_buf_size) +{ + *argc = argv_environ->argc; + *argv_buf_size = argv_environ->argv_buf_size; + return __WASI_ESUCCESS; } -__wasi_errno_t wasmtime_ssp_environ_get( +__wasi_errno_t +wasmtime_ssp_environ_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, + struct argv_environ_values *argv_environ, #endif - char **environ, - char *environ_buf -) { - for (size_t i = 0; i < argv_environ->environ_count; ++i) { - environ[i] = environ_buf + (argv_environ->environ_list[i] - argv_environ->environ_buf); - } - environ[argv_environ->environ_count] = NULL; - bh_memcpy_s(environ_buf, (uint32)argv_environ->environ_buf_size, - argv_environ->environ_buf, (uint32)argv_environ->environ_buf_size); - return __WASI_ESUCCESS; + char **environ, char *environ_buf) +{ + for (size_t i = 0; i < argv_environ->environ_count; ++i) { + environ[i] = + environ_buf + + (argv_environ->environ_list[i] - argv_environ->environ_buf); + } + environ[argv_environ->environ_count] = NULL; + bh_memcpy_s(environ_buf, (uint32)argv_environ->environ_buf_size, + argv_environ->environ_buf, + (uint32)argv_environ->environ_buf_size); + return __WASI_ESUCCESS; } -__wasi_errno_t wasmtime_ssp_environ_sizes_get( +__wasi_errno_t +wasmtime_ssp_environ_sizes_get( #if !defined(WASMTIME_SSP_STATIC_CURFDS) - struct argv_environ_values *argv_environ, + struct argv_environ_values *argv_environ, #endif - size_t *environ_count, - size_t *environ_buf_size -) { - *environ_count = argv_environ->environ_count; - *environ_buf_size = argv_environ->environ_buf_size; - return __WASI_ESUCCESS; + size_t *environ_count, size_t *environ_buf_size) +{ + *environ_count = argv_environ->environ_count; + *environ_buf_size = argv_environ->environ_buf_size; + return __WASI_ESUCCESS; } -bool argv_environ_init(struct argv_environ_values *argv_environ, - char *argv_buf, size_t argv_buf_size, - char **argv_list, size_t argc, - char *environ_buf, size_t environ_buf_size, - char **environ_list, size_t environ_count) +bool +argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf, + size_t argv_buf_size, char **argv_list, size_t argc, + char *environ_buf, size_t environ_buf_size, + char **environ_list, size_t environ_count) { memset(argv_environ, 0, sizeof(struct argv_environ_values)); @@ -2912,11 +2911,12 @@ bool argv_environ_init(struct argv_environ_values *argv_environ, return true; } -void argv_environ_destroy(struct argv_environ_values *argv_environ) -{ -} +void +argv_environ_destroy(struct argv_environ_values *argv_environ) +{} -void fd_table_destroy(struct fd_table *ft) +void +fd_table_destroy(struct fd_table *ft) { if (ft->entries) { for (uint32 i = 0; i < ft->size; i++) { @@ -2929,12 +2929,13 @@ void fd_table_destroy(struct fd_table *ft) } } -void fd_prestats_destroy(struct fd_prestats *pt) +void +fd_prestats_destroy(struct fd_prestats *pt) { if (pt->prestats) { for (uint32 i = 0; i < pt->size; i++) { if (pt->prestats[i].dir != NULL) { - wasm_runtime_free((void*)pt->prestats[i].dir); + wasm_runtime_free((void *)pt->prestats[i].dir); } } rwlock_destroy(&pt->lock); diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h index 1aca4dac45..62214dc2fa 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -20,41 +22,48 @@ struct fd_prestat; struct syscalls; struct fd_table { - struct rwlock lock; - struct fd_entry *entries; - size_t size; - size_t used; + struct rwlock lock; + struct fd_entry *entries; + size_t size; + size_t used; }; struct fd_prestats { - struct rwlock lock; - struct fd_prestat *prestats; - size_t size; - size_t used; + struct rwlock lock; + struct fd_prestat *prestats; + size_t size; + size_t used; }; struct argv_environ_values { - const char *argv_buf; - size_t argv_buf_size; - char **argv_list; - size_t argc; - char *environ_buf; - size_t environ_buf_size; - char **environ_list; - size_t environ_count; + const char *argv_buf; + size_t argv_buf_size; + char **argv_list; + size_t argc; + char *environ_buf; + size_t environ_buf_size; + char **environ_list; + size_t environ_count; }; -bool fd_table_init(struct fd_table *); -bool fd_table_insert_existing(struct fd_table *, __wasi_fd_t, int); -bool fd_prestats_init(struct fd_prestats *); -bool fd_prestats_insert(struct fd_prestats *, const char *, __wasi_fd_t); -bool argv_environ_init(struct argv_environ_values *argv_environ, - char *argv_buf, size_t argv_buf_size, - char **argv_list, size_t argc, - char *environ_buf, size_t environ_buf_size, - char **environ_list, size_t environ_count); -void argv_environ_destroy(struct argv_environ_values *argv_environ); -void fd_table_destroy(struct fd_table *ft); -void fd_prestats_destroy(struct fd_prestats *pt); +bool +fd_table_init(struct fd_table *); +bool +fd_table_insert_existing(struct fd_table *, __wasi_fd_t, int); +bool +fd_prestats_init(struct fd_prestats *); +bool +fd_prestats_insert(struct fd_prestats *, const char *, __wasi_fd_t); +bool +argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf, + size_t argv_buf_size, char **argv_list, size_t argc, + char *environ_buf, size_t environ_buf_size, + char **environ_list, size_t environ_count); +void +argv_environ_destroy(struct argv_environ_values *argv_environ); +void +fd_table_destroy(struct fd_table *ft); +void +fd_prestats_destroy(struct fd_prestats *pt); #endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h index b88f80d860..2d40bc3aae 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -15,76 +17,82 @@ // LIST: Double-linked list. #define LIST_HEAD(name, type) \ - struct name { \ - struct type *l_first; \ - } + struct name { \ + struct type *l_first; \ + } + +/* clang-format off */ #define LIST_HEAD_INITIALIZER(head) \ - { NULL } + { NULL } +/* clang-format on */ -#define LIST_ENTRY(type) \ - struct { \ - struct type *l_next; \ - struct type **l_prev; \ - } +#define LIST_ENTRY(type) \ + struct { \ + struct type *l_next; \ + struct type **l_prev; \ + } #define LIST_FOREACH(var, head, field) \ - for ((var) = (head)->l_first; (var) != NULL; (var) = (var)->field.l_next) -#define LIST_INIT(head) \ - do { \ - (head)->l_first = NULL; \ - } while (0) -#define LIST_INSERT_HEAD(head, element, field) \ - do { \ - (element)->field.l_next = (head)->l_first; \ - if ((head)->l_first != NULL) \ - (head)->l_first->field.l_prev = &(element)->field.l_next; \ - (head)->l_first = (element); \ - (element)->field.l_prev = &(head)->l_first; \ - } while (0) -#define LIST_REMOVE(element, field) \ - do { \ - if ((element)->field.l_next != NULL) \ - (element)->field.l_next->field.l_prev = (element)->field.l_prev; \ - *(element)->field.l_prev = (element)->field.l_next; \ - } while (0) + for ((var) = (head)->l_first; (var) != NULL; (var) = (var)->field.l_next) + +#define LIST_INIT(head) \ + do { \ + (head)->l_first = NULL; \ + } while (0) + +#define LIST_INSERT_HEAD(head, element, field) \ + do { \ + (element)->field.l_next = (head)->l_first; \ + if ((head)->l_first != NULL) \ + (head)->l_first->field.l_prev = &(element)->field.l_next; \ + (head)->l_first = (element); \ + (element)->field.l_prev = &(head)->l_first; \ + } while (0) + +#define LIST_REMOVE(element, field) \ + do { \ + if ((element)->field.l_next != NULL) \ + (element)->field.l_next->field.l_prev = (element)->field.l_prev; \ + *(element)->field.l_prev = (element)->field.l_next; \ + } while (0) // TAILQ: Double-linked list with tail pointer. #define TAILQ_HEAD(name, type) \ - struct name { \ - struct type *t_first; \ - struct type **t_last; \ - } + struct name { \ + struct type *t_first; \ + struct type **t_last; \ + } -#define TAILQ_ENTRY(type) \ - struct { \ - struct type *t_next; \ - struct type **t_prev; \ - } +#define TAILQ_ENTRY(type) \ + struct { \ + struct type *t_next; \ + struct type **t_prev; \ + } #define TAILQ_EMPTY(head) ((head)->t_first == NULL) #define TAILQ_FIRST(head) ((head)->t_first) #define TAILQ_FOREACH(var, head, field) \ - for ((var) = (head)->t_first; (var) != NULL; (var) = (var)->field.t_next) -#define TAILQ_INIT(head) \ - do { \ - (head)->t_first = NULL; \ - (head)->t_last = &(head)->t_first; \ - } while (0) -#define TAILQ_INSERT_TAIL(head, elm, field) \ - do { \ - (elm)->field.t_next = NULL; \ - (elm)->field.t_prev = (head)->t_last; \ - *(head)->t_last = (elm); \ - (head)->t_last = &(elm)->field.t_next; \ - } while (0) -#define TAILQ_REMOVE(head, element, field) \ - do { \ - if ((element)->field.t_next != NULL) \ - (element)->field.t_next->field.t_prev = (element)->field.t_prev; \ - else \ - (head)->t_last = (element)->field.t_prev; \ - *(element)->field.t_prev = (element)->field.t_next; \ - } while (0) + for ((var) = (head)->t_first; (var) != NULL; (var) = (var)->field.t_next) +#define TAILQ_INIT(head) \ + do { \ + (head)->t_first = NULL; \ + (head)->t_last = &(head)->t_first; \ + } while (0) +#define TAILQ_INSERT_TAIL(head, elm, field) \ + do { \ + (elm)->field.t_next = NULL; \ + (elm)->field.t_prev = (head)->t_last; \ + *(head)->t_last = (elm); \ + (head)->t_last = &(elm)->field.t_next; \ + } while (0) +#define TAILQ_REMOVE(head, element, field) \ + do { \ + if ((element)->field.t_next != NULL) \ + (element)->field.t_next->field.t_prev = (element)->field.t_prev; \ + else \ + (head)->t_last = (element)->field.t_prev; \ + *(element)->field.t_prev = (element)->field.t_next; \ + } while (0) #endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c index 0428828958..01a1dab3a6 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -15,8 +17,10 @@ #if CONFIG_HAS_ARC4RANDOM_BUF -void random_buf(void *buf, size_t len) { - arc4random_buf(buf, len); +void +random_buf(void *buf, size_t len) +{ + arc4random_buf(buf, len); } #elif CONFIG_HAS_GETRANDOM @@ -25,42 +29,48 @@ void random_buf(void *buf, size_t len) { #include #endif -void random_buf(void *buf, size_t len) { - for (;;) { - ssize_t x = getrandom(buf, len, 0); - if (x < 0) { - if (errno == EINTR) - continue; - os_printf("getrandom failed: %s", strerror(errno)); - abort(); - } - if ((size_t)x == len) - return; - buf = (void *)((unsigned char *)buf + x); - len -= (size_t)x; - } +void +random_buf(void *buf, size_t len) +{ + for (;;) { + ssize_t x = getrandom(buf, len, 0); + if (x < 0) { + if (errno == EINTR) + continue; + os_printf("getrandom failed: %s", strerror(errno)); + abort(); + } + if ((size_t)x == len) + return; + buf = (void *)((unsigned char *)buf + x); + len -= (size_t)x; + } } #else static int urandom; -static void open_urandom(void) { - urandom = open("/dev/urandom", O_RDONLY); - if (urandom < 0) { - os_printf("Failed to open /dev/urandom\n"); - abort(); - } +static void +open_urandom(void) +{ + urandom = open("/dev/urandom", O_RDONLY); + if (urandom < 0) { + os_printf("Failed to open /dev/urandom\n"); + abort(); + } } -void random_buf(void *buf, size_t len) { - static pthread_once_t open_once = PTHREAD_ONCE_INIT; - pthread_once(&open_once, open_urandom); +void +random_buf(void *buf, size_t len) +{ + static pthread_once_t open_once = PTHREAD_ONCE_INIT; + pthread_once(&open_once, open_urandom); - if ((size_t)read(urandom, buf, len) != len) { - os_printf("Short read on /dev/urandom\n"); - abort(); - } + if ((size_t)read(urandom, buf, len) != len) { + os_printf("Short read on /dev/urandom\n"); + abort(); + } } #endif @@ -72,15 +82,17 @@ void random_buf(void *buf, size_t len) { // arc4random() until it lies within the range [2^k % upper, 2^k). As // this range has length k * upper, we can safely obtain a number // without any modulo bias. -uintmax_t random_uniform(uintmax_t upper) { - // Compute 2^k % upper - // == (2^k - upper) % upper - // == -upper % upper. - uintmax_t lower = -upper % upper; - for (;;) { - uintmax_t value; - random_buf(&value, sizeof(value)); - if (value >= lower) - return value % upper; - } +uintmax_t +random_uniform(uintmax_t upper) +{ + // Compute 2^k % upper + // == (2^k - upper) % upper + // == -upper % upper. + uintmax_t lower = -upper % upper; + for (;;) { + uintmax_t value; + random_buf(&value, sizeof(value)); + if (value >= lower) + return value % upper; + } } diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h index 8f9ecaf736..23c2da4dbd 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -12,7 +14,8 @@ #ifndef RANDOM_H #define RANDOM_H -void random_buf(void *, size_t); +void +random_buf(void *, size_t); uintmax_t random_uniform(uintmax_t); #endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h index a1c9541eda..ac348ebb4c 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -46,8 +48,8 @@ refcount_acquire(struct refcount *r) PRODUCES(*r) static inline bool refcount_release(struct refcount *r) CONSUMES(*r) { - int old = (int)atomic_fetch_sub_explicit(&r->count, 1, - memory_order_release); + int old = + (int)atomic_fetch_sub_explicit(&r->count, 1, memory_order_release); bh_assert(old != 0 && "Reference count becoming negative"); return old == 1; } diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h index 565635e7b6..434561dcbf 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -12,6 +14,8 @@ #ifndef RIGHTS_H #define RIGHTS_H +/* clang-format off */ + #define RIGHTS_ALL \ (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_READ | \ __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ @@ -80,4 +84,6 @@ __WASI_RIGHT_POLL_FD_READWRITE) #define RIGHTS_TTY_INHERITING 0 +/* clang-format on */ + #endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/signals.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/signals.h index ead95e79a9..cad78ad3ce 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/signals.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/signals.h @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -12,6 +14,7 @@ #ifndef SIGNALS_H #define SIGNALS_H -void signals_init(void); +void +signals_init(void); #endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h index 3dd40b67a5..a64d90f3bf 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -14,7 +16,8 @@ #include -#if defined(__FreeBSD__) || defined(__APPLE__) || (defined(ANDROID) && __ANDROID_API__ < 28) +#if defined(__FreeBSD__) || defined(__APPLE__) \ + || (defined(ANDROID) && __ANDROID_API__ < 28) #define CONFIG_HAS_ARC4RANDOM_BUF 1 #else #define CONFIG_HAS_ARC4RANDOM_BUF 0 @@ -22,10 +25,9 @@ // On Linux, prefer to use getrandom, though it isn't available in // GLIBC before 2.25. -#if defined(__linux__) && \ - (!defined(__GLIBC__) || \ - __GLIBC__ > 2 || \ - (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) +#if defined(__linux__) \ + && (!defined(__GLIBC__) || __GLIBC__ > 2 \ + || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) #define CONFIG_HAS_GETRANDOM 1 #else #define CONFIG_HAS_GETRANDOM 0 diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c index 442112b9c2..858d8d5e40 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -27,7 +29,8 @@ bh_strndup(const char *s, size_t n) } char * -str_nullterminate(const char *s, size_t len) { +str_nullterminate(const char *s, size_t len) +{ /* Copy string */ char *ret = bh_strndup(s, len); @@ -40,5 +43,5 @@ str_nullterminate(const char *s, size_t len) { errno = EILSEQ; return NULL; } - return ret; + return ret; } diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h index bf46dda340..7d633e5c8b 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h @@ -1,5 +1,7 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license information. +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See +// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license +// information. // // Significant parts of this file are derived from cloudabi-utils. See // https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE @@ -14,6 +16,7 @@ #include "ssp_config.h" -char *str_nullterminate(const char *, size_t); +char * +str_nullterminate(const char *, size_t); #endif diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 4ee917a8f0..2c1f3e6c74 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -7,7 +7,6 @@ typedef struct { bh_list_link l; - void (*destroy_cb)(WASMCluster *); } DestroyCallBackNode; @@ -133,8 +132,7 @@ wasm_cluster_create(WASMExecEnv *exec_env) } /* Prepare the aux stack top and size for every thread */ - if (!wasm_exec_env_get_aux_stack(exec_env, - &aux_stack_start, + if (!wasm_exec_env_get_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) { LOG_VERBOSE("No aux stack info for this module, can't create thread"); @@ -167,13 +165,13 @@ wasm_cluster_create(WASMExecEnv *exec_env) total_size = cluster_max_thread_num * sizeof(uint32); if (total_size >= UINT32_MAX || !(cluster->stack_tops = - wasm_runtime_malloc((uint32)total_size))) { + wasm_runtime_malloc((uint32)total_size))) { goto fail; } memset(cluster->stack_tops, 0, (uint32)total_size); if (!(cluster->stack_segment_occupied = - wasm_runtime_malloc(cluster_max_thread_num * sizeof(bool)))) { + wasm_runtime_malloc(cluster_max_thread_num * sizeof(bool)))) { goto fail; } memset(cluster->stack_segment_occupied, 0, @@ -215,8 +213,8 @@ destroy_cluster_visitor(void *node, void *user_data) void wasm_cluster_destroy(WASMCluster *cluster) { - traverse_list(destroy_callback_list, - destroy_cluster_visitor, (void *)cluster); + traverse_list(destroy_callback_list, destroy_cluster_visitor, + (void *)cluster); /* Remove the cluster from the cluster list */ os_mutex_lock(&cluster_list_lock); @@ -302,7 +300,7 @@ wasm_cluster_search_exec_env(WASMCluster *cluster, } /* search the global cluster list to find if the given - module instance have a corresponding exec_env */ + module instance have a corresponding exec_env */ WASMExecEnv * wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst) { @@ -338,21 +336,19 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) return NULL; } - if (!(new_module_inst = - wasm_runtime_instantiate_internal(module, true, 8192, - 0, NULL, 0))) { + if (!(new_module_inst = wasm_runtime_instantiate_internal( + module, true, 8192, 0, NULL, 0))) { return NULL; } if (module_inst) { /* Set custom_data to new module instance */ wasm_runtime_set_custom_data_internal( - new_module_inst, - wasm_runtime_get_custom_data(module_inst)); + new_module_inst, wasm_runtime_get_custom_data(module_inst)); } - new_exec_env = wasm_exec_env_create_internal( - new_module_inst, exec_env->wasm_stack_size); + new_exec_env = wasm_exec_env_create_internal(new_module_inst, + exec_env->wasm_stack_size); if (!new_exec_env) goto fail1; @@ -400,7 +396,7 @@ wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env) } /* start routine of thread manager */ -static void* +static void * thread_manager_start_routine(void *arg) { void *ret; @@ -432,8 +428,7 @@ thread_manager_start_routine(void *arg) int32 wasm_cluster_create_thread(WASMExecEnv *exec_env, wasm_module_inst_t module_inst, - void* (*thread_routine)(void *), - void *arg) + void *(*thread_routine)(void *), void *arg) { WASMCluster *cluster; WASMExecEnv *new_exec_env; @@ -443,8 +438,8 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, cluster = wasm_exec_env_get_cluster(exec_env); bh_assert(cluster); - new_exec_env = wasm_exec_env_create_internal( - module_inst, exec_env->wasm_stack_size); + new_exec_env = + wasm_exec_env_create_internal(module_inst, exec_env->wasm_stack_size); if (!new_exec_env) return -1; @@ -466,9 +461,10 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, new_exec_env->thread_start_routine = thread_routine; new_exec_env->thread_arg = arg; - if (0 != os_thread_create(&tid, thread_manager_start_routine, - (void *)new_exec_env, - APP_THREAD_STACK_SIZE_DEFAULT)) { + if (0 + != os_thread_create(&tid, thread_manager_start_routine, + (void *)new_exec_env, + APP_THREAD_STACK_SIZE_DEFAULT)) { goto fail3; } @@ -484,6 +480,122 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, return -1; } +#if WASM_ENABLE_DEBUG_INTERP != 0 +WASMCurrentEnvStatus * +wasm_cluster_create_exenv_status() +{ + WASMCurrentEnvStatus *status; + + if (!(status = wasm_runtime_malloc(sizeof(WASMCurrentEnvStatus)))) { + goto fail; + } + if (os_mutex_init(&status->wait_lock) != 0) + goto fail1; + + if (os_cond_init(&status->wait_cond) != 0) + goto fail2; + status->step_count = 0; + status->signal_flag = 0; + status->running_status = 0; + return status; + +fail2: + os_mutex_destroy(&status->wait_lock); +fail1: + wasm_runtime_free(status); +fail: + return NULL; +} + +void +wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status) +{ + os_mutex_destroy(&status->wait_lock); + os_cond_destroy(&status->wait_cond); + wasm_runtime_free(status); +} + +inline static bool +wasm_cluster_thread_is_running(WASMExecEnv *exec_env) +{ + return exec_env->current_status->running_status == STATUS_RUNNING + || exec_env->current_status->running_status == STATUS_STEP; +} + +void +wasm_cluster_clear_thread_signal(WASMExecEnv *exec_env) +{ + exec_env->current_status->signal_flag = 0; +} + +void +wasm_cluster_wait_thread_status(WASMExecEnv *exec_env, uint32 *status) +{ + os_mutex_lock(&exec_env->current_status->wait_lock); + while (wasm_cluster_thread_is_running(exec_env)) { + os_cond_wait(&exec_env->current_status->wait_cond, + &exec_env->current_status->wait_lock); + } + *status = exec_env->current_status->signal_flag; + os_mutex_unlock(&exec_env->current_status->wait_lock); +} + +void +wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo) +{ + exec_env->current_status->signal_flag = signo; +} + +void +wasm_cluster_thread_stopped(WASMExecEnv *exec_env) +{ + exec_env->current_status->running_status = STATUS_STOP; + os_cond_signal(&exec_env->current_status->wait_cond); +} + +void +wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env) +{ + os_mutex_lock(&exec_env->wait_lock); + while (!wasm_cluster_thread_is_running(exec_env)) { + os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); + } + os_mutex_unlock(&exec_env->wait_lock); +} + +void +wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo) +{ + WASMExecEnv *exec_env = bh_list_first_elem(&cluster->exec_env_list); + while (exec_env) { + wasm_cluster_thread_send_signal(exec_env, signo); + exec_env = bh_list_elem_next(exec_env); + } +} + +void +wasm_cluster_thread_exited(WASMExecEnv *exec_env) +{ + exec_env->current_status->running_status = STATUS_EXIT; + os_cond_signal(&exec_env->current_status->wait_cond); +} + +void +wasm_cluster_thread_continue(WASMExecEnv *exec_env) +{ + wasm_cluster_clear_thread_signal(exec_env); + exec_env->current_status->running_status = STATUS_RUNNING; + os_cond_signal(&exec_env->wait_cond); +} + +void +wasm_cluster_thread_step(WASMExecEnv *exec_env) +{ + exec_env->current_status->running_status = STATUS_STEP; + os_cond_signal(&exec_env->wait_cond); +} +#endif + int32 wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val) { @@ -520,7 +632,10 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) cluster = wasm_exec_env_get_cluster(exec_env); bh_assert(cluster); - +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_cluster_clear_thread_signal(exec_env); + wasm_cluster_thread_exited(exec_env); +#endif /* App exit the thread, free the resources before exit native thread */ /* Free aux stack space */ free_aux_stack(cluster, exec_env->aux_stack_bottom.bottom); @@ -537,7 +652,12 @@ int32 wasm_cluster_cancel_thread(WASMExecEnv *exec_env) { /* Set the termination flag */ +#if WASM_ENABLE_DEBUG_INTERP != 0 + wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM); + wasm_cluster_thread_exited(exec_env); +#else exec_env->suspend_flags.flags |= 0x01; +#endif return 0; } @@ -557,16 +677,15 @@ terminate_thread_visitor(void *node, void *user_data) void wasm_cluster_terminate_all(WASMCluster *cluster) { - traverse_list(&cluster->exec_env_list, - terminate_thread_visitor, NULL); + traverse_list(&cluster->exec_env_list, terminate_thread_visitor, NULL); } void wasm_cluster_terminate_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env) { - traverse_list(&cluster->exec_env_list, - terminate_thread_visitor, (void *)exec_env); + traverse_list(&cluster->exec_env_list, terminate_thread_visitor, + (void *)exec_env); } bool @@ -605,22 +724,22 @@ suspend_thread_visitor(void *node, void *user_data) void wasm_cluster_suspend_all(WASMCluster *cluster) { - traverse_list(&cluster->exec_env_list, - suspend_thread_visitor, NULL); + traverse_list(&cluster->exec_env_list, suspend_thread_visitor, NULL); } void wasm_cluster_suspend_all_except_self(WASMCluster *cluster, WASMExecEnv *exec_env) { - traverse_list(&cluster->exec_env_list, - suspend_thread_visitor, (void *)exec_env); + traverse_list(&cluster->exec_env_list, suspend_thread_visitor, + (void *)exec_env); } void wasm_cluster_resume_thread(WASMExecEnv *exec_env) { exec_env->suspend_flags.flags &= ~0x02; + os_cond_signal(&exec_env->wait_cond); } static void @@ -643,8 +762,7 @@ set_exception_visitor(void *node, void *user_data) WASMExecEnv *curr_exec_env = (WASMExecEnv *)node; WASMExecEnv *exec_env = (WASMExecEnv *)user_data; WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env); - WASMModuleInstanceCommon *curr_module_inst = - get_module_inst(curr_exec_env); + WASMModuleInstanceCommon *curr_module_inst = get_module_inst(curr_exec_env); const char *exception = wasm_runtime_get_exception(module_inst); /* skip "Exception: " */ exception += 11; @@ -684,7 +802,6 @@ wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst, cluster = wasm_exec_env_get_cluster(exec_env); bh_assert(cluster); - traverse_list(&cluster->exec_env_list, - set_custom_data_visitor, + traverse_list(&cluster->exec_env_list, set_custom_data_visitor, custom_data); } diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.h b/core/iwasm/libraries/thread-mgr/thread_manager.h index 392ebe4a7e..0baa4f5efe 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.h +++ b/core/iwasm/libraries/thread-mgr/thread_manager.h @@ -15,9 +15,62 @@ #ifdef __cplusplus extern "C" { #endif +#if WASM_ENABLE_DEBUG_INTERP != 0 +#define WAMR_SIG_TRAP (5) +#define WAMR_SIG_STOP (19) +#define WAMR_SIG_TERM (15) +#define WAMR_SIG_SINGSTEP (0x1ff) -typedef struct WASMCluster -{ +#define STATUS_RUNNING (0) +#define STATUS_STOP (1) +#define STATUS_EXIT (2) +#define STATUS_STEP (3) + +#define IS_WAMR_TERM_SIG(signo) ((signo) == WAMR_SIG_TERM) + +#define IS_WAMR_STOP_SIG(signo) \ + ((signo) == WAMR_SIG_STOP || (signo) == WAMR_SIG_TRAP) + +typedef struct WASMCurrentEnvStatus { + uint64 signal_flag : 32; + uint64 step_count : 16; + uint64 running_status : 16; + korp_mutex wait_lock; + korp_cond wait_cond; +} WASMCurrentEnvStatus; + +WASMCurrentEnvStatus * +wasm_cluster_create_exenv_status(); + +void +wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status); + +void +wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo); + +void +wasm_cluster_thread_stopped(WASMExecEnv *exec_env); + +void +wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env); + +void +wasm_cluster_wait_thread_status(WASMExecEnv *exec_env, uint32 *status); + +void +wasm_cluster_thread_exited(WASMExecEnv *exec_env); + +void +wasm_cluster_thread_continue(WASMExecEnv *exec_env); + +void +wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo); + +void +wasm_cluster_thread_step(WASMExecEnv *exec_env); + +#endif +typedef struct WASMCluster { struct WASMCluster *next; korp_mutex lock; @@ -33,7 +86,8 @@ typedef struct WASMCluster bool *stack_segment_occupied; } WASMCluster; -void wasm_cluster_set_max_thread_num(uint32 num); +void +wasm_cluster_set_max_thread_num(uint32 num); bool thread_manager_init(); @@ -50,14 +104,13 @@ void wasm_cluster_destroy(WASMCluster *cluster); /* Get the cluster of the current exec_env */ -WASMCluster* +WASMCluster * wasm_exec_env_get_cluster(WASMExecEnv *exec_env); int32 wasm_cluster_create_thread(WASMExecEnv *exec_env, wasm_module_inst_t module_inst, - void* (*thread_routine)(void *), - void *arg); + void *(*thread_routine)(void *), void *arg); int32 wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val); diff --git a/core/shared/mem-alloc/ems/ems_gc_internal.h b/core/shared/mem-alloc/ems/ems_gc_internal.h index e72e470179..b099211c1e 100644 --- a/core/shared/mem-alloc/ems/ems_gc_internal.h +++ b/core/shared/mem-alloc/ems/ems_gc_internal.h @@ -88,16 +88,16 @@ hmu_verify(void *vheap, hmu_t *hmu); * hmu bit operation */ -#define SETBIT(v, offset) (v) |= (1 << (offset)) -#define GETBIT(v, offset) ((v) & (1 << (offset)) ? 1 : 0) -#define CLRBIT(v, offset) (v) &= (uint32)(~(1 << (offset))) +#define SETBIT(v, offset) (v) |= ((uint32)1 << (offset)) +#define GETBIT(v, offset) ((v) & ((uint32)1 << (offset)) ? 1 : 0) +#define CLRBIT(v, offset) (v) &= (~((uint32)1 << (offset))) #define SETBITS(v, offset, size, value) do { \ - (v) &= (uint32)(~(((1 << size) - 1) << offset));\ - (v) |= (uint32)(value << offset); \ + (v) &= ~((((uint32)1 << size) - 1) << offset); \ + (v) |= ((uint32)value << offset); \ } while(0) -#define CLRBITS(v, offset, size) (v) &= ~(((1 << size) - 1) << offset) -#define GETBITS(v, offset, size) (((v) & ((uint32)(((1 << size) - 1) << offset))) >> offset) +#define CLRBITS(v, offset, size) (v) &= ~((((uint32)1 << size) - 1) << offset) +#define GETBITS(v, offset, size) (((v) & (((((uint32)1 << size) - 1) << offset))) >> offset) /** * gc object layout definition diff --git a/core/shared/platform/android/platform_internal.h b/core/shared/platform/android/platform_internal.h index 82adc93ff8..703e6bf5bb 100644 --- a/core/shared/platform/android/platform_internal.h +++ b/core/shared/platform/android/platform_internal.h @@ -61,7 +61,9 @@ typedef pthread_t korp_thread; #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) \ || defined(BUILD_TARGET_AMD_64) \ - || defined(BUILD_TARGET_AARCH64) + || defined(BUILD_TARGET_AARCH64) \ + || defined(BUILD_TARGET_RISCV64_LP64D) \ + || defined(BUILD_TARGET_RISCV64_LP64) #include @@ -86,7 +88,7 @@ bool os_thread_signal_inited(); void os_signal_unmask(); void os_sigreturn(); -#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64 */ +#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ typedef long int __syscall_slong_t; diff --git a/core/shared/platform/common/math/math.c b/core/shared/platform/common/math/math.c index 4f6a7ce7c7..6b4f25f2b7 100644 --- a/core/shared/platform/common/math/math.c +++ b/core/shared/platform/common/math/math.c @@ -132,76 +132,110 @@ static union { /* Get two 32 bit ints from a double. */ -#define EXTRACT_WORDS_L(ix0,ix1,d) \ - do { \ - ieee_double_shape_type_little ew_u; \ - ew_u.value = (d); \ - (ix0) = ew_u.parts.msw; \ - (ix1) = ew_u.parts.lsw; \ +#define EXTRACT_WORDS_L(ix0,ix1,d) \ + do { \ + ieee_double_shape_type_little ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ } while (0) /* Set a double from two 32 bit ints. */ -#define INSERT_WORDS_L(d,ix0,ix1) \ - do { \ - ieee_double_shape_type_little iw_u; \ - iw_u.parts.msw = (ix0); \ - iw_u.parts.lsw = (ix1); \ - (d) = iw_u.value; \ +#define INSERT_WORDS_L(d,ix0,ix1) \ + do { \ + ieee_double_shape_type_little iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ } while (0) /* Get two 32 bit ints from a double. */ -#define EXTRACT_WORDS_B(ix0,ix1,d) \ - do { \ - ieee_double_shape_type_big ew_u; \ - ew_u.value = (d); \ - (ix0) = ew_u.parts.msw; \ - (ix1) = ew_u.parts.lsw; \ +#define EXTRACT_WORDS_B(ix0,ix1,d) \ + do { \ + ieee_double_shape_type_big ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ } while (0) /* Set a double from two 32 bit ints. */ -#define INSERT_WORDS_B(d,ix0,ix1) \ - do { \ - ieee_double_shape_type_big iw_u; \ - iw_u.parts.msw = (ix0); \ - iw_u.parts.lsw = (ix1); \ - (d) = iw_u.value; \ +#define INSERT_WORDS_B(d,ix0,ix1) \ + do { \ + ieee_double_shape_type_big iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ } while (0) /* Get the more significant 32 bit int from a double. */ -#define GET_HIGH_WORD_L(i,d) \ - do { \ - ieee_double_shape_type_little gh_u; \ - gh_u.value = (d); \ - (i) = gh_u.parts.msw; \ +#define GET_HIGH_WORD_L(i,d) \ + do { \ + ieee_double_shape_type_little gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ } while (0) /* Get the more significant 32 bit int from a double. */ -#define GET_HIGH_WORD_B(i,d) \ - do { \ - ieee_double_shape_type_big gh_u; \ - gh_u.value = (d); \ - (i) = gh_u.parts.msw; \ +#define GET_HIGH_WORD_B(i,d) \ + do { \ + ieee_double_shape_type_big gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ } while (0) /* Set the more significant 32 bits of a double from an int. */ -#define SET_HIGH_WORD_L(d,v) \ - do { \ - ieee_double_shape_type_little sh_u; \ - sh_u.value = (d); \ - sh_u.parts.msw = (v); \ - (d) = sh_u.value; \ +#define SET_HIGH_WORD_L(d,v) \ + do { \ + ieee_double_shape_type_little sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ } while (0) /* Set the more significant 32 bits of a double from an int. */ -#define SET_HIGH_WORD_B(d,v) \ - do { \ - ieee_double_shape_type_big sh_u; \ - sh_u.value = (d); \ - sh_u.parts.msw = (v); \ - (d) = sh_u.value; \ +#define SET_HIGH_WORD_B(d,v) \ + do { \ + ieee_double_shape_type_big sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ + } while (0) + +/* Set the less significant 32 bits of a double from an int. */ +#define SET_LOW_WORD_L(d,v) \ + do { \ + ieee_double_shape_type_little sh_u; \ + sh_u.value = (d); \ + sh_u.parts.lsw = (v); \ + (d) = sh_u.value; \ + } while (0) + +/* Set the more significant 32 bits of a double from an int. */ +#define SET_LOW_WORD_B(d,v) \ + do { \ + ieee_double_shape_type_big sh_u; \ + sh_u.value = (d); \ + sh_u.parts.lsw = (v); \ + (d) = sh_u.value; \ + } while (0) + +/* Get the less significant 32 bit int from a double. */ +#define GET_LOW_WORD_L(i,d) \ + do { \ + ieee_double_shape_type_little gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ + } while (0) + +/* Get the less significant 32 bit int from a double. */ +#define GET_LOW_WORD_B(i,d) \ + do { \ + ieee_double_shape_type_big gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ } while (0) /* @@ -262,6 +296,22 @@ typedef union SET_HIGH_WORD_B(d,v); \ } while (0) +#define GET_LOW_WORD(d,v) \ + do { \ + if (is_little_endian()) \ + GET_LOW_WORD_L(d,v); \ + else \ + GET_LOW_WORD_B(d,v); \ + } while (0) + +#define SET_LOW_WORD(d,v) \ + do { \ + if (is_little_endian()) \ + SET_LOW_WORD_L(d,v); \ + else \ + SET_LOW_WORD_B(d,v); \ + } while (0) + #define __HI(x) (is_little_endian() ? __HIL(x) : __HIB(x)) #define __LO(x) (is_little_endian() ? __LOL(x) : __LOB(x)) @@ -314,12 +364,222 @@ TWO52[2]={ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ }; +#ifdef __STDC__ +static const double +#else +static double +#endif +atanhi[] = { + 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ + 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ + 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ + 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ +}; + +#ifdef __STDC__ +static const double +#else +static double +#endif +atanlo[] = { + 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ + 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ + 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ + 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ +}; + +#ifdef __STDC__ +static const double +#else +static double +#endif +aT[] = { + 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ + -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ + 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ + -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ + 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ + -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ + 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ + -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ + 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ + -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ + 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ +}; + +#ifdef __STDC__ +static const double +#else +static double +#endif +zero = 0.0, +pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ +pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */ +pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ +pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ + +#ifdef __STDC__ +static const double +#else +static double +#endif +bp[] = {1.0, 1.5,}, +dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ +dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ +two = 2.0, +two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ + /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ +L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ +L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ +L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ +L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ +L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ +L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ +lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ +lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ +lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ +ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ +cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ +cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ +cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ +ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ +ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ +ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ + static double freebsd_sqrt(double x); static double freebsd_floor(double x); static double freebsd_ceil(double x); static double freebsd_fabs(double x); static double freebsd_rint(double x); static int freebsd_isnan(double x); +static double freebsd_atan(double x); +static double freebsd_atan2(double y, double x); + + +static double freebsd_atan(double x) +{ + double w,s1,s2,z; + int32_t ix,hx,id; + + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x44100000) { /* if |x| >= 2^66 */ + u_int32_t low; + GET_LOW_WORD(low,x); + if(ix>0x7ff00000|| + (ix==0x7ff00000&&(low!=0))) + return x+x; /* NaN */ + if(hx>0) return atanhi[3]+*(volatile double *)&atanlo[3]; + else return -atanhi[3]-*(volatile double *)&atanlo[3]; + } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ + if (ix < 0x3e400000) { /* |x| < 2^-27 */ + if(huge+x>one) return x; /* raise inexact */ + } + id = -1; + } else { + x = freebsd_fabs(x); + if (ix < 0x3ff30000) { /* |x| < 1.1875 */ + if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ + id = 0; x = (2.0*x-one)/(2.0+x); + } else { /* 11/16<=|x|< 19/16 */ + id = 1; x = (x-one)/(x+one); + } + } else { + if (ix < 0x40038000) { /* |x| < 2.4375 */ + id = 2; x = (x-1.5)/(one+1.5*x); + } else { /* 2.4375 <= |x| < 2^66 */ + id = 3; x = -1.0/x; + } + }} + /* end of argument reduction */ + z = x*x; + w = z*z; + /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ + s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); + s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); + if (id<0) return x - x*(s1+s2); + else { + z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); + return (hx<0)? -z:z; + } +} + + +static double freebsd_atan2(double y, double x) +{ + double z; + int32_t k,m,hx,hy,ix,iy; + u_int32_t lx,ly; + + EXTRACT_WORDS(hx,lx,x); + ix = hx&0x7fffffff; + EXTRACT_WORDS(hy,ly,y); + iy = hy&0x7fffffff; + if(((ix|((lx|-lx)>>31))>0x7ff00000)|| + ((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */ + return x+y; + if(hx==0x3ff00000&&lx==0) return freebsd_atan(y); /* x=1.0 */ + m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ + + /* when y = 0 */ + if((iy|ly)==0) { + switch(m) { + case 0: + case 1: return y; /* atan(+-0,+anything)=+-0 */ + case 2: return pi+tiny;/* atan(+0,-anything) = pi */ + case 3: + default: return -pi-tiny;/* atan(-0,-anything) =-pi */ + } + } + /* when x = 0 */ + if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; + + /* when x is INF */ + if(ix==0x7ff00000) { + if(iy==0x7ff00000) { + switch(m) { + case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ + case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ + case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ + case 3: + default: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ + } + } else { + switch(m) { + case 0: return zero ; /* atan(+...,+INF) */ + case 1: return -zero ; /* atan(-...,+INF) */ + case 2: return pi+tiny ; /* atan(+...,-INF) */ + case 3: + default: return -pi-tiny ; /* atan(-...,-INF) */ + } + } + } + /* when y is INF */ + if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; + + /* compute y/x */ + k = (iy-ix)>>20; + if(k > 60) { /* |y/x| > 2**60 */ + z=pi_o_2+0.5*pi_lo; + m&=1; + } + else if(hx<0&&k<-60) z=0.0; /* 0 > |y|/x > -2**-60 */ + else z=freebsd_atan(fabs(y/x)); /* safe to do y/x */ + switch (m) { + case 0: return z ; /* atan(+,+) */ + case 1: return -z ; /* atan(-,+) */ + case 2: return pi-(z-pi_lo);/* atan(+,-) */ + default: /* case 3 */ + return (z-pi_lo)-pi;/* atan(-,-) */ + } +} static double freebsd_sqrt(double x) /* wrapper sqrt */ { @@ -777,6 +1037,271 @@ freebsd_fmaxf(float x, float y) return (x > y ? x : y); } +static double +freebsd_copysign(double x, double y) +{ + u_int32_t hx,hy; + GET_HIGH_WORD(hx,x); + GET_HIGH_WORD(hy,y); + SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000)); + return x; +} + +static double +freebsd_scalbn(double x, int n) +{ + int32_t k,hx,lx; + EXTRACT_WORDS(hx,lx,x); + k = (hx&0x7ff00000)>>20; /* extract exponent */ + if (k==0) { /* 0 or subnormal x */ + if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ + x *= two54; + GET_HIGH_WORD(hx,x); + k = ((hx&0x7ff00000)>>20) - 54; + if (n< -50000) return tiny*x; /*underflow*/ + } + if (k==0x7ff) return x+x; /* NaN or Inf */ + k = k+n; + if (k > 0x7fe) return huge*freebsd_copysign(huge,x); /* overflow */ + if (k > 0) /* normal result */ + {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;} + if (k <= -54) { + if (n > 50000) /* in case integer overflow in n+k */ + return huge*freebsd_copysign(huge,x); /*overflow*/ + else return tiny*freebsd_copysign(tiny,x); /*underflow*/ + } + k += 54; /* subnormal result */ + SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); + return x*twom54; +} + +static double +freebsd_pow(double x, double y) +{ + double z,ax,z_h,z_l,p_h,p_l; + double y1,t1,t2,r,s,t,u,v,w; + int32_t i,j,k,yisint,n; + int32_t hx,hy,ix,iy; + u_int32_t lx,ly; + + EXTRACT_WORDS(hx,lx,x); + EXTRACT_WORDS(hy,ly,y); + ix = hx&0x7fffffff; iy = hy&0x7fffffff; + + /* y==zero: x**0 = 1 */ + if((iy|ly)==0) return one; + + /* x==1: 1**y = 1, even if y is NaN */ + if (hx==0x3ff00000 && lx == 0) return one; + + /* y!=zero: result is NaN if either arg is NaN */ + if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) || + iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) + return (x+0.0)+(y+0.0); + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if(hx<0) { + if(iy>=0x43400000) yisint = 2; /* even integer y */ + else if(iy>=0x3ff00000) { + k = (iy>>20)-0x3ff; /* exponent */ + if(k>20) { + j = ly>>(52-k); + if((j<<(52-k))==ly) yisint = 2-(j&1); + } else if(ly==0) { + j = iy>>(20-k); + if((j<<(20-k))==iy) yisint = 2-(j&1); + } + } + } + + /* special value of y */ + if(ly==0) { + if (iy==0x7ff00000) { /* y is +-inf */ + if(((ix-0x3ff00000)|lx)==0) + return one; /* (-1)**+-inf is NaN */ + else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */ + return (hy>=0)? y: zero; + else /* (|x|<1)**-,+inf = inf,0 */ + return (hy<0)?-y: zero; + } + if(iy==0x3ff00000) { /* y is +-1 */ + if(hy<0) return one/x; else return x; + } + if(hy==0x40000000) return x*x; /* y is 2 */ + if(hy==0x40080000) return x*x*x; /* y is 3 */ + if(hy==0x40100000) { /* y is 4 */ + u = x*x; + return u*u; + } + if(hy==0x3fe00000) { /* y is 0.5 */ + if(hx>=0) /* x >= +0 */ + return sqrt(x); + } + } + + ax = fabs(x); + /* special value of x */ + if(lx==0) { + if(ix==0x7ff00000||ix==0||ix==0x3ff00000){ + z = ax; /*x is +-0,+-inf,+-1*/ + if(hy<0) z = one/z; /* z = (1/|x|) */ + if(hx<0) { + if(((ix-0x3ff00000)|yisint)==0) { + z = (z-z)/(z-z); /* (-1)**non-int is NaN */ + } else if(yisint==1) + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + return z; + } + } + + /* CYGNUS LOCAL + fdlibm-5.3 fix: This used to be + n = (hx>>31)+1; + but ANSI C says a right shift of a signed negative quantity is + implementation defined. */ + n = ((u_int32_t)hx>>31)-1; + + /* (x<0)**(non-int) is NaN */ + if((n|yisint)==0) return (x-x)/(x-x); + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */ + + /* |y| is huge */ + if(iy>0x41e00000) { /* if |y| > 2**31 */ + if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */ + if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; + if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; + } + /* over/underflow if x is not close to one */ + if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny; + if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny; + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = ax-one; /* t has 20 trailing zeros */ + w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25)); + u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ + v = t*ivln2_l-w*ivln2; + t1 = u+v; + SET_LOW_WORD(t1,0); + t2 = v-(t1-u); + } else { + double ss,s2,s_h,s_l,t_h,t_l; + n = 0; + /* take care subnormal number */ + if(ix<0x00100000) + {ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); } + n += ((ix)>>20)-0x3ff; + j = ix&0x000fffff; + /* determine interval */ + ix = j|0x3ff00000; /* normalize ix */ + if(j<=0x3988E) k=0; /* |x|>1)|0x20000000)+0x00080000+(k<<18)); + t_l = ax - (t_h-bp[k]); + s_l = v*((u-s_h*t_h)-s_h*t_l); + /* compute log(ax) */ + s2 = ss*ss; + r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); + r += s_l*(s_h+ss); + s2 = s_h*s_h; + t_h = 3.0+s2+r; + SET_LOW_WORD(t_h,0); + t_l = r-((t_h-3.0)-s2); + /* u+v = ss*(1+...) */ + u = s_h*t_h; + v = s_l*t_h+t_l*ss; + /* 2/(3log2)*(ss+...) */ + p_h = u+v; + SET_LOW_WORD(p_h,0); + p_l = v-(p_h-u); + z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l*p_h+p_l*cp+dp_l[k]; + /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (double)n; + t1 = (((z_h+z_l)+dp_h[k])+t); + SET_LOW_WORD(t1,0); + t2 = z_l-(((t1-t)-dp_h[k])-z_h); + } + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + y1 = y; + SET_LOW_WORD(y1,0); + p_l = (y-y1)*t1+y*t2; + p_h = y1*t1; + z = p_l+p_h; + EXTRACT_WORDS(j,i,z); + if (j>=0x40900000) { /* z >= 1024 */ + if(((j-0x40900000)|i)!=0) /* if z > 1024 */ + return s*huge*huge; /* overflow */ + else { + if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */ + } + } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */ + if(((j-0xc090cc00)|i)!=0) /* z < -1075 */ + return s*tiny*tiny; /* underflow */ + else { + if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */ + } + } + /* + * compute 2**(p_h+p_l) + */ + i = j&0x7fffffff; + k = (i>>20)-0x3ff; + n = 0; + if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j+(0x00100000>>(k+1)); + k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ + t = zero; + SET_HIGH_WORD(t,n&~(0x000fffff>>k)); + n = ((n&0x000fffff)|0x00100000)>>(20-k); + if(j<0) n = -n; + p_h -= t; + } + t = p_l+p_h; + SET_LOW_WORD(t,0); + u = t*lg2_h; + v = (p_l-(t-p_h))*lg2+t*lg2_l; + z = u+v; + w = v-(z-u); + t = z*z; + t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); + r = (z*t1)/(t1-two)-(w+z*w); + z = one-(r-z); + GET_HIGH_WORD(j,z); + j += (n<<20); + if((j>>20)<=0) z = freebsd_scalbn(z,n); /* subnormal output */ + else SET_HIGH_WORD(z,j); + return s*z; +} + +double atan(double x) +{ + return freebsd_atan(x); +} + +double atan2(double y, double x) +{ + return freebsd_atan2(y, x); +} + double sqrt(double x) { return freebsd_sqrt(x); @@ -863,3 +1388,14 @@ fmaxf(float x, float y) return freebsd_fmaxf(x, y); } +double +pow(double x, double y) +{ + return freebsd_pow(x, y); +} + +double +scalbn(double x, int n) +{ + return freebsd_scalbn(x, n); +} diff --git a/core/shared/platform/common/posix/posix_memmap.c b/core/shared/platform/common/posix/posix_memmap.c index 825afefcdf..15a4de8b65 100644 --- a/core/shared/platform/common/posix/posix_memmap.c +++ b/core/shared/platform/common/posix/posix_memmap.c @@ -44,8 +44,57 @@ os_mmap(void *hint, size_t size, int prot, int flags) if (flags & MMAP_MAP_FIXED) map_flags |= MAP_FIXED; +#if defined(BUILD_TARGET_RISCV64_LP64D) || defined(BUILD_TARGET_RISCV64_LP64) + /* As AOT relocation in RISCV64 may require that the code/data mapped + * is in range 0 to 2GB, we try to map the memory with hint address + * (mmap's first argument) to meet the requirement. + */ + if (!hint && !(flags & MMAP_MAP_FIXED) && (flags & MMAP_MAP_32BIT)) { + uint8 *stack_addr = (uint8*)&map_prot; + uint8 *text_addr = (uint8*)os_mmap; + /* hint address begins with 1MB */ + static uint8 *hint_addr = (uint8 *)(uintptr_t)BH_MB; + + if ((hint_addr - text_addr >= 0 + && hint_addr - text_addr < 100 * BH_MB) + || (text_addr - hint_addr >= 0 + && text_addr - hint_addr < 100 * BH_MB)) { + /* hint address is possibly in text section, skip it */ + hint_addr += 100 * BH_MB; + } + + if ((hint_addr - stack_addr >= 0 + && hint_addr - stack_addr < 8 * BH_MB) + || (stack_addr - hint_addr >= 0 + && stack_addr - hint_addr < 8 * BH_MB)) { + /* hint address is possibly in native stack area, skip it */ + hint_addr += 8 * BH_MB; + } + + /* try 10 times, step with 1MB each time */ + for (i = 0; + i < 10 && hint_addr < (uint8 *)(uintptr_t)(2ULL * BH_GB); + i++) { + addr = mmap(hint_addr, request_size, map_prot, map_flags, -1, 0); + if (addr != MAP_FAILED) { + if (addr > (uint8 *)(uintptr_t)(2ULL * BH_GB)) { + /* unmap and try again if the mapped address doesn't + * meet the requirement */ + os_munmap(addr, request_size); + } + else { + /* reset next hint address */ + hint_addr += request_size; + return addr; + } + } + hint_addr += BH_MB; + } + } +#endif + /* try 5 times */ - for (i = 0; i < 5; i ++) { + for (i = 0; i < 5; i++) { addr = mmap(hint, request_size, map_prot, map_flags, -1, 0); if (addr != MAP_FAILED) break; diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index 60a13fb613..3da44a6904 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -305,7 +305,7 @@ uint8 *os_thread_get_stack_boundary() addr += guard_size; } (void)stack_size; -#elif defined(__APPLE__) +#elif defined(__APPLE__) || defined(__NuttX__) if ((addr = (uint8*)pthread_get_stackaddr_np(self))) { stack_size = pthread_get_stacksize_np(self); if (stack_size > max_stack_size) @@ -339,8 +339,7 @@ static os_thread_local_attribute uint8 *sigalt_stack_base_addr; #if defined(__clang__) #pragma clang optimize off -#endif -#if defined(__GNUC__) +#elif defined(__GNUC__) #pragma GCC push_options #pragma GCC optimize("O0") __attribute__((no_sanitize_address)) @@ -361,11 +360,10 @@ touch_pages(uint8 *stack_min_addr, uint32 page_size) } return sum; } -#if defined(__GNUC__) -#pragma GCC pop_options -#endif #if defined(__clang__) #pragma clang optimize on +#elif defined(__GNUC__) +#pragma GCC pop_options #endif static bool diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h index d6ee41cdab..3fa85a3078 100644 --- a/core/shared/platform/darwin/platform_internal.h +++ b/core/shared/platform/darwin/platform_internal.h @@ -62,7 +62,9 @@ typedef pthread_t korp_thread; #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) \ || defined(BUILD_TARGET_AMD_64) \ - || defined(BUILD_TARGET_AARCH64) + || defined(BUILD_TARGET_AARCH64) \ + || defined(BUILD_TARGET_RISCV64_LP64D) \ + || defined(BUILD_TARGET_RISCV64_LP64) #include @@ -87,7 +89,7 @@ bool os_thread_signal_inited(); void os_signal_unmask(); void os_sigreturn(); -#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64 */ +#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ #ifdef __cplusplus diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 5239929d00..7b92824cc1 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -84,11 +84,24 @@ int os_thread_detach(korp_tid); */ void os_thread_exit(void *retval); +/** + * Initialize current thread environment if current thread + * is created by developer but not runtime + * + * @return 0 if success, -1 otherwise + */ +int os_thread_env_init(); + +/** + * Destroy current thread environment + */ +void os_thread_env_destroy(); + /** * Suspend execution of the calling thread for (at least) * usec microseconds * - * @param return 0 if success, -1 otherwise + * @return 0 if success, -1 otherwise */ int os_usleep(uint32 usec); diff --git a/core/shared/platform/include/platform_common.h b/core/shared/platform/include/platform_common.h index 8a331d97c3..92418f8120 100644 --- a/core/shared/platform/include/platform_common.h +++ b/core/shared/platform/include/platform_common.h @@ -80,8 +80,13 @@ int BH_VPRINTF(const char *format, va_list ap); /* Return the offset of the given field in the given type */ #ifndef offsetof +/* GCC 4.0 and later has the builtin. */ +#if defined(__GNUC__) && __GNUC__ >= 4 +#define offsetof(Type, field) __builtin_offsetof(Type, field) +#else #define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) #endif +#endif typedef uint8_t uint8; typedef int8_t int8; diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h index e2a52a6bbd..3e5c7e3f06 100644 --- a/core/shared/platform/linux/platform_internal.h +++ b/core/shared/platform/linux/platform_internal.h @@ -61,7 +61,9 @@ typedef pthread_t korp_thread; #if WASM_DISABLE_HW_BOUND_CHECK == 0 #if defined(BUILD_TARGET_X86_64) \ || defined(BUILD_TARGET_AMD_64) \ - || defined(BUILD_TARGET_AARCH64) + || defined(BUILD_TARGET_AARCH64) \ + || defined(BUILD_TARGET_RISCV64_LP64D) \ + || defined(BUILD_TARGET_RISCV64_LP64) #include @@ -86,7 +88,7 @@ bool os_thread_signal_inited(); void os_signal_unmask(); void os_sigreturn(); -#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64 */ +#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ #ifdef __cplusplus diff --git a/core/shared/platform/rt-thread/platform_internal.h b/core/shared/platform/rt-thread/platform_internal.h index 1480a9e44b..9fe1c9c616 100644 --- a/core/shared/platform/rt-thread/platform_internal.h +++ b/core/shared/platform/rt-thread/platform_internal.h @@ -25,6 +25,8 @@ #define BUILD_TARGET "armv6" #elif defined(RTT_WAMR_BUILD_TARGET_ARMV4) #define BUILD_TARGET "armv4" +#elif defined(RTT_WAMR_BUILD_TARGET_X86_32) +#define BUILD_TARGET "X86_32" #else #error "unsupported aot platform." #endif diff --git a/core/shared/platform/rt-thread/rtt_platform.c b/core/shared/platform/rt-thread/rtt_platform.c index 6ac8c70f68..493d766ca2 100644 --- a/core/shared/platform/rt-thread/rtt_platform.c +++ b/core/shared/platform/rt-thread/rtt_platform.c @@ -180,12 +180,10 @@ void os_munmap(void *addr, size_t size) rt_free(addr); } -#ifdef OS_ENABLE_HW_BOUND_CHECK int os_mprotect(void *addr, size_t size, int prot) { return 0; } -#endif void os_dcache_flush(void) { diff --git a/core/shared/platform/windows/win_thread.c b/core/shared/platform/windows/win_thread.c index 221214bdf3..95792f72c1 100644 --- a/core/shared/platform/windows/win_thread.c +++ b/core/shared/platform/windows/win_thread.c @@ -288,6 +288,62 @@ os_thread_exit(void *retval) _endthreadex(0); } +int +os_thread_env_init() +{ + os_thread_data *thread_data = TlsGetValue(thread_data_key); + + if (thread_data) + /* Already created */ + return BHT_OK; + + if (!(thread_data = BH_MALLOC(sizeof(os_thread_data)))) + return BHT_ERROR; + + memset(thread_data, 0, sizeof(os_thread_data)); + thread_data->thread_id = GetCurrentThreadId(); + + if (os_sem_init(&thread_data->wait_node.sem) != BHT_OK) + goto fail1; + + if (os_mutex_init(&thread_data->wait_lock) != BHT_OK) + goto fail2; + + if (os_cond_init(&thread_data->wait_cond) != BHT_OK) + goto fail3; + + if (!TlsSetValue(thread_data_key, thread_data)) + goto fail4; + + return BHT_OK; + +fail4: + os_cond_destroy(&thread_data->wait_cond); +fail3: + os_mutex_destroy(&thread_data->wait_lock); +fail2: + os_sem_destroy(&thread_data->wait_node.sem); +fail1: + BH_FREE(thread_data); + return BHT_ERROR; +} + +void +os_thread_env_destroy() +{ + os_thread_data *thread_data = TlsGetValue(thread_data_key); + + /* Note that supervisor_thread_data's resources will be destroyed + by os_thread_sys_destroy() */ + if (thread_data && thread_data != &supervisor_thread_data) { + TlsSetValue(thread_data_key, NULL); + os_cond_destroy(&thread_data->wait_cond); + os_mutex_destroy(&thread_data->wait_lock); + os_sem_destroy(&thread_data->wait_node.sem); + BH_FREE(thread_data); + } +} + int os_sem_init(korp_sem *sem) { diff --git a/core/shared/platform/zephyr/platform_internal.h b/core/shared/platform/zephyr/platform_internal.h index 256d98de72..9de485f8f1 100644 --- a/core/shared/platform/zephyr/platform_internal.h +++ b/core/shared/platform/zephyr/platform_internal.h @@ -67,6 +67,8 @@ size_t strspn(const char *s, const char *accept); size_t strcspn(const char *s, const char *reject); /* math functions which are not provided by os */ +double atan(double x); +double atan2(double y, double x); double sqrt(double x); double floor(double x); double ceil(double x); @@ -83,6 +85,8 @@ float rintf(float x); float truncf(float x); int signbit(double x); int isnan(double x); +double pow(double x, double y); +double scalbn(double x, int n); unsigned long long int strtoull(const char *nptr, char **endptr, int base); double strtod(const char *nptr, char **endptr); diff --git a/core/shared/platform/zephyr/zephyr_platform.c b/core/shared/platform/zephyr/zephyr_platform.c index 42a9d00aa7..4ecc828d3b 100644 --- a/core/shared/platform/zephyr/zephyr_platform.c +++ b/core/shared/platform/zephyr/zephyr_platform.c @@ -202,6 +202,11 @@ os_dcache_flush() key = irq_lock(); SCB_CleanDCache(); irq_unlock(key); +#elif defined(CONFIG_SOC_CVF_EM7D) && defined(CONFIG_ARC_MPU) \ + && defined (CONFIG_CACHE_FLUSHING) + __asm__ __volatile__("sync"); + z_arc_v2_aux_reg_write(_ARC_V2_DC_FLSH, BIT(0)); + __asm__ __volatile__("sync"); #endif } diff --git a/core/shared/platform/zephyr/zephyr_thread.c b/core/shared/platform/zephyr/zephyr_thread.c index 9322551957..55cadb47c9 100644 --- a/core/shared/platform/zephyr/zephyr_thread.c +++ b/core/shared/platform/zephyr/zephyr_thread.c @@ -14,6 +14,55 @@ } \ } while (0) +#if defined(CONFIG_ARM_MPU) || defined(CONFIG_ARC_MPU) \ + || KERNEL_VERSION_NUMBER > 0x020300 /* version 2.3.0 */ +#define BH_ENABLE_ZEPHYR_MPU_STACK 1 +#elif !defined(BH_ENABLE_ZEPHYR_MPU_STACK) +#define BH_ENABLE_ZEPHYR_MPU_STACK 0 +#endif +#if !defined(BH_ZEPHYR_MPU_STACK_SIZE) +#define BH_ZEPHYR_MPU_STACK_SIZE APP_THREAD_STACK_SIZE_MIN +#endif +#if !defined(BH_ZEPHYR_MPU_STACK_COUNT) +#define BH_ZEPHYR_MPU_STACK_COUNT 4 +#endif + +#if BH_ENABLE_ZEPHYR_MPU_STACK != 0 +static K_THREAD_STACK_ARRAY_DEFINE(mpu_stacks, + BH_ZEPHYR_MPU_STACK_COUNT, + BH_ZEPHYR_MPU_STACK_SIZE); +static bool mpu_stack_allocated[BH_ZEPHYR_MPU_STACK_COUNT]; +static struct k_mutex mpu_stack_lock; + +static char *mpu_stack_alloc() +{ + int i; + + k_mutex_lock(&mpu_stack_lock, K_FOREVER); + for (i = 0; i < BH_ZEPHYR_MPU_STACK_COUNT; i++) { + if (!mpu_stack_allocated[i]) { + mpu_stack_allocated[i] = true; + k_mutex_unlock(&mpu_stack_lock); + return (char*)mpu_stacks[i]; + } + } + k_mutex_unlock(&mpu_stack_lock); + return NULL; +} + +static void mpu_stack_free(char *stack) +{ + int i; + + k_mutex_lock(&mpu_stack_lock, K_FOREVER); + for (i = 0; i < BH_ZEPHYR_MPU_STACK_COUNT; i++) { + if ((char *)mpu_stacks[i] == stack) + mpu_stack_allocated[i] = false; + } + k_mutex_unlock(&mpu_stack_lock); +} +#endif + typedef struct os_thread_wait_node { struct k_sem sem; os_thread_wait_list next; @@ -32,8 +81,12 @@ typedef struct os_thread_data { os_thread_wait_list thread_wait_list; /* Thread stack size */ unsigned stack_size; +#if BH_ENABLE_ZEPHYR_MPU_STACK == 0 /* Thread stack */ char stack[1]; +#else + char *stack; +#endif } os_thread_data; typedef struct os_thread_obj { @@ -164,6 +217,9 @@ int os_thread_sys_init() if (is_thread_sys_inited) return BHT_OK; +#if BH_ENABLE_ZEPHYR_MPU_STACK != 0 + k_mutex_init(&mpu_stack_lock); +#endif k_mutex_init(&thread_data_lock); k_mutex_init(&thread_obj_lock); @@ -214,6 +270,9 @@ static void os_thread_cleanup(void) /* Set flag to true for the next thread creating to free the thread object */ ((os_thread_obj*) thread_data->tid)->to_be_freed = true; +#if BH_ENABLE_ZEPHYR_MPU_STACK != 0 + mpu_stack_free(thread_data->stack); +#endif BH_FREE(thread_data); } @@ -253,14 +312,17 @@ int os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, memset(tid, 0, sizeof(os_thread_obj)); + /* Create and initialize thread data */ +#if BH_ENABLE_ZEPHYR_MPU_STACK == 0 if (stack_size < APP_THREAD_STACK_SIZE_MIN) stack_size = APP_THREAD_STACK_SIZE_MIN; - - /* Create and initialize thread data */ thread_data_size = offsetof(os_thread_data, stack) + stack_size; +#else + stack_size = BH_ZEPHYR_MPU_STACK_SIZE; + thread_data_size = sizeof(os_thread_data); +#endif if (!(thread_data = BH_MALLOC(thread_data_size))) { - BH_FREE(tid); - return BHT_ERROR; + goto fail1; } memset(thread_data, 0, thread_data_size); @@ -268,22 +330,36 @@ int os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, thread_data->stack_size = stack_size; thread_data->tid = tid; +#if BH_ENABLE_ZEPHYR_MPU_STACK != 0 + if (!(thread_data->stack = mpu_stack_alloc())) { + goto fail2; + } +#endif + /* Create the thread */ if (!((tid = k_thread_create(tid, (k_thread_stack_t *)thread_data->stack, stack_size, os_thread_wrapper, start, arg, thread_data, prio, 0, K_NO_WAIT)))) { - BH_FREE(tid); - BH_FREE(thread_data); - return BHT_ERROR; + goto fail3; } bh_assert(tid == thread_data->tid); /* Set thread custom data */ thread_data_list_add(thread_data); - thread_obj_list_add((os_thread_obj*) tid); + thread_obj_list_add((os_thread_obj*)tid); *p_tid = tid; return BHT_OK; + +fail3: +#if BH_ENABLE_ZEPHYR_MPU_STACK != 0 + mpu_stack_free(thread_data->stack); +fail2: +#endif + BH_FREE(thread_data); +fail1: + BH_FREE(tid); + return BHT_ERROR; } korp_tid os_self_thread() diff --git a/core/shared/utils/runtime_timer.c b/core/shared/utils/runtime_timer.c index ba495369c4..205b92ab98 100644 --- a/core/shared/utils/runtime_timer.c +++ b/core/shared/utils/runtime_timer.c @@ -19,7 +19,7 @@ typedef struct _app_timer { bool is_periodic; } app_timer_t; -typedef struct _timer_ctx { +struct _timer_ctx { app_timer_t *app_timers; app_timer_t *idle_timers; app_timer_t *free_timers; @@ -33,7 +33,7 @@ typedef struct _timer_ctx { timer_callback_f timer_callback; check_timer_expiry_f refresh_checker; -} *timer_ctx_t; +}; uint64 bh_get_tick_ms() diff --git a/doc/build_wamr.md b/doc/build_wamr.md index 72eb1f16a9..1203008f2e 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -19,8 +19,9 @@ The script `runtime_lib.cmake` defines a number of variables for configuring the - **WAMR_BUILD_PLATFORM**: set the target platform. It can be set to any platform name (folder name) under folder [core/shared/platform](../core/shared/platform). -- **WAMR_BUILD_TARGET**: set the target CPU architecture. Current supported targets are: X86_64, X86_32, AARCH64, ARM, THUMB, XTENSA, RISCV64 and MIPS. - - For ARM and THUMB, the format is \\[\]\[_VFP], where \ is the ARM sub-architecture and the "_VFP" suffix means using VFP coprocessor registers s0-s15 (d0-d7) for passing arguments or returning results in standard procedure-call. For AARCH64, the format is\[\], VFP is enabled by default. Both \ and "_VFP" are optional, e.g. AARCH64, AARCH64V8, AARCHV8.1, ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on. +- **WAMR_BUILD_TARGET**: set the target CPU architecture. Current supported targets are: X86_64, X86_32, AARCH64, ARM, THUMB, XTENSA, ARC, RISCV32, RISCV64 and MIPS. + - For ARM and THUMB, the format is \\[\]\[_VFP], where \ is the ARM sub-architecture and the "_VFP" suffix means using VFP coprocessor registers s0-s15 (d0-d7) for passing arguments or returning results in standard procedure-call. Both \ and "_VFP" are optional, e.g. ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on. + - For AARCH64, the format is\[\], VFP is enabled by default. \ is optional, e.g. AARCH64, AARCH64V8, AARCH64V8.1 and so on. - For RISCV64, the format is \[_abi], where "_abi" is optional, currently the supported formats are RISCV64, RISCV64_LP64D and RISCV64_LP64: RISCV64 and RISCV64_LP64D are identical, using [LP64D](https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#-named-abis) as abi (LP64 with hardware floating-point calling convention for FLEN=64). And RISCV64_LP64 uses [LP64](https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#-named-abis) as abi (Integer calling-convention only, and hardware floating-point calling convention is not used). - For RISCV32, the format is \[_abi], where "_abi" is optional, currently the supported formats are RISCV32, RISCV32_ILP32D and RISCV32_ILP32: RISCV32 and RISCV32_ILP32D are identical, using [ILP32D](https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#-named-abis) as abi (ILP32 with hardware floating-point calling convention for FLEN=64). And RISCV32_ILP32 uses [ILP32](https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#-named-abis) as abi (Integer calling-convention only, and hardware floating-point calling convention is not used). @@ -40,6 +41,7 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM - **WAMR_BUILD_AOT**=1/0, default to enable if not set - **WAMR_BUILD_JIT**=1/0, default to disable if not set +- **WAMR_BUILD_LAZY_JIT**=1/0, default to disable if not set #### **Configure LIBC** @@ -197,8 +199,8 @@ make ``` -By default in Linux, the interpreter, AOT and WASI are enabled, and JIT is disabled. And the build target is -set to X86_64 or X86_32 depending on the platform's bitwidth. +By default in Linux, the interpreter, AOT and WASI are enabled, and JIT and LazyJIT are disabled. +And the build target is set to X86_64 or X86_32 depending on the platform's bitwidth. To enable WASM JIT, firstly we should build LLVM: @@ -216,6 +218,11 @@ cmake .. -DWAMR_BUILD_JIT=1 make ``` +Moreover, pass arguments `-DWAMR_BUILD_JIT=1` and `-DWAMR_BUILD_LAZY_JIT=1` together to cmake to enable WASM Lazy JIT. +If Lazy JIT is enabled, then jit function bodies in the module will not be compiled until they are first called, +so compile time reduces significantly. + + Linux SGX (Intel Software Guard Extension) ------------------------- @@ -251,6 +258,7 @@ Then build the source codes: ``` Bash cd core/deps/ git clone https://github.com/nodejs/uvwasi.git + cd product-mini/platforms/windows/ mkdir build cd build @@ -465,4 +473,4 @@ $ ls ../build_out/ *build_wamr.sh* will generate *linux* compatible libraries ( libiwasm.so and libvmlib.a ) and an executable binary (*iwasm*) and copy *iwasm* to *build_out*. All original generated files are still under -*product-mini/platforms/linux/build*. \ No newline at end of file +*product-mini/platforms/linux/build*. diff --git a/doc/build_wasm_app.md b/doc/build_wasm_app.md index ca82531f02..2ceb51f9ca 100644 --- a/doc/build_wasm_app.md +++ b/doc/build_wasm_app.md @@ -6,6 +6,11 @@ For C and C++, WASI-SDK version 12.0+ is the major tool supported by WAMR to bui To install WASI SDK, please download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. +The offical *wasi-sdk release* doesn't fully support *latest 128-bit SIMD spec* yet. WARM provides a script in [build-wasi-sdk](../test-tools/build-wasi-sdk/) to generate +another wasi-sdk with *llvm-13* from source code and installs it at *../test-tools/wasi-sdk*. If you plan to build WASM applications with *latest 128-bit SIMD*, please use it instead of the offical release. + +And [sample workloads](../samples/workload) are using the self-compiled wasi-sdk. + For [AssemblyScript](https://github.com/AssemblyScript/assemblyscript), please refer to [AssemblyScript quick start](https://www.assemblyscript.org/quick-start.html) and [AssemblyScript compiler](https://www.assemblyscript.org/compiler.html#command-line-options) for how to install `asc` compiler and build WASM applications. For Rust, please firstly ref to [Install Rust and Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) to install cargo, rustc and rustup, by default they are installed under ~/.cargo/bin, and then run `rustup target add wasm32-wasi` to install wasm32-wasi target for Rust toolchain. To build WASM applications, we can run `cargo build --target wasm32-wasi`, the output files are under `target/wasm32-wasi`. @@ -236,11 +241,14 @@ wamrc supports a number of compilation options through the command line argument wamrc --help Usage: wamrc [options] -o output_file wasm_file --target= Set the target arch, which has the general format: - = x86_64, i386, aarch64, arm, thumb, xtensa, mips. + = x86_64, i386, aarch64, arm, thumb, xtensa, mips, + riscv64, riscv32. Default is host arch, e.g. x86_64 = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc. Use --target=help to list supported targets - --target-abi= Set the target ABI, e.g. gnu, eabi, gnueabihf, etc. (default: gnu) + --target-abi= Set the target ABI, e.g. gnu, eabi, gnueabihf, msvc, etc. + Default is gnu if target isn't riscv64 or riscv32 + For target riscv64 and riscv32, default is lp64d and ilp32d Use --target-abi=help to list all the ABI supported --cpu= Set the target CPU (default: host CPU, e.g. skylake) Use --cpu=help to list all the CPU supported @@ -263,10 +271,16 @@ Usage: wamrc [options] -o output_file wasm_file llvmir-opt Optimized LLVM IR --enable-bulk-memory Enable the post-MVP bulk memory feature --enable-multi-thread Enable multi-thread feature, the dependent features bulk-memory and - --enable-tail-call Enable the post-MVP tail call feature thread-mgr will be enabled automatically - --enable-simd Enable the post-MVP 128-bit SIMD feature + --enable-tail-call Enable the post-MVP tail call feature + --disable-simd Disable the post-MVP 128-bit SIMD feature: + currently 128-bit SIMD is only supported for x86-64 target, + and by default it is enabled in x86-64 target and disabled + in other targets + --enable-ref-types Enable the post-MVP reference types feature + --disable-aux-stack-check Disable auxiliary stack overflow/underflow check --enable-dump-call-stack Enable stack trace feature + --enable-perf-profiling Enable function performance profiling -v=n Set log verbose level (0 to 5, default is 2), larger with more log Examples: wamrc -o test.aot test.wasm wamrc --target=i386 -o test.aot test.wasm diff --git a/doc/embed_wamr.md b/doc/embed_wamr.md index d0c8e3612c..3c1223fa60 100644 --- a/doc/embed_wamr.md +++ b/doc/embed_wamr.md @@ -200,7 +200,7 @@ wasm_runtime_module_malloc(wasm_module_inst_t module_inst, * size: the size of buffer to be allocated and copy data */ uint32_t -wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst, +wasm_runtime_module_dup_data(wasm_module_inst_t module_inst, const char *src, uint32_t size); /* free the memory allocated from module memory space */ diff --git a/doc/source_debugging.md b/doc/source_debugging.md new file mode 100644 index 0000000000..4c09c3e18f --- /dev/null +++ b/doc/source_debugging.md @@ -0,0 +1,90 @@ +# WAMR source debugging + +WAMR supports source level debugging based on DWARF (normally used in C/C++/Rust), source map (normally used in AssemblyScript) is not supported. + +## Build wasm application with debug information +To debug your application, you need to compile them with debug information. You can use `-g` option when compiling the source code if you are using wasi-sdk (also work for emcc and rustc): +``` bash +/opt/wasi-sdk/bin/clang -g test.c -o test.wasm +``` + +Then you will get `test.wasm` which is a WebAssembly module with embedded DWARF sections. Further, you can use `llvm-dwarfdump` to check if the generated wasm file contains DWARF information: +``` bash +llvm-dwarfdump-12 test.wasm +``` + +## Debugging with interpreter +1. Install dependent libraries +``` bash +apt update && apt install cmake make g++ libxml2-dev -y +``` + +2. Build iwasm with source debugging feature +``` bash +cd ${WAMR_ROOT}/product-mini/platforms/linux +mkdir build && cd build +cmake .. -DWAMR_BUILD_DEBUG_INTERP=1 +make +``` + +3. Execute iwasm with debug engine enabled +``` bash +iwasm -g=127.0.0.1:1234 test.wasm +``` + +4. Build customized lldb (assume you have already cloned llvm) +``` bash +cd ${WAMR_ROOT}/core/deps/llvm +git apply ../../../build-scripts/lldb-wasm.patch +mkdir build-lldb && cd build-lldb +cmake -DCMAKE_BUILD_TYPE:STRING="Release" -DLLVM_ENABLE_PROJECTS="clang;lldb" -DLLVM_TARGETS_TO_BUILD:STRING="X86;WebAssembly" -DLLVM_ENABLE_LIBXML2:BOOL=ON ../llvm +make -j $(nproc) +``` + +5. Launch customized lldb and connect to iwasm +``` bash +lldb +(lldb) process connect -p wasm connect://127.0.0.1:1234 +``` +Then you can use lldb commands to debug your applications. Please refer to [lldb document](https://lldb.llvm.org/use/tutorial.html) for command usage. + +> Known issue: `step over` on some function may be treated as `step in`, it will be fixed later. + +## Debugging with AoT + +> Note: AoT debugging is experimental and only a few debugging capabilities are supported. + +1. Build lldb (assume you have already built llvm) +``` bash +cd ${WAMR_ROOT}/core/deps/llvm/build +cmake . -DLLVM_ENABLE_PROJECTS="clang;lldb" +make -j $(nproc) +``` + +2. Build wamrc with debugging feature +``` bash +cd ${WAMR_ROOT}/wamr-compiler +mkdir build && cd build +cmake .. -DWAMR_BUILD_DEBUG_AOT=1 +make -j $(nproc) +``` + +3. Build iwasm with debugging feature +``` bash +cd ${WAMR_ROOT}/product-mini/platforms/linux +mkdir build && cd build +cmake .. -DWAMR_BUILD_DEBUG_AOT=1 +make +``` + +4. Compile wasm module to AoT module +``` bash +wamrc -o test.aot test.wasm +``` + +5. Execute iwasm using lldb +``` bash +lldb-12 iwasm -- test.aot +``` + +Then you can use lldb commands to debug both wamr runtime and your wasm application in ***current terminal*** diff --git a/doc/wasm_c_api.md b/doc/wasm_c_api.md index a23096e558..bd678a9503 100644 --- a/doc/wasm_c_api.md +++ b/doc/wasm_c_api.md @@ -12,59 +12,26 @@ them in next releases. a summary of unsupported APIs -- Configuration - -``` c -WASM_API_EXTERN own wasm_config_t* wasm_config_new(void); -``` - - References ``` c -WASM_API_EXTERN bool wasm_##name##_same(const wasm_##name##_t*, const wasm_##name##_t*); \ -WASM_API_EXTERN void* wasm_##name##_get_host_info(const wasm_##name##_t*); \ -WASM_API_EXTERN void wasm_##name##_set_host_info(wasm_##name##_t*, void*); \ -WASM_API_EXTERN void wasm_##name##_set_host_info_with_finalizer( \ -WASM_API_EXTERN wasm_ref_t* wasm_##name##_as_ref(wasm_##name##_t*); \ -WASM_API_EXTERN wasm_##name##_t* wasm_ref_as_##name(wasm_ref_t*); \ -WASM_API_EXTERN const wasm_ref_t* wasm_##name##_as_ref_const(const wasm_##name##_t*); \ -WASM_API_EXTERN const wasm_##name##_t* wasm_ref_as_##name##_const(const wasm_ref_t*); -WASM_API_EXTERN own wasm_shared_##name##_t* wasm_##name##_share(const wasm_##name##_t*); \ +WASM_API_EXTERN own wasm_shared_##name##_t* wasm_##name##_share(const wasm_##name##_t*); WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_obtain(wasm_store_t*, const wasm_shared_##name##_t*); ``` -- Frames - -``` c -WASM_API_EXTERN own wasm_frame_t* wasm_frame_copy(const wasm_frame_t*); -WASM_API_EXTERN struct wasm_instance_t* wasm_frame_instance(const wasm_frame_t*); -WASM_API_EXTERN uint32_t wasm_frame_func_index(const wasm_frame_t*); -WASM_API_EXTERN size_t wasm_frame_func_offset(const wasm_frame_t*); -WASM_API_EXTERN size_t wasm_frame_module_offset(const wasm_frame_t*); -WASM_API_EXTERN own wasm_frame_t* wasm_trap_origin(const wasm_trap_t*); -WASM_API_EXTERN void wasm_trap_trace(const wasm_trap_t*, own wasm_frame_vec_t* out); -``` - - Foreign Objects - -``` c -WASM_API_EXTERN own wasm_foreign_t* wasm_foreign_new(wasm_store_t*); -``` - - Several Module APIs ``` c -WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t* binary); -WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out); WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out); +WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const wasm_byte_vec_t*); ``` -- Table Operations APIs +we tend to grow a table or a memory by opcode only and not support growing both +by host-side function callings. + +- Table Grow APIs ``` c -WASM_API_EXTERN own wasm_ref_t* wasm_table_get(const wasm_table_t*, wasm_table_size_t index); -WASM_API_EXTERN bool wasm_table_set(wasm_table_t*, wasm_table_size_t index, wasm_ref_t*); -WASM_API_EXTERN wasm_table_size_t wasm_table_size(const wasm_table_t*); WASM_API_EXTERN bool wasm_table_grow(wasm_table_t*, wasm_table_size_t delta, wasm_ref_t* init); ``` @@ -72,4 +39,4 @@ WASM_API_EXTERN bool wasm_table_grow(wasm_table_t*, wasm_table_size_t delta, was ``` c WASM_API_EXTERN bool wasm_memory_grow(wasm_memory_t*, wasm_memory_pages_t delta); -``` \ No newline at end of file +``` diff --git a/product-mini/platforms/alios-things/aos.mk b/product-mini/platforms/alios-things/aos.mk index 09c636d68b..62bdcb9c4e 100644 --- a/product-mini/platforms/alios-things/aos.mk +++ b/product-mini/platforms/alios-things/aos.mk @@ -99,6 +99,7 @@ $(NAME)_SOURCES := ${SHARED_ROOT}/platform/alios/alios_platform.c \ ${IWASM_ROOT}/common/wasm_native.c \ ${IWASM_ROOT}/common/wasm_exec_env.c \ ${IWASM_ROOT}/common/wasm_memory.c \ + ${IWASM_ROOT}/common/wasm_c_api.c \ ${IWASM_ROOT}/common/arch/${INVOKE_NATIVE} \ src/main.c diff --git a/product-mini/platforms/android/build_llvm.sh b/product-mini/platforms/android/build_llvm.sh index d585792646..dd4fc0907b 100755 --- a/product-mini/platforms/android/build_llvm.sh +++ b/product-mini/platforms/android/build_llvm.sh @@ -1,43 +1,6 @@ #!/bin/sh -# Copyright (C) 2019 Intel Corporation. All rights reserved. +# Copyright (C) 2020 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -DEPS_DIR=${PWD}/../../../core/deps - -cd ${DEPS_DIR} -if [ ! -d "llvm" ]; then - echo "Clone llvm to core/deps/ .." - git clone https://github.com/llvm-mirror/llvm.git -fi - -cd llvm -mkdir -p build -cd build - -if [ ! -f bin/llvm-lto ]; then - - CORE_NUM=$(nproc --all) - if [ -z "${CORE_NUM}" ]; then - CORE_NUM=1 - fi - - echo "Build llvm with" ${CORE_NUM} "cores" - - cmake .. \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_BUILD_TYPE:STRING="Release" \ - -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ - -DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \ - -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \ - -DLLVM_INCLUDE_TESTS:BOOL=OFF \ - -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \ - -DLLVM_APPEND_VC_REV:BOOL=OFF - make -j ${CORE_NUM} - -else - echo "llvm has already been built" -fi - -cd ${PWD} - +/usr/bin/env python3 ../../../build-scripts/build_llvm.py --platform android diff --git a/product-mini/platforms/darwin/CMakeLists.txt b/product-mini/platforms/darwin/CMakeLists.txt index 6c38456320..5ef30eb4cb 100644 --- a/product-mini/platforms/darwin/CMakeLists.txt +++ b/product-mini/platforms/darwin/CMakeLists.txt @@ -32,6 +32,8 @@ if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif () +set(CMAKE_CXX_STANDARD 14) + if (NOT DEFINED WAMR_BUILD_INTERP) # Enable Interpreter by default set (WAMR_BUILD_INTERP 1) @@ -82,6 +84,17 @@ if (NOT DEFINED WAMR_BUILD_SIMD) set (WAMR_BUILD_SIMD 1) endif () +if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP) + # Disable Debug feature by default + set (WAMR_BUILD_DEBUG_INTERP 0) +endif () + +if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) + set (WAMR_BUILD_FAST_INTERP 0) + set (WAMR_BUILD_MINI_LOADER 0) + set (WAMR_BUILD_SIMD 0) +endif () + set (CMAKE_SHARED_LINKER_FLAGS "-Wl,-U,_get_ext_lib_export_apis") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") diff --git a/product-mini/platforms/darwin/build_jit.sh b/product-mini/platforms/darwin/build_jit.sh new file mode 100755 index 0000000000..908d1560c3 --- /dev/null +++ b/product-mini/platforms/darwin/build_jit.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +rm -fr build && mkdir build +cd build +cmake .. -DWAMR_BUILD_JIT=1 +make +cd .. diff --git a/product-mini/platforms/darwin/build_llvm.sh b/product-mini/platforms/darwin/build_llvm.sh new file mode 100755 index 0000000000..f037b4ff61 --- /dev/null +++ b/product-mini/platforms/darwin/build_llvm.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# Copyright (C) 2020 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +/usr/bin/env python3 ../../../build-scripts/build_llvm.py --platform darwin diff --git a/product-mini/platforms/darwin/main.c b/product-mini/platforms/darwin/main.c index defc0d949c..8f0e84a97f 100644 --- a/product-mini/platforms/darwin/main.c +++ b/product-mini/platforms/darwin/main.c @@ -3,317 +3,4 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include -#include -#include "bh_platform.h" -#include "bh_assert.h" -#include "bh_log.h" -#include "bh_read_file.h" -#include "wasm_export.h" - -static int app_argc; -static char **app_argv; - -static int print_help() -{ - printf("Usage: iwasm [-options] wasm_file [args...]\n"); - printf("options:\n"); - printf(" -f|--function name Specify function name to run in module\n" - " rather than main\n"); -#if WASM_ENABLE_LOG != 0 - printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" - " larger level with more log\n"); -#endif - printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); - printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); - printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" - " that runs commands in the form of `FUNC ARG...`\n"); -#if WASM_ENABLE_LIBC_WASI != 0 - printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - printf(" to the program, for example:\n"); - printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - printf(" --dir= Grant wasi access to the given host directories\n"); - printf(" to the program, for example:\n"); - printf(" --dir= --dir=\n"); -#endif - - return 1; -} - -static void* -app_instance_main(wasm_module_inst_t module_inst) -{ - const char *exception; - - wasm_application_execute_main(module_inst, app_argc, app_argv); - if ((exception = wasm_runtime_get_exception(module_inst))) - printf("%s\n", exception); - return NULL; -} - -static void* -app_instance_func(wasm_module_inst_t module_inst, const char *func_name) -{ - wasm_application_execute_func(module_inst, func_name, app_argc - 1, - app_argv + 1); - /* The result of wasm function or exception info was output inside - wasm_application_execute_func(), here we don't output them again. */ - return NULL; -} - -/** - * Split a space separated strings into an array of strings - * Returns NULL on failure - * Memory must be freed by caller - * Based on: http://stackoverflow.com/a/11198630/471795 - */ -static char ** -split_string(char *str, int *count) -{ - char **res = NULL; - char *p; - int idx = 0; - - /* split string and append tokens to 'res' */ - do { - p = strtok(str, " "); - str = NULL; - res = (char**) realloc(res, sizeof(char*) * (uint32)(idx + 1)); - if (res == NULL) { - return NULL; - } - res[idx++] = p; - } while (p); - - if (count) { - *count = idx - 1; - } - return res; -} - -static void* -app_instance_repl(wasm_module_inst_t module_inst) -{ - char *cmd = NULL; - size_t len = 0; - ssize_t n; - - while ((printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { - bh_assert(n > 0); - if (cmd[n - 1] == '\n') { - if (n == 1) - continue; - else - cmd[n - 1] = '\0'; - } - app_argv = split_string(cmd, &app_argc); - if (app_argv == NULL) { - LOG_ERROR("Wasm prepare param failed: split string failed.\n"); - break; - } - if (app_argc != 0) { - wasm_application_execute_func(module_inst, app_argv[0], - app_argc - 1, app_argv + 1); - } - free(app_argv); - } - free(cmd); - return NULL; -} - -#if WASM_ENABLE_LIBC_WASI != 0 -static bool -validate_env_str(char *env) -{ - char *p = env; - int key_len = 0; - - while (*p != '\0' && *p != '=') { - key_len++; - p++; - } - - if (*p != '=' || key_len == 0) - return false; - - return true; -} -#endif - -#define USE_GLOBAL_HEAP_BUF 0 - -#if USE_GLOBAL_HEAP_BUF != 0 -static char global_heap_buf[10 * 1024 * 1024] = { 0 }; -#endif - -int main(int argc, char *argv[]) -{ - char *wasm_file = NULL; - const char *func_name = NULL; - uint8 *wasm_file_buf = NULL; - uint32 wasm_file_size; - uint32 stack_size = 16 * 1024, heap_size = 16 * 1024; - wasm_module_t wasm_module = NULL; - wasm_module_inst_t wasm_module_inst = NULL; - RuntimeInitArgs init_args; - char error_buf[128] = { 0 }; -#if WASM_ENABLE_LOG != 0 - int log_verbose_level = 2; -#endif - bool is_repl_mode = false; -#if WASM_ENABLE_LIBC_WASI != 0 - const char *dir_list[8] = { NULL }; - uint32 dir_list_size = 0; - const char *env_list[8] = { NULL }; - uint32 env_list_size = 0; -#endif - - /* Process options. */ - for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { - if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { - argc--, argv++; - if (argc < 2) { - print_help(); - return 0; - } - func_name = argv[0]; - } -#if WASM_ENABLE_LOG != 0 - else if (!strncmp(argv[0], "-v=", 3)) { - log_verbose_level = atoi(argv[0] + 3); - if (log_verbose_level < 0 || log_verbose_level > 5) - return print_help(); - } -#endif - else if (!strcmp(argv[0], "--repl")) - is_repl_mode = true; - else if (!strncmp(argv[0], "--stack-size=", 13)) { - if (argv[0][13] == '\0') - return print_help(); - stack_size = atoi(argv[0] + 13); - } - else if (!strncmp(argv[0], "--heap-size=", 12)) { - if (argv[0][12] == '\0') - return print_help(); - heap_size = atoi(argv[0] + 12); - } -#if WASM_ENABLE_LIBC_WASI != 0 - else if (!strncmp(argv[0], "--dir=", 6)) { - if (argv[0][6] == '\0') - return print_help(); - if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { - printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char*))); - return -1; - } - dir_list[dir_list_size++] = argv[0] + 6; - } - else if (!strncmp(argv[0], "--env=", 6)) { - char *tmp_env; - - if (argv[0][6] == '\0') - return print_help(); - if (env_list_size >= sizeof(env_list) / sizeof(char*)) { - printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char*))); - return -1; - } - tmp_env = argv[0] + 6; - if (validate_env_str(tmp_env)) - env_list[env_list_size++] = tmp_env; - else { - printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", - tmp_env); - return print_help(); - } - } -#endif - else - return print_help(); - } - - if (argc == 0) - return print_help(); - - wasm_file = argv[0]; - app_argc = argc; - app_argv = argv; - - memset(&init_args, 0, sizeof(RuntimeInitArgs)); - -#if USE_GLOBAL_HEAP_BUF != 0 - init_args.mem_alloc_type = Alloc_With_Pool; - init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; - init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); -#else - init_args.mem_alloc_type = Alloc_With_Allocator; - init_args.mem_alloc_option.allocator.malloc_func = malloc; - init_args.mem_alloc_option.allocator.realloc_func = realloc; - init_args.mem_alloc_option.allocator.free_func = free; -#endif - - /* initialize runtime environment */ - if (!wasm_runtime_full_init(&init_args)) { - printf("Init runtime environment failed.\n"); - return -1; - } - - bh_log_set_verbose_level(log_verbose_level); - - /* load WASM byte buffer from WASM bin file */ - if (!(wasm_file_buf = (uint8*) bh_read_file_to_buffer(wasm_file, - &wasm_file_size))) - goto fail1; - - /* load WASM module */ - if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, - error_buf, sizeof(error_buf)))) { - printf("%s\n", error_buf); - goto fail2; - } - -#if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_set_wasi_args(wasm_module, - dir_list, dir_list_size, - NULL, 0, - env_list, env_list_size, - argv, argc); -#endif - - /* instantiate the module */ - if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, - stack_size, - heap_size, - error_buf, - sizeof(error_buf)))) { - printf("%s\n", error_buf); - goto fail3; - } - - if (is_repl_mode) - app_instance_repl(wasm_module_inst); - else if (func_name) - app_instance_func(wasm_module_inst, func_name); - else - app_instance_main(wasm_module_inst); - - /* destroy the module instance */ - wasm_runtime_deinstantiate(wasm_module_inst); - -fail3: - /* unload the module */ - wasm_runtime_unload(wasm_module); - -fail2: - /* free the file buffer */ - wasm_runtime_free(wasm_file_buf); - -fail1: - /* destroy runtime environment */ - wasm_runtime_destroy(); - return 0; -} - +#include "../posix/main.c" diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt index 231bd0720e..7692d6107e 100644 --- a/product-mini/platforms/linux/CMakeLists.txt +++ b/product-mini/platforms/linux/CMakeLists.txt @@ -90,6 +90,17 @@ if (NOT DEFINED WAMR_BUILD_REF_TYPES) set (WAMR_BUILD_REF_TYPES 0) endif () +if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP) + # Disable Debug feature by default + set (WAMR_BUILD_DEBUG_INTERP 0) +endif () + +if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) + set (WAMR_BUILD_FAST_INTERP 0) + set (WAMR_BUILD_MINI_LOADER 0) + set (WAMR_BUILD_SIMD 0) +endif () + if (COLLECT_CODE_COVERAGE EQUAL 1) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") endif () @@ -107,6 +118,19 @@ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") + # UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub + if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT WAMR_BUILD_JIT EQUAL 1) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined \ + -fno-sanitize=bounds,bounds-strict,alignment \ + -fno-sanitize-recover") + endif() + else () + # UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub + if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT WAMR_BUILD_JIT EQUAL 1) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined \ + -fno-sanitize=bounds,alignment \ + -fno-sanitize-recover") + endif() endif () endif () diff --git a/product-mini/platforms/linux/build_jit.sh b/product-mini/platforms/linux/build_jit.sh index 908d1560c3..8cfdb73693 100755 --- a/product-mini/platforms/linux/build_jit.sh +++ b/product-mini/platforms/linux/build_jit.sh @@ -5,6 +5,8 @@ rm -fr build && mkdir build cd build +# Build With LazyJIT +# cmake .. -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1 cmake .. -DWAMR_BUILD_JIT=1 make cd .. diff --git a/product-mini/platforms/linux/build_llvm.sh b/product-mini/platforms/linux/build_llvm.sh index f4e4ee533b..70371529fd 100755 --- a/product-mini/platforms/linux/build_llvm.sh +++ b/product-mini/platforms/linux/build_llvm.sh @@ -3,44 +3,4 @@ # Copyright (C) 2020 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -DEPS_DIR=${PWD}/../../../core/deps - -cd ${DEPS_DIR} -if [ ! -d "llvm" ]; then - echo "Clone llvm to core/deps/ .." - git clone --depth 1 --branch release/11.x https://github.com/llvm/llvm-project.git llvm -fi - -cd llvm -mkdir -p build -cd build - -if [ ! -f bin/llvm-lto ]; then - - CORE_NUM=$(nproc --all) - if [ -z "${CORE_NUM}" ]; then - CORE_NUM=1 - fi - - echo "Build llvm with" ${CORE_NUM} "cores" - - cmake ../llvm \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_BUILD_TYPE:STRING="Release" \ - -DLLVM_TARGETS_TO_BUILD:STRING="X86;ARM;AArch64;Mips" \ - -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ - -DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \ - -DLLVM_ENABLE_ZLIB:BOOL=OFF \ - -DLLVM_INCLUDE_DOCS:BOOL=OFF \ - -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \ - -DLLVM_INCLUDE_TESTS:BOOL=OFF \ - -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \ - -DLLVM_APPEND_VC_REV:BOOL=OFF - make -j ${CORE_NUM} - -else - echo "llvm has already been built" -fi - -cd ${PWD} - +/usr/bin/env python3 ../../../build-scripts/build_llvm.py diff --git a/product-mini/platforms/linux/main.c b/product-mini/platforms/linux/main.c index 7184e7ebd0..8f0e84a97f 100644 --- a/product-mini/platforms/linux/main.c +++ b/product-mini/platforms/linux/main.c @@ -3,400 +3,4 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include -#include - -#include "bh_platform.h" -#include "bh_read_file.h" -#include "wasm_export.h" - -static int app_argc; -static char **app_argv; - -#define MODULE_PATH ("--module-path=") - -static int -print_help() -{ - printf("Usage: iwasm [-options] wasm_file [args...]\n"); - printf("options:\n"); - printf(" -f|--function name Specify a function name of the module to run rather\n" - " than main\n"); -#if WASM_ENABLE_LOG != 0 - printf(" -v=n Set log verbose level (0 to 5, default is 2) larger\n" - " level with more log\n"); -#endif - printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); - printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); - printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" - " that runs commands in the form of `FUNC ARG...`\n"); -#if WASM_ENABLE_LIBC_WASI != 0 - printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - printf(" to the program, for example:\n"); - printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - printf(" --dir= Grant wasi access to the given host directories\n"); - printf(" to the program, for example:\n"); - printf(" --dir= --dir=\n"); -#endif -#if WASM_ENABLE_MULTI_MODULE != 0 - printf(" --module-path= Indicate a module search path. default is current\n" - " directory('./')\n"); -#endif -#if WASM_ENABLE_LIB_PTHREAD != 0 - printf(" --max-threads=n Set maximum thread number per cluster, default is 4\n"); -#endif - return 1; -} - -static void * -app_instance_main(wasm_module_inst_t module_inst) -{ - const char *exception; - - wasm_application_execute_main(module_inst, app_argc, app_argv); - if ((exception = wasm_runtime_get_exception(module_inst))) - printf("%s\n", exception); - return NULL; -} - -static void * -app_instance_func(wasm_module_inst_t module_inst, const char *func_name) -{ - wasm_application_execute_func(module_inst, func_name, app_argc - 1, - app_argv + 1); - /* The result of wasm function or exception info was output inside - wasm_application_execute_func(), here we don't output them again. */ - return NULL; -} - -/** - * Split a space separated strings into an array of strings - * Returns NULL on failure - * Memory must be freed by caller - * Based on: http://stackoverflow.com/a/11198630/471795 - */ -static char ** -split_string(char *str, int *count) -{ - char **res = NULL; - char *p; - int idx = 0; - - /* split string and append tokens to 'res' */ - do { - p = strtok(str, " "); - str = NULL; - res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1)); - if (res == NULL) { - return NULL; - } - res[idx++] = p; - } while (p); - - /** - * since the function name, - * res[0] might be contains a '\' to indicate a space - * func\name -> func name - */ - p = strchr(res[0], '\\'); - while (p) { - *p = ' '; - p = strchr(p, '\\'); - } - - if (count) { - *count = idx - 1; - } - return res; -} - -static void * -app_instance_repl(wasm_module_inst_t module_inst) -{ - char *cmd = NULL; - size_t len = 0; - ssize_t n; - - while ((printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { - bh_assert(n > 0); - if (cmd[n - 1] == '\n') { - if (n == 1) - continue; - else - cmd[n - 1] = '\0'; - } - if (!strcmp(cmd, "__exit__")) { - printf("exit repl mode\n"); - break; - } - app_argv = split_string(cmd, &app_argc); - if (app_argv == NULL) { - LOG_ERROR("Wasm prepare param failed: split string failed.\n"); - break; - } - if (app_argc != 0) { - wasm_application_execute_func(module_inst, app_argv[0], - app_argc - 1, app_argv + 1); - } - free(app_argv); - } - free(cmd); - return NULL; -} - -#if WASM_ENABLE_LIBC_WASI != 0 -static bool -validate_env_str(char *env) -{ - char *p = env; - int key_len = 0; - - while (*p != '\0' && *p != '=') { - key_len++; - p++; - } - - if (*p != '=' || key_len == 0) - return false; - - return true; -} -#endif - -#define USE_GLOBAL_HEAP_BUF 0 - -#if USE_GLOBAL_HEAP_BUF != 0 -static char global_heap_buf[10 * 1024 * 1024] = { 0 }; -#endif - -#if WASM_ENABLE_MULTI_MODULE != 0 -static char * -handle_module_path(const char *module_path) -{ - /* next character after = */ - return (strchr(module_path, '=')) + 1; -} - -static char *module_search_path = "."; - -static bool -module_reader_callback(const char *module_name, uint8 **p_buffer, - uint32 *p_size) -{ - const char *format = "%s/%s.wasm"; - int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + - strlen(".wasm") + 1; - char *wasm_file_name = BH_MALLOC(sz); - if (!wasm_file_name) { - return false; - } - - snprintf(wasm_file_name, sz, format, module_search_path, module_name); - - *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); - - wasm_runtime_free(wasm_file_name); - return *p_buffer != NULL; -} - -static void -moudle_destroyer(uint8 *buffer, uint32 size) -{ - if (!buffer) { - return; - } - - wasm_runtime_free(buffer); - buffer = NULL; -} -#endif /* WASM_ENABLE_MULTI_MODULE */ - -int -main(int argc, char *argv[]) -{ - char *wasm_file = NULL; - const char *func_name = NULL; - uint8 *wasm_file_buf = NULL; - uint32 wasm_file_size; - uint32 stack_size = 16 * 1024, heap_size = 16 * 1024; - wasm_module_t wasm_module = NULL; - wasm_module_inst_t wasm_module_inst = NULL; - RuntimeInitArgs init_args; - char error_buf[128] = { 0 }; -#if WASM_ENABLE_LOG != 0 - int log_verbose_level = 2; -#endif - bool is_repl_mode = false; -#if WASM_ENABLE_LIBC_WASI != 0 - const char *dir_list[8] = { NULL }; - uint32 dir_list_size = 0; - const char *env_list[8] = { NULL }; - uint32 env_list_size = 0; -#endif - - /* Process options. */ - for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { - if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { - argc--, argv++; - if (argc < 2) { - print_help(); - return 0; - } - func_name = argv[0]; - } -#if WASM_ENABLE_LOG != 0 - else if (!strncmp(argv[0], "-v=", 3)) { - log_verbose_level = atoi(argv[0] + 3); - if (log_verbose_level < 0 || log_verbose_level > 5) - return print_help(); - } -#endif - else if (!strcmp(argv[0], "--repl")) { - is_repl_mode = true; - } - else if (!strncmp(argv[0], "--stack-size=", 13)) { - if (argv[0][13] == '\0') - return print_help(); - stack_size = atoi(argv[0] + 13); - } - else if (!strncmp(argv[0], "--heap-size=", 12)) { - if (argv[0][12] == '\0') - return print_help(); - heap_size = atoi(argv[0] + 12); - } -#if WASM_ENABLE_LIBC_WASI != 0 - else if (!strncmp(argv[0], "--dir=", 6)) { - if (argv[0][6] == '\0') - return print_help(); - if (dir_list_size >= sizeof(dir_list) / sizeof(char *)) { - printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char *))); - return -1; - } - dir_list[dir_list_size++] = argv[0] + 6; - } - else if (!strncmp(argv[0], "--env=", 6)) { - char *tmp_env; - - if (argv[0][6] == '\0') - return print_help(); - if (env_list_size >= sizeof(env_list) / sizeof(char *)) { - printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char *))); - return -1; - } - tmp_env = argv[0] + 6; - if (validate_env_str(tmp_env)) - env_list[env_list_size++] = tmp_env; - else { - printf("Wasm parse env string failed: expect \"key=value\", " - "got \"%s\"\n", - tmp_env); - return print_help(); - } - } -#endif /* WASM_ENABLE_LIBC_WASI */ -#if WASM_ENABLE_MULTI_MODULE != 0 - else if (!strncmp(argv[0], MODULE_PATH, strlen(MODULE_PATH))) { - module_search_path = handle_module_path(argv[0]); - if (!strlen(module_search_path)) { - return print_help(); - } - } -#endif -#if WASM_ENABLE_LIB_PTHREAD != 0 - else if (!strncmp(argv[0], "--max-threads=", 14)) { - if (argv[0][14] == '\0') - return print_help(); - wasm_runtime_set_max_thread_num(atoi(argv[0] + 14)); - } -#endif - else - return print_help(); - } - - if (argc == 0) - return print_help(); - - wasm_file = argv[0]; - app_argc = argc; - app_argv = argv; - - memset(&init_args, 0, sizeof(RuntimeInitArgs)); - -#if USE_GLOBAL_HEAP_BUF != 0 - init_args.mem_alloc_type = Alloc_With_Pool; - init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; - init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); -#else - init_args.mem_alloc_type = Alloc_With_Allocator; - init_args.mem_alloc_option.allocator.malloc_func = malloc; - init_args.mem_alloc_option.allocator.realloc_func = realloc; - init_args.mem_alloc_option.allocator.free_func = free; -#endif - - /* initialize runtime environment */ - if (!wasm_runtime_full_init(&init_args)) { - printf("Init runtime environment failed.\n"); - return -1; - } - -#if WASM_ENABLE_LOG != 0 - bh_log_set_verbose_level(log_verbose_level); -#endif - - /* load WASM byte buffer from WASM bin file */ - if (!(wasm_file_buf = - (uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size))) - goto fail1; - -#if WASM_ENABLE_MULTI_MODULE != 0 - wasm_runtime_set_module_reader(module_reader_callback, moudle_destroyer); -#endif - - /* load WASM module */ - if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, - error_buf, sizeof(error_buf)))) { - printf("%s\n", error_buf); - goto fail2; - } - -#if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, - env_list, env_list_size, argv, argc); -#endif - - /* instantiate the module */ - if (!(wasm_module_inst = - wasm_runtime_instantiate(wasm_module, stack_size, heap_size, - error_buf, sizeof(error_buf)))) { - printf("%s\n", error_buf); - goto fail3; - } - - if (is_repl_mode) - app_instance_repl(wasm_module_inst); - else if (func_name) - app_instance_func(wasm_module_inst, func_name); - else - app_instance_main(wasm_module_inst); - - /* destroy the module instance */ - wasm_runtime_deinstantiate(wasm_module_inst); - -fail3: - /* unload the module */ - wasm_runtime_unload(wasm_module); - -fail2: - /* free the file buffer */ - wasm_runtime_free(wasm_file_buf); - -fail1: - /* destroy runtime environment */ - wasm_runtime_destroy(); - return 0; -} +#include "../posix/main.c" diff --git a/product-mini/platforms/nuttx/main.c b/product-mini/platforms/nuttx/main.c index 0ddf7c1287..8f0e84a97f 100644 --- a/product-mini/platforms/nuttx/main.c +++ b/product-mini/platforms/nuttx/main.c @@ -3,410 +3,4 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include -#include -#include - -#include - -#include "bh_platform.h" -#include "bh_read_file.h" -#include "wasm_export.h" - -static int app_argc; -static char **app_argv; - -#define MODULE_PATH ("--module-path=") - -static int -print_help() -{ - /* clang-format off */ - printf("Usage: iwasm [-options] wasm_file [args...]\n"); - printf("options:\n"); - printf(" -f|--function name Specify a function name of the module to run rather\n" - " than main\n"); - printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" - " that runs commands in the form of `FUNC ARG...`\n"); -#if WASM_ENABLE_LOG != 0 - printf(" -v=n Set log verbose level (0 to 5, default is 2) larger\n" - " level with more log\n"); -#endif - printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); - printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); -#if WASM_ENABLE_LIBC_WASI != 0 - printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - printf(" to the program, for example:\n"); - printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - printf(" --dir= Grant wasi access to the given host directories\n"); - printf(" to the program, for example:\n"); - printf(" --dir= --dir=\n"); -#endif -#if WASM_ENABLE_MULTI_MODULE != 0 - printf(" --module-path= Indicate a module search path. default is current\n" - " directory('./')\n"); -#endif -#if WASM_ENABLE_LIB_PTHREAD != 0 - printf(" --max-threads=n Set maximum thread number per cluster, default is 4\n"); -#endif - /* clang-format on */ - return 1; -} - -static void * -app_instance_main(wasm_module_inst_t module_inst) -{ - const char *exception; - - wasm_application_execute_main(module_inst, app_argc, app_argv); - if ((exception = wasm_runtime_get_exception(module_inst))) - printf("%s\n", exception); - return NULL; -} - -static void * -app_instance_func(wasm_module_inst_t module_inst, const char *func_name) -{ - wasm_application_execute_func(module_inst, func_name, app_argc - 1, - app_argv + 1); - /* The result of wasm function or exception info was output inside - wasm_application_execute_func(), here we don't output them again. */ - return NULL; -} - -/** - * Split a space separated strings into an array of strings - * Returns NULL on failure - * Memory must be freed by caller - * Based on: http://stackoverflow.com/a/11198630/471795 - */ -static char ** -split_string(char *str, int *count) -{ - char **res = NULL; - char *p; - int idx = 0; - - /* split string and append tokens to 'res' */ - do { - p = strtok(str, " "); - str = NULL; - res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1)); - if (res == NULL) { - return NULL; - } - res[idx++] = p; - } while (p); - - /** - * since the function name, - * res[0] might be contains a '\' to indicate a space - * func\name -> func name - */ - p = strchr(res[0], '\\'); - while (p) { - *p = ' '; - p = strchr(p, '\\'); - } - - if (count) { - *count = idx - 1; - } - return res; -} - -static void * -app_instance_repl(wasm_module_inst_t module_inst) -{ - size_t len = 128; - char *cmd = malloc(len); - ssize_t n; - - if (NULL == cmd) { - LOG_ERROR("Wasm repl cmd buffer alloc failed.\n"); - return NULL; - } - - while ( - (printf("webassembly> "), fflush(stdout), n = std_readline(cmd, len)) - != -1) { - bh_assert(n > 0); - if ((cmd[n - 1] == '\n') || (cmd[n - 1] == '\r')) { - if (n == 1) - continue; - else - cmd[n - 1] = '\0'; - } - if (!strcmp(cmd, "__exit__")) { - printf("exit repl mode\n"); - break; - } - app_argv = split_string(cmd, &app_argc); - if (app_argv == NULL) { - LOG_ERROR("Wasm prepare param failed: split string failed.\n"); - break; - } - if (app_argc != 0) { - wasm_application_execute_func(module_inst, app_argv[0], - app_argc - 1, app_argv + 1); - } - free(app_argv); - } - free(cmd); - return NULL; -} - -#if WASM_ENABLE_LIBC_WASI != 0 -static bool -validate_env_str(char *env) -{ - char *p = env; - int key_len = 0; - - while (*p != '\0' && *p != '=') { - key_len++; - p++; - } - - if (*p != '=' || key_len == 0) - return false; - - return true; -} -#endif - -#if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 -static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE * BH_KB] = { 0 }; -#endif - -#if WASM_ENABLE_MULTI_MODULE != 0 -static char * -handle_module_path(const char *module_path) -{ - /* next character after = */ - return (strchr(module_path, '=')) + 1; -} - -static char *module_search_path = "."; -static bool -module_reader_callback(const char *module_name, - uint8 **p_buffer, - uint32 *p_size) -{ - const char *format = "%s/%s.wasm"; - int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) - + strlen(".wasm") + 1; - char *wasm_file_name = BH_MALLOC(sz); - if (!wasm_file_name) { - return false; - } - - snprintf(wasm_file_name, sz, format, module_search_path, module_name); - - *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); - - wasm_runtime_free(wasm_file_name); - return *p_buffer != NULL; -} - -static void -moudle_destroyer(uint8 *buffer, uint32 size) -{ - if (!buffer) { - return; - } - - wasm_runtime_free(buffer); - buffer = NULL; -} -#endif /* WASM_ENABLE_MULTI_MODULE */ - -int -main(int argc, char *argv[]) -{ - char *wasm_file = NULL; - const char *func_name = NULL; - uint8 *wasm_file_buf = NULL; - uint32 wasm_file_size; - uint32 stack_size = 16 * 1024, heap_size = 16 * 1024; - wasm_module_t wasm_module = NULL; - wasm_module_inst_t wasm_module_inst = NULL; - RuntimeInitArgs init_args; - char error_buf[128] = { 0 }; -#if WASM_ENABLE_LOG != 0 - int log_verbose_level = 2; -#endif - bool is_repl_mode = false; -#if WASM_ENABLE_LIBC_WASI != 0 - const char *dir_list[8] = { NULL }; - uint32 dir_list_size = 0; - const char *env_list[8] = { NULL }; - uint32 env_list_size = 0; -#endif - - /* Process options. */ - for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { - if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { - argc--, argv++; - if (argc < 2) { - print_help(); - return 0; - } - func_name = argv[0]; - } -#if WASM_ENABLE_LOG != 0 - else if (!strncmp(argv[0], "-v=", 3)) { - log_verbose_level = atoi(argv[0] + 3); - if (log_verbose_level < 0 || log_verbose_level > 5) - return print_help(); - } -#endif - else if (!strcmp(argv[0], "--repl")) { - is_repl_mode = true; - } - else if (!strncmp(argv[0], "--stack-size=", 13)) { - if (argv[0][13] == '\0') - return print_help(); - stack_size = atoi(argv[0] + 13); - } - else if (!strncmp(argv[0], "--heap-size=", 12)) { - if (argv[0][12] == '\0') - return print_help(); - heap_size = atoi(argv[0] + 12); - } -#if WASM_ENABLE_LIBC_WASI != 0 - else if (!strncmp(argv[0], "--dir=", 6)) { - if (argv[0][6] == '\0') - return print_help(); - if (dir_list_size >= sizeof(dir_list) / sizeof(char *)) { - printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char *))); - return -1; - } - dir_list[dir_list_size++] = argv[0] + 6; - } - else if (!strncmp(argv[0], "--env=", 6)) { - char *tmp_env; - - if (argv[0][6] == '\0') - return print_help(); - if (env_list_size >= sizeof(env_list) / sizeof(char *)) { - printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char *))); - return -1; - } - tmp_env = argv[0] + 6; - if (validate_env_str(tmp_env)) - env_list[env_list_size++] = tmp_env; - else { - printf("Wasm parse env string failed: expect \"key=value\", " - "got \"%s\"\n", - tmp_env); - return print_help(); - } - } -#endif /* WASM_ENABLE_LIBC_WASI */ -#if WASM_ENABLE_MULTI_MODULE != 0 - else if (!strncmp(argv[0], MODULE_PATH, strlen(MODULE_PATH))) { - module_search_path = handle_module_path(argv[0]); - if (!strlen(module_search_path)) { - return print_help(); - } - } -#endif -#if WASM_ENABLE_LIB_PTHREAD != 0 - else if (!strncmp(argv[0], "--max-threads=", 14)) { - if (argv[0][14] == '\0') - return print_help(); - wasm_runtime_set_max_thread_num(atoi(argv[0] + 14)); - } -#endif - else - return print_help(); - } - - if (argc == 0) - return print_help(); - - wasm_file = argv[0]; - app_argc = argc; - app_argv = argv; - - memset(&init_args, 0, sizeof(RuntimeInitArgs)); - -#if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 - init_args.mem_alloc_type = Alloc_With_Pool; - init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; - init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); -#else - init_args.mem_alloc_type = Alloc_With_Allocator; - init_args.mem_alloc_option.allocator.malloc_func = malloc; - init_args.mem_alloc_option.allocator.realloc_func = realloc; - init_args.mem_alloc_option.allocator.free_func = free; -#endif - - /* initialize runtime environment */ - if (!wasm_runtime_full_init(&init_args)) { - printf("Init runtime environment failed.\n"); - return -1; - } - -#if WASM_ENABLE_LOG != 0 - bh_log_set_verbose_level(log_verbose_level); -#endif - - /* load WASM byte buffer from WASM bin file */ - if (!(wasm_file_buf = - (uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size))) - goto fail1; - -#if WASM_ENABLE_MULTI_MODULE != 0 - wasm_runtime_set_module_reader(module_reader_callback, moudle_destroyer); -#endif - - /* load WASM module */ - if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, - error_buf, sizeof(error_buf)))) { - printf("%s\n", error_buf); - goto fail2; - } - -#if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, - env_list, env_list_size, argv, argc); -#endif - - /* instantiate the module */ - if (!(wasm_module_inst = - wasm_runtime_instantiate(wasm_module, stack_size, heap_size, - error_buf, sizeof(error_buf)))) { - printf("%s\n", error_buf); - goto fail3; - } - - if (is_repl_mode) - app_instance_repl(wasm_module_inst); - else if (func_name) - app_instance_func(wasm_module_inst, func_name); - else - app_instance_main(wasm_module_inst); - - /* destroy the module instance */ - wasm_runtime_deinstantiate(wasm_module_inst); - -fail3: - /* unload the module */ - wasm_runtime_unload(wasm_module); - -fail2: - /* free the file buffer */ - wasm_runtime_free(wasm_file_buf); - -fail1: - /* destroy runtime environment */ - wasm_runtime_destroy(); - return 0; -} +#include "../posix/main.c" diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 03de0c7cb6..081323dfc8 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -35,11 +35,11 @@ endif WAMR_BUILD_PLATFORM := nuttx -ifeq (${WAMR_BUILD_TARGET}, X86_32) +ifeq ($(WAMR_BUILD_TARGET), X86_32) CFLAGS += -DBUILD_TARGET_X86_32 INVOKE_NATIVE := invokeNative_ia32.s AOT_RELOC := aot_reloc_x86_32.c -else ifeq (${WAMR_BUILD_TARGET}, X86_64) +else ifeq ($(WAMR_BUILD_TARGET), X86_64) CFLAGS += -DBUILD_TARGET_X86_64 INVOKE_NATIVE := invokeNative_em64.s AOT_RELOC := aot_reloc_x86_64.c @@ -72,43 +72,42 @@ ifeq (${CONFIG_ARCH_FPU},y) $(error riscv64 lp64f is unsupported) else ifeq (${CONFIG_ARCH_DPFPU}, y) CFLAGS += -DBUILD_TARGET_RISCV64_LP64D - INVOKE_NATIVE += invokeNative_riscv64_lp64d.s else CFLAGS += -DBUILD_TARGET_RISCV64_LP64 - INVOKE_NATIVE += invokeNative_riscv64_lp64.s endif + INVOKE_NATIVE += invokeNative_riscv.S - AOT_RELOC := + AOT_RELOC := aot_reloc_riscv.c else ifeq (${WAMR_BUILD_TARGET}, RISCV32) ifeq (${CONFIG_ARCH_FPU}, y) $(error riscv32 ilp32f is unsupported) else ifeq (${CONFIG_ARCH_DPFPU}, y) - CFLAGS += -DBUILD_TARGET_RISCV64_ILP32D - INVOKE_NATIVE += invokeNative_riscv32_ilp32d.s + CFLAGS += -DBUILD_TARGET_RISCV32_ILP32D else - CFLAGS += -DBUILD_TARGET_RISCV64_ILP32 - INVOKE_NATIVE += invokeNative_riscv32_ilp32.s + CFLAGS += -DBUILD_TARGET_RISCV32_ILP32 endif - AOT_RELOC := + INVOKE_NATIVE += invokeNative_riscv.S + AOT_RELOC := aot_reloc_riscv.c else $(error Build target is unsupported) endif -ifeq (${CONFIG_INTERPRETERS_WAMR_LOG},y) +ifeq ($(CONFIG_INTERPRETERS_WAMR_LOG),y) CFLAGS += -DWASM_ENABLE_LOG=1 else CFLAGS += -DWASM_ENABLE_LOG=0 endif -ifeq (${CONFIG_INTERPRETERS_WAMR_AOT},y) -CFLAGS += -I${IWASM_ROOT}/aot +ifeq ($(CONFIG_INTERPRETERS_WAMR_AOT),y) +CFLAGS += -I$(IWASM_ROOT)/aot CFLAGS += -DWASM_ENABLE_AOT=1 CSRCS += aot_loader.c \ - ${AOT_RELOC} \ + $(AOT_RELOC) \ + aot_intrinsic.c \ aot_runtime.c else CFLAGS += -DWASM_ENABLE_AOT=0 @@ -117,7 +116,7 @@ endif CFLAGS += -DWASM_ENABLE_INTERP=1 CSRCS += wasm_runtime.c -ifeq (${CONFIG_INTERPRETERS_WAMR_FAST},y) +ifeq ($(CONFIG_INTERPRETERS_WAMR_FAST),y) CFLAGS += -DWASM_ENABLE_FAST_INTERP=1 CSRCS += wasm_interp_fast.c else @@ -139,7 +138,7 @@ endif ifeq ($(CONFIG_INTERPRETERS_WAMR_THREAD_MGR),y) CFLAGS += -DWASM_ENABLE_THREAD_MGR=1 CSRCS += thread_manager.c -VPATH += ${IWASM_ROOT}/libraries/thread-mgr +VPATH += $(IWASM_ROOT)/libraries/thread-mgr else CFLAGS += -DWASM_ENABLE_THREAD_MGR=0 endif @@ -182,7 +181,8 @@ CFLAGS += -Wno-strict-prototypes -Wno-shadow -Wno-unused-variable CFLAGS += -Wno-int-conversion -Wno-implicit-function-declaration CFLAGS += -I${CORE_ROOT} \ - -I${IWASM_ROOT}/include \ + -I${IWASM_ROOT}/include \ + -I${IWASM_ROOT}/interpreter \ -I${IWASM_ROOT}/common \ -I${IWASM_ROOT}/libraries/thread-mgr \ -I${SHARED_ROOT}/include \ @@ -192,9 +192,8 @@ CFLAGS += -I${CORE_ROOT} \ -I${SHARED_ROOT}/mem-alloc \ -I${SHARED_ROOT}/platform/nuttx - -ifeq (${WAMR_BUILD_INTERP}, 1) -CFLAGS += -I${IWASM_ROOT}/interpreter +ifeq ($(WAMR_BUILD_INTERP), 1) +CFLAGS += -I$(IWASM_ROOT)/interpreter endif CSRCS += nuttx_platform.c \ @@ -218,21 +217,22 @@ CSRCS += nuttx_platform.c \ wasm_runtime_common.c \ wasm_native.c \ wasm_exec_env.c \ - wasm_memory.c - -ASRCS += ${INVOKE_NATIVE} - -VPATH += ${SHARED_ROOT}/platform/nuttx -VPATH += ${SHARED_ROOT}/platform/common/posix -VPATH += ${SHARED_ROOT}/mem-alloc -VPATH += ${SHARED_ROOT}/mem-alloc/ems -VPATH += ${SHARED_ROOT}/utils -VPATH += ${SHARED_ROOT}/utils/uncommon -VPATH += ${IWASM_ROOT}/common -VPATH += ${IWASM_ROOT}/interpreter -VPATH += ${IWASM_ROOT}/libraries -VPATH += ${IWASM_ROOT}/libraries/libc-builtin -VPATH += ${IWASM_ROOT}/libraries/lib-pthread -VPATH += ${IWASM_ROOT}/common/arch -VPATH += ${IWASM_ROOT}/aot -VPATH += ${IWASM_ROOT}/aot/arch + wasm_memory.c \ + wasm_c_api.c + +ASRCS += $(INVOKE_NATIVE) + +VPATH += $(SHARED_ROOT)/platform/nuttx +VPATH += $(SHARED_ROOT)/platform/common/posix +VPATH += $(SHARED_ROOT)/mem-alloc +VPATH += $(SHARED_ROOT)/mem-alloc/ems +VPATH += $(SHARED_ROOT)/utils +VPATH += $(SHARED_ROOT)/utils/uncommon +VPATH += $(IWASM_ROOT)/common +VPATH += $(IWASM_ROOT)/interpreter +VPATH += $(IWASM_ROOT)/libraries +VPATH += $(IWASM_ROOT)/libraries/libc-builtin +VPATH += $(IWASM_ROOT)/libraries/lib-pthread +VPATH += $(IWASM_ROOT)/common/arch +VPATH += $(IWASM_ROOT)/aot +VPATH += $(IWASM_ROOT)/aot/arch diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c new file mode 100644 index 0000000000..de24175160 --- /dev/null +++ b/product-mini/platforms/posix/main.c @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include + +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" + +static int app_argc; +static char **app_argv; + +#define MODULE_PATH ("--module-path=") + +static int +print_help() +{ + printf("Usage: iwasm [-options] wasm_file [args...]\n"); + printf("options:\n"); + printf(" -f|--function name Specify a function name of the module to run rather\n" + " than main\n"); +#if WASM_ENABLE_LOG != 0 + printf(" -v=n Set log verbose level (0 to 5, default is 2) larger\n" + " level with more log\n"); +#endif + printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); + printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); + printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" + " that runs commands in the form of \"FUNC ARG...\"\n"); + printf(" --xip Enable XIP (Execution In Place) mode to run AOT file\n" + " generated with \"--enable-indirect-mode\" flag\n"); +#if WASM_ENABLE_LIBC_WASI != 0 + printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + printf(" to the program, for example:\n"); + printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + printf(" --dir= Grant wasi access to the given host directories\n"); + printf(" to the program, for example:\n"); + printf(" --dir= --dir=\n"); +#endif +#if WASM_ENABLE_MULTI_MODULE != 0 + printf(" --module-path= Indicate a module search path. default is current\n" + " directory('./')\n"); +#endif +#if WASM_ENABLE_LIB_PTHREAD != 0 + printf(" --max-threads=n Set maximum thread number per cluster, default is 4\n"); +#endif +#if WASM_ENABLE_DEBUG_INTERP != 0 + printf(" -g=ip:port Set the debug sever address, default is debug disabled\n"); +#endif + return 1; +} + +static void * +app_instance_main(wasm_module_inst_t module_inst) +{ + const char *exception; + + wasm_application_execute_main(module_inst, app_argc, app_argv); + if ((exception = wasm_runtime_get_exception(module_inst))) + printf("%s\n", exception); + return NULL; +} + +static void * +app_instance_func(wasm_module_inst_t module_inst, const char *func_name) +{ + wasm_application_execute_func(module_inst, func_name, app_argc - 1, + app_argv + 1); + /* The result of wasm function or exception info was output inside + wasm_application_execute_func(), here we don't output them again. */ + return NULL; +} + +/** + * Split a space separated strings into an array of strings + * Returns NULL on failure + * Memory must be freed by caller + * Based on: http://stackoverflow.com/a/11198630/471795 + */ +static char ** +split_string(char *str, int *count) +{ + char **res = NULL; + char *p; + int idx = 0; + + /* split string and append tokens to 'res' */ + do { + p = strtok(str, " "); + str = NULL; + res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1)); + if (res == NULL) { + return NULL; + } + res[idx++] = p; + } while (p); + + /** + * since the function name, + * res[0] might be contains a '\' to indicate a space + * func\name -> func name + */ + p = strchr(res[0], '\\'); + while (p) { + *p = ' '; + p = strchr(p, '\\'); + } + + if (count) { + *count = idx - 1; + } + return res; +} + +static void * +app_instance_repl(wasm_module_inst_t module_inst) +{ + char *cmd = NULL; + size_t len = 0; + ssize_t n; + + while ((printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { + bh_assert(n > 0); + if (cmd[n - 1] == '\n') { + if (n == 1) + continue; + else + cmd[n - 1] = '\0'; + } + if (!strcmp(cmd, "__exit__")) { + printf("exit repl mode\n"); + break; + } + app_argv = split_string(cmd, &app_argc); + if (app_argv == NULL) { + LOG_ERROR("Wasm prepare param failed: split string failed.\n"); + break; + } + if (app_argc != 0) { + wasm_application_execute_func(module_inst, app_argv[0], + app_argc - 1, app_argv + 1); + } + free(app_argv); + } + free(cmd); + return NULL; +} + +#if WASM_ENABLE_LIBC_WASI != 0 +static bool +validate_env_str(char *env) +{ + char *p = env; + int key_len = 0; + + while (*p != '\0' && *p != '=') { + key_len++; + p++; + } + + if (*p != '=' || key_len == 0) + return false; + + return true; +} +#endif + +#if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 +#ifdef __NuttX__ +static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE * BH_KB] = { 0 }; +#else +static char global_heap_buf[10 * 1024 * 1024] = { 0 }; +#endif +#endif + +#if WASM_ENABLE_MULTI_MODULE != 0 +static char * +handle_module_path(const char *module_path) +{ + /* next character after = */ + return (strchr(module_path, '=')) + 1; +} + +static char *module_search_path = "."; + +static bool +module_reader_callback(const char *module_name, uint8 **p_buffer, + uint32 *p_size) +{ + const char *format = "%s/%s.wasm"; + int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + + strlen(".wasm") + 1; + char *wasm_file_name = BH_MALLOC(sz); + if (!wasm_file_name) { + return false; + } + + snprintf(wasm_file_name, sz, format, module_search_path, module_name); + + *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); + + wasm_runtime_free(wasm_file_name); + return *p_buffer != NULL; +} + +static void +moudle_destroyer(uint8 *buffer, uint32 size) +{ + if (!buffer) { + return; + } + + wasm_runtime_free(buffer); + buffer = NULL; +} +#endif /* WASM_ENABLE_MULTI_MODULE */ + +int +main(int argc, char *argv[]) +{ + char *wasm_file = NULL; + const char *func_name = NULL; + uint8 *wasm_file_buf = NULL; + uint32 wasm_file_size; + uint32 stack_size = 16 * 1024, heap_size = 16 * 1024; + wasm_module_t wasm_module = NULL; + wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; + char error_buf[128] = { 0 }; +#if WASM_ENABLE_LOG != 0 + int log_verbose_level = 2; +#endif + bool is_repl_mode = false; + bool is_xip_mode = false; +#if WASM_ENABLE_LIBC_WASI != 0 + const char *dir_list[8] = { NULL }; + uint32 dir_list_size = 0; + const char *env_list[8] = { NULL }; + uint32 env_list_size = 0; +#endif +#if WASM_ENABLE_DEBUG_INTERP != 0 + char * ip_addr = NULL; + //int platform_port = 0; + int instance_port = 0; +#endif + + /* Process options. */ + for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { + if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { + argc--, argv++; + if (argc < 2) { + print_help(); + return 0; + } + func_name = argv[0]; + } +#if WASM_ENABLE_LOG != 0 + else if (!strncmp(argv[0], "-v=", 3)) { + log_verbose_level = atoi(argv[0] + 3); + if (log_verbose_level < 0 || log_verbose_level > 5) + return print_help(); + } +#endif + else if (!strcmp(argv[0], "--repl")) { + is_repl_mode = true; + } + else if (!strcmp(argv[0], "--xip")) { + is_xip_mode = true; + } + else if (!strncmp(argv[0], "--stack-size=", 13)) { + if (argv[0][13] == '\0') + return print_help(); + stack_size = atoi(argv[0] + 13); + } + else if (!strncmp(argv[0], "--heap-size=", 12)) { + if (argv[0][12] == '\0') + return print_help(); + heap_size = atoi(argv[0] + 12); + } +#if WASM_ENABLE_LIBC_WASI != 0 + else if (!strncmp(argv[0], "--dir=", 6)) { + if (argv[0][6] == '\0') + return print_help(); + if (dir_list_size >= sizeof(dir_list) / sizeof(char *)) { + printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char *))); + return -1; + } + dir_list[dir_list_size++] = argv[0] + 6; + } + else if (!strncmp(argv[0], "--env=", 6)) { + char *tmp_env; + + if (argv[0][6] == '\0') + return print_help(); + if (env_list_size >= sizeof(env_list) / sizeof(char *)) { + printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char *))); + return -1; + } + tmp_env = argv[0] + 6; + if (validate_env_str(tmp_env)) + env_list[env_list_size++] = tmp_env; + else { + printf("Wasm parse env string failed: expect \"key=value\", " + "got \"%s\"\n", + tmp_env); + return print_help(); + } + } +#endif /* WASM_ENABLE_LIBC_WASI */ +#if WASM_ENABLE_MULTI_MODULE != 0 + else if (!strncmp(argv[0], MODULE_PATH, strlen(MODULE_PATH))) { + module_search_path = handle_module_path(argv[0]); + if (!strlen(module_search_path)) { + return print_help(); + } + } +#endif +#if WASM_ENABLE_LIB_PTHREAD != 0 + else if (!strncmp(argv[0], "--max-threads=", 14)) { + if (argv[0][14] == '\0') + return print_help(); + wasm_runtime_set_max_thread_num(atoi(argv[0] + 14)); + } +#endif +#if WASM_ENABLE_DEBUG_INTERP != 0 + else if (!strncmp(argv[0], "-g=", 3)) { + char * port_str = strchr(argv[0] + 3, ':'); + char *port_end; + if (port_str == NULL) + return print_help(); + *port_str = '\0'; + instance_port = strtoul(port_str + 1, &port_end, 10); + if (port_str[1] == '\0' || *port_end != '\0') + return print_help(); + ip_addr = argv[0] + 3; + } +#endif + else + return print_help(); + } + + if (argc == 0) + return print_help(); + + wasm_file = argv[0]; + app_argc = argc; + app_argv = argv; + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + +#if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); +#else + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = malloc; + init_args.mem_alloc_option.allocator.realloc_func = realloc; + init_args.mem_alloc_option.allocator.free_func = free; +#endif + +#if WASM_ENABLE_DEBUG_INTERP != 0 + init_args.platform_port = 0; + init_args.instance_port = instance_port; + if (ip_addr) + strcpy(init_args.ip_addr, ip_addr); +#endif + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + printf("Init runtime environment failed.\n"); + return -1; + } + +#if WASM_ENABLE_LOG != 0 + bh_log_set_verbose_level(log_verbose_level); +#endif + + /* load WASM byte buffer from WASM bin file */ + if (!(wasm_file_buf = + (uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size))) + goto fail1; + + if (is_xip_mode) { + uint8 *wasm_file_mapped; + int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC; + int map_flags = MMAP_MAP_NONE; + + if (!(wasm_file_mapped = os_mmap(NULL, (uint32)wasm_file_size, + map_prot, map_flags))) { + printf("mmap memory failed\n"); + wasm_runtime_free(wasm_file_buf); + goto fail1; + } + + bh_memcpy_s(wasm_file_mapped, wasm_file_size, + wasm_file_buf, wasm_file_size); + wasm_runtime_free(wasm_file_buf); + wasm_file_buf = wasm_file_mapped; + } + +#if WASM_ENABLE_MULTI_MODULE != 0 + wasm_runtime_set_module_reader(module_reader_callback, moudle_destroyer); +#endif + + /* load WASM module */ + if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("%s\n", error_buf); + goto fail2; + } + +#if WASM_ENABLE_LIBC_WASI != 0 + wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, + env_list, env_list_size, argv, argc); +#endif + + /* instantiate the module */ + if (!(wasm_module_inst = + wasm_runtime_instantiate(wasm_module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("%s\n", error_buf); + goto fail3; + } + + if (is_repl_mode) + app_instance_repl(wasm_module_inst); + else if (func_name) + app_instance_func(wasm_module_inst, func_name); + else + app_instance_main(wasm_module_inst); + + /* destroy the module instance */ + wasm_runtime_deinstantiate(wasm_module_inst); + +fail3: + /* unload the module */ + wasm_runtime_unload(wasm_module); + +fail2: + /* free the file buffer */ + if (!is_xip_mode) + wasm_runtime_free(wasm_file_buf); + else + os_munmap(wasm_file_buf, wasm_file_size); + +fail1: + /* destroy runtime environment */ + wasm_runtime_destroy(); + return 0; +} diff --git a/product-mini/platforms/rt-thread/SConscript b/product-mini/platforms/rt-thread/SConscript index 8f866caf1d..4f7ffe63ed 100644 --- a/product-mini/platforms/rt-thread/SConscript +++ b/product-mini/platforms/rt-thread/SConscript @@ -6,13 +6,9 @@ from building import * -cwd = GetCurrentDir() - - +cwd = GetCurrentDir() src = Glob('*.c') -CPPPATH = [cwd] - -group = DefineGroup('iwasm_entry', src, depend = ['PKG_USING_WAMR'], CPPPATH = CPPPATH) +group = DefineGroup('iwasm', src, depend = ['PKG_USING_WAMR']) Return('group') diff --git a/product-mini/platforms/rt-thread/rtt_wamr_entry.c b/product-mini/platforms/rt-thread/iwasm.c similarity index 99% rename from product-mini/platforms/rt-thread/rtt_wamr_entry.c rename to product-mini/platforms/rt-thread/iwasm.c index 799fd44d2c..c7ab46a8a9 100644 --- a/product-mini/platforms/rt-thread/rtt_wamr_entry.c +++ b/product-mini/platforms/rt-thread/iwasm.c @@ -373,18 +373,17 @@ int iwasm(int argc, char **argv) /* destroy the module instance */ wasm_runtime_deinstantiate(wasm_module_inst); - fail3: +fail3: /* unload the module */ wasm_runtime_unload(wasm_module); - fail2: +fail2: /* free the file buffer */ rt_free(wasm_file_buf); - fail1: +fail1: /* destroy runtime environment */ wasm_runtime_destroy(); return 0; } MSH_CMD_EXPORT(iwasm, Embeded VM of WebAssembly); - diff --git a/product-mini/platforms/rt-thread/rtt_embed_entry.cmake b/product-mini/platforms/rt-thread/iwasm.cmake similarity index 100% rename from product-mini/platforms/rt-thread/rtt_embed_entry.cmake rename to product-mini/platforms/rt-thread/iwasm.cmake diff --git a/product-mini/platforms/vxworks/CMakeLists.txt b/product-mini/platforms/vxworks/CMakeLists.txt index 37e71d819e..d681e9213c 100644 --- a/product-mini/platforms/vxworks/CMakeLists.txt +++ b/product-mini/platforms/vxworks/CMakeLists.txt @@ -59,6 +59,17 @@ if (NOT DEFINED WAMR_BUILD_LIBC_WASI) set (WAMR_BUILD_LIBC_WASI 0) endif () +if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP) + # Disable Debug feature by default + set (WAMR_BUILD_DEBUG_INTERP 0) +endif () + +if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) + set (WAMR_BUILD_FAST_INTERP 0) + set (WAMR_BUILD_MINI_LOADER 0) + set (WAMR_BUILD_SIMD 0) +endif () + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) diff --git a/product-mini/platforms/vxworks/main.c b/product-mini/platforms/vxworks/main.c index defc0d949c..8f0e84a97f 100644 --- a/product-mini/platforms/vxworks/main.c +++ b/product-mini/platforms/vxworks/main.c @@ -3,317 +3,4 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include -#include -#include "bh_platform.h" -#include "bh_assert.h" -#include "bh_log.h" -#include "bh_read_file.h" -#include "wasm_export.h" - -static int app_argc; -static char **app_argv; - -static int print_help() -{ - printf("Usage: iwasm [-options] wasm_file [args...]\n"); - printf("options:\n"); - printf(" -f|--function name Specify function name to run in module\n" - " rather than main\n"); -#if WASM_ENABLE_LOG != 0 - printf(" -v=n Set log verbose level (0 to 5, default is 2),\n" - " larger level with more log\n"); -#endif - printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); - printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); - printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" - " that runs commands in the form of `FUNC ARG...`\n"); -#if WASM_ENABLE_LIBC_WASI != 0 - printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - printf(" to the program, for example:\n"); - printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - printf(" --dir= Grant wasi access to the given host directories\n"); - printf(" to the program, for example:\n"); - printf(" --dir= --dir=\n"); -#endif - - return 1; -} - -static void* -app_instance_main(wasm_module_inst_t module_inst) -{ - const char *exception; - - wasm_application_execute_main(module_inst, app_argc, app_argv); - if ((exception = wasm_runtime_get_exception(module_inst))) - printf("%s\n", exception); - return NULL; -} - -static void* -app_instance_func(wasm_module_inst_t module_inst, const char *func_name) -{ - wasm_application_execute_func(module_inst, func_name, app_argc - 1, - app_argv + 1); - /* The result of wasm function or exception info was output inside - wasm_application_execute_func(), here we don't output them again. */ - return NULL; -} - -/** - * Split a space separated strings into an array of strings - * Returns NULL on failure - * Memory must be freed by caller - * Based on: http://stackoverflow.com/a/11198630/471795 - */ -static char ** -split_string(char *str, int *count) -{ - char **res = NULL; - char *p; - int idx = 0; - - /* split string and append tokens to 'res' */ - do { - p = strtok(str, " "); - str = NULL; - res = (char**) realloc(res, sizeof(char*) * (uint32)(idx + 1)); - if (res == NULL) { - return NULL; - } - res[idx++] = p; - } while (p); - - if (count) { - *count = idx - 1; - } - return res; -} - -static void* -app_instance_repl(wasm_module_inst_t module_inst) -{ - char *cmd = NULL; - size_t len = 0; - ssize_t n; - - while ((printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { - bh_assert(n > 0); - if (cmd[n - 1] == '\n') { - if (n == 1) - continue; - else - cmd[n - 1] = '\0'; - } - app_argv = split_string(cmd, &app_argc); - if (app_argv == NULL) { - LOG_ERROR("Wasm prepare param failed: split string failed.\n"); - break; - } - if (app_argc != 0) { - wasm_application_execute_func(module_inst, app_argv[0], - app_argc - 1, app_argv + 1); - } - free(app_argv); - } - free(cmd); - return NULL; -} - -#if WASM_ENABLE_LIBC_WASI != 0 -static bool -validate_env_str(char *env) -{ - char *p = env; - int key_len = 0; - - while (*p != '\0' && *p != '=') { - key_len++; - p++; - } - - if (*p != '=' || key_len == 0) - return false; - - return true; -} -#endif - -#define USE_GLOBAL_HEAP_BUF 0 - -#if USE_GLOBAL_HEAP_BUF != 0 -static char global_heap_buf[10 * 1024 * 1024] = { 0 }; -#endif - -int main(int argc, char *argv[]) -{ - char *wasm_file = NULL; - const char *func_name = NULL; - uint8 *wasm_file_buf = NULL; - uint32 wasm_file_size; - uint32 stack_size = 16 * 1024, heap_size = 16 * 1024; - wasm_module_t wasm_module = NULL; - wasm_module_inst_t wasm_module_inst = NULL; - RuntimeInitArgs init_args; - char error_buf[128] = { 0 }; -#if WASM_ENABLE_LOG != 0 - int log_verbose_level = 2; -#endif - bool is_repl_mode = false; -#if WASM_ENABLE_LIBC_WASI != 0 - const char *dir_list[8] = { NULL }; - uint32 dir_list_size = 0; - const char *env_list[8] = { NULL }; - uint32 env_list_size = 0; -#endif - - /* Process options. */ - for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { - if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { - argc--, argv++; - if (argc < 2) { - print_help(); - return 0; - } - func_name = argv[0]; - } -#if WASM_ENABLE_LOG != 0 - else if (!strncmp(argv[0], "-v=", 3)) { - log_verbose_level = atoi(argv[0] + 3); - if (log_verbose_level < 0 || log_verbose_level > 5) - return print_help(); - } -#endif - else if (!strcmp(argv[0], "--repl")) - is_repl_mode = true; - else if (!strncmp(argv[0], "--stack-size=", 13)) { - if (argv[0][13] == '\0') - return print_help(); - stack_size = atoi(argv[0] + 13); - } - else if (!strncmp(argv[0], "--heap-size=", 12)) { - if (argv[0][12] == '\0') - return print_help(); - heap_size = atoi(argv[0] + 12); - } -#if WASM_ENABLE_LIBC_WASI != 0 - else if (!strncmp(argv[0], "--dir=", 6)) { - if (argv[0][6] == '\0') - return print_help(); - if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { - printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char*))); - return -1; - } - dir_list[dir_list_size++] = argv[0] + 6; - } - else if (!strncmp(argv[0], "--env=", 6)) { - char *tmp_env; - - if (argv[0][6] == '\0') - return print_help(); - if (env_list_size >= sizeof(env_list) / sizeof(char*)) { - printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char*))); - return -1; - } - tmp_env = argv[0] + 6; - if (validate_env_str(tmp_env)) - env_list[env_list_size++] = tmp_env; - else { - printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", - tmp_env); - return print_help(); - } - } -#endif - else - return print_help(); - } - - if (argc == 0) - return print_help(); - - wasm_file = argv[0]; - app_argc = argc; - app_argv = argv; - - memset(&init_args, 0, sizeof(RuntimeInitArgs)); - -#if USE_GLOBAL_HEAP_BUF != 0 - init_args.mem_alloc_type = Alloc_With_Pool; - init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; - init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); -#else - init_args.mem_alloc_type = Alloc_With_Allocator; - init_args.mem_alloc_option.allocator.malloc_func = malloc; - init_args.mem_alloc_option.allocator.realloc_func = realloc; - init_args.mem_alloc_option.allocator.free_func = free; -#endif - - /* initialize runtime environment */ - if (!wasm_runtime_full_init(&init_args)) { - printf("Init runtime environment failed.\n"); - return -1; - } - - bh_log_set_verbose_level(log_verbose_level); - - /* load WASM byte buffer from WASM bin file */ - if (!(wasm_file_buf = (uint8*) bh_read_file_to_buffer(wasm_file, - &wasm_file_size))) - goto fail1; - - /* load WASM module */ - if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, - error_buf, sizeof(error_buf)))) { - printf("%s\n", error_buf); - goto fail2; - } - -#if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_set_wasi_args(wasm_module, - dir_list, dir_list_size, - NULL, 0, - env_list, env_list_size, - argv, argc); -#endif - - /* instantiate the module */ - if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, - stack_size, - heap_size, - error_buf, - sizeof(error_buf)))) { - printf("%s\n", error_buf); - goto fail3; - } - - if (is_repl_mode) - app_instance_repl(wasm_module_inst); - else if (func_name) - app_instance_func(wasm_module_inst, func_name); - else - app_instance_main(wasm_module_inst); - - /* destroy the module instance */ - wasm_runtime_deinstantiate(wasm_module_inst); - -fail3: - /* unload the module */ - wasm_runtime_unload(wasm_module); - -fail2: - /* free the file buffer */ - wasm_runtime_free(wasm_file_buf); - -fail1: - /* destroy runtime environment */ - wasm_runtime_destroy(); - return 0; -} - +#include "../posix/main.c" diff --git a/product-mini/platforms/windows/CMakeLists.txt b/product-mini/platforms/windows/CMakeLists.txt index 377297a345..c03a064ee8 100644 --- a/product-mini/platforms/windows/CMakeLists.txt +++ b/product-mini/platforms/windows/CMakeLists.txt @@ -124,7 +124,7 @@ add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) install (TARGETS libiwasm DESTINATION lib) -set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) +set_target_properties (libiwasm PROPERTIES OUTPUT_NAME libiwasm) target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS}) diff --git a/product-mini/platforms/windows/build_llvm.py b/product-mini/platforms/windows/build_llvm.py index f476e9e6c6..9325a0209b 100644 --- a/product-mini/platforms/windows/build_llvm.py +++ b/product-mini/platforms/windows/build_llvm.py @@ -1,69 +1,16 @@ +#!/usr/bin/env python3 # # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # -#!/usr/bin/env python3 -import os +import pathlib +import subprocess import sys -from pathlib import Path - -def clone_llvm(): - llvm_dir = Path("llvm") - if(llvm_dir.exists() == False): - print("Clone llvm to core/deps/ ..") - for line in os.popen("git clone --branch release/11.x https://github.com/llvm/llvm-project.git llvm"): - print(line) - else: - print("llvm source codes already existed") - return llvm_dir - -def main(): - current_os = sys.platform - print("current OS is ", current_os) - - current_dir = Path.cwd() - deps_dir = current_dir.joinpath( "../../../core/deps") - - os.chdir(deps_dir) - llvm_dir = clone_llvm() - os.chdir(llvm_dir) - - build_dir_name = "win32build" - llvm_file = "LLVM.sln" - - Path(build_dir_name).mkdir(exist_ok = True) - build_dir = Path(build_dir_name) - os.chdir(build_dir) - - if ( not Path(llvm_file).exists()): - core_number = os.cpu_count() - print("Build llvm with", core_number, " cores") - cmd = 'cmake ../llvm \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_BUILD_TYPE:STRING="Release" \ - -DLLVM_TARGETS_TO_BUILD:STRING="X86;ARM;AArch64;Mips" \ - -DLLVM_INCLUDE_GO_TESTS=OFF \ - -DLLVM_INCLUDE_TOOLS=OFF \ - -DLLVM_INCLUDE_UTILS=OFF \ - -DLLVM_ENABLE_TERMINFO=OFF \ - -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ - -DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \ - -DLLVM_ENABLE_ZLIB:BOOL=OFF \ - -DLLVM_INCLUDE_DOCS:BOOL=OFF \ - -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \ - -DLLVM_INCLUDE_TESTS:BOOL=OFF \ - -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \ - -DLLVM_APPEND_VC_REV:BOOL=OFF' - print(cmd) - for line in os.popen(cmd): - print(line) - else: - print("llvm has already been Cmaked") - - print("Please open LLVM.sln in {} to build *Release* version".format(build_dir.absolute())) - - os.chdir(current_dir) -if __name__ == "__main__": - main() +script = ( + pathlib.Path(__file__) + .parent.joinpath("../../../build-scripts/build_llvm.py") + .resolve() +) +subprocess.check_call([sys.executable, script]) diff --git a/product-mini/platforms/zephyr/simple/build_and_run.sh b/product-mini/platforms/zephyr/simple/build_and_run.sh index e928e4b133..b5d1b6177f 100755 --- a/product-mini/platforms/zephyr/simple/build_and_run.sh +++ b/product-mini/platforms/zephyr/simple/build_and_run.sh @@ -10,11 +10,12 @@ QEMU_CORTEX_A53="qemu_cortex_a53" QEMU_XTENSA_TARGET="qemu_xtensa" QEMU_RISCV64_TARGET="qemu_riscv64" QEMU_RISCV32_TARGET="qemu_riscv32" +QEMU_ARC_TARGET="qemu_arc" usage () { echo "USAGE:" - echo "$0 $X86_TARGET|$STM32_TARGET|$ESP32_TARGET|$QEMU_CORTEX_A53|$QEMU_XTENSA_TARGET|$QEMU_RISCV64_TARGET|$QEMU_RISCV32_TARGET" + echo "$0 $X86_TARGET|$STM32_TARGET|$ESP32_TARGET|$QEMU_CORTEX_A53|$QEMU_XTENSA_TARGET|$QEMU_RISCV64_TARGET|$QEMU_RISCV32_TARGET|$QEMU_ARC_TARGET" echo "Example:" echo " $0 $X86_TARGET" echo " $0 $STM32_TARGET" @@ -88,6 +89,14 @@ case $TARGET in -DWAMR_BUILD_AOT=0 west build -t run ;; + $QEMU_ARC_TARGET) + west build -b qemu_arc_em \ + . -p always -- \ + -DCONF_FILE=prj_qemu_arc.conf \ + -DWAMR_BUILD_TARGET=ARC \ + -DWAMR_BUILD_AOT=0 + west build -t run + ;; *) echo "unsupported target: $TARGET" usage diff --git a/product-mini/platforms/zephyr/simple/prj_qemu_arc.conf b/product-mini/platforms/zephyr/simple/prj_qemu_arc.conf new file mode 100644 index 0000000000..7f4a328322 --- /dev/null +++ b/product-mini/platforms/zephyr/simple/prj_qemu_arc.conf @@ -0,0 +1,6 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +CONFIG_STACK_SENTINEL=y +CONFIG_PRINTK=y +CONFIG_LOG=y diff --git a/product-mini/platforms/zephyr/simple/src/main.c b/product-mini/platforms/zephyr/simple/src/main.c index 14e6fad2ff..f5b83e6dfd 100644 --- a/product-mini/platforms/zephyr/simple/src/main.c +++ b/product-mini/platforms/zephyr/simple/src/main.c @@ -64,10 +64,42 @@ static void* app_instance_main(wasm_module_inst_t module_inst) { const char *exception; + wasm_function_inst_t func; + wasm_exec_env_t exec_env; + unsigned argv[2] = { 0 }; + + if (wasm_runtime_lookup_function(module_inst, "main", NULL) + || wasm_runtime_lookup_function(module_inst, + "__main_argc_argv", NULL)) { + LOG_VERBOSE("Calling main funciton\n"); + wasm_application_execute_main(module_inst, app_argc, app_argv); + } + else if ((func = wasm_runtime_lookup_function(module_inst, + "app_main", NULL))) { + exec_env = wasm_runtime_create_exec_env(module_inst, + CONFIG_APP_HEAP_SIZE); + if (!exec_env) { + os_printf("Create exec env failed\n"); + return NULL; + } + + LOG_VERBOSE("Calling app_main funciton\n"); + wasm_runtime_call_wasm(exec_env, func, 0, argv); + + if (!wasm_runtime_get_exception(module_inst)) { + os_printf("result: 0x%x\n", argv[0]); + } + + wasm_runtime_destroy_exec_env(exec_env); + } + else { + os_printf("Failed to lookup function main or app_main to call\n"); + return NULL; + } - wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - printf("%s\n", exception); + os_printf("%s\n", exception); + return NULL; } diff --git a/samples/basic/CMakeLists.txt b/samples/basic/CMakeLists.txt index dfa6f0fa49..d8a37652d9 100644 --- a/samples/basic/CMakeLists.txt +++ b/samples/basic/CMakeLists.txt @@ -21,28 +21,48 @@ set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # WAMR features switch -set (WAMR_BUILD_TARGET "X86_64") -set(CMAKE_BUILD_TYPE Debug) + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Release) +endif () + set (WAMR_BUILD_INTERP 1) set (WAMR_BUILD_AOT 1) set (WAMR_BUILD_JIT 0) set (WAMR_BUILD_LIBC_BUILTIN 1) + if (NOT MSVC) set (WAMR_BUILD_LIBC_WASI 1) endif () -set (WAMR_BUILD_FAST_INTERP 0) if (NOT MSVC) # linker flags set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie -fPIE") if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif () set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") - endif () + endif () endif () endif () diff --git a/samples/basic/src/main.c b/samples/basic/src/main.c index d937be3c8a..8cb13d84bf 100644 --- a/samples/basic/src/main.c +++ b/samples/basic/src/main.c @@ -24,7 +24,7 @@ int main(int argc, char *argv_main[]) static char global_heap_buf[512 * 1024]; char *buffer, error_buf[128]; int opt; - char * wasm_path; + char * wasm_path = NULL; wasm_module_t module = NULL; wasm_module_inst_t module_inst = NULL; @@ -148,7 +148,8 @@ int main(int argc, char *argv_main[]) goto fail; } - float ret_val = *(float*)argv; + float ret_val; + memcpy(&ret_val, argv, sizeof(float)); printf("Native finished calling wasm function generate_float(), returned a float value: %ff\n", ret_val ); // Next we will pass a buffer to the WASM function @@ -157,7 +158,7 @@ int main(int argc, char *argv_main[]) // must allocate buffer from wasm instance memory space (never use pointer from host runtime) wasm_buffer = wasm_runtime_module_malloc(module_inst, 100, (void**)&native_buffer); - *(float*)argv2 = ret_val; // the first argument + memcpy(argv2, &ret_val, sizeof(float)); // the first argument argv2[1] = wasm_buffer; // the second argument is the wasm buffer address argv2[2] = 100; // the third argument is the wasm buffer size argv2[3] = 3; // the last argument is the digits after decimal point for converting float to string diff --git a/samples/gui/README.md b/samples/gui/README.md index 2d3d062cbd..d79453c3e6 100644 --- a/samples/gui/README.md +++ b/samples/gui/README.md @@ -77,7 +77,7 @@ Refer to [Zephyr getting started](https://docs.zephyrproject.org/latest/getting b. copy samples ```bash cd zephyr/samples - cp -a samples/gui/wasm-runtime-wgl wasm-runtime-wgl + cp -a /samples/gui/wasm-runtime-wgl wasm-runtime-wgl cd wasm-runtime-wgl/zephyr_build ``` c. create a link to wamr root dir @@ -123,7 +123,8 @@ Refer to [Zephyr getting started](https://docs.zephyrproject.org/latest/getting - Install WASM application to Zephyr using host_tool First, connect PC and STM32 with UART. Then install to use host_tool. ```bash - ./host_tool -D /dev/ttyUSBXXX -i inc -f ui_increase.wasm + sudo ./host_tool -D /dev/ttyUSBXXX -i inc -f ui_increase.wasm + # /dev/ttyUSBXXX is the UART device, e.g. /dev/ttyUSB0 ``` - Install AOT version WASM application diff --git a/samples/littlevgl/README.md b/samples/littlevgl/README.md index 0b6bbe9fbe..87fd2bd429 100644 --- a/samples/littlevgl/README.md +++ b/samples/littlevgl/README.md @@ -103,7 +103,7 @@ We can use a STM32 NUCLEO_F767ZI board with ILI9341 display and XPT2046 touch s b. copy samples ```bash cd zephyr/samples/ - cp -a samples/littlevgl/vgl-wasm-runtime vgl-wasm-runtime + cp -a /samples/littlevgl/vgl-wasm-runtime vgl-wasm-runtime cd vgl-wasm-runtime/zephyr_build ``` c. create a link to wamr root dir @@ -161,7 +161,8 @@ d. build source code - Install WASM application to Zephyr using host_tool First, connect PC and STM32 with UART. Then install to use host_tool. ```bash - ./host_tool -D /dev/ttyUSBXXX -i ui_app -f ui_app_builtin_libc.wasm + sudo ./host_tool -D /dev/ttyUSBXXX -i ui_app -f ui_app_builtin_libc.wasm + # /dev/ttyUSBXXX is the UART device, e.g. /dev/ttyUSB0 ``` **Note**: WASI is unavailable on zephyr currently, so you have to use the ui_app_builtin_libc.wasm which doesn't depend on WASI. diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c index eb42950943..4a02767871 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c @@ -26,7 +26,7 @@ struct ili9340_data { struct device *spi_dev; struct spi_config spi_config; #ifdef DT_ILITEK_ILI9340_0_CS_GPIO_CONTROLLER -struct spi_cs_control cs_ctrl; + struct spi_cs_control cs_ctrl; #endif }; diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c index 391e48e047..6ec3bd49e6 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c @@ -27,7 +27,8 @@ extern int aee_host_msg_callback(void *msg, uint32_t msg_len); int uart_char_cnt = 0; -static void uart_irq_callback(struct device *dev) +static void uart_irq_callback(const struct device *dev, + void *user_data) { unsigned char ch; @@ -35,9 +36,10 @@ static void uart_irq_callback(struct device *dev) uart_char_cnt++; aee_host_msg_callback(&ch, 1); } + (void)user_data; } -struct device *uart_dev = NULL; +const struct device *uart_dev = NULL; static bool host_init() { @@ -74,7 +76,7 @@ host_interface interface = { timer_ctx_t timer_ctx; -static char global_heap_buf[368 * 1024] = { 0 }; +static char global_heap_buf[350 * 1024] = { 0 }; static NativeSymbol native_symbols[] = { EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"), diff --git a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/prj.conf b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/prj.conf index f9f13f9a78..6ca7f44265 100644 --- a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/prj.conf +++ b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/prj.conf @@ -1,6 +1,5 @@ CONFIG_SPI=y CONFIG_SPI_STM32=y -CONFIG_SPI_1=y CONFIG_PRINTK=y CONFIG_LOG=y #CONFIG_UART_2=y diff --git a/samples/multi-module/CMakeLists.txt b/samples/multi-module/CMakeLists.txt index ba239d567f..76e326edb1 100644 --- a/samples/multi-module/CMakeLists.txt +++ b/samples/multi-module/CMakeLists.txt @@ -15,13 +15,33 @@ set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # WAMR features switch -set(WAMR_BUILD_TARGET "X86_64") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Release) +endif () + set(WAMR_BUILD_INTERP 1) set(WAMR_BUILD_AOT 0) set(WAMR_BUILD_JIT 0) set(WAMR_BUILD_LIBC_BUILTIN 1) set(WAMR_BUILD_LIBC_WASI 0) -set(WAMR_BUILD_FAST_INTERP 0) set(WAMR_BUILD_MULTI_MODULE 1) # compiling and linking flags diff --git a/samples/multi-thread/CMakeLists.txt b/samples/multi-thread/CMakeLists.txt index 34151d05fb..0cf2bed13e 100644 --- a/samples/multi-thread/CMakeLists.txt +++ b/samples/multi-thread/CMakeLists.txt @@ -15,7 +15,28 @@ set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # WAMR features switch -set(WAMR_BUILD_TARGET "X86_64") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Release) +endif () + set(WAMR_BUILD_INTERP 1) set(WAMR_BUILD_AOT 1) set(WAMR_BUILD_JIT 0) diff --git a/samples/ref-types/CMakeLists.txt b/samples/ref-types/CMakeLists.txt index 38c1d4750d..1da1517ef6 100644 --- a/samples/ref-types/CMakeLists.txt +++ b/samples/ref-types/CMakeLists.txt @@ -10,10 +10,6 @@ else() enable_language (ASM_MASM) endif() -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug) -endif() - ################ runtime settings ################ string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) if (APPLE) @@ -25,7 +21,27 @@ set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # WAMR features switch -set(WAMR_BUILD_TARGET "X86_64") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Release) +endif () if(NOT DEFINED WAMR_BUILD_INTERP) set(WAMR_BUILD_INTERP 1) diff --git a/samples/spawn-thread/CMakeLists.txt b/samples/spawn-thread/CMakeLists.txt index b40af9a85a..9fa129b219 100644 --- a/samples/spawn-thread/CMakeLists.txt +++ b/samples/spawn-thread/CMakeLists.txt @@ -15,7 +15,28 @@ set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # WAMR features switch -set(WAMR_BUILD_TARGET "X86_64") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Release) +endif () + set(WAMR_BUILD_INTERP 1) set(WAMR_BUILD_AOT 1) set(WAMR_BUILD_JIT 0) diff --git a/samples/spawn-thread/src/main.c b/samples/spawn-thread/src/main.c index 6df1042d4c..d0581b50e4 100644 --- a/samples/spawn-thread/src/main.c +++ b/samples/spawn-thread/src/main.c @@ -23,9 +23,15 @@ void *thread(void* arg) wasm_function_inst_t func; uint32 argv[2]; + if (!wasm_runtime_init_thread_env()) { + printf("failed to initialize thread environment"); + return NULL; + } + func = wasm_runtime_lookup_function(module_inst, "sum", NULL); if (!func) { printf("failed to lookup function sum"); + wasm_runtime_destroy_thread_env(); return NULL; } argv[0] = thread_arg->start; @@ -34,9 +40,11 @@ void *thread(void* arg) /* call the WASM function */ if (!wasm_runtime_call_wasm(exec_env, func, 2, argv)) { printf("%s\n", wasm_runtime_get_exception(module_inst)); + wasm_runtime_destroy_thread_env(); return NULL; } + wasm_runtime_destroy_thread_env(); return (void *)(uintptr_t)argv[0]; } diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index 334232e8d6..5d4a34ba1d 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -13,7 +13,10 @@ endif() if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() + +set(CMAKE_CXX_STANDARD 14) ################ runtime settings ################ + string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) if (APPLE) add_definitions(-DBH_PLATFORM_DARWIN) @@ -24,14 +27,30 @@ set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # WAMR features switch -set(WAMR_BUILD_TARGET "X86_64") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () if(NOT DEFINED WAMR_BUILD_INTERP) set(WAMR_BUILD_INTERP 1) endif() if(NOT DEFINED WAMR_BUILD_AOT) - set(WAMR_BUILD_AOT 1) + set(WAMR_BUILD_AOT 0) endif() if(NOT DEFINED WAMR_BUILD_JIT) @@ -41,6 +60,8 @@ endif() set(WAMR_BUILD_LIBC_BUILTIN 1) set(WAMR_BUILD_LIBC_WASI 0) set(WAMR_BUILD_MULTI_MODULE 1) +set(WAMR_BUILD_DUMP_CALL_STACK 1) +set(WAMR_BUILD_REF_TYPES 1) if(NOT DEFINED WAMR_BUILD_FAST_INTERP) set(WAMR_BUILD_FAST_INTERP 1) @@ -61,7 +82,6 @@ if (NOT MSVC) endif() # build out vmlib set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) -set(WAMRC ${WAMR_ROOT_DIR}/wamr-compiler/build/wamrc) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) add_library(vmlib STATIC ${WAMR_RUNTIME_LIB_SOURCE}) @@ -83,17 +103,34 @@ if(NOT WAT2WASM) message(SEND_ERROR "can not find wat2wasm") endif() +if(${WAMR_BUILD_AOT} EQUAL 1) + ## locate wamrc + find_program(WAMRC + wamrc + PATHS ${WAMR_ROOT_DIR}/wamr-compiler/build/ + ) + + if(NOT WAMRC) + message(SEND_ERROR "can not find wamrc. refer to \ + https://github.com/bytecodealliance/wasm-micro-runtime#build-wamrc-aot-compiler" + ) + endif() +endif() include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) set(MM_UTIL src/utils/multi_module_utils.c) # build executable for each .c set(EXAMPLES - hello callback + callback_chain + empty_imports global + hello + hostref + memory reflect + table trap - callback_chain ) foreach(EX ${EXAMPLES}) @@ -110,7 +147,7 @@ foreach(EX ${EXAMPLES}) set(WAT ${CMAKE_CURRENT_LIST_DIR}/src/${EX}.wat) add_custom_target(${EX}_WASM - COMMAND ${WAT2WASM} ${WAT} -o ${PROJECT_BINARY_DIR}/${EX}.wasm + COMMAND ${WAT2WASM} ${WAT} --enable-reference-types -o ${PROJECT_BINARY_DIR}/${EX}.wasm DEPENDS ${WAT} BYPRODUCTS ${PROJECT_BINARY_DIR}/${EX}.wasm VERBATIM @@ -119,17 +156,15 @@ foreach(EX ${EXAMPLES}) # generate .aot file if(${WAMR_BUILD_AOT} EQUAL 1) - if(EXISTS ${WAMRC}) - add_custom_target(${EX}_AOT - COMMAND ${WAMRC} -o ${PROJECT_BINARY_DIR}/${EX}.aot - ${PROJECT_BINARY_DIR}/${EX}.wasm - DEPENDS ${EX}_WASM - BYPRODUCTS ${PROJECT_BINARY_DIR}/${EX}.aot - VERBATIM - COMMENT "generate a aot file ${PROJECT_BINARY_DIR}/${EX}.aot" - ) - add_dependencies(${EX} ${EX}_AOT) - endif() + add_custom_target(${EX}_AOT + COMMAND ${WAMRC} --enable-ref-types -o ${PROJECT_BINARY_DIR}/${EX}.aot + ${PROJECT_BINARY_DIR}/${EX}.wasm + DEPENDS ${EX}_WASM + BYPRODUCTS ${PROJECT_BINARY_DIR}/${EX}.aot + VERBATIM + COMMENT "generate a aot file ${PROJECT_BINARY_DIR}/${EX}.aot" + ) + add_dependencies(${EX} ${EX}_AOT) endif() endforeach() diff --git a/samples/wasm-c-api/src/callback.c b/samples/wasm-c-api/src/callback.c index e350edc64f..b62d72894d 100644 --- a/samples/wasm-c-api/src/callback.c +++ b/samples/wasm-c-api/src/callback.c @@ -35,27 +35,27 @@ void wasm_val_print(wasm_val_t val) { // A function to be called from Wasm code. own wasm_trap_t* print_callback( - const wasm_val_t args[], wasm_val_t results[] + const wasm_val_vec_t *args, wasm_val_vec_t *results ) { printf("Calling back...\n> "); - wasm_val_print(args[0]); + wasm_val_print(args->data[0]); printf("\n"); - wasm_val_copy(&results[0], &args[0]); + wasm_val_copy(&results->data[0], &args->data[0]); return NULL; } // A function closure. own wasm_trap_t* closure_callback( - void* env, const wasm_val_t args[], wasm_val_t results[] + void* env, const wasm_val_vec_t *args, wasm_val_vec_t *results ) { int i = *(int*)env; printf("Calling back closure...\n"); printf("> %d\n", i); - results[0].kind = WASM_I32; - results[0].of.i32 = (int32_t)i; + results->data[0].kind = WASM_I32; + results->data[0].of.i32 = (int32_t)i; return NULL; } @@ -113,11 +113,13 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = { + + wasm_extern_vec_t imports; + wasm_extern_vec_new(&imports, 2, (wasm_extern_t *[]) { wasm_func_as_extern(print_func), wasm_func_as_extern(closure_func) - }; + }); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -145,9 +147,10 @@ int main(int argc, const char* argv[]) { // Call. printf("Calling export...\n"); - wasm_val_t args[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) }; - wasm_val_t results[1] = { WASM_INIT_VAL }; - if (wasm_func_call(run_func, args, results)) { + wasm_val_vec_t args, results; + wasm_val_vec_new(&args, 2, (wasm_val_t[]){ WASM_I32_VAL(3), WASM_I32_VAL(4) }); + wasm_val_vec_new(&results, 1, (wasm_val_t[]) { WASM_INIT_VAL }); + if (wasm_func_call(run_func, &args, &results)) { printf("> Error calling function!\n"); return 1; } @@ -156,7 +159,7 @@ int main(int argc, const char* argv[]) { // Print result. printf("Printing result...\n"); - printf("> %u\n", results[0].of.i32); + printf("> %u\n", results.data[0].of.i32); // Shut down. printf("Shutting down...\n"); diff --git a/samples/wasm-c-api/src/callback_chain.c b/samples/wasm-c-api/src/callback_chain.c index ab15d08235..1b5f1b5941 100644 --- a/samples/wasm-c-api/src/callback_chain.c +++ b/samples/wasm-c-api/src/callback_chain.c @@ -17,8 +17,8 @@ get_memory_data(uint32_t offset, uint32_t length); static bool call_wasm_function(uint32_t export_id, - const wasm_val_t *args, - wasm_val_t *results, + const wasm_val_vec_t *args, + wasm_val_vec_t *results, const char *name); /************************ IMPORTED FUNCTIONS **************************/ @@ -49,7 +49,7 @@ enum EXPORT_ITEM_NAME { }; #define DEFINE_FUNCTION(name) \ - wasm_trap_t *STUB_##name(const wasm_val_t args[], wasm_val_t results[]) + wasm_trap_t *STUB_##name(const wasm_val_vec_t* args, wasm_val_vec_t* results) #define DEFINE_EMPTY_FUNCTION(name) \ DEFINE_FUNCTION(name) \ @@ -61,16 +61,17 @@ enum EXPORT_ITEM_NAME { DEFINE_FUNCTION(get_pairs) { - wasm_val_t ret[1] = { WASM_INIT_VAL }; - call_wasm_function(e_malloc, (wasm_val_t[]){ WASM_I32_VAL(24) }, ret, - "malloc"); + wasm_val_vec_t arg, ret; + wasm_val_vec_new(&ret, 1, (wasm_val_t []){ WASM_INIT_VAL }); + wasm_val_vec_new(&arg, 1, (wasm_val_t []){ WASM_I32_VAL(24) }); + call_wasm_function(e_malloc, &arg, &ret, "malloc"); return NULL; } DEFINE_FUNCTION(log) { - wasm_val_t offset = args[0]; - wasm_val_t length = args[1]; + wasm_val_t offset = args->data[0]; + wasm_val_t length = args->data[1]; const byte_t *data = NULL; printf("[WASM -> NATIVE] calling back %s\n", __FUNCTION__); @@ -92,32 +93,6 @@ DEFINE_FUNCTION(log) return NULL; } -static inline void -create_import_function_list(wasm_store_t *store, - const wasm_extern_t *import_function_list[]) -{ -#define IMPORT_FUNCTION_VARIABLE_NAME(name, ...) \ - own wasm_func_t *function_##name = NULL; - IMPORT_FUNCTION_LIST(IMPORT_FUNCTION_VARIABLE_NAME) -#undef IMPORT_FUNCTION_VARIABLE_NAME - -#define CREATE_WASM_FUNCTION(name, index, CREATE_FUNC_TYPE) \ - { \ - own wasm_functype_t *type = CREATE_FUNC_TYPE; \ - if (!(function_##name = wasm_func_new(store, type, STUB_##name))) { \ - printf("> Error creating new function\n"); \ - } \ - wasm_functype_delete(type); \ - } - IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION) -#undef CREATE_WASM_FUNCTION - -#define ADD_TO_FUNCTION_LIST(name, index, ...) \ - import_function_list[index] = wasm_func_as_extern(function_##name); - IMPORT_FUNCTION_LIST(ADD_TO_FUNCTION_LIST) -#undef CREATE_IMPORT_FUNCTION -} - /**********************************************************************/ // all exportted wasm functions. check with "/opt/wabt/bin/wasm-objdump -x -j Export X.wasm" // -1: memory @@ -146,8 +121,8 @@ get_memory_data(uint32_t offset, uint32_t length) static bool call_wasm_function(uint32_t export_id, - const wasm_val_t *args, - wasm_val_t *results, + const wasm_val_vec_t *args, + wasm_val_vec_t *results, const char *name) { const wasm_func_t *function; @@ -221,19 +196,48 @@ main(int argc, const char *argv[]) // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t *imports[10] = { 0 }; // Create external functions. printf("Creating callback...\n"); - create_import_function_list(store, imports); +#define IMPORT_FUNCTION_VARIABLE_NAME(name, ...) \ + own wasm_func_t *function_##name = NULL; + IMPORT_FUNCTION_LIST(IMPORT_FUNCTION_VARIABLE_NAME) +#undef IMPORT_FUNCTION_VARIABLE_NAME + + wasm_extern_vec_t imports; + wasm_extern_vec_new_uninitialized(&imports, 10); + +#define CREATE_WASM_FUNCTION(name, index, CREATE_FUNC_TYPE) \ + { \ + own wasm_functype_t *type = CREATE_FUNC_TYPE; \ + if (!(function_##name = wasm_func_new(store, type, STUB_##name))) { \ + printf("> Error creating new function\n"); \ + return 1; \ + } \ + wasm_functype_delete(type); \ + } + IMPORT_FUNCTION_LIST(CREATE_WASM_FUNCTION) +#undef CREATE_WASM_FUNCTION + +#define ADD_TO_FUNCTION_LIST(name, index, ...) \ + imports.data[index] = wasm_func_as_extern(function_##name); \ + imports.num_elems += 1; + IMPORT_FUNCTION_LIST(ADD_TO_FUNCTION_LIST) +#undef CREATE_IMPORT_FUNCTION + own wasm_instance_t *instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; } +#define DESTROY_WASM_FUNCITON(name, index, ...) \ + wasm_func_delete(function_##name); + IMPORT_FUNCTION_LIST(DESTROY_WASM_FUNCITON) +#undef DESTROY_WASM_FUNCITON + // Extract export. printf("Extracting export...\n"); wasm_instance_exports(instance, &exports); diff --git a/samples/wasm-c-api/src/empty_imports.c b/samples/wasm-c-api/src/empty_imports.c new file mode 100644 index 0000000000..902704ed82 --- /dev/null +++ b/samples/wasm-c-api/src/empty_imports.c @@ -0,0 +1,97 @@ +#include + +#include "wasm_c_api.h" + +#define own + +int main(int argc, const char* argv[]) { + // Initialize. + printf("Initializing...\n"); + wasm_engine_t* engine = wasm_engine_new(); + wasm_store_t* store = wasm_store_new(engine); + + // Load binary. + printf("Loading binary...\n"); +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0 + FILE* file = fopen("empty_imports.aot", "rb"); +#else + FILE* file = fopen("empty_imports.wasm", "rb"); +#endif + if (!file) { + printf("> Error loading module!\n"); + return 1; + } + fseek(file, 0L, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0L, SEEK_SET); + wasm_byte_vec_t binary; + wasm_byte_vec_new_uninitialized(&binary, file_size); + if (fread(binary.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + fclose(file); + return 1; + } + fclose(file); + + // Compile. + printf("Compiling module...\n"); + own wasm_module_t* module = wasm_module_new(store, &binary); + if (!module) { + printf("> Error compiling module!\n"); + return 1; + } + + wasm_byte_vec_delete(&binary); + + // Instantiate with non-null but empty imports array. + printf("Instantiating module...\n"); + wasm_extern_vec_t imports = WASM_EMPTY_VEC; + own wasm_instance_t* instance = + wasm_instance_new(store, module, &imports, NULL); + if (!instance) { + printf("> Error instantiating module!\n"); + return 1; + } + + // Run an exported function to verify that the instance was created correctly. + printf("Extracting export...\n"); + own wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + if (exports.size == 0) { + printf("> Error accessing exports!\n"); + return 1; + } + + const wasm_func_t* add_func = wasm_extern_as_func(exports.data[0]); + if (add_func == NULL) { + printf("> Error accessing export!\n"); + return 1; + } + + wasm_module_delete(module); + wasm_instance_delete(instance); + + printf("Calling export...\n"); + wasm_val_t args[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) }; + wasm_val_vec_t args_vec = WASM_ARRAY_VEC(args); + + wasm_val_t results[1] = { WASM_INIT_VAL }; + wasm_val_vec_t results_vec = WASM_ARRAY_VEC(results); + + if (wasm_func_call(add_func, &args_vec, &results_vec) + || results_vec.data[0].of.i32 != 7) { + printf("> Error calling function!\n"); + return 1; + } + + wasm_extern_vec_delete(&exports); + + // Shut down. + printf("Shutting down...\n"); + wasm_store_delete(store); + wasm_engine_delete(engine); + + // All done. + printf("Done.\n"); + return 0; +} diff --git a/samples/wasm-c-api/src/empty_imports.wat b/samples/wasm-c-api/src/empty_imports.wat new file mode 100644 index 0000000000..38639790b3 --- /dev/null +++ b/samples/wasm-c-api/src/empty_imports.wat @@ -0,0 +1,5 @@ +(module + (func (export "add") (param i32 i32) (result i32) + (i32.add (local.get 0) (local.get 1)) + ) +) diff --git a/samples/wasm-c-api/src/global.c b/samples/wasm-c-api/src/global.c index 5a3b3f4ce4..dab1bb49af 100644 --- a/samples/wasm-c-api/src/global.c +++ b/samples/wasm-c-api/src/global.c @@ -39,9 +39,10 @@ wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { #define check_call(func, type, expected) \ { \ - wasm_val_t results[1]; \ - wasm_func_call(func, NULL, results); \ - check(results[0], type, expected); \ + wasm_val_vec_t results; \ + wasm_val_vec_new_uninitialized(&results, 1); \ + wasm_func_call(func, NULL, &results); \ + check(results.data[0], type, expected); \ } @@ -115,14 +116,21 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = { + /*const wasm_extern_t* imports1[] = { wasm_global_as_extern(const_f32_import), wasm_global_as_extern(const_i64_import), wasm_global_as_extern(var_f32_import), wasm_global_as_extern(var_i64_import) - }; + };*/ + wasm_extern_vec_t imports; + wasm_extern_vec_new(&imports, 4, (wasm_extern_t* []) { + wasm_global_as_extern(const_f32_import), + wasm_global_as_extern(const_i64_import), + wasm_global_as_extern(var_f32_import), + wasm_global_as_extern(var_i64_import) + }); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -200,14 +208,18 @@ int main(int argc, const char* argv[]) { check_call(get_var_i64_export, i64, 38); // Modify variables through calls and check again. - wasm_val_t args73[] = { WASM_F32_VAL(73) }; - wasm_func_call(set_var_f32_import, args73, NULL); - wasm_val_t args74[] = { WASM_I64_VAL(74) }; - wasm_func_call(set_var_i64_import, args74, NULL); - wasm_val_t args77[] = { WASM_F32_VAL(77) }; - wasm_func_call(set_var_f32_export, args77, NULL); - wasm_val_t args78[] = { WASM_I64_VAL(78) }; - wasm_func_call(set_var_i64_export, args78, NULL); + wasm_val_vec_t args73; + wasm_val_vec_new(&args73, 1, (wasm_val_t []){ WASM_F32_VAL(73) }); + wasm_func_call(set_var_f32_import, &args73, NULL); + wasm_val_vec_t args74; + wasm_val_vec_new(&args74, 1, (wasm_val_t []){ WASM_I64_VAL(74) }); + wasm_func_call(set_var_i64_import, &args74, NULL); + wasm_val_vec_t args77; + wasm_val_vec_new(&args77, 1, (wasm_val_t []){ WASM_F32_VAL(77) }); + wasm_func_call(set_var_f32_export, &args77, NULL); + wasm_val_vec_t args78; + wasm_val_vec_new(&args78, 1, (wasm_val_t []){ WASM_I64_VAL(78) }); + wasm_func_call(set_var_i64_export, &args78, NULL); check_global(var_f32_import, f32, 73); check_global(var_i64_import, i64, 74); diff --git a/samples/wasm-c-api/src/globalexportimport.c b/samples/wasm-c-api/src/globalexportimport.c index c8f58b499c..92420a1b9f 100644 --- a/samples/wasm-c-api/src/globalexportimport.c +++ b/samples/wasm-c-api/src/globalexportimport.c @@ -52,9 +52,10 @@ wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { #define check_call(func, type, expected) \ { \ - wasm_val_t results[1]; \ - wasm_func_call(func, NULL, results); \ - check(results[0], type, expected); \ + wasm_val_vec_t results; \ + wasm_val_vec_new_uninitialized(&results, 1); \ + wasm_func_call(func, NULL, &results); \ + check(results.data[0], type, expected); \ } wasm_module_t * create_module_from_file(wasm_store_t* store, const char * filename) @@ -146,16 +147,18 @@ int main(int argc, const char* argv[]) { // Modify variables through calls and check again. printf("Modify the variable to 77.0...\n"); - wasm_val_t args77[] = { {.kind = WASM_F32, .of = {.f32 = 77.}} }; - wasm_func_call(set_var_f32_export, args77, NULL); //Call to module export + wasm_val_vec_t args77; + wasm_val_vec_new(&args77, 1, (wasm_val_t []){ {.kind = WASM_F32, .of = {.f32 = 77.0}} }); + wasm_func_call(set_var_f32_export, &args77, NULL); //Call to module export check_call(get_var_f32_export, f32, 77.0); //Call to module export check_global(var_f32_export, f32, 77.0); //Failed here, still 37 check_call(get_var_f32_import, f32, 77.0); //Call to module import Failed here, still 37 printf("Modify the variable to 78.0...\n"); - wasm_val_t args78[] = { {.kind = WASM_F32, .of = {.f32 = 78.0}} }; - wasm_func_call(set_var_f32_import, args78, NULL); + wasm_val_vec_t args78; + wasm_val_vec_new(&args78, 1, (wasm_val_t []){ {.kind = WASM_F32, .of = {.f32 = 78.0}} }); + wasm_func_call(set_var_f32_import, &args78, NULL); check_global(var_f32_export, f32, 78.0); check_call(get_var_f32_export, f32, 78.0); //Call to module export Failed here, still 77 check_call(get_var_f32_import, f32, 78.0); //Call to module import diff --git a/samples/wasm-c-api/src/hello.c b/samples/wasm-c-api/src/hello.c index fde1b82d40..9a6834b56f 100644 --- a/samples/wasm-c-api/src/hello.c +++ b/samples/wasm-c-api/src/hello.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* hello_callback( - const wasm_val_t args[], wasm_val_t results[] + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); printf("> Hello World!\n"); @@ -66,9 +66,11 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = { wasm_func_as_extern(hello_func) }; + wasm_extern_vec_t imports; + wasm_extern_vec_new(&imports, 1, (wasm_extern_t* []) { wasm_func_as_extern(hello_func) }); + own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -112,3 +114,4 @@ int main(int argc, const char* argv[]) { printf("Done.\n"); return 0; } + diff --git a/samples/wasm-c-api/src/hostref.c b/samples/wasm-c-api/src/hostref.c new file mode 100644 index 0000000000..d802c2b661 --- /dev/null +++ b/samples/wasm-c-api/src/hostref.c @@ -0,0 +1,269 @@ +#include +#include +#include +#include + +#include "wasm_c_api.h" + +#define own + + +// A function to be called from Wasm code. +own wasm_trap_t* callback( + const wasm_val_vec_t* args, wasm_val_vec_t* results +) { + printf("Calling back...\n> "); + printf("> %p\n", + args->data[0].of.ref ? wasm_ref_get_host_info(args->data[0].of.ref) : NULL); + wasm_val_copy(&results->data[0], &args->data[0]); + return NULL; +} + + +wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { + if (exports->size <= i || !wasm_extern_as_func(exports->data[i])) { + printf("> Error accessing function export %zu!\n", i); + exit(1); + } + return wasm_extern_as_func(exports->data[i]); +} + +wasm_global_t* get_export_global(const wasm_extern_vec_t* exports, size_t i) { + if (exports->size <= i || !wasm_extern_as_global(exports->data[i])) { + printf("> Error accessing global export %zu!\n", i); + exit(1); + } + return wasm_extern_as_global(exports->data[i]); +} + +wasm_table_t* get_export_table(const wasm_extern_vec_t* exports, size_t i) { + if (exports->size <= i || !wasm_extern_as_table(exports->data[i])) { + printf("> Error accessing table export %zu!\n", i); + exit(1); + } + return wasm_extern_as_table(exports->data[i]); +} + + +own wasm_ref_t* call_v_r(const wasm_func_t* func) { + printf("call_v_r... "); fflush(stdout); + wasm_val_vec_t rs; + wasm_val_vec_new_uninitialized(&rs, 1); + if (wasm_func_call(func, NULL, &rs)) { + printf("> Error calling function!\n"); + exit(1); + } + printf("okay\n"); + return rs.data[0].of.ref; +} + +void call_r_v(const wasm_func_t* func, wasm_ref_t* ref) { + printf("call_r_v... "); fflush(stdout); + wasm_val_vec_t vs; + wasm_val_vec_new(&vs, 1, (wasm_val_t []){ WASM_REF_VAL(ref) }); + if (wasm_func_call(func, &vs, NULL)) { + printf("> Error calling function!\n"); + exit(1); + } + printf("okay\n"); +} + +own wasm_ref_t* call_r_r(const wasm_func_t* func, wasm_ref_t* ref) { + printf("call_r_r... "); fflush(stdout); + wasm_val_vec_t vs, rs; + wasm_val_vec_new(&vs, 1, (wasm_val_t []){ WASM_REF_VAL(ref) }); + wasm_val_vec_new_uninitialized(&rs, 1); + if (wasm_func_call(func, &vs, &rs)) { + printf("> Error calling function!\n"); + exit(1); + } + printf("okay\n"); + return rs.data[0].of.ref; +} + +void call_ir_v(const wasm_func_t* func, int32_t i, wasm_ref_t* ref) { + printf("call_ir_v... "); fflush(stdout); + wasm_val_vec_t vs; + wasm_val_vec_new(&vs, 2, (wasm_val_t []){ WASM_I32_VAL(i), WASM_REF_VAL(ref) }); + if (wasm_func_call(func, &vs, NULL)) { + printf("> Error calling function!\n"); + exit(1); + } + printf("okay\n"); +} + +own wasm_ref_t* call_i_r(const wasm_func_t* func, int32_t i) { + printf("call_i_r... "); fflush(stdout); + wasm_val_vec_t vs, rs; + wasm_val_vec_new(&vs, 1, (wasm_val_t []){ WASM_I32_VAL(i) }); + wasm_val_vec_new_uninitialized(&rs, 1); + if (wasm_func_call(func, &vs, &rs)) { + printf("> Error calling function!\n"); + exit(1); + } + printf("okay\n"); + return rs.data[0].of.ref; +} + +void +check(own wasm_ref_t *actual, const wasm_ref_t *expected, bool release_ref) +{ + if (actual != expected + && !(actual && expected && wasm_ref_same(actual, expected))) { + printf("> Error reading reference, expected %p, got %p\n", + expected ? wasm_ref_get_host_info(expected) : NULL, + actual ? wasm_ref_get_host_info(actual) : NULL); + exit(1); + } + if (release_ref && actual) + wasm_ref_delete(actual); +} + +int main(int argc, const char* argv[]) { + // Initialize. + printf("Initializing...\n"); + wasm_engine_t* engine = wasm_engine_new(); + wasm_store_t* store = wasm_store_new(engine); + + // Load binary. + printf("Loading binary...\n"); +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0 + FILE* file = fopen("hostref.aot", "rb"); +#else + FILE* file = fopen("hostref.wasm", "rb"); +#endif + if (!file) { + printf("> Error loading module!\n"); + return 1; + } + fseek(file, 0L, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0L, SEEK_SET); + wasm_byte_vec_t binary; + wasm_byte_vec_new_uninitialized(&binary, file_size); + if (fread(binary.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + fclose(file); + return 1; + } + fclose(file); + + // Compile. + printf("Compiling module...\n"); + own wasm_module_t* module = wasm_module_new(store, &binary); + if (!module) { + printf("> Error compiling module!\n"); + return 1; + } + + wasm_byte_vec_delete(&binary); + + // Create external callback function. + printf("Creating callback...\n"); + own wasm_functype_t* callback_type = wasm_functype_new_1_1( + wasm_valtype_new(WASM_ANYREF), wasm_valtype_new(WASM_ANYREF)); + own wasm_func_t* callback_func = + wasm_func_new(store, callback_type, callback); + + wasm_functype_delete(callback_type); + + // Instantiate. + printf("Instantiating module...\n"); + wasm_extern_vec_t imports; + wasm_extern_vec_new(&imports, 1, (wasm_extern_t* []) { wasm_func_as_extern(callback_func) }); + own wasm_instance_t* instance = + wasm_instance_new(store, module, &imports, NULL); + if (!instance) { + printf("> Error instantiating module!\n"); + return 1; + } + + wasm_func_delete(callback_func); + wasm_module_delete(module); + + // Extract export. + printf("Extracting exports...\n"); + own wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + size_t i = 0; + wasm_global_t* global = get_export_global(&exports, i++); + wasm_table_t* table = get_export_table(&exports, i++); + wasm_func_t* global_set = get_export_func(&exports, i++); + wasm_func_t* global_get = get_export_func(&exports, i++); + wasm_func_t* table_set = get_export_func(&exports, i++); + wasm_func_t* table_get = get_export_func(&exports, i++); + wasm_func_t* func_call = get_export_func(&exports, i++); + + wasm_instance_delete(instance); + + // Create host references. + printf("Creating host references...\n"); + own wasm_ref_t* host1 = wasm_foreign_as_ref(wasm_foreign_new(store)); + own wasm_ref_t* host2 = wasm_foreign_as_ref(wasm_foreign_new(store)); + wasm_ref_set_host_info(host1, (void*)1); + wasm_ref_set_host_info(host2, (void*)2); + + // Some sanity checks. + check(NULL, NULL, true); + check(wasm_ref_copy(host1), host1, true); + check(wasm_ref_copy(host2), host2, true); + + own wasm_val_t val; + val.kind = WASM_ANYREF; + val.of.ref = wasm_ref_copy(host1); + check(wasm_ref_copy(val.of.ref), host1, true); + own wasm_ref_t* ref = val.of.ref; + check(wasm_ref_copy(ref), host1, true); + wasm_ref_delete(val.of.ref); + + // Interact. + printf("Accessing global...\n"); + check(call_v_r(global_get), NULL, false); + call_r_v(global_set, host1); + check(call_v_r(global_get), host1, false); + call_r_v(global_set, host2); + check(call_v_r(global_get), host2, false); + call_r_v(global_set, NULL); + check(call_v_r(global_get), NULL, false); + + wasm_global_get(global, &val); + assert(val.kind == WASM_ANYREF); + check(val.of.ref, NULL, false); + val.of.ref = host2; + wasm_global_set(global, &val); + check(call_v_r(global_get), host2, false); + wasm_global_get(global, &val); + assert(val.kind == WASM_ANYREF); + check(val.of.ref, host2, false); + + printf("Accessing table...\n"); + check(call_i_r(table_get, 0), NULL, false); + check(call_i_r(table_get, 1), NULL, false); + call_ir_v(table_set, 0, host1); + call_ir_v(table_set, 1, host2); + check(call_i_r(table_get, 0), host1, false); + check(call_i_r(table_get, 1), host2, false); + call_ir_v(table_set, 0, NULL); + check(call_i_r(table_get, 0), NULL, false); + + check(wasm_table_get(table, 2), NULL, false); + + printf("Accessing function...\n"); + check(call_r_r(func_call, NULL), NULL, false); + check(call_r_r(func_call, host1), host1, false); + check(call_r_r(func_call, host2), host2, false); + + wasm_ref_delete(host1); + wasm_ref_delete(host2); + + wasm_extern_vec_delete(&exports); + + // Shut down. + printf("Shutting down...\n"); + wasm_store_delete(store); + wasm_engine_delete(engine); + + // All done. + printf("Done.\n"); + return 0; +} diff --git a/samples/wasm-c-api/src/hostref.wat b/samples/wasm-c-api/src/hostref.wat new file mode 100644 index 0000000000..9ed43dbcb2 --- /dev/null +++ b/samples/wasm-c-api/src/hostref.wat @@ -0,0 +1,24 @@ +(module + (import "" "f" (func $fun (param externref) (result externref))) + + (global $glob (export "global") (mut externref) (ref.null extern)) + (table $tab (export "table") 10 externref) + + (func (export "global.set") (param $r externref) + (global.set $glob (local.get $r)) + ) + (func (export "global.get") (result externref) + (global.get $glob) + ) + + (func (export "table.set") (param $i i32) (param $r externref) + (table.set $tab (local.get $i) (local.get $r)) + ) + (func (export "table.get") (param $i i32) (result externref) + (table.get $tab (local.get $i)) + ) + + (func (export "func.call") (param $r externref) (result externref) + (call $fun (local.get $r)) + ) +) diff --git a/samples/wasm-c-api/src/memory.c b/samples/wasm-c-api/src/memory.c new file mode 100644 index 0000000000..a6c17654ff --- /dev/null +++ b/samples/wasm-c-api/src/memory.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include + +#include "wasm_c_api.h" + +#define own + + +wasm_memory_t* get_export_memory(const wasm_extern_vec_t* exports, size_t i) { + if (exports->size <= i || !wasm_extern_as_memory(exports->data[i])) { + printf("> Error accessing memory export %zu!\n", i); + exit(1); + } + return wasm_extern_as_memory(exports->data[i]); +} + +wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { + if (exports->size <= i || !wasm_extern_as_func(exports->data[i])) { + printf("> Error accessing function export %zu!\n", i); + exit(1); + } + return wasm_extern_as_func(exports->data[i]); +} + + +void check(bool success) { + if (!success) { + printf("> Error, expected success\n"); + exit(1); + } +} + +void check_call(wasm_func_t* func, int i, wasm_val_t args[], int32_t expected) { + wasm_val_vec_t args_vec; + wasm_val_vec_t results_vec; + if (args) + wasm_val_vec_new(&args_vec, i, args); + wasm_val_vec_new(&results_vec, 1, (wasm_val_t []){ WASM_INIT_VAL }); + if (wasm_func_call(func, args ? &args_vec : NULL, &results_vec) + || results_vec.data[0].of.i32 != expected) { + printf("> Error on result\n"); + exit(1); + } +} + +void check_call0(wasm_func_t* func, int32_t expected) { + check_call(func, 0, NULL, expected); +} + +void check_call1(wasm_func_t* func, int32_t arg, int32_t expected) { + wasm_val_t args[] = { WASM_I32_VAL(arg) }; + check_call(func, 1, args, expected); +} + +void check_call2(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) { + wasm_val_t args[] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) }; + check_call(func, 2, args, expected); +} + +void check_ok(wasm_func_t* func, int i, wasm_val_t args[]) { + wasm_val_vec_t args_vec; + wasm_val_vec_new(&args_vec, i, args); + if (wasm_func_call(func, &args_vec, NULL)) { + printf("> Error on result, expected empty\n"); + exit(1); + } +} + +void check_ok2(wasm_func_t* func, int32_t arg1, int32_t arg2) { + wasm_val_t args[] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) }; + check_ok(func, 2, args); +} + +void check_trap(wasm_func_t* func, int i, wasm_val_t args[]) { + wasm_val_vec_t args_vec, results_vec; + wasm_val_vec_new(&args_vec, i, args); + wasm_val_vec_new(&results_vec, 1, (wasm_val_t []){ WASM_INIT_VAL }); + own wasm_trap_t* trap = wasm_func_call(func, &args_vec, &results_vec); + if (! trap) { + printf("> Error on result, expected trap\n"); + exit(1); + } + wasm_trap_delete(trap); +} + +void check_trap1(wasm_func_t* func, int32_t arg) { + wasm_val_t args[] = { WASM_I32_VAL(arg) }; + check_trap(func, 1, args); +} + +void check_trap2(wasm_func_t* func, int32_t arg1, int32_t arg2) { + wasm_val_t args[] = { WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) }; + check_trap(func, 2, args); +} + + +int main(int argc, const char* argv[]) { + // Initialize. + printf("Initializing...\n"); + wasm_engine_t* engine = wasm_engine_new(); + wasm_store_t* store = wasm_store_new(engine); + + // Load binary. + printf("Loading binary...\n"); +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0 + FILE* file = fopen("memory.aot", "rb"); +#else + FILE* file = fopen("memory.wasm", "rb"); +#endif + if (!file) { + printf("> Error loading module!\n"); + return 1; + } + fseek(file, 0L, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0L, SEEK_SET); + wasm_byte_vec_t binary; + wasm_byte_vec_new_uninitialized(&binary, file_size); + if (fread(binary.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + fclose(file); + return 1; + } + fclose(file); + + // Compile. + printf("Compiling module...\n"); + own wasm_module_t* module = wasm_module_new(store, &binary); + if (!module) { + printf("> Error compiling module!\n"); + return 1; + } + + wasm_byte_vec_delete(&binary); + + // Instantiate. + printf("Instantiating module...\n"); + own wasm_instance_t* instance = + wasm_instance_new_with_args(store, module, NULL, NULL, KILOBYTE(8), 0); + if (!instance) { + printf("> Error instantiating module!\n"); + return 1; + } + + // Extract export. + printf("Extracting exports...\n"); + own wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + size_t i = 0; + wasm_memory_t* memory = get_export_memory(&exports, i++); + wasm_func_t* size_func = get_export_func(&exports, i++); + wasm_func_t* load_func = get_export_func(&exports, i++); + wasm_func_t* store_func = get_export_func(&exports, i++); + + wasm_module_delete(module); + + if (!memory || !wasm_memory_data(memory)) { + printf("> Error getting memory!\n"); + wasm_extern_vec_delete(&exports); + wasm_instance_delete(instance); + wasm_store_delete(store); + wasm_engine_delete(engine); + return 1; + } + + // Try cloning. + own wasm_memory_t* copy = wasm_memory_copy(memory); + assert(wasm_memory_same(memory, copy)); + wasm_memory_delete(copy); + + // Check initial memory. + printf("Checking memory...\n"); + check(wasm_memory_size(memory) >= 2); + check(wasm_memory_data_size(memory) >= 0x20000); + check(wasm_memory_data(memory)[0] == 0); + check(wasm_memory_data(memory)[0x1000] == 1); + check(wasm_memory_data(memory)[0x1003] == 4); + + (void)size_func; + check_call1(load_func, 0, 0); + check_call1(load_func, 0x1000, 1); + check_call1(load_func, 0x1003, 4); + check_call1(load_func, 0x1ffff, 0); + check_trap1(load_func, 0x20000); + + // Mutate memory. + printf("Mutating memory...\n"); + wasm_memory_data(memory)[0x1003] = 5; + check_ok2(store_func, 0x1002, 6); + check_trap2(store_func, 0x20000, 0); + + check(wasm_memory_data(memory)[0x1002] == 6); + check(wasm_memory_data(memory)[0x1003] == 5); + check_call1(load_func, 0x1002, 6); + check_call1(load_func, 0x1003, 5); + + // Grow memory. + // DO NOT SUPPORT + printf("Bypass Growing memory...\n"); + wasm_extern_vec_delete(&exports); + wasm_instance_delete(instance); + + // Create stand-alone memory. + // DO NOT SUPPORT + // TODO(wasm+): Once Wasm allows multiple memories, turn this into import. + printf("Bypass Creating stand-alone memory...\n"); + + // Shut down. + printf("Shutting down...\n"); + wasm_store_delete(store); + wasm_engine_delete(engine); + + // All done. + printf("Done.\n"); + return 0; +} diff --git a/samples/wasm-c-api/src/memory.wat b/samples/wasm-c-api/src/memory.wat new file mode 100644 index 0000000000..4cf43e2c7d --- /dev/null +++ b/samples/wasm-c-api/src/memory.wat @@ -0,0 +1,11 @@ +(module + (memory (export "memory") 2 3) + + (func (export "size") (result i32) (memory.size)) + (func (export "load") (param i32) (result i32) (i32.load8_s (local.get 0))) + (func (export "store") (param i32 i32) + (i32.store8 (local.get 0) (local.get 1)) + ) + + (data (i32.const 0x1000) "\01\02\03\04") +) diff --git a/samples/wasm-c-api/src/multi.c b/samples/wasm-c-api/src/multi.c index 65c9afd433..c4599640a5 100644 --- a/samples/wasm-c-api/src/multi.c +++ b/samples/wasm-c-api/src/multi.c @@ -9,18 +9,18 @@ // A function to be called from Wasm code. own wasm_trap_t* callback( - const wasm_val_t args[], wasm_val_t results[] + const wasm_val_vec_t *args, wasm_val_vec_t *results ) { printf("Calling back...\n> "); printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n", - args[0].of.i32, args[1].of.i64, - args[2].of.i64, args[3].of.i32); + args->data[0].of.i32, args->data[1].of.i64, + args->data[2].of.i64, args->data[3].of.i32); printf("\n"); - wasm_val_copy(&results[0], &args[3]); - wasm_val_copy(&results[1], &args[1]); - wasm_val_copy(&results[2], &args[2]); - wasm_val_copy(&results[3], &args[0]); + wasm_val_copy(&results->data[0], &args->data[3]); + wasm_val_copy(&results->data[1], &args->data[1]); + wasm_val_copy(&results->data[2], &args->data[2]); + wasm_val_copy(&results->data[3], &args->data[0]); return NULL; } @@ -91,9 +91,10 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = { wasm_func_as_extern(callback_func) }; + wasm_extern_vec_t imports; + wasm_extern_vec_new(&imports, 1, (wasm_extern_t *[]) { wasm_func_as_extern(callback_func) }); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -120,13 +121,14 @@ int main(int argc, const char* argv[]) { // Call. printf("Calling export...\n"); - wasm_val_t args[4] = { - WASM_I32_VAL(1), WASM_I64_VAL(2), WASM_I64_VAL(3), WASM_I32_VAL(4) - }; - wasm_val_t results[4] = { - WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL - }; - if (wasm_func_call(run_func, args, results)) { + wasm_val_vec_t args, results; + wasm_val_vec_new(&args, 4, (wasm_val_t []){ + WASM_I32_VAL(1), WASM_I64_VAL(2), WASM_I64_VAL(3), WASM_I32_VAL(4) + }); + wasm_val_vec_new(&results, 4, (wasm_val_t []) { + WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL, WASM_INIT_VAL + }); + if (wasm_func_call(run_func, &args, &results)) { printf("> Error calling function!\n"); return 1; } @@ -136,12 +138,12 @@ int main(int argc, const char* argv[]) { // Print result. printf("Printing result...\n"); printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n", - results[0].of.i32, results[1].of.i64, results[2].of.i64, results[3].of.i32); + results.data[0].of.i32, results.data[1].of.i64, results.data[2].of.i64, results.data[3].of.i32); - assert(results[0].of.i32 == 1); - assert(results[1].of.i64 == 2); - assert(results[2].of.i64 == 3); - assert(results[3].of.i32 == 4); + assert(results.data[0].of.i32 == 1); + assert(results.data[1].of.i64 == 2); + assert(results.data[2].of.i64 == 3); + assert(results.data[3].of.i32 == 4); // Shut down. printf("Shutting down...\n"); diff --git a/samples/wasm-c-api/src/table.c b/samples/wasm-c-api/src/table.c new file mode 100644 index 0000000000..942f281cfc --- /dev/null +++ b/samples/wasm-c-api/src/table.c @@ -0,0 +1,184 @@ +#include +#include +#include +#include + +#include "wasm_c_api.h" + +#define own + +// A function to be called from Wasm code. +own wasm_trap_t* neg_callback( + const wasm_val_vec_t* args, wasm_val_vec_t* results +) { + printf("Calling back...\n"); + results->data[0].kind = WASM_I32; + results->data[0].of.i32 = -args->data[0].of.i32; + return NULL; +} + + +wasm_table_t* get_export_table(const wasm_extern_vec_t* exports, size_t i) { + if (exports->size <= i || !wasm_extern_as_table(exports->data[i])) { + printf("> Error accessing table export %zu!\n", i); + exit(1); + } + return wasm_extern_as_table(exports->data[i]); +} + +wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { + if (exports->size <= i || !wasm_extern_as_func(exports->data[i])) { + printf("> Error accessing function export %zu!\n", i); + exit(1); + } + return wasm_extern_as_func(exports->data[i]); +} + + +void check(bool success) { + if (!success) { + printf("> Error, expected success\n"); + exit(1); + } +} + +void check_table(wasm_table_t* table, int32_t i, bool expect_set) { + own wasm_ref_t* ref = wasm_table_get(table, i); + check((ref != NULL) == expect_set); + if (ref) wasm_ref_delete(ref); +} + +void check_call(wasm_func_t* func, int32_t arg1, int32_t arg2, int32_t expected) { + wasm_val_vec_t args, results; + wasm_val_vec_new(&args, 2, (wasm_val_t []){ WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) }); + wasm_val_vec_new(&results, 1, (wasm_val_t []){ WASM_INIT_VAL }); + if (wasm_func_call(func, &args, &results) || results.data[0].of.i32 != expected) { + printf("> Error on result\n"); + exit(1); + } +} + +void check_trap(wasm_func_t* func, int32_t arg1, int32_t arg2) { + wasm_val_vec_t args, results; + wasm_val_vec_new(&args, 2, (wasm_val_t []){ WASM_I32_VAL(arg1), WASM_I32_VAL(arg2) }); + wasm_val_vec_new(&results, 1, (wasm_val_t []){ WASM_INIT_VAL }); + own wasm_trap_t* trap = wasm_func_call(func, &args, &results); + if (! trap) { + printf("> Error on result, expected trap\n"); + exit(1); + } + wasm_trap_delete(trap); +} + + +int main(int argc, const char* argv[]) { + // Initialize. + printf("Initializing...\n"); + wasm_engine_t* engine = wasm_engine_new(); + wasm_store_t* store = wasm_store_new(engine); + + // Load binary. + printf("Loading binary...\n"); +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0 + FILE* file = fopen("table.aot", "rb"); +#else + FILE* file = fopen("table.wasm", "rb"); +#endif + if (!file) { + printf("> Error loading module!\n"); + return 1; + } + fseek(file, 0L, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0L, SEEK_SET); + wasm_byte_vec_t binary; + wasm_byte_vec_new_uninitialized(&binary, file_size); + if (fread(binary.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + fclose(file); + return 1; + } + fclose(file); + + // Compile. + printf("Compiling module...\n"); + own wasm_module_t* module = wasm_module_new(store, &binary); + if (!module) { + printf("> Error compiling module!\n"); + return 1; + } + + wasm_byte_vec_delete(&binary); + + // Instantiate. + printf("Instantiating module...\n"); + own wasm_instance_t *instance = + wasm_instance_new(store, module, NULL, NULL); + if (!instance) { + printf("> Error instantiating module!\n"); + return 1; + } + + // Extract export. + printf("Extracting exports...\n"); + own wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + size_t i = 0; + wasm_table_t* table = get_export_table(&exports, i++); + wasm_func_t* call_indirect = get_export_func(&exports, i++); + wasm_func_t* f = get_export_func(&exports, i++); + wasm_func_t* g = get_export_func(&exports, i++); + + wasm_module_delete(module); + + // Create external function. + printf("Creating callback...\n"); + own wasm_functype_t* neg_type = wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32()); + + wasm_functype_delete(neg_type); + + // Try cloning. + own wasm_table_t* copy = wasm_table_copy(table); + assert(wasm_table_same(table, copy)); + wasm_table_delete(copy); + + // Check initial table. + printf("Checking table...\n"); + check(wasm_table_size(table) == 2); + check_table(table, 0, false); + check_table(table, 1, true); + check_trap(call_indirect, 0, 0); + check_call(call_indirect, 7, 1, 7); + check_trap(call_indirect, 0, 2); + + // Mutate table. + printf("Mutating table...\n"); + check(wasm_table_set(table, 0, wasm_func_as_ref(g))); + check(wasm_table_set(table, 1, NULL)); + check(! wasm_table_set(table, 2, wasm_func_as_ref(f))); + check_table(table, 0, true); + check_table(table, 1, false); + check_call(call_indirect, 7, 0, 666); + check_trap(call_indirect, 0, 1); + check_trap(call_indirect, 0, 2); + + // Grow table. + // DO NOT SUPPORT + printf("Bypass Growing table...\n"); + wasm_extern_vec_delete(&exports); + wasm_instance_delete(instance); + + // Create stand-alone table. + // DO NOT SUPPORT + // TODO(wasm+): Once Wasm allows multiple tables, turn this into import. + printf("Bypass Creating stand-alone table...\n"); + + // Shut down. + printf("Shutting down...\n"); + wasm_store_delete(store); + wasm_engine_delete(engine); + + // All done. + printf("Done.\n"); + return 0; +} diff --git a/samples/wasm-c-api/src/table.wat b/samples/wasm-c-api/src/table.wat new file mode 100644 index 0000000000..d3e3a945aa --- /dev/null +++ b/samples/wasm-c-api/src/table.wat @@ -0,0 +1,12 @@ +(module + (table (export "table") 2 10 funcref) + + (func (export "call_indirect") (param i32 i32) (result i32) + (call_indirect (param i32) (result i32) (local.get 0) (local.get 1)) + ) + + (func $f (export "f") (param i32) (result i32) (local.get 0)) + (func (export "g") (param i32) (result i32) (i32.const 666)) + + (elem (i32.const 1) $f) +) diff --git a/samples/wasm-c-api/src/trap.c b/samples/wasm-c-api/src/trap.c index e121419036..16dc2e0c34 100644 --- a/samples/wasm-c-api/src/trap.c +++ b/samples/wasm-c-api/src/trap.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* fail_callback( - void* env, const wasm_val_t args[], wasm_val_t results[] + void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); own wasm_name_t message; @@ -19,6 +19,17 @@ own wasm_trap_t* fail_callback( return trap; } + +void print_frame(wasm_frame_t* frame) { + printf("> %p @ 0x%zx = %"PRIu32".0x%zx\n", + wasm_frame_instance(frame), + wasm_frame_module_offset(frame), + wasm_frame_func_index(frame), + wasm_frame_func_offset(frame) + ); +} + + int main(int argc, const char* argv[]) { // Initialize. printf("Initializing...\n"); @@ -69,9 +80,10 @@ int main(int argc, const char* argv[]) { // Instantiate. printf("Instantiating module...\n"); - const wasm_extern_t* imports[] = { wasm_func_as_extern(fail_func) }; + wasm_extern_vec_t imports; + wasm_extern_vec_new(&imports, 1, (wasm_extern_t* []) { wasm_func_as_extern(fail_func) }); own wasm_instance_t* instance = - wasm_instance_new(store, module, imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -93,7 +105,6 @@ int main(int argc, const char* argv[]) { // Call. for (int i = 0; i < 2; ++i) { - char buf[32]; const wasm_func_t* func = wasm_extern_as_func(exports.data[i]); if (func == NULL) { printf("> Error accessing export!\n"); @@ -101,8 +112,10 @@ int main(int argc, const char* argv[]) { } printf("Calling export %d...\n", i); - wasm_val_t results[1]; \ - own wasm_trap_t* trap = wasm_func_call(func, NULL, results); + + wasm_val_vec_t results; + wasm_val_vec_new_uninitialized(&results, 1); + own wasm_trap_t* trap = wasm_func_call(func, NULL, &results); if (!trap) { printf("> Error calling function, expected trap!\n"); return 1; @@ -111,9 +124,29 @@ int main(int argc, const char* argv[]) { printf("Printing message...\n"); own wasm_name_t message; wasm_trap_message(trap, &message); - snprintf(buf, sizeof(buf), "> %%.%us\n", (unsigned)message.size); - printf(buf, message.data); + printf("> %s\n", message.data); + + printf("Printing origin...\n"); + own wasm_frame_t* frame = wasm_trap_origin(trap); + if (frame) { + print_frame(frame); + wasm_frame_delete(frame); + } else { + printf("> Empty origin.\n"); + } + + printf("Printing trace...\n"); + own wasm_frame_vec_t trace; + wasm_trap_trace(trap, &trace); + if (trace.size > 0) { + for (size_t i = 0; i < trace.size; ++i) { + print_frame(trace.data[i]); + } + } else { + printf("> Empty trace.\n"); + } + wasm_frame_vec_delete(&trace); wasm_trap_delete(trap); wasm_name_delete(&message); } diff --git a/samples/workload/README.md b/samples/workload/README.md index 624126cbcc..dd94e05ca0 100644 --- a/samples/workload/README.md +++ b/samples/workload/README.md @@ -1,5 +1,5 @@ All workloads have similar requirment of software dependencies, including -**wasi-sdk**, **emsdk**, **wabt** and **binaryen** +**emsdk**, **wabt** and **binaryen** > There might be slight differences when using MacOS and other Linux distro than Ubuntu. This document only target Ubuntu 18.04 as example. @@ -10,17 +10,36 @@ use [preparation.sh](./preparation.sh) to install all dependencies before compil for details, the script includes below steps: -- **wasi-sdk**. Install - [latest release](https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz) - to */opt/wasi-sdk* - - **wabt**. Install - [latest release](https://github.com/WebAssembly/wabt/releases/download/1.0.20/wabt-1.0.20-ubuntu.tar.gz) - to */opt/wabt* or */opt/wabt-1.0.20* + [latest release](https://github.com/WebAssembly/wabt/releases/download/1.0.23/wabt-1.0.23-ubuntu.tar.gz) + to */opt/wabt* + +``` bash +$ wget https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/${WABT_FILE} +$ tar zxf ${WABT_FILE} -C /opt +$ ln -sf /opt/wabt-${WABT_VER} /opt/wabt +``` - **emsdk**. Refer to [the guide](https://emscripten.org/docs/getting_started/downloads.html). Don't forget to activate - emsdk and set up environment variables. Verify it with `echo ${EMSDK}`. + emsdk and set up environment variables. Verify it with `echo ${EMSDK}`. Please be sure to install and activate the building + of 2.0.26 + +``` bash +$ cd /opt +$ git clone https://github.com/emscripten-core/emsdk.git +$ cd emsdk +$ git pull +$ ./emsdk install 2.0.26 +$ ./emsdk activate 2.0.26 +$ echo "source /opt/emsdk/emsdk_env.sh" >> "${HOME}"/.bashrc +``` - **binaryen**. Install - [latest release](https://github.com/WebAssembly/binaryen/releases/download/version_97/binaryen-version_97-x86_64-linux.tar.gz) - to */opt/binaryen* or */opt/binaryen-version_97* + [latest release](https://github.com/WebAssembly/binaryen/releases/download/version_101/binaryen-version_101-x86_64-linux.tar.gz) + to */opt/binaryen* + +``` bash +$ wget https://github.com/WebAssembly/binaryen/releases/download/${BINARYEN_VER}/${BINARYEN_FILE} +$ tar zxf ${BINARYEN_FILE} -C /opt +$ ln -sf /opt/binaryen-${BINARYEN_VER} /opt/binaryen +``` diff --git a/samples/workload/XNNPACK/CMakeLists.txt b/samples/workload/XNNPACK/CMakeLists.txt index 3e00f20f59..054d326997 100644 --- a/samples/workload/XNNPACK/CMakeLists.txt +++ b/samples/workload/XNNPACK/CMakeLists.txt @@ -6,15 +6,6 @@ cmake_minimum_required (VERSION 3.0) project(xnnpack_wasm) ################ EMCC ################ -if(NOT DEFINED ENV{EMSDK}) - message(SEND_ERROR - "can not find emsdk. " - "please refer to https://emscripten.org/docs/getting_started/downloads.html " - "and install it, " - "or active emsdk by 'source ./emsdk_env.sh'" - ) -endif() - include(ExternalProject) ExternalProject_Add(xnnpack @@ -24,67 +15,78 @@ ExternalProject_Add(xnnpack GIT_PROGRESS ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack UPDATE_COMMAND git checkout . + && cmake -E copy ${CMAKE_CURRENT_SOURCE_DIR}/benchmark.patch ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/third_party && git apply ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack.patch CONFIGURE_COMMAND "" + # grep xnnpack_benchmark -A 1 BUILD.bazel \ + # | grep "name =" \ + # | awk '{print $3}' \ + # | sed -e 's/\"//g' -e 's/,//g' -e 's/^/\/\/:/g' BUILD_COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack && bazel --output_user_root=build_user_output build -c opt --config=wasm - //:qs8_gemm_bench - //:qs8_requantization_bench - //:qu8_gemm_bench - //:qu8_requantization_bench - //:f16_igemm_bench - //:f16_gemm_bench - //:f16_spmm_bench - //:f32_igemm_bench - //:f16_relu_bench - //:f32_conv_hwc_bench - //:f32_conv_hwc2chw_bench - //:f16_dwconv_bench - //:f32_dwconv_bench - //:f32_dwconv2d_chw_bench - //:f32_gemm_bench - //:f32_hswish_bench - //:f32_raddexpminusmax_bench - //:f32_raddextexp_bench - //:f32_raddstoreexpminusmax_bench - //:f32_relu_bench - //:f32_rmax_bench - //:f32_sigmoid_bench - //:f32_spmm_bench - //:f32_softmax_bench - //:f32_velu_bench - //:f32_vscaleexpminusmax_bench - //:f32_vscaleextexp_bench - //:f32_vsqrt_bench - //:f32_im2col_gemm_bench - //:rounding_bench - //:average_pooling_bench - //:bankers_rounding_bench - //:ceiling_bench - //:channel_shuffle_bench - //:convolution_bench - //:deconvolution_bench - //:elu_bench - //:floor_bench - //:global_average_pooling_bench - //:hardswish_bench - //:max_pooling_bench - //:sigmoid_bench - //:prelu_bench - //:softmax_bench - //:square_root_bench - //:truncation_bench - //:f32_dwconv_e2e_bench - //:f32_gemm_e2e_bench - //:qs8_gemm_e2e_bench - //:end2end_bench - //:f32_exp_ulp_eval - //:f32_expminus_ulp_eval - //:f32_expm1minus_ulp_eval - //:f32_extexp_ulp_eval - //:f32_sigmoid_ulp_eval - //:f32_sqrt_ulp_eval - #--sandbox_debug + //:qs8_dwconv_bench.wasm + //:qs8_gemm_bench.wasm + //:qs8_requantization_bench.wasm + //:qs8_vadd_bench.wasm + //:qs8_vaddc_bench.wasm + //:qu8_gemm_bench.wasm + //:qu8_requantization_bench.wasm + //:qu8_vadd_bench.wasm + //:qu8_vaddc_bench.wasm + //:f16_igemm_bench.wasm + //:f16_gemm_bench.wasm + //:f16_spmm_bench.wasm + //:f16_vrelu_bench.wasm + //:f32_igemm_bench.wasm + //:f32_conv_hwc_bench.wasm + //:f32_conv_hwc2chw_bench.wasm + //:f16_dwconv_bench.wasm + //:f32_dwconv_bench.wasm + //:f32_dwconv2d_chw_bench.wasm + //:f32_gemm_bench.wasm + //:f32_raddexpminusmax_bench.wasm + //:f32_raddextexp_bench.wasm + //:f32_raddstoreexpminusmax_bench.wasm + //:f32_rmax_bench.wasm + //:f32_spmm_bench.wasm + //:f32_softmax_bench.wasm + //:f32_velu_bench.wasm + //:f32_vhswish_bench.wasm + //:f32_vrelu_bench.wasm + //:f32_vscaleexpminusmax_bench.wasm + //:f32_vscaleextexp_bench.wasm + //:f32_vsigmoid_bench.wasm + //:f32_vsqrt_bench.wasm + //:f32_im2col_gemm_bench.wasm + //:rounding_bench.wasm + //:average_pooling_bench.wasm + //:bankers_rounding_bench.wasm + //:ceiling_bench.wasm + //:channel_shuffle_bench.wasm + //:convolution_bench.wasm + //:deconvolution_bench.wasm + //:elu_bench.wasm + //:floor_bench.wasm + //:global_average_pooling_bench.wasm + //:hardswish_bench.wasm + //:max_pooling_bench.wasm + //:sigmoid_bench.wasm + //:prelu_bench.wasm + //:softmax_bench.wasm + //:square_root_bench.wasm + //:truncation_bench.wasm + //:f32_dwconv_e2e_bench.wasm + //:f32_gemm_e2e_bench.wasm + //:qs8_dwconv_e2e_bench.wasm + //:qs8_gemm_e2e_bench.wasm + //:qu8_dwconv_e2e_bench.wasm + //:end2end_bench.wasm + //:f32_exp_ulp_eval.wasm + //:f32_expminus_ulp_eval.wasm + //:f32_expm1minus_ulp_eval.wasm + //:f32_extexp_ulp_eval.wasm + //:f32_sigmoid_ulp_eval.wasm + //:f32_sqrt_ulp_eval.wasm INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/bazel-out/wasm-opt/bin/ ${CMAKE_CURRENT_SOURCE_DIR}/build/wasm-opt diff --git a/samples/workload/XNNPACK/README.md b/samples/workload/XNNPACK/README.md index ffbe236107..f6a207293b 100644 --- a/samples/workload/XNNPACK/README.md +++ b/samples/workload/XNNPACK/README.md @@ -5,20 +5,7 @@ This sample demonstrates how to build [XNNPACK](https://github.com/google/XNNPAC ## Installation toolchains -- **bazel**. Please install bazel from [latest release](https://github.com/bazelbuild/bazel/releases) - -- **emsdk**. Please install [emsdk](https://github.com/emscripten-core/emsdk) to /opt/emsdk: -```bash -cd /opt -git clone https://github.com/emscripten-core/emsdk.git -cd emsdk -./emsdk install latest -./emsdk activate latest -``` -And set up ensdk environment: -```bash -source /opt/emsdk/emsdk_env.sh -``` +please refer to [installation instructions](../README.md). ## Build XNNPACK diff --git a/samples/workload/XNNPACK/benchmark.patch b/samples/workload/XNNPACK/benchmark.patch new file mode 100644 index 0000000000..713b476d26 --- /dev/null +++ b/samples/workload/XNNPACK/benchmark.patch @@ -0,0 +1,14 @@ +diff --git include/benchmark/benchmark.h include/benchmark/benchmark.h +index 9b54802..baa5938 100755 +--- include/benchmark/benchmark.h ++++ include/benchmark/benchmark.h +@@ -364,7 +364,9 @@ template + inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { + internal::UseCharPointer(&reinterpret_cast(value)); + } ++ + // FIXME Add ClobberMemory() for non-gnu and non-msvc compilers ++inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { } + #endif + + // This class is used for user-defined counters. diff --git a/samples/workload/XNNPACK/build_workload.sh b/samples/workload/XNNPACK/build_workload.sh new file mode 120000 index 0000000000..a31afa9282 --- /dev/null +++ b/samples/workload/XNNPACK/build_workload.sh @@ -0,0 +1 @@ +../docker/build_workload.sh \ No newline at end of file diff --git a/samples/workload/XNNPACK/docker_build.sh b/samples/workload/XNNPACK/docker_build.sh deleted file mode 120000 index 3c6de9bca7..0000000000 --- a/samples/workload/XNNPACK/docker_build.sh +++ /dev/null @@ -1 +0,0 @@ -../docker/docker_build.sh \ No newline at end of file diff --git a/samples/workload/XNNPACK/xnnpack.patch b/samples/workload/XNNPACK/xnnpack.patch index 17dafbf2e2..cab32b7ff2 100644 --- a/samples/workload/XNNPACK/xnnpack.patch +++ b/samples/workload/XNNPACK/xnnpack.patch @@ -1,8 +1,8 @@ diff --git a/.bazelrc b/.bazelrc -index ec740f38..2c193244 100644 +index ec740f38..29f9d56e 100644 --- a/.bazelrc +++ b/.bazelrc -@@ -49,4 +49,10 @@ build:ios_fat --watchos_cpus=armv7k +@@ -49,4 +49,9 @@ build:ios_fat --watchos_cpus=armv7k build:macos --apple_platform_type=macos build:macos_arm64 --config=macos @@ -10,46 +10,31 @@ index ec740f38..2c193244 100644 \ No newline at end of file +build:macos_arm64 --cpu=darwin_arm64 + -+build:wasm --copt=-msimd128 +build:wasm --cpu=wasm ++build:wasm --copt=-msimd128 +build:wasm --crosstool_top=@emsdk//emscripten_toolchain:everything +build:wasm --host_crosstool_top=@bazel_tools//tools/cpp:toolchain -+ -diff --git a/BUILD.bazel b/BUILD.bazel -index ae4108bc..1c11fac2 100644 ---- a/BUILD.bazel -+++ b/BUILD.bazel -@@ -5038,7 +5038,6 @@ xnnpack_benchmark( - srcs = [ - "bench/f16-igemm.cc", - "bench/conv.h", -- "bench/google/conv.h", - "src/xnnpack/AlignedAllocator.h", - ] + MICROKERNEL_BENCHMARK_HDRS, - deps = MICROKERNEL_BENCHMARK_DEPS + [ -@@ -5120,7 +5119,6 @@ xnnpack_benchmark( - srcs = [ - "bench/f16-dwconv.cc", - "bench/dwconv.h", -- "bench/google/dwconv.h", - "src/xnnpack/AlignedAllocator.h", - ] + MICROKERNEL_BENCHMARK_HDRS, - deps = MICROKERNEL_BENCHMARK_DEPS + [ diff --git a/WORKSPACE b/WORKSPACE -index 4fa1aa2f..86040d42 100644 +index c58e76b6..30934678 100644 --- a/WORKSPACE +++ b/WORKSPACE -@@ -89,3 +89,18 @@ android_ndk_repository(name = "androidndk") +@@ -21,6 +21,7 @@ http_archive( + name = "com_google_benchmark", + strip_prefix = "benchmark-master", + urls = ["https://github.com/google/benchmark/archive/master.zip"], ++ patches = ["@//third_party:benchmark.patch"], + ) + + # FP16 library, used for half-precision conversions +@@ -84,6 +85,19 @@ http_archive( + ], + ) - # Android SDK location and API is auto-detected from $ANDROID_HOME environment variable - android_sdk_repository(name = "androidsdk") -+ -+# emscripten library +http_archive( -+ name = "emsdk", -+ strip_prefix = "emsdk-c1589b55641787d55d53e883852035beea9aec3f/bazel", -+ url = "https://github.com/emscripten-core/emsdk/archive/c1589b55641787d55d53e883852035beea9aec3f.tar.gz", -+ sha256 = "7a58a9996b113d3e0675df30b5f17e28aa47de2e684a844f05394fe2f6f12e8e", ++ name = "emsdk", ++ strip_prefix = "emsdk-2.0.26/bazel", ++ url = "https://github.com/emscripten-core/emsdk/archive/refs/tags/2.0.26.tar.gz", ++ sha256 = "79e7166aa8eaae6e52cef1363b2d8db795d03684846066bc51f9dcf905dd58ad", +) + +load("@emsdk//:deps.bzl", emsdk_deps = "deps") @@ -58,72 +43,50 @@ index 4fa1aa2f..86040d42 100644 +load("@emsdk//:emscripten_deps.bzl", emsdk_emscripten_deps = "emscripten_deps") +emsdk_emscripten_deps() + + # Android NDK location and version is auto-detected from $ANDROID_NDK_HOME environment variable + android_ndk_repository(name = "androidndk") + diff --git a/build_defs.bzl b/build_defs.bzl -index 10345032..0e926fca 100644 +index 2442bed1..b860dfef 100644 --- a/build_defs.bzl +++ b/build_defs.bzl -@@ -1,6 +1,6 @@ - """Build definitions and rules for XNNPACK.""" - --load(":emscripten.bzl", "xnnpack_emscripten_benchmark_linkopts", "xnnpack_emscripten_deps", "xnnpack_emscripten_minimal_linkopts", "xnnpack_emscripten_test_linkopts") -+load(":emscripten.bzl", "xnnpack_emscripten_benchmark_linkopts", "xnnpack_emscripten_deps", "xnnpack_emscripten_minimal_linkopts", "xnnpack_emscripten_test_linkopts", "xnnpack_emscripten_benchmark_copts") - - def xnnpack_visibility(): - """Visibility of :XNNPACK target. -@@ -424,10 +424,15 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): - ":windows_x86_64_mingw": ["-Wno-unused-function"], - ":windows_x86_64_msys": ["-Wno-unused-function"], - ":windows_x86_64": [], -+ ":emscripten": xnnpack_emscripten_benchmark_copts(), -+ ":emscripten_wasm": xnnpack_emscripten_benchmark_copts(), -+ ":emscripten_wasmsimd": xnnpack_emscripten_benchmark_copts(), - "//conditions:default": ["-Wno-unused-function"], - }) + copts, - linkopts = select({ - ":emscripten": xnnpack_emscripten_benchmark_linkopts(), -+ ":emscripten_wasm": xnnpack_emscripten_benchmark_linkopts(), -+ ":emscripten_wasmsimd": xnnpack_emscripten_benchmark_linkopts(), - ":windows_x86_64_mingw": ["-lshlwapi"], - ":windows_x86_64_msys": ["-lshlwapi"], - "//conditions:default": [], +@@ -414,7 +414,7 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): + explicitly specified. + """ + native.cc_binary( +- name = name, ++ name = name + ".wasm", + srcs = srcs, + copts = xnnpack_std_cxxopts() + [ + "-Iinclude", diff --git a/emscripten.bzl b/emscripten.bzl -index 0a0caedf..d28afa30 100644 +index 130d5f16..2696ad54 100644 --- a/emscripten.bzl +++ b/emscripten.bzl -@@ -23,15 +23,28 @@ def xnnpack_emscripten_benchmark_linkopts(): +@@ -25,12 +25,19 @@ def xnnpack_emscripten_benchmark_linkopts(): """Emscripten-specific linkopts for benchmarks.""" return [ "-s ASSERTIONS=1", +- "-s ENVIRONMENT=node,shell,web", - "-s ERROR_ON_UNDEFINED_SYMBOLS=1", - "-s EXIT_RUNTIME=1", -- "-s ALLOW_MEMORY_GROWTH=1", + "-s ERROR_ON_UNDEFINED_SYMBOLS=0", -+ "-s ALLOW_MEMORY_GROWTH=0", - "-s TOTAL_MEMORY=436207616", # 416M + "-s ALLOW_MEMORY_GROWTH=1", + "-s TOTAL_MEMORY=445644800", # 425M - "--pre-js $(location :preamble.js.lds)", + "-s USE_PTHREADS=0", + "-s STANDALONE_WASM=1", + "-Wno-unused", ++ "-Wno-unused-variable", ++ "-Wno-unused-command-line-argument", + "-Wl,--export=__heap_base", + "-Wl,--export=__data_end", + "-Wl,--export=malloc", + "-Wl,--export=free", ++ "--oformat=wasm", ] def xnnpack_emscripten_deps(): - """Emscripten-specific dependencies for unit tests and benchmarks.""" -+ return [] -+ -+def xnnpack_emscripten_benchmark_copts(): - return [ -- ":preamble.js.lds", -+ "-s ASSERTIONS=1", -+ "-s ERROR_ON_UNDEFINED_SYMBOLS=0", -+ "-s ALLOW_MEMORY_GROWTH=0", -+ "-s USE_PTHREADS=0", -+ "-s STANDALONE_WASM=1", -+ "-Wno-unused", - ] diff --git a/third_party/cpuinfo.BUILD b/third_party/cpuinfo.BUILD index 128d683e..f6c287c4 100644 --- a/third_party/cpuinfo.BUILD diff --git a/samples/workload/bwa/CMakeLists.bwa_wasm.txt b/samples/workload/bwa/CMakeLists.bwa_wasm.txt index f315bf9c23..c68b942f1a 100644 --- a/samples/workload/bwa/CMakeLists.bwa_wasm.txt +++ b/samples/workload/bwa/CMakeLists.bwa_wasm.txt @@ -5,6 +5,8 @@ cmake_minimum_required (VERSION 3.0) project(bwa_wasm C) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/preparation.cmake) + ################ LIBZ ################ set(LIBZ_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../libz) add_library(z_wasm STATIC @@ -86,16 +88,15 @@ set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME bwa.wasm) target_include_directories(${PROJECT_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/../include - ${CMAKE_CURRENT_SOURCE_DIR}/../include/SSE - ${CMAKE_CURRENT_SOURCE_DIR}/../include/pthread + ${WASI_SDK_HOME}/share/wasi-sysroot/include/libc/musl + ${WASI_SDK_HOME}/share/wasi-sysroot/include/sse ) target_compile_definitions(${PROJECT_NAME} PRIVATE USE_MALLOC_WRAPPERS __SSE__ __SSE2__ __SSE4_1__ - _WASI_EMULATED_MMAN _WASI_EMULATED_SIGNAL + _WASI_EMULATED_MMAN _WASI_EMULATED_SIGNAL _WASI_EMULATED_PROCESS_CLOCKS ) target_compile_options(${PROJECT_NAME} @@ -112,16 +113,7 @@ target_link_options(${PROJECT_NAME} LINKER:-z,stack-size=1048576 ) -target_link_libraries(${PROJECT_NAME} z_wasm) - -find_program(WASM_OPT - NAMES wasm-opt - PATHS /opt/binaryen-version_97/bin /opt/binaryen/bin -) - -if (NOT WASM_OPT) - message(WARNING "can not find wasm-opt and will not optimize any wasm module") -endif() +target_link_libraries(${PROJECT_NAME} z_wasm wasi-emulated-process-clocks) add_custom_target(bwa_wasm_opt ALL COMMAND diff --git a/samples/workload/bwa/CMakeLists.txt b/samples/workload/bwa/CMakeLists.txt index 489c3e7d6b..9ea6704b34 100644 --- a/samples/workload/bwa/CMakeLists.txt +++ b/samples/workload/bwa/CMakeLists.txt @@ -1,127 +1,46 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required (VERSION 2.8...3.16) project(bwa_wasm) -################ WASI-SDK ################ -find_path(WASI_SDK_HOME - NAMES wasi-sdk - PATHS /opt/ - REQUIRED -) - -if (NOT WASI_SDK_HOME) - message(FATAL_ERROR - "can not find wasi-sdk. " - "please download it from " - "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz " - "and install it under /opt/wasi-sdk" - ) -endif() - -# -# check clang version -execute_process(COMMAND - ${WASI_SDK_HOME}/wasi-sdk/bin/clang --version - OUTPUT_VARIABLE clang_full_version_string -) -string(REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" - CLANG_VERSION_STRING ${clang_full_version_string} -) -message("cur clang version is ${CLANG_VERSION_STRING}") -if(CLANG_VERSION_STRING VERSION_LESS 11.0) - message(FATAL_ERROR - "please install latest wai-sdk to get a clang-11 at least" - ) -endif() - -################ EMCC ################ -if(NOT DEFINED ENV{EMSDK}) - message(FATAL_ERROR - "can not find emsdk. " - "please refer to https://emscripten.org/docs/getting_started/downloads.html " - "and install it, " - "or active emsdk by 'source ./emsdk_env.sh'" - ) -endif() - -################ BINARYEN ################ -find_program(WASM_OPT - NAMES wasm-opt - PATHS /opt/binaryen-version_97/bin /opt/binaryen/bin -) - -if (NOT WASM_OPT) - message(FATAL_ERROR - "can not find wasm-opt. " - "please download it from " - "https://github.com/WebAssembly/binaryen/releases/download/version_97/binaryen-version_97-x86_64-linux.tar.gz " - "and install it under /opt" - ) -endif() +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/preparation.cmake) ####################################### include(ExternalProject) -################ HEADERS ################ -ExternalProject_Add(headers_from_emcc - PREFIX headers - SOURCE_DIR "$ENV{EM_CACHE}/sysroot/include" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND mkdir -p ${CMAKE_CURRENT_SOURCE_DIR}/include/SSE - && ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/sys - && ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/emscripten - # copy emscripten SSE header files - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/compat/immintrin.h ${CMAKE_CURRENT_SOURCE_DIR}/include/SSE/ - # SSE - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/compat/xmmintrin.h ${CMAKE_CURRENT_SOURCE_DIR}/include/SSE/ - # SSE2 - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/compat/emmintrin.h ${CMAKE_CURRENT_SOURCE_DIR}/include/SSE/ - # SSE4.1 - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/compat/smmintrin.h ${CMAKE_CURRENT_SOURCE_DIR}/include/SSE/ - # a fake empty header to aovid further depenency - && ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_SOURCE_DIR}/include/emscripten/emscripten.h - # copy emscripten pthread related header files - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/pthread.h ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/ - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/signal.h ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/ - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/netdb.h ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/ - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/sys/wait.h ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/sys/ - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/sys/socket.h ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/sys/ -) - ################ libz ################ ExternalProject_Add(libz_src - PREFIX libz GIT_REPOSITORY https://github.com/madler/zlib.git GIT_TAG master GIT_PROGRESS ON GIT_SHALLOW ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libz + UPDATE_COMMAND "" + PATCH_COMMAND "" CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" ) ################ bwa ################ ExternalProject_Add(bwa - PREFIX bwa GIT_REPOSITORY https://github.com/lh3/bwa.git GIT_TAG master GIT_PROGRESS ON GIT_SHALLOW ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bwa - DEPENDS libz_src headers_from_emcc - UPDATE_COMMAND git clean -fd && git checkout -- * + DEPENDS libz_src + UPDATE_COMMAND git clean -ffdx && git checkout -- * && ${CMAKE_COMMAND} -E echo "Copying pre-installed CMakeLists.txt" && ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.bwa_wasm.txt CMakeLists.txt && git apply ../bwa.patch CONFIGURE_COMMAND ${CMAKE_COMMAND} - -DWASI_SDK_PREFIX=${WASI_SDK_HOME}/wasi-sdk - -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_HOME}/wasi-sdk/share/cmake/wasi-sdk.cmake - ${CMAKE_CURRENT_SOURCE_DIR}/bwa + -DWASI_SDK_PREFIX=${WASI_SDK_HOME} + -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_HOME}/share/cmake/wasi-sdk.cmake + -DCMAKE_SYSROOT=${WASI_SDK_HOME}/share/wasi-sysroot + ${CMAKE_CURRENT_SOURCE_DIR}/bwa BUILD_COMMAND make bwa_wasm_opt INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ./bwa.opt.wasm ${CMAKE_CURRENT_SOURCE_DIR}/build/bwa.wasm ) diff --git a/samples/workload/bwa/build_workload.sh b/samples/workload/bwa/build_workload.sh new file mode 120000 index 0000000000..a31afa9282 --- /dev/null +++ b/samples/workload/bwa/build_workload.sh @@ -0,0 +1 @@ +../docker/build_workload.sh \ No newline at end of file diff --git a/samples/workload/bwa/docker_build.sh b/samples/workload/bwa/docker_build.sh deleted file mode 120000 index 3c6de9bca7..0000000000 --- a/samples/workload/bwa/docker_build.sh +++ /dev/null @@ -1 +0,0 @@ -../docker/docker_build.sh \ No newline at end of file diff --git a/samples/workload/cmake/preparation.cmake b/samples/workload/cmake/preparation.cmake new file mode 100644 index 0000000000..326943c838 --- /dev/null +++ b/samples/workload/cmake/preparation.cmake @@ -0,0 +1,49 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +####################################### +include(ExternalProject) + +file(REAL_PATH ../../.. WAMR_ROOT + BASE_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) + +find_path(WASI_SDK_PARENT + name wasi-sdk + PATHS ${WAMR_ROOT}/test-tools/ + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH +) + +if(NOT WASI_SDK_PARENT) + message(FATAL_ERROR + "can not find 'wasi-sdk' under ${WAMR_ROOT}/test-tools, " + "please run ${WAMR_ROOT}/test-tools/build-wasi-sdk/build_wasi_sdk.py " + "to build wasi-sdk and try again" + ) +endif() + +set(WASI_SDK_HOME ${WASI_SDK_PARENT}/wasi-sdk) +message(CHECK_START "Detecting WASI-SDK at ${WASI_SDK_HOME}") +if(EXISTS "${WASI_SDK_HOME}/share/cmake/wasi-sdk.cmake") + message(CHECK_PASS "found") +else() + message(CHECK_FAIL "not found") +endif() + +################ BINARYEN ################ +find_program(WASM_OPT + NAMES wasm-opt + PATHS /opt/binaryen-version_101/bin /opt/binaryen/bin + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH +) + +if(NOT WASM_OPT) + message(FATAL_ERROR + "can not find wasm-opt. " + "please download it from " + "https://github.com/WebAssembly/binaryen/releases/download/version_101/binaryen-version_101-x86_64-linux.tar.gz " + "and install it under /opt" + ) +endif() diff --git a/samples/workload/docker/.gitignore b/samples/workload/docker/.gitignore deleted file mode 100644 index 9db0a28078..0000000000 --- a/samples/workload/docker/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build_scripts diff --git a/samples/workload/docker/Dockerfile b/samples/workload/docker/Dockerfile deleted file mode 100644 index 9906920dd7..0000000000 --- a/samples/workload/docker/Dockerfile +++ /dev/null @@ -1,99 +0,0 @@ -FROM ubuntu:18.04 as builder - -RUN apt update \ - && apt install -y lsb-release software-properties-common build-essential \ - wget curl git tree zip unzip - -# -# install clang and llvm -# COPY llvm.sh /tmp -# RUN apt update \ -# && apt install -y lsb-release wget software-properties-common build-essential \ -# && cd /tmp \ -# && chmod a+x llvm.sh \ -# && ./llvm.sh 11 - -ARG WASI_SDK_VER=12 -ARG WABT_VER=1.0.20 -ARG CMAKE_VER=3.16.2 -ARG BINARYEN_VER=version_97 - -# -# install wasi-sdk -ARG WASI_SDK_FILE="wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz" -COPY ${WASI_SDK_FILE} /opt -RUN cd /opt \ - && tar zxf ${WASI_SDK_FILE} \ - && rm ${WASI_SDK_FILE} \ - && ln -sf /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk - -# -# install wabt -ARG WABT_FILE="wabt-${WABT_VER}-ubuntu.tar.gz" -COPY ${WABT_FILE} /opt -RUN cd /opt \ - && tar zxf ${WABT_FILE} \ - && rm ${WABT_FILE} \ - && ln -sf /opt/wabt-${WABT_VER} /opt/wabt - -# -# install cmake -ARG CMAKE_FILE="cmake-${CMAKE_VER}-Linux-x86_64.sh" -COPY ${CMAKE_FILE} /tmp -RUN cd /tmp \ - && chmod a+x ${CMAKE_FILE} \ - && mkdir /opt/cmake \ - && ./${CMAKE_FILE} --prefix=/opt/cmake --skip-license \ - && ln -sf /opt/cmake/bin/cmake /usr/local/bin/cmake - -# -# install emsdk -RUN cd /opt \ - && git clone https://github.com/emscripten-core/emsdk.git \ - && cd emsdk \ - && git pull \ - && ./emsdk install latest \ - && ./emsdk activate latest \ - && echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc - -# -# install binaryen -ARG BINARYEN_FILE="binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz" -COPY ${BINARYEN_FILE} /opt -RUN cd /opt \ - && tar zxf ${BINARYEN_FILE} \ - && rm ${BINARYEN_FILE} \ - && ln -sf /opt/binaryen-${BINARYEN_VER} /opt/binaryen - -# -# install bazelisk -ARG BAZEL_FILE="bazelisk-linux-amd64" -COPY ${BAZEL_FILE} /opt/bazelisk/bin/bazelisk -RUN cd /opt/bazelisk/bin/ \ - && chmod a+x bazelisk \ - && ln -sf /opt/bazelisk/bin/bazelisk /usr/local/bin/bazel - -# -# Clean up -RUN apt-get autoremove -y \ - && apt-get clean -y \ - && rm -rf /var/lib/apt/lists/* \ - && rm -rf /tmp/* - -VOLUME /data - -# -# -RUN touch /build.sh \ - && echo "\ -#!/bin/bash \n\ -if [[ -d /data/project/build ]]; then \n\ - rm -r /data/project/build \n\ -fi \n\ -mkdir /data/project/build \n\ -cd /data/project/build \n\ -source /opt/emsdk/emsdk_env.sh \n\ -cmake .. \n\ -make \n\ -cd - > /dev/null" > /build.sh \ - && chmod a+x /build.sh diff --git a/samples/workload/docker/build_workload.sh b/samples/workload/docker/build_workload.sh new file mode 100755 index 0000000000..62fe69a93c --- /dev/null +++ b/samples/workload/docker/build_workload.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +readonly SCRIPT_PATH=$(dirname "$(realpath "$0")") +readonly ROOT=$(realpath "${SCRIPT_PATH}"/../../../) +readonly CURRENT_PATH=$(pwd) +readonly CURRENT_RELATIVE_ROOT=$(realpath --relative-base ${ROOT} ${CURRENT_PATH}) +readonly VARIANT=$(lsb_release -c | awk '{print $2}') + +docker build \ + --build-arg VARIANT=${VARIANT} \ + --memory 4G --cpu-quota 50000 \ + -t wamr_dev_${VARIANT}:0.1 -f "${ROOT}"/ci/Dockerfile "${ROOT}"/ci && + docker run --rm -it \ + --memory 4G \ + --cpus ".5" \ + --name workload_build_env \ + --mount type=bind,source="${ROOT}",target=/workspace \ + wamr_dev_${VARIANT}:0.1 \ + /bin/bash -c "\ + pwd \ + && pushd ${CURRENT_RELATIVE_ROOT} \ + && rm -rf build \ + && mkdir build \ + && pushd build \ + && cmake .. \ + && cmake --build . --config Release \ + && popd \ + && popd \ + && echo 'Go and find out results under ${CURRENT_RELATIVE_ROOT}/build' " diff --git a/samples/workload/docker/docker_build.sh b/samples/workload/docker/docker_build.sh deleted file mode 100755 index d4cb10a334..0000000000 --- a/samples/workload/docker/docker_build.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# - -readonly BUILD_CONTENT="/tmp/build_content" -if [[ ! -d ${BUILD_CONTENT} ]]; then - mkdir ${BUILD_CONTENT} -fi - -readonly WASI_SDK_VER=12 -readonly WABT_VER=1.0.20 -readonly CMAKE_VER=3.16.2 -readonly BINARYEN_VER=version_97 -readonly BAZELISK_VER=1.7.5 - -cd ${BUILD_CONTENT} || exit -if [[ ! -f wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz ]]; then - wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -fi - -if [[ ! -f wabt-${WABT_VER}-ubuntu.tar.gz ]]; then - wget https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -fi - -# if [[ ! -f llvm.sh ]]; then -# wget https://apt.llvm.org/llvm.sh -# fi - -if [[ ! -f cmake-${CMAKE_VER}-Linux-x86_64.sh ]]; then - wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh -fi - -if [[ ! -f binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz ]]; then - wget https://github.com/WebAssembly/binaryen/releases/download/${BINARYEN_VER}/binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz -fi - -if [[ ! -f bazelisk-linux-amd64.sh ]]; then - wget https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -fi -cd - > /dev/null || exit - -DOCKERFILE_PATH=$(dirname "$(realpath "$0")") - -docker build \ - --build-arg WASI_SDK_VER=${WASI_SDK_VER} \ - --build-arg WABT_VER=${WABT_VER} \ - --build-arg CMAKE_VER=${CMAKE_VER} \ - --build-arg BINARYEN_VER=${BINARYEN_VER} \ - -t clang_env:0.1 -f "${DOCKERFILE_PATH}"/Dockerfile ${BUILD_CONTENT} \ - && docker run --rm \ - --name workload_w_clang \ - --mount type=bind,source="$(pwd)",target=/data/project \ - -w /data/project \ - clang_env:0.1 \ - /bin/bash -c /build.sh diff --git a/samples/workload/meshoptimizer/CMakeLists.txt b/samples/workload/meshoptimizer/CMakeLists.txt index 1ac8ee18d5..97f98fa3ad 100644 --- a/samples/workload/meshoptimizer/CMakeLists.txt +++ b/samples/workload/meshoptimizer/CMakeLists.txt @@ -5,52 +5,7 @@ cmake_minimum_required (VERSION 3.0) project(bench-meshoptimizer) -################ WASI-SDK ################ -find_path(WASI_SDK_HOME - NAMES wasi-sdk - PATHS /opt/ - REQUIRED -) - -if (NOT WASI_SDK_HOME) - message(FATAL_ERROR - "can not find wasi-sdk. " - "please download it from " - "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz " - "and install it under /opt/wasi-sdk" - ) -endif() - -# -# check clang version -execute_process(COMMAND - ${WASI_SDK_HOME}/wasi-sdk/bin/clang --version - OUTPUT_VARIABLE clang_full_version_string -) -string(REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" - CLANG_VERSION_STRING ${clang_full_version_string} -) -message("cur clang version is ${CLANG_VERSION_STRING}") -if(CLANG_VERSION_STRING VERSION_LESS 11.0) - message(FATAL_ERROR - "please install latest wai-sdk to get a clang-11 at least" - ) -endif() - -################ BINARYEN ################ -find_program(WASM_OPT - NAMES wasm-opt - PATHS /opt/binaryen-version_97/bin /opt/binaryen/bin -) - -if (NOT WASM_OPT) - message(FATAL_ERROR - "can not find wasm-opt. " - "please download it from " - "https://github.com/WebAssembly/binaryen/releases/download/version_97/binaryen-version_97-x86_64-linux.tar.gz " - "and install it under /opt" - ) -endif() +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/preparation.cmake) ################ MESHOPTIMIZER ################ include(ExternalProject) @@ -66,9 +21,10 @@ ExternalProject_Add(codecbench && ${CMAKE_COMMAND} -E echo "Applying patch" && git apply ${CMAKE_CURRENT_SOURCE_DIR}/codecbench.patch CONFIGURE_COMMAND ${CMAKE_COMMAND} - -DWASI_SDK_PREFIX=${WASI_SDK_HOME}/wasi-sdk - -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_HOME}/wasi-sdk/share/cmake/wasi-sdk.cmake - ${CMAKE_CURRENT_SOURCE_DIR}/meshoptimizer - BUILD_COMMAND make codecbench.opt - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ./codecbench.opt.wasm ${CMAKE_CURRENT_SOURCE_DIR}/build/codecbench.wasm + -DWASI_SDK_PREFIX=${WASI_SDK_HOME} + -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_HOME}/share/cmake/wasi-sdk.cmake + -DCMAKE_SYSROOT=${WASI_SDK_HOME}/share/wasi-sysroot + ${CMAKE_CURRENT_SOURCE_DIR}/meshoptimizer + BUILD_COMMAND make codecbench + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ./codecbench.wasm ${CMAKE_CURRENT_SOURCE_DIR}/build/codecbench.wasm ) diff --git a/samples/workload/meshoptimizer/README.md b/samples/workload/meshoptimizer/README.md index 92e10391e3..ceefb5723b 100644 --- a/samples/workload/meshoptimizer/README.md +++ b/samples/workload/meshoptimizer/README.md @@ -32,7 +32,7 @@ $ em++ tools/codecbench.cpp src/vertexcodec.cpp src/vertexfilter.cpp \ src/spatialorder.cpp src/allocator.cpp src/vcacheanalyzer.cpp \ src/vfetchoptimizer.cpp src/overdrawoptimizer.cpp src/simplifier.cpp \ src/stripifier.cpp -O3 -msimd128 \ - -s TOTAL_MEMORY=268435456 -s "EXPORTED_FUNCTIONS=['_main']" \ + -s TOTAL_MEMORY=268435456 \ -o codecbench.wasm $ ls -l codecbench.wasm ``` diff --git a/samples/workload/meshoptimizer/build_workload.sh b/samples/workload/meshoptimizer/build_workload.sh new file mode 120000 index 0000000000..a31afa9282 --- /dev/null +++ b/samples/workload/meshoptimizer/build_workload.sh @@ -0,0 +1 @@ +../docker/build_workload.sh \ No newline at end of file diff --git a/samples/workload/meshoptimizer/codecbench.patch b/samples/workload/meshoptimizer/codecbench.patch index d739558a29..4c9063aa16 100644 --- a/samples/workload/meshoptimizer/codecbench.patch +++ b/samples/workload/meshoptimizer/codecbench.patch @@ -1,8 +1,8 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index ffdb4da..a397427 100644 +index f4378ce..9bc104b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -127,3 +127,43 @@ install(FILES +@@ -129,3 +129,43 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/meshoptimizerConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/meshoptimizerConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/meshoptimizer) @@ -46,3 +46,74 @@ index ffdb4da..a397427 100644 +) + +add_dependencies(codecbench.opt codecbench) +diff --git a/src/vertexcodec.cpp b/src/vertexcodec.cpp +index 5f3ec20..b79bfad 100644 +--- a/src/vertexcodec.cpp ++++ b/src/vertexcodec.cpp +@@ -81,13 +81,13 @@ + #endif + + #ifdef SIMD_WASM +-#define wasmx_splat_v32x4(v, i) wasm_v32x4_shuffle(v, v, i, i, i, i) +-#define wasmx_unpacklo_v8x16(a, b) wasm_v8x16_shuffle(a, b, 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23) +-#define wasmx_unpackhi_v8x16(a, b) wasm_v8x16_shuffle(a, b, 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31) +-#define wasmx_unpacklo_v16x8(a, b) wasm_v16x8_shuffle(a, b, 0, 8, 1, 9, 2, 10, 3, 11) +-#define wasmx_unpackhi_v16x8(a, b) wasm_v16x8_shuffle(a, b, 4, 12, 5, 13, 6, 14, 7, 15) +-#define wasmx_unpacklo_v64x2(a, b) wasm_v64x2_shuffle(a, b, 0, 2) +-#define wasmx_unpackhi_v64x2(a, b) wasm_v64x2_shuffle(a, b, 1, 3) ++#define wasmx_splat_v32x4(v, i) wasm_i32x4_shuffle(v, v, i, i, i, i) ++#define wasmx_unpacklo_v8x16(a, b) wasm_i8x16_shuffle(a, b, 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23) ++#define wasmx_unpackhi_v8x16(a, b) wasm_i8x16_shuffle(a, b, 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31) ++#define wasmx_unpacklo_v16x8(a, b) wasm_i16x8_shuffle(a, b, 0, 8, 1, 9, 2, 10, 3, 11) ++#define wasmx_unpackhi_v16x8(a, b) wasm_i16x8_shuffle(a, b, 4, 12, 5, 13, 6, 14, 7, 15) ++#define wasmx_unpacklo_v64x2(a, b) wasm_i64x2_shuffle(a, b, 0, 2) ++#define wasmx_unpackhi_v64x2(a, b) wasm_i64x2_shuffle(a, b, 1, 3) + #endif + + namespace meshopt +@@ -700,7 +700,7 @@ static v128_t decodeShuffleMask(unsigned char mask0, unsigned char mask1) + v128_t sm1 = wasm_v128_load(&kDecodeBytesGroupShuffle[mask1]); + + v128_t sm1off = wasm_v128_load(&kDecodeBytesGroupCount[mask0]); +- sm1off = wasm_v8x16_shuffle(sm1off, sm1off, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); ++ sm1off = wasm_i8x16_shuffle(sm1off, sm1off, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + v128_t sm1r = wasm_i8x16_add(sm1, sm1off); + +@@ -751,7 +751,7 @@ static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsi + + v128_t shuf = decodeShuffleMask(mask0, mask1); + +- v128_t result = wasm_v128_bitselect(wasm_v8x16_swizzle(rest, shuf), sel, mask); ++ v128_t result = wasm_v128_bitselect(wasm_i8x16_swizzle(rest, shuf), sel, mask); + + wasm_v128_store(buffer, result); + +@@ -773,7 +773,7 @@ static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsi + + v128_t shuf = decodeShuffleMask(mask0, mask1); + +- v128_t result = wasm_v128_bitselect(wasm_v8x16_swizzle(rest, shuf), sel, mask); ++ v128_t result = wasm_v128_bitselect(wasm_i8x16_swizzle(rest, shuf), sel, mask); + + wasm_v128_store(buffer, result); + +diff --git a/src/vertexfilter.cpp b/src/vertexfilter.cpp +index 023452c..2374cf7 100644 +--- a/src/vertexfilter.cpp ++++ b/src/vertexfilter.cpp +@@ -56,10 +56,10 @@ + #endif + + #ifdef SIMD_WASM +-#define wasmx_unpacklo_v16x8(a, b) wasm_v16x8_shuffle(a, b, 0, 8, 1, 9, 2, 10, 3, 11) +-#define wasmx_unpackhi_v16x8(a, b) wasm_v16x8_shuffle(a, b, 4, 12, 5, 13, 6, 14, 7, 15) +-#define wasmx_unziplo_v32x4(a, b) wasm_v32x4_shuffle(a, b, 0, 2, 4, 6) +-#define wasmx_unziphi_v32x4(a, b) wasm_v32x4_shuffle(a, b, 1, 3, 5, 7) ++#define wasmx_unpacklo_v16x8(a, b) wasm_i16x8_shuffle(a, b, 0, 8, 1, 9, 2, 10, 3, 11) ++#define wasmx_unpackhi_v16x8(a, b) wasm_i16x8_shuffle(a, b, 4, 12, 5, 13, 6, 14, 7, 15) ++#define wasmx_unziplo_v32x4(a, b) wasm_i32x4_shuffle(a, b, 0, 2, 4, 6) ++#define wasmx_unziphi_v32x4(a, b) wasm_i32x4_shuffle(a, b, 1, 3, 5, 7) + #endif + + namespace meshopt diff --git a/samples/workload/meshoptimizer/docker_build.sh b/samples/workload/meshoptimizer/docker_build.sh deleted file mode 120000 index 3c6de9bca7..0000000000 --- a/samples/workload/meshoptimizer/docker_build.sh +++ /dev/null @@ -1 +0,0 @@ -../docker/docker_build.sh \ No newline at end of file diff --git a/samples/workload/preparation.sh b/samples/workload/preparation.sh index 1d086f1092..3f49f0cf64 100755 --- a/samples/workload/preparation.sh +++ b/samples/workload/preparation.sh @@ -5,13 +5,11 @@ # readonly BUILD_CONTENT="/tmp/build_content" -readonly WASI_SDK_VER=12 -readonly WASI_SDK_FILE="wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz" -readonly WABT_VER=1.0.20 +readonly WABT_VER=1.0.23 readonly WABT_FILE="wabt-${WABT_VER}-ubuntu.tar.gz" readonly CMAKE_VER=3.16.2 readonly CMAKE_FILE="cmake-${CMAKE_VER}-Linux-x86_64.sh" -readonly BINARYEN_VER=version_97 +readonly BINARYEN_VER=version_101 readonly BINARYEN_FILE="binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz" readonly BAZEL_VER=3.7.0 readonly BAZEL_FILE=bazel-${BAZEL_VER}-installer-linux-x86_64.sh @@ -28,28 +26,6 @@ function install_deps() { build-essential git tree zip unzip } -# -# install clang -#function install_clang() { -# if [[ ! -f llvm.sh ]]; then -# wget https://apt.llvm.org/llvm.sh -# fi -# -# chmod a+x llvm.sh -# ./llvm.sh 11 -#} - -# -# install wasi-sdk -function install_wasi-sdk() { - if [[ ! -f ${WASI_SDK_FILE} ]]; then - wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/${WASI_SDK_FILE} - fi - - tar zxf ${WASI_SDK_FILE} -C /opt - ln -sf /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk -} - # # install wabt function install_wabt() { @@ -81,8 +57,8 @@ function install_emsdk() { git clone https://github.com/emscripten-core/emsdk.git cd emsdk git pull - ./emsdk install latest - ./emsdk activate latest + ./emsdk install 2.0.26 + ./emsdk activate 2.0.26 echo "source /opt/emsdk/emsdk_env.sh" >> "${HOME}"/.bashrc } @@ -120,12 +96,12 @@ if DEBUG; then "$@" else install_deps \ - && install_wasi-sdk \ - && install_wabt \ + && install_bazel \ + && install_binaryen \ && install_cmake \ && install_emsdk \ - && install_binaryen \ - && install_bazel + && install_wabt \ + && install_wasi-sdk fi cd - > /dev/null || exit DEBUG && set +xevu diff --git a/samples/workload/tensorflow/README.md b/samples/workload/tensorflow/README.md index 2aca871ad6..164b6bb09a 100644 --- a/samples/workload/tensorflow/README.md +++ b/samples/workload/tensorflow/README.md @@ -5,8 +5,8 @@ This sample demonstrates how to build [tensorflow](https://github.com/tensorflow ```bash git clone https://github.com/emscripten-core/emsdk.git cd emsdk -./emsdk install latest -./emsdk activate latest +./emsdk install 2.0.26 +./emsdk activate 2.0.26 ``` And set up ensdk environment: ```bash @@ -26,4 +26,4 @@ to build tensorflow and run it with iwasm, which basically contains the followin - build tf-lite with emcc compiler - build iwasm with pthread enable and include libiary under libc-emcc - run benchmark model with iwasm: - --max-secs 300: means the max training time cost is 5 minutes, you can adjust by yourself + --max-secs 300: means the max training time cost is 5 minutes, you can adjust it by yourself diff --git a/samples/workload/tensorflow/build.sh b/samples/workload/tensorflow/build.sh index f3e686b71b..7289e617b6 100755 --- a/samples/workload/tensorflow/build.sh +++ b/samples/workload/tensorflow/build.sh @@ -17,7 +17,7 @@ fi set -xe -EMSDK_WASM_DIR="$EM_CACHE/sysroot/lib/wasm32-emscripten" +EMSDK_WASM_DIR="${EMSDK}/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten" BUILD_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" OUT_DIR="${BUILD_SCRIPT_DIR}/out" TENSORFLOW_DIR="${BUILD_SCRIPT_DIR}/tensorflow" diff --git a/samples/workload/wasm-av1/CMakeLists.avx_wasm.txt b/samples/workload/wasm-av1/CMakeLists.avx_wasm.txt index 78244b456a..d114961236 100644 --- a/samples/workload/wasm-av1/CMakeLists.avx_wasm.txt +++ b/samples/workload/wasm-av1/CMakeLists.avx_wasm.txt @@ -1,12 +1,14 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required (VERSION 2.8...3.16) project(testavx) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/preparation.cmake) + # a workaround to let aom find our non-public headers -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include/libc) +include_directories(${WASI_SDK_HOME}/share/wasi-sysroot/include/libc/musl) ################ AOM ################ set(ENABLE_CCACHE ON) @@ -58,15 +60,6 @@ target_link_libraries(${PROJECT_NAME} add_dependencies(${PROJECT_NAME} aom) -find_program(WASM_OPT - NAMES wasm-opt - PATHS /opt/binaryen-version_97/bin /opt/binaryen/bin -) - -if (NOT WASM_OPT) - message(WARNING "can not find wasm-opt and will not optimize any wasm module") -endif() - add_custom_target(${PROJECT_NAME}_opt ALL COMMAND ${WASM_OPT} -Oz --enable-simd -o ${PROJECT_NAME}.opt.wasm ${PROJECT_NAME}.wasm diff --git a/samples/workload/wasm-av1/CMakeLists.txt b/samples/workload/wasm-av1/CMakeLists.txt index 0dd57d905e..8b1f0df0cb 100644 --- a/samples/workload/wasm-av1/CMakeLists.txt +++ b/samples/workload/wasm-av1/CMakeLists.txt @@ -1,79 +1,15 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required (VERSION 2.8...3.16) project(av1_wasm) -################ WASI-SDK ################ -find_path(WASI_SDK_HOME - NAMES wasi-sdk - PATHS /opt/ - REQUIRED -) - -if (NOT WASI_SDK_HOME) - message(FATAL_ERROR - "can not find wasi-sdk. " - "please download it from " - "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz " - "and install it under /opt/wasi-sdk" - ) -endif() - -# -# check clang version -execute_process(COMMAND - ${WASI_SDK_HOME}/wasi-sdk/bin/clang --version - OUTPUT_VARIABLE clang_full_version_string -) -string(REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" - CLANG_VERSION_STRING ${clang_full_version_string} -) -message("cur clang version is ${CLANG_VERSION_STRING}") -if(CLANG_VERSION_STRING VERSION_LESS 11.0) - message(FATAL_ERROR - "please install latest wai-sdk to get a clang-11 at least" - ) -endif() - -################ BINARYEN ################ -find_program(WASM_OPT - NAMES wasm-opt - PATHS /opt/binaryen-version_97/bin /opt/binaryen/bin -) - -if (NOT WASM_OPT) - message(FATAL_ERROR - "can not find wasm-opt. " - "please download it from " - "https://github.com/WebAssembly/binaryen/releases/download/version_97/binaryen-version_97-x86_64-linux.tar.gz " - "and install it under /opt" - ) -endif() +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/preparation.cmake) ####################################### include(ExternalProject) -################ HEADERS ################ -ExternalProject_Add(headers_from_emcc - PREFIX headers - SOURCE_DIR "$ENV{EM_CACHE}/sysroot/include" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/sys - && ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/include/libc/bits - # copy emscripten pthread related header files - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/pthread.h ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/ - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/signal.h ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/ - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/netdb.h ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/ - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/sys/wait.h ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/sys/ - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/sys/socket.h ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread/sys/ - # copy emscripten setjmp headers - && ${CMAKE_COMMAND} -E copy $ENV{EM_CACHE}/sysroot/include/setjmp.h ${CMAKE_CURRENT_SOURCE_DIR}/include/libc/setjmp.h - && ${CMAKE_COMMAND} -E copy $ENV{EMSDK}/upstream/emscripten/system/lib/libc/musl/arch/emscripten/bits/setjmp.h ${CMAKE_CURRENT_SOURCE_DIR}/include/libc/bits/setjmp.h -) - ################ av1 ################ ExternalProject_Add(av1 PREFIX av1 @@ -82,15 +18,15 @@ ExternalProject_Add(av1 GIT_PROGRESS ON GIT_SHALLOW ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/av1 - DEPENDS headers_from_emcc UPDATE_COMMAND git clean -fd && git checkout -- * && ${CMAKE_COMMAND} -E echo "Copying pre-installed CMakeLists.txt" && ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.avx_wasm.txt CMakeLists.txt && git apply ../av1-clang.patch CONFIGURE_COMMAND ${CMAKE_COMMAND} - -DWASI_SDK_PREFIX=${WASI_SDK_HOME}/wasi-sdk - -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_HOME}/wasi-sdk/share/cmake/wasi-sdk.cmake - ${CMAKE_CURRENT_SOURCE_DIR}/av1 + -DWASI_SDK_PREFIX=${WASI_SDK_HOME} + -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_HOME}/share/cmake/wasi-sdk.cmake + -DCMAKE_SYSROOT=${WASI_SDK_HOME}/share/wasi-sysroot + ${CMAKE_CURRENT_SOURCE_DIR}/av1 BUILD_COMMAND make testavx_opt INSTALL_COMMAND ${CMAKE_COMMAND} -E copy testavx.opt.wasm ${CMAKE_CURRENT_BINARY_DIR}/testavx.wasm ) diff --git a/samples/workload/wasm-av1/build.sh b/samples/workload/wasm-av1/build.sh index 1ef9a3ab2c..7f82c6c524 100755 --- a/samples/workload/wasm-av1/build.sh +++ b/samples/workload/wasm-av1/build.sh @@ -17,7 +17,7 @@ fi set -xe -EMSDK_WASM_DIR="$EM_CACHE/sysroot/lib/wasm32-emscripten" +EMSDK_WASM_DIR="${EMSDK}/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten" BUILD_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" OUT_DIR="${BUILD_SCRIPT_DIR}/out" WASM_AV1_DIR="${BUILD_SCRIPT_DIR}/wasm-av1" diff --git a/samples/workload/wasm-av1/build_workload.sh b/samples/workload/wasm-av1/build_workload.sh new file mode 120000 index 0000000000..a31afa9282 --- /dev/null +++ b/samples/workload/wasm-av1/build_workload.sh @@ -0,0 +1 @@ +../docker/build_workload.sh \ No newline at end of file diff --git a/samples/workload/wasm-av1/docker_build.sh b/samples/workload/wasm-av1/docker_build.sh deleted file mode 120000 index 3c6de9bca7..0000000000 --- a/samples/workload/wasm-av1/docker_build.sh +++ /dev/null @@ -1 +0,0 @@ -../docker/docker_build.sh \ No newline at end of file diff --git a/test-tools/.gitignore b/test-tools/.gitignore new file mode 100644 index 0000000000..6aa8dc0ee2 --- /dev/null +++ b/test-tools/.gitignore @@ -0,0 +1 @@ +/wasi-sdk diff --git a/test-tools/build-wasi-sdk/build_wasi_sdk.py b/test-tools/build-wasi-sdk/build_wasi_sdk.py new file mode 100755 index 0000000000..4c6789116d --- /dev/null +++ b/test-tools/build-wasi-sdk/build_wasi_sdk.py @@ -0,0 +1,299 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +""" +The script operates on such directories and files +|-- core +| `-- deps +| |-- emscripten +| `-- wasi-sdk +| `-- src +| |-- llvm-project +| `-- wasi-libc +`-- test-tools + |-- build-wasi-sdk + | |-- build_wasi_sdk.py + | |-- include + | `-- patches + `-- wasi-sdk + |-- bin + |-- lib + `-- share + `-- wasi-sysroot +""" + +import hashlib +import logging +import os +import pathlib +import shlex +import shutil +import subprocess +import sys +import tarfile +import tempfile +import urllib +import urllib.request + +logger = logging.getLogger("build_wasi_sdk") + +external_repos = { + "config": { + "sha256": "302e5e7f3c4996976c58efde8b2f28f71d51357e784330eeed738e129300dc33", + "store_dir": "core/deps/wasi-sdk/src/config", + "strip_prefix": "config-191bcb948f7191c36eefe634336f5fc5c0c4c2be", + "url": "https://git.savannah.gnu.org/cgit/config.git/snapshot/config-191bcb948f7191c36eefe634336f5fc5c0c4c2be.tar.gz", + }, + "emscripten": { + "sha256": "0904a65379aea3ea94087b8c12985b2fee48599b473e3bef914fec2e3941532d", + "store_dir": "core/deps/emscripten", + "strip_prefix": "emscripten-2.0.28", + "url": "https://github.com/emscripten-core/emscripten/archive/refs/tags/2.0.28.tar.gz", + }, + "llvm-project": { + "sha256": "dc5169e51919f2817d06615285e9da6a804f0f881dc55d6247baa25aed3cc143", + "store_dir": "core/deps/wasi-sdk/src/llvm-project", + "strip_prefix": "llvm-project-34ff6a75f58377f32a5046a29f55c4c0e58bee9e", + "url": "https://github.com/llvm/llvm-project/archive/34ff6a75f58377f32a5046a29f55c4c0e58bee9e.tar.gz", + }, + "wasi-sdk": { + "sha256": "fc4fdb0e97b915241f32209492a7d0fab42c24216f87c1d5d75f46f7c70a553d", + "store_dir": "core/deps/wasi-sdk", + "strip_prefix": "wasi-sdk-1a953299860bbcc198ad8c12a21d1b2e2f738355", + "url": "https://github.com/WebAssembly/wasi-sdk/archive/1a953299860bbcc198ad8c12a21d1b2e2f738355.tar.gz", + }, + "wasi-libc": { + "sha256": "f6316ca9479d3463eb1c4f6a1d1f659bf15f67cb3c1e2e83d9d11f188dccd864", + "store_dir": "core/deps/wasi-sdk/src/wasi-libc", + "strip_prefix": "wasi-libc-a78cd329aec717f149934d7362f57050c9401f60", + "url": "https://github.com/WebAssembly/wasi-libc/archive/a78cd329aec717f149934d7362f57050c9401f60.tar.gz", + }, +} + +# TOOD: can we use headers from wasi-libc and clang directly ? +emscripten_headers_src_dst = [ + ("include/compat/emmintrin.h", "sse/emmintrin.h"), + ("include/compat/immintrin.h", "sse/immintrin.h"), + ("include/compat/smmintrin.h", "sse/smmintrin.h"), + ("include/compat/xmmintrin.h", "sse/xmmintrin.h"), + ("lib/libc/musl/include/pthread.h", "libc/musl/pthread.h"), + ("lib/libc/musl/include/signal.h", "libc/musl/signal.h"), + ("lib/libc/musl/include/netdb.h", "libc/musl/netdb.h"), + ("lib/libc/musl/include/sys/wait.h", "libc/musl/sys/wait.h"), + ("lib/libc/musl/include/sys/socket.h", "libc/musl/sys/socket.h"), + ("lib/libc/musl/include/setjmp.h", "libc/musl/setjmp.h"), + ("lib/libc/musl/arch/emscripten/bits/setjmp.h", "libc/musl/bits/setjmp.h"), +] + + +def checksum(name, local_file): + sha256 = hashlib.sha256() + with open(local_file, "rb") as f: + bytes = f.read(4096) + while bytes: + sha256.update(bytes) + bytes = f.read(4096) + + return sha256.hexdigest() == external_repos[name]["sha256"] + + +def download(url, local_file): + logger.debug(f"download from {url}") + urllib.request.urlretrieve(url, local_file) + return local_file.exists() + + +def unpack(tar_file, strip_prefix, dest_dir): + # extract .tar.gz to /tmp, then move back without strippred prefix directories + with tempfile.TemporaryDirectory() as tmp: + with tarfile.open(tar_file) as tar: + logger.debug(f"extract to {tmp}") + tar.extractall(tmp) + + strip_prefix_dir = ( + pathlib.Path(tmp).joinpath(strip_prefix + os.path.sep).resolve() + ) + if not strip_prefix_dir.exists(): + logger.error(f"extract {tar_file.name} failed") + return False + + # mv /tmp/${strip_prefix} dest_dir/* + logger.debug(f"move {strip_prefix_dir} to {dest_dir}") + shutil.copytree( + str(strip_prefix_dir), + str(dest_dir), + copy_function=shutil.move, + dirs_exist_ok=True, + ) + + return True + + +def download_repo(name, root): + if not name in external_repos: + logger.error(f"{name} is not a known repository") + return False + + store_dir = root.joinpath(f'{external_repos[name]["store_dir"]}').resolve() + download_flag = store_dir.joinpath("DOWNLOADED") + if store_dir.exists() and download_flag.exists(): + logger.info( + f"keep using '{store_dir.relative_to(root)}'. Or to remove it and try again" + ) + return True + + # download only when the target is neither existed nor broken + download_dir = pathlib.Path("/tmp/build_wasi_sdk/") + download_dir.mkdir(exist_ok=True) + + tar_name = pathlib.Path(external_repos[name]["url"]).name + tar_file = download_dir.joinpath(tar_name) + if tar_file.exists(): + if checksum(name, tar_file): + logger.debug(f"use pre-downloaded {tar_file}") + else: + logger.debug(f"{tar_file} is broken, remove it") + tar_file.unlink() + + if not tar_file.exists(): + if not download(external_repos[name]["url"], tar_file) or not checksum( + name, tar_file + ): + logger.error(f"download {name} failed") + return False + + # unpack and removing *strip_prefix* + if not unpack(tar_file, external_repos[name]["strip_prefix"], store_dir): + return False + + # leave a FLAG + download_flag.touch() + + # leave download files in /tmp + return True + + +def run_patch(patch_file, cwd): + if not patch_file.exists(): + logger.error(f"{patch_file} not found") + return False + + with open(patch_file, "r") as f: + try: + PATCH_DRY_RUN_CMD = "patch -f -p1 --dry-run" + if subprocess.check_call(shlex.split(PATCH_DRY_RUN_CMD), stdin=f, cwd=cwd): + logger.error(f"patch dry-run {cwd} failed") + return False + + PATCH_CMD = "patch -f -p1" + f.seek(0) + if subprocess.check_call(shlex.split(PATCH_CMD), stdin=f, cwd=cwd): + logger.error(f"patch {cwd} failed") + return False + except subprocess.CalledProcessError: + logger.error(f"patch {cwd} failed") + return False + return True + + +def build_and_install_wasi_sdk(root): + store_dir = root.joinpath(f'{external_repos["wasi-sdk"]["store_dir"]}').resolve() + if not store_dir.exists(): + logger.error(f"{store_dir} does not found") + return False + + # patch wasi-libc and wasi-sdk + patch_flag = store_dir.joinpath("PATCHED") + if not patch_flag.exists(): + if not run_patch( + root.joinpath("test-tools/build-wasi-sdk/patches/wasi_libc.patch"), + store_dir.joinpath("src/wasi-libc"), + ): + return False + + if not run_patch( + root.joinpath("test-tools/build-wasi-sdk/patches/wasi_sdk.patch"), store_dir + ): + return False + + patch_flag.touch() + else: + logger.info("bypass the patch phase") + + # build + build_flag = store_dir.joinpath("BUILDED") + if not build_flag.exists(): + BUILD_CMD = "make build" + if subprocess.check_call(shlex.split(BUILD_CMD), cwd=store_dir): + logger.error(f"build wasi-sdk failed") + return False + + build_flag.touch() + else: + logger.info("bypass the build phase") + + # install + install_flag = store_dir.joinpath("INSTALLED") + binary_path = root.joinpath("test-tools").resolve() + if not install_flag.exists(): + shutil.copytree( + str(store_dir.joinpath("build/install/opt").resolve()), + str(binary_path), + dirs_exist_ok=True, + ) + + # install headers + emscripten_headers = ( + root.joinpath(external_repos["emscripten"]["store_dir"]) + .joinpath("system") + .resolve() + ) + wasi_sysroot_headers = binary_path.joinpath( + "wasi-sdk/share/wasi-sysroot/include" + ).resolve() + for (src, dst) in emscripten_headers_src_dst: + src = emscripten_headers.joinpath(src) + dst = wasi_sysroot_headers.joinpath(dst) + dst.parent.mkdir(parents=True, exist_ok=True) + shutil.copy(src, dst) + + install_flag.touch() + else: + logger.info("bypass the install phase") + + return True + + +def main(): + console = logging.StreamHandler() + console.setFormatter(logging.Formatter("%(asctime)s - %(message)s")) + logger.setLevel(logging.INFO) + logger.addHandler(console) + logger.propagate = False + + # locate the root of WAMR + current_file = pathlib.Path(__file__) + if current_file.is_symlink(): + current_file = pathlib.Path(os.readlink(current_file)) + root = current_file.parent.joinpath("../..").resolve() + logger.info(f"The root of WAMR is {root}") + + # download repos + for repo in external_repos.keys(): + if not download_repo(repo, root): + return False + + # build wasi_sdk and install + if not build_and_install_wasi_sdk(root): + return False + + # TODO install headers from emscripten + + return True + + +if __name__ == "__main__": + sys.exit(0 if main() else 1) diff --git a/test-tools/build-wasi-sdk/include/.gitkeep b/test-tools/build-wasi-sdk/include/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test-tools/build-wasi-sdk/patches/wasi_libc.patch b/test-tools/build-wasi-sdk/patches/wasi_libc.patch new file mode 100644 index 0000000000..e236735b40 --- /dev/null +++ b/test-tools/build-wasi-sdk/patches/wasi_libc.patch @@ -0,0 +1,13 @@ +diff --git a/expected/wasm32-wasi/predefined-macros.txt b/expected/wasm32-wasi/predefined-macros.txt +index c1bb19e..954f3b5 100644 +--- a/expected/wasm32-wasi/predefined-macros.txt ++++ b/expected/wasm32-wasi/predefined-macros.txt +@@ -3002,6 +3002,8 @@ + #define __alignof_is_defined 1 + #define __bitop(x,i,o) ((x)[(i)/8] o (1<<(i)%8)) + #define __bool_true_false_are_defined 1 ++#define __clang_literal_encoding__ "UTF-8" ++#define __clang_wide_literal_encoding__ "UTF-32" + #define __inline inline + #define __restrict restrict + #define __tg_complex(fun,x) (__RETCAST_CX(x)( __FLTCX((x)+I) && __IS_FP(x) ? fun ## f (x) : __LDBLCX((x)+I) ? fun ## l (x) : fun(x) )) diff --git a/test-tools/build-wasi-sdk/patches/wasi_sdk.patch b/test-tools/build-wasi-sdk/patches/wasi_sdk.patch new file mode 100644 index 0000000000..0fc4caee76 --- /dev/null +++ b/test-tools/build-wasi-sdk/patches/wasi_sdk.patch @@ -0,0 +1,15 @@ +diff --git a/version.sh b/version.sh +index 8e7c44c..ff0d3ba 100755 +--- a/version.sh ++++ b/version.sh +@@ -1,5 +1,6 @@ + #!/usr/bin/env bash +-set -e +-GIT_DESCR=$(git describe --long --candidates=999 --match='wasi-sdk-*' --dirty='+m' --abbrev=12) +-GIT_PACKAGE_VERSION=$(echo $GIT_DESCR | perl -ne 'if(/^wasi-sdk-(\d+)-(\d+)-g([0-9a-f]{7,12})([+]m)?$/) { if($2 == 0) { print "$1.$2$4" } else { print "$1.$2g$3$4" } exit } else { print "could not parse git description"; exit 1 }';) +-echo $GIT_PACKAGE_VERSION ++#set -e ++#GIT_DESCR=$(git describe --long --candidates=999 --match='wasi-sdk-*' --dirty='+m' --abbrev=12) ++#GIT_PACKAGE_VERSION=$(echo $GIT_DESCR | perl -ne 'if(/^wasi-sdk-(\d+)-(\d+)-g([0-9a-f]{7,12})([+]m)?$/) { if($2 == 0) { print "$1.$2$4" } else { print "$1.$2g$3$4" } exit } else { print "could not parse git description"; exit 1 }';) ++#echo $GIT_PACKAGE_VERSION ++echo wasi-sdk-13-eng diff --git a/test-tools/host-tool/src/main.c b/test-tools/host-tool/src/main.c index 230977b4c9..305abc7adb 100644 --- a/test-tools/host-tool/src/main.c +++ b/test-tools/host-tool/src/main.c @@ -750,7 +750,7 @@ static void output_event(request_t *obj) int main(int argc, char *argv[]) { - int ret; + int ret = -1; imrt_link_recv_context_t recv_ctx = { 0 }; char buffer[BUF_SIZE] = { 0 }; uint32_t last_check = 0, total_elpased_ms = 0; diff --git a/tests/wamr-test-suites/README.md b/tests/wamr-test-suites/README.md new file mode 100644 index 0000000000..e33649c848 --- /dev/null +++ b/tests/wamr-test-suites/README.md @@ -0,0 +1,40 @@ +# WAMR test suites + +This folder contains test scripts and cases for wamr. + +## Help +``` +./test_wamr.sh --help +``` + +## Examples +Test spec cases with fast interpreter mode, which will create folder `workspace`, download the `spec` and `wabt` repo, and build `iwasm` automatically to test spec cases: +``` +./test_wamr.sh -s spec -t fast-interp +``` + +Test spec cases with aot mode, and use the wabt binary release package instead of compiling wabt from the source code: +``` +./test_wamr.sh -s spec -t aot -b +``` + +Test spec cases with all modes (classic-interp/fast-interp/aot/jit): +``` +./test_wamr.sh -s spec +``` + +Test spec cases with aot mode and pthread enabled: +``` +./test_wamr.sh -s spec -t aot -p +``` + +Test spec cases with aot mode and SIMD enabled: +``` +./test_wamr.sh -s spec -t aot -S +``` + +Test spec cases with fast-interp on target x86_32: +``` +./test_wamr.sh -s spec -t fast-interp -m x86_32 +``` + diff --git a/tests/wamr-test-suites/spec-test-script/CHANGES b/tests/wamr-test-suites/spec-test-script/CHANGES new file mode 100644 index 0000000000..0b0cc9a670 --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/CHANGES @@ -0,0 +1,5 @@ +#################### +2021-9-8 + +Modify runtest.py from https://github.com/kanaka/wac/blob/master/runtest.py +to enable testing spec cases with more checks and support more runtime modes. diff --git a/tests/wamr-test-suites/spec-test-script/LICENSE b/tests/wamr-test-suites/spec-test-script/LICENSE new file mode 100644 index 0000000000..49b2aa2cf2 --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/LICENSE @@ -0,0 +1,387 @@ +Copyright (C) Joel Martin + +The wac project is licensed under the MPL 2.0 (Mozilla Public License +2.0). The text of the MPL 2.0 license is included below and can be +found at https://www.mozilla.org/MPL/2.0/ + +By default, wac and wace link with the BSD licensed editline library +(http://www.thrysoee.dk/editline/). The wac/wace build process can be +switched to link with the GPL license GNU readline library with the +USE_READLINE=1 flag. + + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + + diff --git a/tests/wamr-test-suites/spec-test-script/all.sh b/tests/wamr-test-suites/spec-test-script/all.sh new file mode 100755 index 0000000000..ebbab2a0a1 --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/all.sh @@ -0,0 +1,163 @@ +#!/bin/bash + +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +# exit if meet an exception +function DEBUG() { + [[ -n $(env | grep "\") ]] && $@ +} +DEBUG set -xevu + +# Run the following command to test a single wast file: +# ./spec-test-script/runtest.py --wast2wasm ./workspace/wabt/out/gcc/Release/wat2wasm \ +# --interpreter iwasm + +readonly SPEC_TEST_DIR="spec/test/core" +readonly WAST2WASM_CMD="./wabt/out/gcc/Release/wat2wasm" +readonly WAMRC_CMD="../../../wamr-compiler/build/wamrc" +PLATFORM=$(uname -s | tr A-Z a-z) +IWASM_CMD="../../../product-mini/platforms/${PLATFORM}/build/iwasm" + +# "imports" and "linking" are only avilable when enabling multi modules +# "comments" is for runtest.py + +IGNORE_LIST=( + "comments" "inline-module" "imports" "linking" "names" +) + +readonly -a MULTI_MODULE_LIST=( + "imports" "linking" +) + +SGX_IGNORE_LIST=("conversions" "f32_bitwise" "f64_bitwise") + +# these cases run failed due to native stack overflow check failed +SGX_AOT_IGNORE_LIST=("call_indirect" "call" "fac" "skip-stack-guard-page") + +function usage() +{ + echo "Usage: all.sh [-t] [-m ] [-M] [-x] [-S] [-r]" + exit 1 +} + +function run_case_w_aot() +{ + local test_case=$1 + echo "============> run ${test_case} with AOT" + python2.7 runtest.py \ + --wast2wasm ${WAST2WASM_CMD} \ + --interpreter ${IWASM_CMD} \ + ${SPEC_TEST_DIR}/${test_case} \ + --aot-compiler ${WAMRC_CMD} \ + --aot --aot-target ${TARGET} \ + ${SGX_OPT} \ + ${SIMD_OPT} \ + ${REF_TYPES_OPT} + #--no_cleanup + if [[ $? != 0 ]]; then + echo "============> run ${test_case} failed" + exit 1 + fi +} + +function run_case_wo_aot() +{ + local test_case=$1 + echo "============> run ${test_case}" + python2.7 runtest.py \ + --wast2wasm ${WAST2WASM_CMD} \ + --interpreter ${IWASM_CMD} \ + ${SPEC_TEST_DIR}/${test_case}\ + --aot-compiler ${WAMRC_CMD} \ + ${SGX_OPT} \ + ${SIMD_OPT} \ + ${REF_TYPES_OPT} + #--no_cleanup + if [[ $? != 0 ]]; then + echo "============> run ${test_case} failed" + exit 1 + fi +} + +ENABLE_MULTI_MODULE=0 +TARGET="X86_64" +SGX_OPT="" +AOT=false +SIMD_OPT="" +REF_TYPES_OPT="" +while getopts ":Mm:txSr" opt; do + case $opt in + t) AOT=true ;; + m) + TARGET=$OPTARG + if [[ ${TARGET} == 'X86_32' ]];then + TARGET='i386' + elif [[ ${TARGET} == 'X86_64' ]];then + TARGET='x86_64' + elif [[ ${TARGET} == 'ARMV7_VFP' ]];then + TARGET='armv7' + elif [[ ${TARGET} == 'THUMBV7_VFP' ]];then + TARGET='thumbv7' + elif [[ ${TARGET} == 'RISCV64' || ${TARGET} == 'RISCV64_LP64D' ]];then + TARGET='riscv64_lp64d' + elif [[ ${TARGET} == 'RISCV64_LP64' ]];then + TARGET='riscv64_lp64' + else + usage + fi + ;; + M) ENABLE_MULTI_MODULE=1 ;; + x) SGX_OPT="--sgx" ;; + S) SIMD_OPT="--simd" ;; + r) REF_TYPES_OPT="--ref_types" ;; + *) usage ;; + esac +done + +function contain() +{ + # [$1, $-1) + local list=${@:0:${#}} + # [$-1] + local item=${@:${#}} + [[ ${list} =~ (^| )${item}($| ) ]] && return 0 || return 1 +} + +if [[ ${SGX_OPT} ]];then + IWASM_CMD="../../../product-mini/platforms/linux-sgx/enclave-sample/iwasm" + IGNORE_LIST+=("${SGX_IGNORE_LIST[@]}") + if [[ "true" == ${AOT} ]];then + IGNORE_LIST+=("${SGX_AOT_IGNORE_LIST[@]}") + fi +fi + +declare -i COUNTER=0 +for wast in $(find ${SPEC_TEST_DIR} -name "*.wast" -type f | sort -n); do + # remove a prefix spec/test/core/ + wast=${wast#${SPEC_TEST_DIR}/} + # ${wast%.wast} will remove a surfix .wast + if contain "${IGNORE_LIST[@]}" ${wast%.wast}; then + echo "============> ignore ${wast}" + continue + else + [[ "true" == ${AOT} ]] && run_case_w_aot ${wast} \ + || run_case_wo_aot ${wast} + (( COUNTER += 1)) + fi +done + +# for now, Multi_Module is always disabled while AOT is true +if [[ "false" == ${AOT} && 1 == ${ENABLE_MULTI_MODULE} ]]; then + echo "============> run cases about multi module" + for wast in ${MULTI_MODULE_LIST[@]}; do + run_case_wo_aot ${wast}.wast + (( COUNTER += 1)) + done +fi + +echo "PASS ALL ${COUNTER} SPEC CASES" +DEBUG set -xevu +exit 0 diff --git a/tests/wamr-test-suites/spec-test-script/ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/ignore_cases.patch new file mode 100644 index 0000000000..70256dfedd --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/ignore_cases.patch @@ -0,0 +1,804 @@ +diff --git a/test/core/binary.wast b/test/core/binary.wast +index c6f9755..a479212 100644 +--- a/test/core/binary.wast ++++ b/test/core/binary.wast +@@ -161,7 +161,7 @@ + ) + + ;; Type section with signed LEB128 encoded type +-(assert_malformed ++(;assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01" ;; Type section id +@@ -171,7 +171,7 @@ + "\00\00" + ) + "integer representation too long" +-) ++;) + + ;; Unsigned LEB128 must not be overlong + (assert_malformed +@@ -1582,7 +1582,7 @@ + ) + + ;; 2 elem segment declared, 1 given +-(assert_malformed ++(;assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01" ;; type section +@@ -1595,7 +1595,7 @@ + ;; "\00\41\00\0b\01\00" ;; elem 1 (missed) + ) + "unexpected end" +-) ++;) + + ;; 2 elem segment declared, 1.5 given + (assert_malformed +diff --git a/test/core/data.wast b/test/core/data.wast +index 4f339be..0b5b3e6 100644 +--- a/test/core/data.wast ++++ b/test/core/data.wast +@@ -306,9 +306,10 @@ + "\02\01\41\00\0b" ;; active data segment 0 for memory 1 + "\00" ;; empty vec(byte) + ) +- "unknown memory 1" ++ "unknown memory" + ) + ++(; not supported by wat2wasm + ;; Data segment with memory index 0 (no memory section) + (assert_invalid + (module binary +@@ -317,7 +318,7 @@ + "\00\41\00\0b" ;; active data segment 0 for memory 0 + "\00" ;; empty vec(byte) + ) +- "unknown memory 0" ++ "unknown memory" + ) + + ;; Data segment with memory index 1 (no memory section) +@@ -328,7 +329,7 @@ + "\02\01\41\00\0b" ;; active data segment 0 for memory 1 + "\00" ;; empty vec(byte) + ) +- "unknown memory 1" ++ "unknown memory" + ) + + ;; Data segment with memory index 1 and vec(byte) as above, +@@ -348,7 +349,7 @@ + "\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f" + "\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d" + ) +- "unknown memory 1" ++ "unknown memory" + ) + + ;; Data segment with memory index 1 and specially crafted vec(byte) after. +@@ -368,8 +369,9 @@ + "\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f" + "\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d" + ) +- "unknown memory 1" ++ "unknown memory" + ) ++;) + + + ;; Invalid offsets +diff --git a/test/core/elem.wast b/test/core/elem.wast +index 575ecef..204b748 100644 +--- a/test/core/elem.wast ++++ b/test/core/elem.wast +@@ -467,6 +467,7 @@ + "type mismatch" + ) + ++(; not supported by wat2wasm + (assert_invalid + (module + (table 1 funcref) +@@ -507,6 +508,7 @@ + ) + "constant expression required" + ) ++;) + + ;; Two elements target the same slot + +@@ -571,9 +573,11 @@ + (func $const-i32-d (type $out-i32) (i32.const 68)) + ) + ++(; + (assert_return (invoke $module1 "call-7") (i32.const 67)) + (assert_return (invoke $module1 "call-8") (i32.const 68)) + (assert_return (invoke $module1 "call-9") (i32.const 66)) ++;) + + (module $module3 + (type $out-i32 (func (result i32))) +@@ -584,6 +588,8 @@ + (func $const-i32-f (type $out-i32) (i32.const 70)) + ) + ++(; + (assert_return (invoke $module1 "call-7") (i32.const 67)) + (assert_return (invoke $module1 "call-8") (i32.const 69)) + (assert_return (invoke $module1 "call-9") (i32.const 70)) ++;) +diff --git a/test/core/global.wast b/test/core/global.wast +index 9fa5e22..8c4b949 100644 +--- a/test/core/global.wast ++++ b/test/core/global.wast +@@ -328,10 +328,12 @@ + "type mismatch" + ) + ++(; + (assert_invalid + (module (global (import "" "") externref) (global funcref (global.get 0))) + "type mismatch" + ) ++;) + + (assert_invalid + (module (global (import "test" "global-i32") i32) (global i32 (global.get 0) (global.get 0))) +diff --git a/test/core/imports.wast b/test/core/imports.wast +index 35e8c91..a7a459d 100644 +--- a/test/core/imports.wast ++++ b/test/core/imports.wast +@@ -577,6 +577,7 @@ + (assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) + (assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) + ++(; unsupported by multi-module currently + (module $Mgm + (memory (export "memory") 1) ;; initial size is 1 + (func (export "grow") (result i32) (memory.grow (i32.const 1))) +@@ -596,6 +597,7 @@ + (func (export "size") (result i32) (memory.size)) + ) + (assert_return (invoke $Mgim2 "size") (i32.const 3)) ++;) + + + ;; Syntax errors +diff --git a/test/core/linking.wast b/test/core/linking.wast +index 994e0f4..d0bfb5f 100644 +--- a/test/core/linking.wast ++++ b/test/core/linking.wast +@@ -64,6 +64,7 @@ + (export "Mg.set_mut" (func $set_mut)) + ) + ++(; + (assert_return (get $Mg "glob") (i32.const 42)) + (assert_return (get $Ng "Mg.glob") (i32.const 42)) + (assert_return (get $Ng "glob") (i32.const 43)) +@@ -81,6 +82,7 @@ + (assert_return (get $Ng "Mg.mut_glob") (i32.const 241)) + (assert_return (invoke $Mg "get_mut") (i32.const 241)) + (assert_return (invoke $Ng "Mg.get_mut") (i32.const 241)) ++;) + + + (assert_unlinkable +@@ -165,6 +167,7 @@ + ) + ) + ++(; + (assert_return (invoke $Mt "call" (i32.const 2)) (i32.const 4)) + (assert_return (invoke $Nt "Mt.call" (i32.const 2)) (i32.const 4)) + (assert_return (invoke $Nt "call" (i32.const 2)) (i32.const 5)) +@@ -187,6 +190,7 @@ + + (assert_return (invoke $Nt "call" (i32.const 3)) (i32.const -4)) + (assert_trap (invoke $Nt "call" (i32.const 4)) "indirect call type mismatch") ++;) + + (module $Ot + (type (func (result i32))) +@@ -201,6 +205,7 @@ + ) + ) + ++(; + (assert_return (invoke $Mt "call" (i32.const 3)) (i32.const 4)) + (assert_return (invoke $Nt "Mt.call" (i32.const 3)) (i32.const 4)) + (assert_return (invoke $Nt "call Mt.call" (i32.const 3)) (i32.const 4)) +@@ -225,6 +230,7 @@ + (assert_trap (invoke $Ot "call" (i32.const 0)) "uninitialized element") + + (assert_trap (invoke $Ot "call" (i32.const 20)) "undefined element") ++;) + + (module + (table (import "Mt" "tab") 0 funcref) +@@ -263,6 +269,7 @@ + + ;; Unlike in the v1 spec, active element segments stored before an + ;; out-of-bounds access persist after the instantiation failure. ++(; + (assert_trap + (module + (table (import "Mt" "tab") 10 funcref) +@@ -274,7 +281,9 @@ + ) + (assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) + (assert_trap (invoke $Mt "call" (i32.const 8)) "uninitialized element") ++;) + ++(; + (assert_trap + (module + (table (import "Mt" "tab") 10 funcref) +@@ -286,6 +295,7 @@ + "out of bounds memory access" + ) + (assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) ++;) + + + (module $Mtable_ex +@@ -299,6 +309,7 @@ + (table (import "Mtable_ex" "t-extern") 1 externref) + ) + ++(; + (assert_unlinkable + (module (table (import "Mtable_ex" "t-func") 1 externref)) + "incompatible import type" +@@ -307,6 +318,7 @@ + (module (table (import "Mtable_ex" "t-extern") 1 funcref)) + "incompatible import type" + ) ++;) + + + ;; Memories +@@ -346,10 +358,12 @@ + ) + ) + ++(; + (assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 0xa7)) + (assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 0xa7)) + (assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) + (assert_return (invoke $Om "load" (i32.const 12)) (i32.const 0xa7)) ++;) + + (module + (memory (import "Mm" "mem") 0) +@@ -372,6 +386,7 @@ + ) + ) + ++(; + (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 1)) + (assert_return (invoke $Pm "grow" (i32.const 2)) (i32.const 1)) + (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 3)) +@@ -380,6 +395,7 @@ + (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) + (assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1)) + (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) ++;) + + (assert_unlinkable + (module +@@ -403,8 +419,10 @@ + ) + "out of bounds memory access" + ) ++(; + (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) + (assert_return (invoke $Mm "load" (i32.const 327670)) (i32.const 0)) ++;) + + (assert_trap + (module +@@ -416,7 +434,9 @@ + ) + "out of bounds table access" + ) ++(; + (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) ++;) + + ;; Store is modified if the start function traps. + (module $Ms +@@ -432,6 +452,7 @@ + ) + (register "Ms" $Ms) + ++(; + (assert_trap + (module + (import "Ms" "memory" (memory 1)) +@@ -451,3 +472,4 @@ + + (assert_return (invoke $Ms "get memory[0]") (i32.const 104)) ;; 'h' + (assert_return (invoke $Ms "get table[0]") (i32.const 0xdead)) ++;) +diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast +index adb5cb7..590f626 100644 +--- a/test/core/ref_func.wast ++++ b/test/core/ref_func.wast +@@ -4,7 +4,8 @@ + (register "M") + + (module +- (func $f (import "M" "f") (param i32) (result i32)) ++ (; aot mode does not support module linking ;) ++ (func $f (param $x i32) (result i32) (local.get $x)) + (func $g (param $x i32) (result i32) + (i32.add (local.get $x) (i32.const 1)) + ) +diff --git a/test/core/select.wast b/test/core/select.wast +index 046e6fe..b677023 100644 +--- a/test/core/select.wast ++++ b/test/core/select.wast +@@ -324,6 +324,7 @@ + (module (func $arity-0 (select (result) (nop) (nop) (i32.const 1)))) + "invalid result arity" + ) ++(; + (assert_invalid + (module (func $arity-2 (result i32 i32) + (select (result i32 i32) +@@ -334,6 +335,7 @@ + )) + "invalid result arity" + ) ++;) + + + (assert_invalid +diff --git a/test/core/table_copy.wast b/test/core/table_copy.wast +index 380e84e..f37e745 100644 +--- a/test/core/table_copy.wast ++++ b/test/core/table_copy.wast +@@ -14,11 +14,12 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ ;; aot mode does not support module linking ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -106,11 +107,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (export "ef0") (result i32) (i32.const 0)) ;; index 0 ++ (func (export "ef1") (result i32) (i32.const 1)) ++ (func (export "ef2") (result i32) (i32.const 2)) ++ (func (export "ef3") (result i32) (i32.const 3)) ++ (func (export "ef4") (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -198,11 +199,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -290,11 +291,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -382,11 +383,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -474,11 +475,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -566,11 +567,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -658,11 +659,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -750,11 +751,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -842,11 +843,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -934,11 +935,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1026,11 +1027,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1118,11 +1119,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1210,11 +1211,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1302,11 +1303,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1394,11 +1395,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1486,11 +1487,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -1578,11 +1579,11 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +diff --git a/test/core/table_init.wast b/test/core/table_init.wast +index 0b2d26f..bdab6a0 100644 +--- a/test/core/table_init.wast ++++ b/test/core/table_init.wast +@@ -14,11 +14,12 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ ;; aot mode does not support module linking ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -72,11 +73,12 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ ;; aot mode does not support module linking ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -130,11 +132,12 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ ;; aot mode does not support module linking ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t0) (i32.const 2) func 3 1 4 1) +@@ -196,11 +199,12 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ ;; aot mode does not support module linking ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -254,11 +258,12 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ ;; aot mode does not support module linking ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +@@ -312,11 +317,12 @@ + + (module + (type (func (result i32))) ;; type #0 +- (import "a" "ef0" (func (result i32))) ;; index 0 +- (import "a" "ef1" (func (result i32))) +- (import "a" "ef2" (func (result i32))) +- (import "a" "ef3" (func (result i32))) +- (import "a" "ef4" (func (result i32))) ;; index 4 ++ ;; aot mode does not support module linking ++ (func (result i32) (i32.const 0)) ;; index 0 ++ (func (result i32) (i32.const 1)) ++ (func (result i32) (i32.const 2)) ++ (func (result i32) (i32.const 3)) ++ (func (result i32) (i32.const 4)) ;; index 4 + (table $t0 30 30 funcref) + (table $t1 30 30 funcref) + (elem (table $t1) (i32.const 2) func 3 1 4 1) +diff --git a/test/core/unreached-valid.wast b/test/core/unreached-valid.wast +index 0025217..07d2788 100644 +--- a/test/core/unreached-valid.wast ++++ b/test/core/unreached-valid.wast +@@ -46,6 +46,7 @@ + + ;; Validation after unreachable + ++(; + (module + (func (export "meet-bottom") + (block (result f64) +@@ -59,4 +60,5 @@ + (drop) + ) + ) ++;) + diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py new file mode 100755 index 0000000000..f795784830 --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -0,0 +1,1288 @@ +#!/usr/bin/env python + +from __future__ import print_function +import os, sys, re +import argparse, time +import signal, atexit, tempfile, subprocess + +from subprocess import Popen, STDOUT, PIPE +from select import select + +# Pseudo-TTY and terminal manipulation +import pty, array, fcntl, termios + +import shutil + +import struct +import math +import traceback + +IS_PY_3 = sys.version_info[0] == 3 + +test_aot = False +# "x86_64", "i386", "aarch64", "armv7" or "thumbv7" +test_target = "x86_64" + +debug_file = None +log_file = None + +# to save the register module with self-define name +temp_file_repo = [] + +# get current work directory +current_work_directory = os.getcwd() +# set temporal file directory +temp_file_directory = os.path.join(current_work_directory,"tempfile") + +def debug(data): + if debug_file: + debug_file.write(data) + debug_file.flush() + +def log(data, end='\n'): + if log_file: + log_file.write(data + end) + log_file.flush() + print(data, end=end) + sys.stdout.flush() + +# TODO: do we need to support '\n' too +import platform +if platform.system().find("CYGWIN_NT") >= 0: + # TODO: this is weird, is this really right on Cygwin? + sep = "\n\r\n" +else: + sep = "\r\n" +rundir = None + +class Runner(): + def __init__(self, args, no_pty=False): + #print "args: %s" % repr(args) + self.no_pty = no_pty + + # Cleanup child process on exit + atexit.register(self.cleanup) + + self.p = None + env = os.environ + env['TERM'] = 'dumb' + env['INPUTRC'] = '/dev/null' + env['PERL_RL'] = 'false' + if no_pty: + self.p = Popen(args, bufsize=0, + stdin=PIPE, stdout=PIPE, stderr=STDOUT, + preexec_fn=os.setsid, + env=env) + self.stdin = self.p.stdin + self.stdout = self.p.stdout + else: + # provide tty to get 'interactive' readline to work + master, slave = pty.openpty() + + # Set terminal size large so that readline will not send + # ANSI/VT escape codes when the lines are long. + buf = array.array('h', [100, 200, 0, 0]) + fcntl.ioctl(master, termios.TIOCSWINSZ, buf, True) + + self.p = Popen(args, bufsize=0, + stdin=slave, stdout=slave, stderr=STDOUT, + preexec_fn=os.setsid, + env=env) + # Now close slave so that we will get an exception from + # read when the child exits early + # http://stackoverflow.com/questions/11165521 + os.close(slave) + self.stdin = os.fdopen(master, 'r+b', 0) + self.stdout = self.stdin + + #print "started" + self.buf = "" + self.last_prompt = "" + + def read_to_prompt(self, prompts, timeout): + end_time = time.time() + timeout + while time.time() < end_time: + [outs,_,_] = select([self.stdout], [], [], 1) + if self.stdout in outs: + new_data = self.stdout.read(1) + if not new_data: + # EOF on macOS ends up here. + break + new_data = new_data.decode("utf-8") if IS_PY_3 else new_data + #print("new_data: '%s'" % new_data) + debug(new_data) + if self.no_pty: + self.buf += new_data.replace("\n", "\r\n") + else: + self.buf += new_data + self.buf = self.buf.replace("\r\r", "\r") + for prompt in prompts: + regexp = re.compile(prompt) + match = regexp.search(self.buf) + if match: + end = match.end() + buf = self.buf[0:end-len(prompt)] + self.buf = self.buf[end:] + self.last_prompt = prompt + return buf + return None + + def writeline(self, str): + def _to_bytes(s): + return bytes(s, "utf-8") if IS_PY_3 else s + + self.stdin.write(_to_bytes(str + "\n")) + + def cleanup(self): + if self.p: + try: + self.writeline("__exit__") + time.sleep(.020) + os.killpg(self.p.pid, signal.SIGTERM) + except OSError: + pass + self.p = None + self.stdin.close() + if self.stdin != self.stdout: + self.stdout.close() + self.stdin = None + self.stdout = None + sys.exc_clear() + +def assert_prompt(runner, prompts, timeout, is_need_execute_result): + # Wait for the initial prompt + header = runner.read_to_prompt(prompts, timeout=timeout) + if not header and is_need_execute_result: + log(" ---------- will terminate cause the case needs result while there is none inside of buf. ----------") + sys.exit(1) + if not header == None: + if header: + log("Started with:\n%s" % header) + else: + log("Did not one of following prompt(s): %s" % repr(prompts)) + log(" Got : %s" % repr(r.buf)) + sys.exit(1) + + +### WebAssembly specific + +parser = argparse.ArgumentParser( + description="Run a test file against a WebAssembly interpreter") +parser.add_argument('--wast2wasm', type=str, + default=os.environ.get("WAST2WASM", "wast2wasm"), + help="Path to wast2wasm program") +parser.add_argument('--interpreter', type=str, + default=os.environ.get("IWASM_CMD", "iwasm"), + help="Path to WebAssembly interpreter") +parser.add_argument('--aot-compiler', type=str, + default=os.environ.get("WAMRC_CMD", "wamrc"), + help="Path to WebAssembly AoT compiler") + +parser.add_argument('--no_cleanup', action='store_true', + help="Keep temporary *.wasm files") + +parser.add_argument('--rundir', + help="change to the directory before running tests") +parser.add_argument('--start-timeout', default=30, type=int, + help="default timeout for initial prompt") +parser.add_argument('--test-timeout', default=20, type=int, + help="default timeout for each individual test action") +parser.add_argument('--no-pty', action='store_true', + help="Use direct pipes instead of pseudo-tty") +parser.add_argument('--log-file', type=str, + help="Write messages to the named file in addition the screen") +parser.add_argument('--debug-file', type=str, + help="Write all test interaction the named file") + +parser.add_argument('test_file', type=argparse.FileType('r'), + help="a WebAssembly *.wast test file") + +parser.add_argument('--aot', action='store_true', + help="Test with AOT") + +parser.add_argument('--aot-target', type=str, + default="x86_64", + help="Set aot target") + +parser.add_argument('--sgx', action='store_true', + help="Test SGX") + +parser.add_argument('--simd', default=False, action='store_true', + help="Enable SIMD") + +parser.add_argument('--ref_types', default=False, action='store_true', + help="Enable Reference types") + +parser.add_argument('--verbose', default=False, action='store_true', + help='show more logs') + +# regex patterns of tests to skip +C_SKIP_TESTS = () +PY_SKIP_TESTS = ( + # names.wast + 'invoke \"~!', + # conversions.wast + '18446742974197923840.0', + '18446744073709549568.0', + '9223372036854775808', + 'reinterpret_f.*nan', + # endianness + '.const 0x1.fff' ) + +def read_forms(string): + forms = [] + form = "" + depth = 0 + line = 0 + pos = 0 + while pos < len(string): + # Keep track of line number + if string[pos] == '\n': line += 1 + + # Handle top-level elements + if depth == 0: + # Add top-level comments + if string[pos:pos+2] == ";;": + end = string.find("\n", pos) + if end == -1: end == len(string) + forms.append(string[pos:end]) + pos = end + continue + + # TODO: handle nested multi-line comments + if string[pos:pos+2] == "(;": + # Skip multi-line comment + end = string.find(";)", pos) + if end == -1: + raise Exception("mismatch multiline comment on line %d: '%s'" % ( + line, string[pos:pos+80])) + pos = end+2 + continue + + # Ignore whitespace between top-level forms + if string[pos] in (' ', '\n', '\t'): + pos += 1 + continue + + # Read a top-level form + if string[pos] == '(': depth += 1 + if string[pos] == ')': depth -= 1 + if depth == 0 and not form: + raise Exception("garbage on line %d: '%s'" % ( + line, string[pos:pos+80])) + form += string[pos] + if depth == 0 and form: + forms.append(form) + form = "" + pos += 1 + return forms + +def get_module_exp_from_assert(string): + depth = 0 + pos = 0 + module = "" + exception = "" + start_record = False + result = [] + while pos < len(string): + # record from the " (module " + if string[pos:pos+7] == "(module": + start_record = True + if start_record: + if string[pos] == '(' : depth += 1 + if string[pos] == ')' : depth -= 1 + module += string[pos] + # if we get all (module ) . + if depth == 0 and module: + result.append(module) + start_record = False + # get expected exception + if string[pos] == '"': + end = string.find("\"", pos+1) + if end != -1: + end_rel = string.find("\"",end+1) + if end_rel == -1: + result.append(string[pos+1:end]) + pos += 1 + return result + +def string_to_unsigned(number_in_string, lane_type): + if not lane_type in ['i8x16', 'i16x8', 'i32x4', 'i64x2']: + raise Exception("invalid value {} and type {} and lane_type {}".format(numbers, type, lane_type)) + + number = int(number_in_string, 16) if '0x' in number_in_string else int(number_in_string) + + if "i8x16" == lane_type: + if number < 0: + packed = struct.pack('b', number) + number = struct.unpack('B', packed)[0] + elif "i16x8" == lane_type: + if number < 0: + packed = struct.pack('h', number) + number = struct.unpack('H', packed)[0] + elif "i32x4" == lane_type: + if number < 0: + packed = struct.pack('i', number) + number = struct.unpack('I', packed)[0] + else: # "i64x2" == lane_type: + if number < 0: + packed = struct.pack('q', number) + number = struct.unpack('Q', packed)[0] + + return number + +def cast_v128_to_i64x2(numbers, type, lane_type): + numbers = [n.replace("_", "") for n in numbers] + + if "i8x16" == lane_type: + assert(16 == len(numbers)), "{} should like {}".format(numbers, lane_type) + # str -> int + numbers = [string_to_unsigned(n, lane_type) for n in numbers] + # i8 -> i64 + packed = struct.pack(16 * "B", *numbers) + elif "i16x8" == lane_type: + assert(8 == len(numbers)), "{} should like {}".format(numbers, lane_type) + # str -> int + numbers = [string_to_unsigned(n, lane_type) for n in numbers] + # i16 -> i64 + packed = struct.pack(8 * "H", *numbers) + elif "i32x4" == lane_type: + assert(4 == len(numbers)), "{} should like {}".format(numbers, lane_type) + # str -> int + numbers = [string_to_unsigned(n, lane_type) for n in numbers] + # i32 -> i64 + packed = struct.pack(4 * "I", *numbers) + elif "i64x2" == lane_type: + assert(2 == len(numbers)), "{} should like {}".format(numbers, lane_type) + # str -> int + numbers = [string_to_unsigned(n, lane_type) for n in numbers] + # i64 -> i64 + packed = struct.pack(2 * "Q", *numbers) + elif "f32x4" == lane_type: + assert(4 == len(numbers)), "{} should like {}".format(numbers, lane_type) + # str -> int + numbers = [parse_simple_const_w_type(n, "f32")[0] for n in numbers] + # f32 -> i64 + packed = struct.pack(4 * "f", *numbers) + elif "f64x2" == lane_type: + assert(2 == len(numbers)), "{} should like {}".format(numbers, lane_type) + # str -> int + numbers = [parse_simple_const_w_type(n, "f64")[0] for n in numbers] + # f64 -> i64 + packed = struct.pack(2 * "d", *numbers) + else: + raise Exception("invalid value {} and type {} and lane_type {}".format(numbers, type, lane_type)) + + assert(packed) + unpacked = struct.unpack("Q Q", packed) + return unpacked, "[{} {}]:{}:v128".format(unpacked[0], unpacked[1], lane_type) + + +def parse_simple_const_w_type(number, type): + number = number.replace('_', '') + if type in ["i32", "i64"]: + number = int(number, 16) if '0x' in number else int(number) + return number, "0x{:x}:{}".format(number, type) \ + if number >= 0 \ + else "-0x{:x}:{}".format(0 - number, type) + elif type in ["f32", "f64"]: + if "nan:" in number: + # TODO: how to handle this correctly + if "nan:canonical" in number: + return float.fromhex("0x200000"), "nan:{}".format(type) + elif "nan:arithmetic" in number: + return float.fromhex("-0x200000"), "nan:{}".format(type) + else: + return float('nan'), "nan:{}".format(type) + else: + number = float.fromhex(number) if '0x' in number else float(number) + return number, "{:.7g}:{}".format(number, type) + elif type == "ref.null": + # hard coding + return "extern", "extern:ref.null" + elif type == "ref.extern": + number = int(number, 16) if '0x' in number else int(number) + return number, "0x{:x}:ref.extern".format(number) + else: + raise Exception("invalid value {} and type {}".format(number, type)) + +def parse_assertion_value(val): + """ + Parse something like: + "ref.null extern" in (assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern)) + "ref.extern 1" in (assert_return (invoke "get-externref" (i32.const 1)) (ref.extern 1)) + "i32.const 0" in (assert_return (invoke "is_null-funcref" (i32.const 1)) (i32.const 0)) + + in summary: + type.const (sub-type) (val1 val2 val3 val4) ... + type.const val + ref.extern val + ref.null ref_type + """ + if not val: + return None, "" + + splitted = re.split('\s+', val) + splitted = [s for s in splitted if s] + type = splitted[0].split(".")[0] + lane_type = splitted[1] if len(splitted) > 2 else "" + numbers = splitted[2:] if len(splitted) > 2 else splitted[1:] + + if type in ["i32", "i64", "f32", "f64"]: + return parse_simple_const_w_type(numbers[0], type) + elif type == "ref": + # need to distinguish between "ref.null" and "ref.extern" + return parse_simple_const_w_type(numbers[0], splitted[0]) + else: + return cast_v128_to_i64x2(numbers, type, lane_type) + +def int2uint32(i): + return i & 0xffffffff + +def int2int32(i): + val = i & 0xffffffff + if val & 0x80000000: + return val - 0x100000000 + else: + return val + +def int2uint64(i): + return i & 0xffffffffffffffff + +def int2int64(i): + val = i & 0xffffffffffffffff + if val & 0x8000000000000000: + return val - 0x10000000000000000 + else: + return val + + +def num_repr(i): + if isinstance(i, int) or isinstance(i, long): + return re.sub("L$", "", hex(i)) + else: + return "%.16g" % i + +def hexpad16(i): + return "0x%04x" % i + +def hexpad24(i): + return "0x%06x" % i + +def hexpad32(i): + return "0x%08x" % i + +def hexpad64(i): + return "0x%016x" % i + +def invoke(r, args, cmd): + r.writeline(cmd) + + return r.read_to_prompt(['\r\nwebassembly> ', '\nwebassembly> '], + timeout=args.test_timeout) + +def vector_value_comparison(out, expected): + """ + out likes ":v128" + expected likes "[number number]:v128" + """ + # print("vector value comparision {} vs {}".format(out, expected)) + + out_val, out_type = out.split(':') + # => number number + out_val = out_val[1:-1] + + expected_val, lane_type, expected_type = expected.split(':') + # [number nubmer] => number number + expected_val = expected_val[1:-1] + + assert("v128" == out_type), "out_type should be v128" + assert("v128" == expected_type), "expected_type should be v128" + + if out_type != expected_type: + return False + + if out_val == expected_val: + return True + + out_val = out_val.split(" ") + expected_val = expected_val.split(" ") + + # since i64x2 + out_packed = struct.pack("QQ", int(out_val[0], 16), int(out_val[1], 16)) + expected_packed = struct.pack("QQ", + int(expected_val[0]) if not "0x" in expected_val[0] else int(expected_val[0], 16), + int(expected_val[1]) if not "0x" in expected_val[1] else int(expected_val[1], 16)) + + if lane_type in ["i8x16", "i16x8", "i32x4", "i64x2"]: + return out_packed == expected_packed; + else: + assert(lane_type in ["f32x4", "f64x2"]), "unexpected lane_type" + + if "f32x4" == lane_type: + out_unpacked = struct.unpack("ffff", out_packed) + expected_unpacked = struct.unpack("ffff", expected_packed) + else: + out_unpacked = struct.unpack("dd", out_packed) + expected_unpacked = struct.unpack("dd", expected_packed) + + out_is_nan = [math.isnan(o) for o in out_unpacked] + expected_is_nan = [math.isnan(e) for e in expected_unpacked] + if out_is_nan and expected_is_nan: + return True; + + # print("compare {} and {}".format(out_unpacked, expected_unpacked)) + result = [o == e for o, e in zip(out_unpacked, expected_unpacked)] + + if not all(result): + result = [ + "{:.7g}".format(o) == "{:.7g}".format(e) + for o, e in zip(out_unpacked, expected_packed) + ] + + return all(result) + + +def simple_value_comparison(out, expected): + """ + compare out of simple types which may like val:i32, val:f64 and so on + """ + if expected == "2.360523e+13:f32" and out == "2.360522e+13:f32": + # one case in float_literals.wast, due to float precision of python + return True + + if expected == "1.797693e+308:f64" and out == "inf:f64": + # one case in float_misc.wast: + # (assert_return (invoke "f64.add" (f64.const 0x1.fffffffffffffp+1023) + # (f64.const 0x1.fffffffffffffp+969)) + # (f64.const 0x1.fffffffffffffp+1023)) + # the add result in x86_32 is inf + return True + + out_val, out_type = out.split(':') + expected_val, expected_type = expected.split(':') + + if not out_type == expected_type: + return False + + out_val, _ = parse_simple_const_w_type(out_val, out_type) + expected_val, _ = parse_simple_const_w_type(expected_val, expected_type) + + if out_val == expected_val \ + or (math.isnan(out_val) and math.isnan(expected_val)): + return True + + if "i32" == expected_type: + out_val_binary = struct.pack('I', out_val) if out_val > 0 \ + else struct.pack('i', out_val) + expected_val_binary = struct.pack('I', expected_val) \ + if expected_val > 0 \ + else struct.pack('i', expected_val) + elif "i64" == expected_type: + out_val_binary = struct.pack('Q', out_val) if out_val > 0 \ + else struct.pack('q', out_val) + expected_val_binary = struct.pack('Q', expected_val) \ + if expected_val > 0 \ + else struct.pack('q', expected_val) + elif "f32" == expected_type: + out_val_binary = struct.pack('f', out_val) + expected_val_binary = struct.pack('f', expected_val) + elif "f64" == expected_type: + out_val_binary = struct.pack('d', out_val) + expected_val_binary = struct.pack('d', expected_val) + elif "ref.extern" == expected_type: + out_val_binary = out_val + expected_val_binary = expected_val + else: + assert(0), "unknown 'expected_type' {}".format(expected_type) + + if out_val_binary == expected_val_binary: + return True + + if expected_type in ["f32", "f64"]: + # compare with a lower precision + out_str = "{:.7g}".format(out_val) + expected_str = "{:.7g}".format(expected_val) + if out_str == expected_str: + return True + + return False + +def value_comparison(out, expected): + if out == expected: + return True + + if not expected: + return False + + assert(':' in out), "out should be in a form likes numbers:type, but {}".format(out) + assert(':' in expected), "expected should be in a form likes numbers:type, but {}".format(expected) + + if 'v128' in out: + return vector_value_comparison(out, expected) + else: + return simple_value_comparison(out, expected) + +def is_result_match_expected(out, expected): + # compare value instead of comparing strings of values + return value_comparison(out, expected) + +def test_assert(r, opts, mode, cmd, expected): + log("Testing(%s) %s = %s" % (mode, cmd, expected)) + + out = invoke(r, opts, cmd) + outs = [''] + out.split('\n')[1:] + out = outs[-1] + + if mode=='trap': + o = re.sub('^Exception: ', '', out) + e = re.sub('^Exception: ', '', expected) + if o.find(e) >= 0 or e.find(o) >= 0: + return True + + if mode=='exhaustion': + o = re.sub('^Exception: ', '', out) + expected = 'Exception: stack overflow' + 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) + if len(expected_list) != len(out_list): + raise Exception("Failed:\n Results count incorrect:\n expected: '%s'\n got: '%s'" % (expected, out)) + for i in range(len(expected_list)): + if not is_result_match_expected(out_list[i], expected_list[i]): + raise Exception("Failed:\n Result %d incorrect:\n expected: '%s'\n got: '%s'" % (i, expected_list[i], out_list[i])) + + return True + +def test_assert_return(r, opts, form): + """ + m. to search a pattern like (assert_return (invoke function_name ... ) ...) + n. to search a pattern like (assert_return (invoke $module_name function_name ... ) ...) + """ + # params, return + m = re.search('^\(assert_return\s+\(invoke\s+"((?:[^"]|\\\")*)"\s+(\(.*\))\s*\)\s*(\(.*\))\s*\)\s*$', form, re.S) + # judge if assert_return cmd includes the module name + n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"((?:[^"]|\\\")*)"\s+(\(.*\))\s*\)\s*(\(.*\))\s*\)\s*$', form, re.S) + + # print("assert_return with {}".format(form)) + + if not m: + # no params, return + m = re.search('^\(assert_return\s+\(invoke\s+"((?:[^"]|\\\")*)"\s*\)\s+()(\(.*\))\s*\)\s*$', form, re.S) + if not m: + # params, no return + m = re.search('^\(assert_return\s+\(invoke\s+"([^"]*)"\s+(\(.*\))()\s*\)\s*\)\s*$', form, re.S) + if not m: + # no params, no return + m = re.search('^\(assert_return\s+\(invoke\s+"([^"]*)"\s*()()\)\s*\)\s*$', form, re.S) + if not m: + # params, return + if not n: + # no params, return + n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"((?:[^"]|\\\")*)"\s*\)\s+()(\(.*\))\s*\)\s*$', form, re.S) + if not n: + # params, no return + n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s+(\(.*\))()\s*\)\s*\)\s*$', form, re.S) + if not n: + # no params, no return + n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"*()()\)\s*\)\s*$', form, re.S) + if not m and not n: + if re.search('^\(assert_return\s+\(get.*\).*\)$', form, re.S): + log("ignoring assert_return get"); + return + else: + raise Exception("unparsed assert_return: '%s'" % form) + if m and not n: + func = m.group(1) + if ' ' in func: + func = func.replace(' ', '\\') + + if m.group(2) == '': + args = [] + else: + #args = [re.split(' +', v)[1].replace('_', "") for v in re.split("\)\s*\(", m.group(2)[1:-1])] + # split arguments with ')spaces(', remove leading and tailing ) and ( + args_type_and_value = re.split(r'\)\s+\(', m.group(2)[1:-1]) + args_type_and_value = [s.replace('_', '') for s in args_type_and_value] + # args are in two forms: + # f32.const -0x1.000001fffffffffffp-50 + # v128.const i32x4 0 0 0 0 + args = [] + for arg in args_type_and_value: + # remove leading and tailing spaces, it might confuse following assertions + arg = arg.strip() + splitted = re.split('\s+', arg) + splitted = [s for s in splitted if s] + + if splitted[0] in ["i32.const", "i64.const"]: + assert(2 == len(splitted)), "{} should have two parts".format(splitted) + # in wast 01234 means 1234 + # in c 0123 means 83 in oct + number, _ = parse_simple_const_w_type(splitted[1], splitted[0][:3]) + args.append(str(number)) + elif splitted[0] in ["f32.const", "f64.const"]: + # let strtof or strtod handle original arguments + assert(2 == len(splitted)), "{} should have two parts".format(splitted) + args.append(splitted[1]) + elif "v128.const" == splitted[0]: + assert(len(splitted) > 2), "{} should have more than two parts".format(splitted) + numbers, _ = cast_v128_to_i64x2(splitted[2:], 'v128', splitted[1]) + + assert(len(numbers) == 2), "has to reform arguments into i64x2" + args.append("{}\{}".format(numbers[0], numbers[1])) + elif "ref.null" == splitted[0]: + args.append("null") + elif "ref.extern" == splitted[0]: + number, _ = parse_simple_const_w_type(splitted[1], splitted[0]) + args.append(str(number)) + else: + assert(0), "an unkonwn parameter type" + + if m.group(3) == '': + returns= [] + else: + returns = re.split("\)\s*\(", m.group(3)[1:-1]) + # processed numbers in strings + expected = [parse_assertion_value(v)[1] for v in returns] + test_assert(r, opts, "return", "%s %s" % (func, " ".join(args)), ",".join(expected)) + elif not m and n: + module = os.path.join(temp_file_directory,n.group(1)) + # assume the cmd is (assert_return(invoke $ABC "func")). + # run the ABC.wasm firstly + if test_aot: + r = compile_wasm_to_aot(module+".wasm", module+".aot", True, opts, r) + try: + assert_prompt(r, ['Compile success'], opts.start_timeout, False) + except: + _, exc, _ = sys.exc_info() + log("Run wamrc failed:\n got: '%s'" % r.buf) + sys.exit(1) + r = run_wasm_with_repl(module+".wasm", module+".aot", opts, r) + else: + r = run_wasm_with_repl(module+".wasm", None, opts, r) + # Wait for the initial prompt + try: + assert_prompt(r, ['webassembly> '], opts.start_timeout, False) + except: + _, exc, _ = sys.exc_info() + raise Exception("Failed:\n expected: '%s'\n got: '%s'" % \ + (repr(exc), r.buf)) + func = n.group(2) + if ' ' in func: + func = func.replace(' ', '\\') + + if n.group(3) == '': + args=[] + else: + args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", n.group(3)[1:-1])] + + # a workaround for "ref.null extern" and "ref.null func" + args = [ arg.replace('extern', 'null').replace('func', 'null') for arg in args] + + _, expected = parse_assertion_value(n.group(4)[1:-1]) + test_assert(r, opts, "return", "%s %s" % (func, " ".join(args)), expected) + +def test_assert_trap(r, opts, form): + # params + m = re.search('^\(assert_trap\s+\(invoke\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form) + # judge if assert_return cmd includes the module name + n = re.search('^\(assert_trap\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form, re.S) + if not m: + # no params + m = re.search('^\(assert_trap\s+\(invoke\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form) + if not m: + if not n: + # no params + n = re.search('^\(assert_trap\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form, re.S) + if not m and not n: + raise Exception("unparsed assert_trap: '%s'" % form) + + if m and not n: + func = m.group(1) + if m.group(2) == '': + args = [] + else: + args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])] + + # workaround for "ref.null extern" + args = [ arg.replace('extern', 'null').replace('func', 'null') for arg in args] + + expected = "Exception: %s" % m.group(3) + test_assert(r, opts, "trap", "%s %s" % (func, " ".join(args)), expected) + + elif not m and n: + module = n.group(1) + # will trigger the module named in assert_return(invoke $ABC). + # run the ABC.wasm firstly + if test_aot: + r = compile_wasm_to_aot(module+".wasm", module+".aot", True, opts, r) + try: + assert_prompt(r, ['Compile success'], opts.start_timeout, False) + except: + _, exc, _ = sys.exc_info() + log("Run wamrc failed:\n got: '%s'" % r.buf) + sys.exit(1) + r = run_wasm_with_repl(module+".wasm", module+".aot", opts, r) + else: + r = run_wasm_with_repl(module+".wasm", None, opts, r) + # Wait for the initial prompt + try: + assert_prompt(r, ['webassembly> '], opts.start_timeout, False) + except: + _, exc, _ = sys.exc_info() + raise Exception("Failed:\n expected: '%s'\n got: '%s'" % \ + (repr(exc), r.buf)) + + func = n.group(2) + if n.group(3) == '': + args = [] + else: + args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", n.group(3)[1:-1])] + expected = "Exception: %s" % n.group(4) + test_assert(r, opts, "trap", "%s %s" % (func, " ".join(args)), expected) + +def test_assert_exhaustion(r,opts,form): + # params + m = re.search('^\(assert_exhaustion\s+\(invoke\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form) + if not m: + # no params + m = re.search('^\(assert_exhaustion\s+\(invoke\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form) + if not m: + raise Exception("unparsed assert_exhaustion: '%s'" % form) + func = m.group(1) + if m.group(2) == '': + args = [] + else: + args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])] + expected = "Exception: %s\n" % m.group(3) + test_assert(r, opts, "exhaustion", "%s %s" % (func, " ".join(args)), expected) + +def do_invoke(r, opts, form): + # params + m = re.search('^\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*$', form) + if not m: + # no params + m = re.search('^\(invoke\s+"([^"]+)"\s*()\)\s*$', form) + if not m: + raise Exception("unparsed invoke: '%s'" % form) + func = m.group(1) + + if ' ' in func: + func = func.replace(' ', '\\') + + if m.group(2) == '': + args = [] + else: + args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])] + + log("Invoking %s(%s)" % ( + func, ", ".join([str(a) for a in args]))) + + invoke(r, opts, "%s %s" % (func, " ".join(args))) + +def skip_test(form, skip_list): + for s in skip_list: + if re.search(s, form): + return True + return False + +def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts): + log("Writing WAST module to '%s'" % wast_tempfile) + file(wast_tempfile, 'w').write(form) + log("Compiling WASM to '%s'" % wasm_tempfile) + + # default arguments + cmd = [opts.wast2wasm, + "--enable-thread", + "--no-check", + wast_tempfile, "-o", wasm_tempfile ] + + # optional arguments + if opts.ref_types: + cmd.append("--enable-reference-types") + cmd.append("--enable-bulk-memory") + + log("Running: %s" % " ".join(cmd)) + try: + subprocess.check_call(cmd) + except subprocess.CalledProcessError as e: + print(str(e)) + return False + + return True + +def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r): + log("Compiling AOT to '%s'" % aot_tempfile) + cmd = [opts.aot_compiler] + + if test_target == "x86_64": + cmd.append("--target=x86_64") + cmd.append("--cpu=skylake") + elif test_target == "i386": + cmd.append("--target=i386") + elif test_target == "aarch64": + cmd += ["--target=aarch64", "--cpu=cortex-a57"] + elif test_target == "armv7": + cmd += ["--target=armv7", "--target-abi=gnueabihf"] + elif test_target == "thumbv7": + cmd += ["--target=thumbv7", "--target-abi=gnueabihf", "--cpu=cortex-a15"] + elif test_target == "riscv64_lp64d": + cmd += ["--target=riscv64", "--target-abi=lp64d"] + elif test_target == "riscv64_lp64": + cmd += ["--target=riscv64", "--target-abi=lp64"] + else: + pass + + if opts.sgx: + cmd.append("-sgx") + + if opts.simd: + cmd.append("--enable-simd") + + if opts.ref_types: + cmd.append("--enable-ref-types") + cmd.append("--enable-bulk-memory") + + cmd += ["-o", aot_tempfile, wasm_tempfile] + + log("Running: %s" % " ".join(cmd)) + if not runner: + subprocess.check_call(cmd) + else: + if (r != None): + r.cleanup() + r = Runner(cmd, no_pty=opts.no_pty) + return r + +def run_wasm_with_repl(wasm_tempfile, aot_tempfile, opts, r): + if not test_aot: + log("Starting interpreter for module '%s'" % wasm_tempfile) + if opts.verbose: + cmd = [opts.interpreter, "--heap-size=0", "-v=5", "--repl", wasm_tempfile] + else: + cmd = [opts.interpreter, "--heap-size=0", "--repl", wasm_tempfile] + else: + log("Starting aot for module '%s'" % aot_tempfile) + if opts.verbose: + cmd = [opts.interpreter, "--heap-size=0", "-v=5", "--repl", aot_tempfile] + else: + cmd = [opts.interpreter, "--heap-size=0", "--repl", aot_tempfile] + + log("Running: %s" % " ".join(cmd)) + if (r != None): + r.cleanup() + r = Runner(cmd, no_pty=opts.no_pty) + return r + +def create_tmpfiles(wast_name): + tempfiles = [] + # make tempfile directory + if not os.path.exists(temp_file_directory): + os.mkdir(temp_file_directory) + + def makefile(name): + open(name, "w").close() + + # create temporal file with particular name + temp_wast_file = os.path.join(temp_file_directory, ""+ wast_name + ".wast") + if not os.path.exists(temp_wast_file): + makefile(temp_wast_file) + tempfiles.append(temp_wast_file) + + # now we define the same file name as wast for wasm & aot + wasm_file = wast_name +".wasm" + temp_wasm_file = os.path.join(temp_file_directory, wasm_file) + if not os.path.exists(temp_wasm_file): + makefile(temp_wasm_file) + tempfiles.append(temp_wasm_file) + + if test_aot: + aot_file = wast_name +".aot" + temp_aot_file =os.path.join(temp_file_directory, aot_file) + if not os.path.exists(temp_aot_file): + makefile(temp_aot_file) + tempfiles.append(temp_aot_file) + + # add these temp file to temporal repo, will be deleted when finishing the test + temp_file_repo.extend(tempfiles) + return tempfiles + +def test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, opts, r): + details_inside_ast = get_module_exp_from_assert(form) + log("module is ....'%s'"%details_inside_ast[0]) + log("exception is ....'%s'"%details_inside_ast[1]) + # parse the module + module = details_inside_ast[0] + expected = details_inside_ast[1] + + if not compile_wast_to_wasm(module, wast_tempfile, wasm_tempfile, opts): + raise Exception("compile wast to wasm failed") + + if test_aot: + r = compile_wasm_to_aot(wasm_tempfile, aot_tempfile, True, opts, r) + try: + assert_prompt(r, ['Compile success'], opts.start_timeout, True) + except: + _, exc, _ = sys.exc_info() + if (r.buf.find(expected) >= 0): + log("Out exception includes expected one, pass:") + log(" Expected: %s" % expected) + log(" Got: %s" % r.buf) + return + else: + log("Run wamrc failed:\n expected: '%s'\n got: '%s'" % \ + (expected, r.buf)) + sys.exit(1) + r = run_wasm_with_repl(wasm_tempfile, aot_tempfile, opts, r) + else: + r = run_wasm_with_repl(wasm_tempfile, None, opts, r) + + # Wait for the initial prompt + try: + assert_prompt(r, ['webassembly> '], opts.start_timeout, True) + except: + _, exc, _ = sys.exc_info() + if (r.buf.find(expected) >= 0): + log("Out exception includes expected one, pass:") + log(" Expected: %s" %expected) + log(" Got: %s" % r.buf) + else: + raise Exception("Failed:\n expected: '%s'\n got: '%s'" % \ + (expected, r.buf)) + +if __name__ == "__main__": + opts = parser.parse_args(sys.argv[1:]) + + if opts.aot: test_aot = True + # default x86_64 + test_target = opts.aot_target + + if opts.rundir: os.chdir(opts.rundir) + + if opts.log_file: log_file = open(opts.log_file, "a") + if opts.debug_file: debug_file = open(opts.debug_file, "a") + + if opts.interpreter.endswith(".py"): + SKIP_TESTS = PY_SKIP_TESTS + else: + SKIP_TESTS = C_SKIP_TESTS + + (t1fd, wast_tempfile) = tempfile.mkstemp(suffix=".wast") + (t2fd, wasm_tempfile) = tempfile.mkstemp(suffix=".wasm") + if test_aot: + (t3fd, aot_tempfile) = tempfile.mkstemp(suffix=".aot") + + try: + log("################################################") + log("### Testing %s" % opts.test_file.name) + log("################################################") + forms = read_forms(opts.test_file.read()) + r = None + + for form in forms: + # log("\n### Current Case is " + form + "\n") + if ";;" == form[0:2]: + log(form) + elif skip_test(form, SKIP_TESTS): + log("Skipping test: %s" % form[0:60]) + elif re.match("^\(assert_trap\s+\(module", form): + if test_aot: + test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, opts, r) + else: + test_assert_with_exception(form, wast_tempfile, wasm_tempfile, None, opts, r) + elif re.match("^\(assert_exhaustion\\b.*", form): + test_assert_exhaustion(r, opts, form) + elif re.match("^\(assert_unlinkable\\b.*", form): + if test_aot: + test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, opts, r) + else: + test_assert_with_exception(form, wast_tempfile, wasm_tempfile, None, opts, r) + elif re.match("^\(assert_malformed\\b.*", form): + # remove comments in wast + form,n = re.subn(";;.*\n", "", form) + m = re.match("^\(assert_malformed\s*\(module binary\s*(\".*\").*\)\s*\"(.*)\"\s*\)$", form, re.DOTALL) + + if m: + # workaround: spec test changes error message to "malformed" while iwasm still use "invalid" + error_msg = m.group(2).replace("malformed", "invalid") + log("Testing(malformed)") + f = file(wasm_tempfile, 'w') + s = m.group(1) + while s: + res = re.match("[^\"]*\"([^\"]*)\"(.*)", s, re.DOTALL) + f.write(res.group(1).replace("\\", "\\x").decode("string_escape")) + s = res.group(2) + f.close() + + # compile wasm to aot + if test_aot: + r = compile_wasm_to_aot(wasm_tempfile, aot_tempfile, True, opts, r) + try: + assert_prompt(r, ['Compile success'], opts.start_timeout, True) + except: + _, exc, _ = sys.exc_info() + if (r.buf.find(error_msg) >= 0): + log("Out exception includes expected one, pass:") + log(" Expected: %s" % error_msg) + log(" Got: %s" % r.buf) + else: + log("Run wamrc failed:\n expected: '%s'\n got: '%s'" % \ + (error_msg, r.buf)) + continue + cmd = [opts.interpreter, "--heap-size=0", "--repl", aot_tempfile] + else: + cmd = [opts.interpreter, "--heap-size=0", "--repl", wasm_tempfile] + log("Running: %s" % " ".join(cmd)) + output = subprocess.check_output(cmd) + + if (error_msg == "unexpected end of section or function") \ + and output.endswith("unexpected end\n"): + # one case in binary.wast + pass + elif (error_msg == "invalid value type") \ + and output.endswith("unexpected end\n"): + # one case in binary.wast + pass + elif (error_msg == "length out of bounds") \ + and output.endswith("unexpected end\n"): + # one case in custom.wast + pass + elif (error_msg == "integer representation too long") \ + and output.endswith("invalid section id\n"): + # several cases in binary-leb128.wast + pass + elif not error_msg in output: + raise Exception("Failed:\n expected: '%s'\n got: '%s'" % (error_msg, output[0:-1])) + else: + pass + elif re.match("^\(assert_malformed\s*\(module quote", form): + log("ignoring assert_malformed module quote") + else: + log("unrecognized assert_malformed") + elif re.match("^\(assert_return[_a-z]*_nan\\b.*", form): + log("ignoring assert_return_.*_nan") + pass + elif re.match(".*\(invoke\s+\$\\b.*", form): + # invoke a particular named module's function + if form.startswith("(assert_return"): + test_assert_return(r,opts,form) + elif form.startswith("(assert_trap"): + test_assert_trap(r,opts,form) + elif re.match("^\(module\\b.*", form): + # if the module includes the particular name startswith $ + m = re.search("^\(module\s+\$.\S+", form) + if m: + # get module name + module_name = re.split('\$', m.group(0).strip())[1] + if module_name: + # create temporal files + temp_files = create_tmpfiles(module_name) + if not compile_wast_to_wasm(form, temp_files[0], temp_files[1], opts): + raise Exception("compile wast to wasm failed") + + if test_aot: + r = compile_wasm_to_aot(temp_files[1], temp_files[2], True, opts, r) + try: + assert_prompt(r, ['Compile success'], opts.start_timeout, False) + except: + _, exc, _ = sys.exc_info() + log("Run wamrc failed:\n got: '%s'" % r.buf) + sys.exit(1) + r = run_wasm_with_repl(temp_files[1], temp_files[2], opts, r) + else: + r = run_wasm_with_repl(temp_files[1], None, opts, r) + else: + if not compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts): + raise Exception("compile wast to wasm failed") + + if test_aot: + r = compile_wasm_to_aot(wasm_tempfile, aot_tempfile, True, opts, r) + try: + assert_prompt(r, ['Compile success'], opts.start_timeout, False) + except: + _, exc, _ = sys.exc_info() + log("Run wamrc failed:\n got: '%s'" % r.buf) + sys.exit(1) + r = run_wasm_with_repl(wasm_tempfile, aot_tempfile, opts, r) + else: + r = run_wasm_with_repl(wasm_tempfile, None, opts, r) + + # Wait for the initial prompt + try: + assert_prompt(r, ['webassembly> '], opts.start_timeout, False) + except: + _, exc, _ = sys.exc_info() + raise Exception("Failed:\n expected: '%s'\n got: '%s'" % \ + (repr(exc), r.buf)) + + elif re.match("^\(assert_return\\b.*", form): + assert(r), "iwasm repl runtime should be not null" + test_assert_return(r, opts, form) + elif re.match("^\(assert_trap\\b.*", form): + test_assert_trap(r, opts, form) + elif re.match("^\(invoke\\b.*", form): + assert(r), "iwasm repl runtime should be not null" + do_invoke(r, opts, form) + elif re.match("^\(assert_invalid\\b.*", form): + if test_aot: + test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, opts, r) + else: + test_assert_with_exception(form, wast_tempfile, wasm_tempfile, None, opts, r) + + + elif re.match("^\(register\\b.*", form): + # get module's new name from the register cmd + name_new =re.split('\"',re.search('\".*\"',form).group(0))[1] + if name_new: + # if the register cmd include the new and old module name. + # like: (register "new" $old) + # we will replace the old with new name. + name_old = re.search('\$.*\)',form) + if name_old: + old_ = re.split('\W', re.search('\$.*\)',form).group(0))[1] + old_module = os.path.join(temp_file_directory,old_+".wasm") + else: + # like: (register "new") + # this kind of register cmd will be behind of a noramal module + # these modules' name are default temporal file name + # we replace them with new name. + old_module = wasm_tempfile + + new_module = os.path.join(current_work_directory,name_new+".wasm") + shutil.copyfile(old_module,new_module) + # add new_module copied from the old into temp_file_repo[] + temp_file_repo.append(new_module) + else: + # there is no name defined in register cmd + raise Exception("can not find module name from the register") + else: + raise Exception("unrecognized form '%s...'" % form[0:40]) + except Exception as e: + traceback.print_exc() + raise Exception("catch an exception {}".format(e)) + else: + sys.exit(0) + finally: + if not opts.no_cleanup: + log("Removing tempfiles") + os.remove(wast_tempfile) + os.remove(wasm_tempfile) + if test_aot: + os.remove(aot_tempfile) + + # remove the files under /tempfiles/ and copy of .wasm files + if temp_file_repo: + for t in temp_file_repo: + if(len(str(t))!=0 and os.path.exists(t)): + os.remove(t) + # remove /tempfiles/ directory + if os.path.exists(temp_file_directory): + shutil.rmtree(temp_file_directory) + + log("### End testing %s" % opts.test_file.name) + else: + log("Leaving tempfiles: %s" % ([wast_tempfile, wasm_tempfile])) diff --git a/tests/wamr-test-suites/spec-test-script/simd_ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/simd_ignore_cases.patch new file mode 100644 index 0000000000..87d3871e1d --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/simd_ignore_cases.patch @@ -0,0 +1,73 @@ +diff --git a/test/core/simd/simd_lane.wast b/test/core/simd/simd_lane.wast +index 9d4b5fd7..4656dd2b 100644 +--- a/test/core/simd/simd_lane.wast ++++ b/test/core/simd/simd_lane.wast +@@ -602,23 +602,23 @@ + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "invalid lane length") + (assert_malformed (module quote "(func (result v128) " +- "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15.0) " ++ "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15.0 " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") + (assert_malformed (module quote "(func (result v128) " +- "(i8x16.shuffle 0.5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) " ++ "(i8x16.shuffle 0.5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") + (assert_malformed (module quote "(func (result v128) " +- "(i8x16.shuffle -inf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) " ++ "(i8x16.shuffle -inf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") + (assert_malformed (module quote "(func (result v128) " +- "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 inf) " ++ "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 inf " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") + (assert_malformed (module quote "(func (result v128) " +- "(i8x16.shuffle nan 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) " ++ "(i8x16.shuffle nan 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") + +@@ -858,7 +858,7 @@ + (assert_return (invoke "as-if-condition-value" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const 0)) + (assert_return (invoke "as-return-value-1" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)) (v128.const i16x8 1 0 0 0 0 0 0 0)) + (assert_return (invoke "as-local_set-value" (v128.const i32x4 -1 -1 -1 -1)) (i32.const -1)) +-(assert_return (invoke "as-global_set-value-1" (v128.const f32x4 0 0 0 0)(f32.const 3.14)) (v128.const f32x4 3.14 0 0 0)) ++(assert_return (invoke "as-global_set-value-1" (v128.const f32x4 0 0 0 0) (f32.const 3.14)) (v128.const f32x4 3.14 0 0 0)) + + (assert_return (invoke "as-return-value-2" + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1) +@@ -870,7 +870,7 @@ + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 8 7 6 5 4 3 2 1)) + + (assert_return (invoke "as-local_set-value-1" (v128.const i64x2 -1 -1)) (i64.const -1)) +-(assert_return (invoke "as-global_set-value-3" (v128.const f64x2 0 0)(f64.const 3.14)) (v128.const f64x2 3.14 0)) ++(assert_return (invoke "as-global_set-value-3" (v128.const f64x2 0 0) (f64.const 3.14)) (v128.const f64x2 3.14 0)) + + ;; Non-nat lane index + +diff --git a/test/core/simd/simd_load.wast b/test/core/simd/simd_load.wast +index 4b2edc16..c7639218 100644 +--- a/test/core/simd/simd_load.wast ++++ b/test/core/simd/simd_load.wast +@@ -124,7 +124,7 @@ + (i8x16.swizzle (v128.load (i32.const 0)) (v128.load offset=15 (i32.const 1))) + ) + ) +-(assert_return(invoke "as-i8x16.swizzle-operand") (v128.const i8x16 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100)) ++(assert_return (invoke "as-i8x16.swizzle-operand") (v128.const i8x16 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100)) + + (module (memory 1) + (data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\00\01\02\03") +@@ -180,7 +180,7 @@ + + (assert_invalid + (module (memory 1) (func (drop (v128.load (local.get 2))))) +- "unknown local 2" ++ "unknown local" + ) + (assert_invalid + (module (memory 1) (func (drop (v128.load)))) diff --git a/tests/wamr-test-suites/spec-test-script/tail-call/return_call.wast b/tests/wamr-test-suites/spec-test-script/tail-call/return_call.wast new file mode 100644 index 0000000000..df75df403f --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/tail-call/return_call.wast @@ -0,0 +1,202 @@ +;; Test `return_call` operator + +(module + ;; Auxiliary definitions + (func $const-i32 (result i32) (i32.const 0x132)) + (func $const-i64 (result i64) (i64.const 0x164)) + (func $const-f32 (result f32) (f32.const 0xf32)) + (func $const-f64 (result f64) (f64.const 0xf64)) + + (func $id-i32 (param i32) (result i32) (get_local 0)) + (func $id-i64 (param i64) (result i64) (get_local 0)) + (func $id-f32 (param f32) (result f32) (get_local 0)) + (func $id-f64 (param f64) (result f64) (get_local 0)) + + (func $f32-i32 (param f32 i32) (result i32) (get_local 1)) + (func $i32-i64 (param i32 i64) (result i64) (get_local 1)) + (func $f64-f32 (param f64 f32) (result f32) (get_local 1)) + (func $i64-f64 (param i64 f64) (result f64) (get_local 1)) + + ;; Typing + + (func (export "type-i32") (result i32) (return_call $const-i32)) + (func (export "type-i64") (result i64) (return_call $const-i64)) + (func (export "type-f32") (result f32) (return_call $const-f32)) + (func (export "type-f64") (result f64) (return_call $const-f64)) + + (func (export "type-first-i32") (result i32) (return_call $id-i32 (i32.const 32))) + (func (export "type-first-i64") (result i64) (return_call $id-i64 (i64.const 64))) + (func (export "type-first-f32") (result f32) (return_call $id-f32 (f32.const 1.32))) + (func (export "type-first-f64") (result f64) (return_call $id-f64 (f64.const 1.64))) + + (func (export "type-second-i32") (result i32) + (return_call $f32-i32 (f32.const 32.1) (i32.const 32)) + ) + (func (export "type-second-i64") (result i64) + (return_call $i32-i64 (i32.const 32) (i64.const 64)) + ) + (func (export "type-second-f32") (result f32) + (return_call $f64-f32 (f64.const 64) (f32.const 32)) + ) + (func (export "type-second-f64") (result f64) + (return_call $i64-f64 (i64.const 64) (f64.const 64.1)) + ) + + ;; Recursion + + (func $fac-acc (export "fac-acc") (param i64 i64) (result i64) + (if (result i64) (i64.eqz (get_local 0)) + (then (get_local 1)) + (else + (return_call $fac-acc + (i64.sub (get_local 0) (i64.const 1)) + (i64.mul (get_local 0) (get_local 1)) + ) + ) + ) + ) + + (func $count (export "count") (param i64) (result i64) + (if (result i64) (i64.eqz (get_local 0)) + (then (get_local 0)) + (else (return_call $count (i64.sub (get_local 0) (i64.const 1)))) + ) + ) + + (func $even (export "even") (param i64) (result i32) + (if (result i32) (i64.eqz (get_local 0)) + (then (i32.const 44)) + (else (return_call $odd (i64.sub (get_local 0) (i64.const 1)))) + ) + ) + (func $odd (export "odd") (param i64) (result i32) + (if (result i32) (i64.eqz (get_local 0)) + (then (i32.const 99)) + (else (return_call $even (i64.sub (get_local 0) (i64.const 1)))) + ) + ) +) + +(assert_return (invoke "type-i32") (i32.const 0x132)) +(assert_return (invoke "type-i64") (i64.const 0x164)) +(assert_return (invoke "type-f32") (f32.const 0xf32)) +(assert_return (invoke "type-f64") (f64.const 0xf64)) + +(assert_return (invoke "type-first-i32") (i32.const 32)) +(assert_return (invoke "type-first-i64") (i64.const 64)) +(assert_return (invoke "type-first-f32") (f32.const 1.32)) +(assert_return (invoke "type-first-f64") (f64.const 1.64)) + +(assert_return (invoke "type-second-i32") (i32.const 32)) +(assert_return (invoke "type-second-i64") (i64.const 64)) +(assert_return (invoke "type-second-f32") (f32.const 32)) +(assert_return (invoke "type-second-f64") (f64.const 64.1)) + +(assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120)) +(assert_return + (invoke "fac-acc" (i64.const 25) (i64.const 1)) + (i64.const 7034535277573963776) +) + +(assert_return (invoke "count" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "count" (i64.const 1000)) (i64.const 0)) +(assert_return (invoke "count" (i64.const 1_000_000)) (i64.const 0)) + +(assert_return (invoke "even" (i64.const 0)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 1)) (i32.const 99)) +(assert_return (invoke "even" (i64.const 100)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 77)) (i32.const 99)) +(assert_return (invoke "even" (i64.const 1_000_000)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 1_000_001)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 0)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 1)) (i32.const 44)) +(assert_return (invoke "odd" (i64.const 200)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 77)) (i32.const 44)) +(assert_return (invoke "odd" (i64.const 1_000_000)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 999_999)) (i32.const 44)) + + +;; Invalid typing + +(assert_invalid + (module + (func $type-void-vs-num (result i32) (return_call 1) (i32.const 0)) + (func) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-num-vs-num (result i32) (return_call 1) (i32.const 0)) + (func (result i64) (i64.const 1)) + ) + "type mismatch" +) + +(assert_invalid + (module + (func $arity-0-vs-1 (return_call 1)) + (func (param i32)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $arity-0-vs-2 (return_call 1)) + (func (param f64 i32)) + ) + "type mismatch" +) + +(module + (func $arity-1-vs-0 (i32.const 1) (return_call 1)) + (func) +) + +(module + (func $arity-2-vs-0 (f64.const 2) (i32.const 1) (return_call 1)) + (func) +) + +(assert_invalid + (module + (func $type-first-void-vs-num (return_call 1 (nop) (i32.const 1))) + (func (param i32 i32)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-second-void-vs-num (return_call 1 (i32.const 1) (nop))) + (func (param i32 i32)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-first-num-vs-num (return_call 1 (f64.const 1) (i32.const 1))) + (func (param i32 f64)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-second-num-vs-num (return_call 1 (i32.const 1) (f64.const 1))) + (func (param f64 i32)) + ) + "type mismatch" +) + + +;; Unbound function + +(assert_invalid + (module (func $unbound-func (return_call 1))) + "unknown function" +) +(assert_invalid + (module (func $large-func (return_call 1012321300))) + "unknown function" +) diff --git a/tests/wamr-test-suites/spec-test-script/tail-call/return_call_indirect.wast b/tests/wamr-test-suites/spec-test-script/tail-call/return_call_indirect.wast new file mode 100644 index 0000000000..515f15d5d0 --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/tail-call/return_call_indirect.wast @@ -0,0 +1,511 @@ +;; Test `return_call_indirect` operator + +(module + ;; Auxiliary definitions + (type $proc (func)) + (type $out-i32 (func (result i32))) + (type $out-i64 (func (result i64))) + (type $out-f32 (func (result f32))) + (type $out-f64 (func (result f64))) + (type $over-i32 (func (param i32) (result i32))) + (type $over-i64 (func (param i64) (result i64))) + (type $over-f32 (func (param f32) (result f32))) + (type $over-f64 (func (param f64) (result f64))) + (type $f32-i32 (func (param f32 i32) (result i32))) + (type $i32-i64 (func (param i32 i64) (result i64))) + (type $f64-f32 (func (param f64 f32) (result f32))) + (type $i64-f64 (func (param i64 f64) (result f64))) + (type $over-i32-duplicate (func (param i32) (result i32))) + (type $over-i64-duplicate (func (param i64) (result i64))) + (type $over-f32-duplicate (func (param f32) (result f32))) + (type $over-f64-duplicate (func (param f64) (result f64))) + + (func $const-i32 (type $out-i32) (i32.const 0x132)) + (func $const-i64 (type $out-i64) (i64.const 0x164)) + (func $const-f32 (type $out-f32) (f32.const 0xf32)) + (func $const-f64 (type $out-f64) (f64.const 0xf64)) + + (func $id-i32 (type $over-i32) (get_local 0)) + (func $id-i64 (type $over-i64) (get_local 0)) + (func $id-f32 (type $over-f32) (get_local 0)) + (func $id-f64 (type $over-f64) (get_local 0)) + + (func $i32-i64 (type $i32-i64) (get_local 1)) + (func $i64-f64 (type $i64-f64) (get_local 1)) + (func $f32-i32 (type $f32-i32) (get_local 1)) + (func $f64-f32 (type $f64-f32) (get_local 1)) + + (func $over-i32-duplicate (type $over-i32-duplicate) (get_local 0)) + (func $over-i64-duplicate (type $over-i64-duplicate) (get_local 0)) + (func $over-f32-duplicate (type $over-f32-duplicate) (get_local 0)) + (func $over-f64-duplicate (type $over-f64-duplicate) (get_local 0)) + + (table anyfunc + (elem + $const-i32 $const-i64 $const-f32 $const-f64 + $id-i32 $id-i64 $id-f32 $id-f64 + $f32-i32 $i32-i64 $f64-f32 $i64-f64 + $fac $fac-acc $even $odd + $over-i32-duplicate $over-i64-duplicate + $over-f32-duplicate $over-f64-duplicate + ) + ) + + ;; Syntax + + (func + (return_call_indirect (i32.const 0)) + (return_call_indirect (param i64) (i64.const 0) (i32.const 0)) + (return_call_indirect (param i64) (param) (param f64 i32 i64) + (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0) + ) + (return_call_indirect (result) (i32.const 0)) + ) + + (func (result i32) + (return_call_indirect (result i32) (i32.const 0)) + (return_call_indirect (result i32) (result) (i32.const 0)) + (return_call_indirect (param i64) (result i32) (i64.const 0) (i32.const 0)) + (return_call_indirect + (param) (param i64) (param) (param f64 i32 i64) (param) (param) + (result) (result i32) (result) (result) + (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0) + ) + ) + + (func (result i64) + (return_call_indirect (type $over-i64) (param i64) (result i64) + (i64.const 0) (i32.const 0) + ) + ) + + ;; Typing + + (func (export "type-i32") (result i32) + (return_call_indirect (type $out-i32) (i32.const 0)) + ) + (func (export "type-i64") (result i64) + (return_call_indirect (type $out-i64) (i32.const 1)) + ) + (func (export "type-f32") (result f32) + (return_call_indirect (type $out-f32) (i32.const 2)) + ) + (func (export "type-f64") (result f64) + (return_call_indirect (type $out-f64) (i32.const 3)) + ) + + (func (export "type-index") (result i64) + (return_call_indirect (type $over-i64) (i64.const 100) (i32.const 5)) + ) + + (func (export "type-first-i32") (result i32) + (return_call_indirect (type $over-i32) (i32.const 32) (i32.const 4)) + ) + (func (export "type-first-i64") (result i64) + (return_call_indirect (type $over-i64) (i64.const 64) (i32.const 5)) + ) + (func (export "type-first-f32") (result f32) + (return_call_indirect (type $over-f32) (f32.const 1.32) (i32.const 6)) + ) + (func (export "type-first-f64") (result f64) + (return_call_indirect (type $over-f64) (f64.const 1.64) (i32.const 7)) + ) + + (func (export "type-second-i32") (result i32) + (return_call_indirect (type $f32-i32) + (f32.const 32.1) (i32.const 32) (i32.const 8) + ) + ) + (func (export "type-second-i64") (result i64) + (return_call_indirect (type $i32-i64) + (i32.const 32) (i64.const 64) (i32.const 9) + ) + ) + (func (export "type-second-f32") (result f32) + (return_call_indirect (type $f64-f32) + (f64.const 64) (f32.const 32) (i32.const 10) + ) + ) + (func (export "type-second-f64") (result f64) + (return_call_indirect (type $i64-f64) + (i64.const 64) (f64.const 64.1) (i32.const 11) + ) + ) + + ;; Dispatch + + (func (export "dispatch") (param i32 i64) (result i64) + (return_call_indirect (type $over-i64) (get_local 1) (get_local 0)) + ) + + (func (export "dispatch-structural") (param i32) (result i64) + (return_call_indirect (type $over-i64-duplicate) + (i64.const 9) (get_local 0) + ) + ) + + ;; Recursion + + (func $fac (export "fac") (type $over-i64) + (return_call_indirect (param i64 i64) (result i64) + (get_local 0) (i64.const 1) (i32.const 13) + ) + ) + + (func $fac-acc (param i64 i64) (result i64) + (if (result i64) (i64.eqz (get_local 0)) + (then (get_local 1)) + (else + (return_call_indirect (param i64 i64) (result i64) + (i64.sub (get_local 0) (i64.const 1)) + (i64.mul (get_local 0) (get_local 1)) + (i32.const 13) + ) + ) + ) + ) + + (func $even (export "even") (param i32) (result i32) + (if (result i32) (i32.eqz (get_local 0)) + (then (i32.const 44)) + (else + (return_call_indirect (type $over-i32) + (i32.sub (get_local 0) (i32.const 1)) + (i32.const 15) + ) + ) + ) + ) + (func $odd (export "odd") (param i32) (result i32) + (if (result i32) (i32.eqz (get_local 0)) + (then (i32.const 99)) + (else + (return_call_indirect (type $over-i32) + (i32.sub (get_local 0) (i32.const 1)) + (i32.const 14) + ) + ) + ) + ) +) + +(assert_return (invoke "type-i32") (i32.const 0x132)) +(assert_return (invoke "type-i64") (i64.const 0x164)) +(assert_return (invoke "type-f32") (f32.const 0xf32)) +(assert_return (invoke "type-f64") (f64.const 0xf64)) + +(assert_return (invoke "type-index") (i64.const 100)) + +(assert_return (invoke "type-first-i32") (i32.const 32)) +(assert_return (invoke "type-first-i64") (i64.const 64)) +(assert_return (invoke "type-first-f32") (f32.const 1.32)) +(assert_return (invoke "type-first-f64") (f64.const 1.64)) + +(assert_return (invoke "type-second-i32") (i32.const 32)) +(assert_return (invoke "type-second-i64") (i64.const 64)) +(assert_return (invoke "type-second-f32") (f32.const 32)) +(assert_return (invoke "type-second-f64") (f64.const 64.1)) + +(assert_return (invoke "dispatch" (i32.const 5) (i64.const 2)) (i64.const 2)) +(assert_return (invoke "dispatch" (i32.const 5) (i64.const 5)) (i64.const 5)) +(assert_return (invoke "dispatch" (i32.const 12) (i64.const 5)) (i64.const 120)) +(assert_return (invoke "dispatch" (i32.const 17) (i64.const 2)) (i64.const 2)) +(assert_trap (invoke "dispatch" (i32.const 0) (i64.const 2)) "indirect call type mismatch") +(assert_trap (invoke "dispatch" (i32.const 15) (i64.const 2)) "indirect call type mismatch") +(assert_trap (invoke "dispatch" (i32.const 20) (i64.const 2)) "undefined element") +(assert_trap (invoke "dispatch" (i32.const -1) (i64.const 2)) "undefined element") +(assert_trap (invoke "dispatch" (i32.const 1213432423) (i64.const 2)) "undefined element") + +(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9)) +(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9)) +(assert_return (invoke "dispatch-structural" (i32.const 12)) (i64.const 362880)) +(assert_return (invoke "dispatch-structural" (i32.const 17)) (i64.const 9)) +(assert_trap (invoke "dispatch-structural" (i32.const 11)) "indirect call type mismatch") +(assert_trap (invoke "dispatch-structural" (i32.const 16)) "indirect call type mismatch") + +(assert_return (invoke "fac" (i64.const 0)) (i64.const 1)) +(assert_return (invoke "fac" (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac" (i64.const 5)) (i64.const 120)) +(assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776)) + +(assert_return (invoke "even" (i32.const 0)) (i32.const 44)) +(assert_return (invoke "even" (i32.const 1)) (i32.const 99)) +(assert_return (invoke "even" (i32.const 100)) (i32.const 44)) +(assert_return (invoke "even" (i32.const 77)) (i32.const 99)) +(assert_return (invoke "even" (i32.const 100_000)) (i32.const 44)) +(assert_return (invoke "even" (i32.const 111_111)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 0)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 1)) (i32.const 44)) +(assert_return (invoke "odd" (i32.const 200)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 77)) (i32.const 44)) +(assert_return (invoke "odd" (i32.const 200_002)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 300_003)) (i32.const 44)) + + +;; Invalid syntax + +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 anyfunc)" + "(func (result i32)" + " (return_call_indirect (type $sig) (result i32) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 anyfunc)" + "(func (result i32)" + " (return_call_indirect (param i32) (type $sig) (result i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 anyfunc)" + "(func (result i32)" + " (return_call_indirect (param i32) (result i32) (type $sig)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 anyfunc)" + "(func (result i32)" + " (return_call_indirect (result i32) (type $sig) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 anyfunc)" + "(func (result i32)" + " (return_call_indirect (result i32) (param i32) (type $sig)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(table 0 anyfunc)" + "(func (result i32)" + " (return_call_indirect (result i32) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) + +(assert_malformed + (module quote + "(table 0 anyfunc)" + "(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0)))" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func))" + "(table 0 anyfunc)" + "(func (result i32)" + " (return_call_indirect (type $sig) (result i32) (i32.const 0))" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 anyfunc)" + "(func (result i32)" + " (return_call_indirect (type $sig) (result i32) (i32.const 0))" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 anyfunc)" + "(func" + " (return_call_indirect (type $sig) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32 i32) (result i32)))" + "(table 0 anyfunc)" + "(func (result i32)" + " (return_call_indirect (type $sig) (param i32) (result i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "inline function type" +) + +;; Invalid typing + +(assert_invalid + (module + (type (func)) + (func $no-table (return_call_indirect (type 0) (i32.const 0))) + ) + "unknown table" +) + +(assert_invalid + (module + (type (func)) + (table 0 anyfunc) + (func $type-void-vs-num (i32.eqz (return_call_indirect (type 0) (i32.const 0)))) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (result i64))) + (table 0 anyfunc) + (func $type-num-vs-num (i32.eqz (return_call_indirect (type 0) (i32.const 0)))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type (func (param i32))) + (table 0 anyfunc) + (func $arity-0-vs-1 (return_call_indirect (type 0) (i32.const 0))) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param f64 i32))) + (table 0 anyfunc) + (func $arity-0-vs-2 (return_call_indirect (type 0) (i32.const 0))) + ) + "type mismatch" +) + +(module + (type (func)) + (table 0 anyfunc) + (func $arity-1-vs-0 (return_call_indirect (type 0) (i32.const 1) (i32.const 0))) +) + +(module + (type (func)) + (table 0 anyfunc) + (func $arity-2-vs-0 + (return_call_indirect (type 0) (f64.const 2) (i32.const 1) (i32.const 0)) + ) +) + +(assert_invalid + (module + (type (func (param i32))) + (table 0 anyfunc) + (func $type-func-void-vs-i32 (return_call_indirect (type 0) (i32.const 1) (nop))) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param i32))) + (table 0 anyfunc) + (func $type-func-num-vs-i32 (return_call_indirect (type 0) (i32.const 0) (i64.const 1))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type (func (param i32 i32))) + (table 0 anyfunc) + (func $type-first-void-vs-num + (return_call_indirect (type 0) (nop) (i32.const 1) (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param i32 i32))) + (table 0 anyfunc) + (func $type-second-void-vs-num + (return_call_indirect (type 0) (i32.const 1) (nop) (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param i32 f64))) + (table 0 anyfunc) + (func $type-first-num-vs-num + (return_call_indirect (type 0) (f64.const 1) (i32.const 1) (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param f64 i32))) + (table 0 anyfunc) + (func $type-second-num-vs-num + (return_call_indirect (type 0) (i32.const 1) (f64.const 1) (i32.const 0)) + ) + ) + "type mismatch" +) + + +;; Unbound type + +(assert_invalid + (module + (table 0 anyfunc) + (func $unbound-type (return_call_indirect (type 1) (i32.const 0))) + ) + "unknown type" +) +(assert_invalid + (module + (table 0 anyfunc) + (func $large-type (return_call_indirect (type 1012321300) (i32.const 0))) + ) + "unknown type" +) + + +;; Unbound function in table + +(assert_invalid + (module (table anyfunc (elem 0 0))) + "unknown function" +) diff --git a/tests/wamr-test-suites/spec-test-script/thread_proposal_ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/thread_proposal_ignore_cases.patch new file mode 100644 index 0000000000..4734318495 --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/thread_proposal_ignore_cases.patch @@ -0,0 +1,198 @@ +diff --git a/test/core/binary.wast b/test/core/binary.wast +index b9fa438c..a5711dd3 100644 +--- a/test/core/binary.wast ++++ b/test/core/binary.wast +@@ -45,7 +45,7 @@ + (assert_malformed (module binary "\00asm\00\00\00\01") "unknown binary version") + + ;; Invalid section id. +-(assert_malformed (module binary "\00asm" "\01\00\00\00" "\0c\00") "malformed section id") ++;; (assert_malformed (module binary "\00asm" "\01\00\00\00" "\0c\00") "malformed section id") + (assert_malformed (module binary "\00asm" "\01\00\00\00" "\7f\00") "malformed section id") + (assert_malformed (module binary "\00asm" "\01\00\00\00" "\80\00\01\00") "malformed section id") + (assert_malformed (module binary "\00asm" "\01\00\00\00" "\81\00\01\00") "malformed section id") +@@ -68,7 +68,7 @@ + "\01" ;; call_indirect reserved byte is not equal to zero! + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + ;; call_indirect reserved byte should not be a "long" LEB128 zero. +@@ -87,7 +87,7 @@ + "\80\00" ;; call_indirect reserved byte + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + ;; Same as above for 3, 4, and 5-byte zero encodings. +@@ -106,7 +106,7 @@ + "\80\80\00" ;; call_indirect reserved byte + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + (assert_malformed +@@ -124,7 +124,7 @@ + "\80\80\80\00" ;; call_indirect reserved byte + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + (assert_malformed +@@ -142,7 +142,7 @@ + "\80\80\80\80\00" ;; call_indirect reserved byte + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + ;; memory.grow reserved byte equal to zero. +@@ -162,7 +162,7 @@ + "\1a" ;; drop + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + ;; memory.grow reserved byte should not be a "long" LEB128 zero. +@@ -182,7 +182,7 @@ + "\1a" ;; drop + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + ;; Same as above for 3, 4, and 5-byte zero encodings. +@@ -202,7 +202,7 @@ + "\1a" ;; drop + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + (assert_malformed +@@ -221,7 +221,7 @@ + "\1a" ;; drop + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + (assert_malformed +@@ -240,7 +240,7 @@ + "\1a" ;; drop + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + ;; memory.size reserved byte equal to zero. +@@ -259,7 +259,7 @@ + "\1a" ;; drop + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + ;; memory.size reserved byte should not be a "long" LEB128 zero. +@@ -278,7 +278,7 @@ + "\1a" ;; drop + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + ;; Same as above for 3, 4, and 5-byte zero encodings. +@@ -297,7 +297,7 @@ + "\1a" ;; drop + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + (assert_malformed +@@ -315,7 +315,7 @@ + "\1a" ;; drop + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + (assert_malformed +@@ -333,7 +333,7 @@ + "\1a" ;; drop + "\0b" ;; end + ) +- "zero flag expected" ++ "zero byte expected" + ) + + ;; No more than 2^32 locals. +@@ -745,6 +745,7 @@ + ) + + ;; 2 elem segment declared, 1 given ++(; + (assert_malformed + (module binary + "\00asm" "\01\00\00\00" +@@ -761,6 +762,7 @@ + ) + "unexpected end" + ) ++;) + + ;; 1 elem segment declared, 2 given + (assert_malformed +diff --git a/test/core/elem.wast b/test/core/elem.wast +index 1ea2b061..f5440e07 100644 +--- a/test/core/elem.wast ++++ b/test/core/elem.wast +@@ -354,6 +354,7 @@ + (assert_return (invoke $module1 "call-8") (i32.const 65)) + (assert_return (invoke $module1 "call-9") (i32.const 66)) + ++(; + (module $module2 + (type $out-i32 (func (result i32))) + (import "module1" "shared-table" (table 10 funcref)) +@@ -379,3 +380,4 @@ + (assert_return (invoke $module1 "call-7") (i32.const 67)) + (assert_return (invoke $module1 "call-8") (i32.const 69)) + (assert_return (invoke $module1 "call-9") (i32.const 70)) ++;) +diff --git a/test/core/thread.wast b/test/core/thread.wast +index c3456a61..83fc2815 100644 +--- a/test/core/thread.wast ++++ b/test/core/thread.wast +@@ -2,6 +2,7 @@ + (memory (export "shared") 1 1 shared) + ) + ++(; + (thread $T1 (shared (module $Mem)) + (register "mem" $Mem) + (module +@@ -26,3 +27,4 @@ + + (wait $T1) + (wait $T2) ++;) diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh new file mode 100755 index 0000000000..25333545d9 --- /dev/null +++ b/tests/wamr-test-suites/test_wamr.sh @@ -0,0 +1,628 @@ +#!/usr/bin/env bash + +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +function DEBUG() { + [[ -n $(env | grep "\") ]] && $@ +} +DEBUG set -xEevuo pipefail + +function help() +{ + echo "test_wamr.sh [options]" + echo "-s {suite_name} test only one suite (spec)" + echo "-c clean previous test results, not start test" + echo "-b use the wabt binary release package instead of compiling from the source code" + echo "-t set compile type of iwasm(classic-interp\fast-interp\jit\aot)" + echo "-m set compile target of iwasm(x86_64\x86_32\armv7_vfp\thumbv7_vfp\riscv64_lp64d\riscv64_lp64)" + echo "-M enable the multi module feature" + echo "-p enable multi thread feature" + echo "-S enable SIMD" + echo "-x test SGX" +} + +OPT_PARSED="" +WABT_BINARY_RELEASE="NO" +#default type +TYPE=("classic-interp" "fast-interp" "jit" "aot") +#default target +TARGET="X86_64" +ENABLE_MULTI_MODULE=0 +ENABLE_MULTI_THREAD=0 +COLLECT_CODE_COVERAGE=0 +ENABLE_SIMD=0 +#unit test case arrary +TEST_CASE_ARR=() +SGX_OPT="" +# enable reference-types and bulk-memory by default +# as they are finished and merged into spec +ENABLE_REF_TYPES=1 +PLATFORM=$(uname -s | tr A-Z a-z) + +while getopts ":s:cabt:m:MCpSxr" opt +do + OPT_PARSED="TRUE" + case $opt in + s) + TEST_CASE_ARR+=($OPTARG) + # get next suite if there are multiple vaule in -s + eval "nxarg=\${$((OPTIND))}" + # just get test cases, loop until the next symbol '-' + # IN ====> -s spec wasi unit -t fast-classic + # GET ====> spec wasi unit + while [[ "${nxarg}" != -* && ${nxarg} ]]; + do + TEST_CASE_ARR+=(${nxarg}) + OPTIND=$((OPTIND+1)) + eval "nxarg=\${$((OPTIND))}" + done + echo "test following cases: ${TEST_CASE_ARR[@]}" + ;; + c) + read -t 5 -p "Are you sure to delete all reports. y/n " cmd + if [[ $cmd == "y" && $(ls -A workspace/report) ]];then + rm -r workspace/report/* + echo "cleaned all reports" + fi + exit 0;; + a) + TEST_ALL_AOT_RUNTIME="all" + echo "test all runtimes in sightglass_aot" + ;; + b) + WABT_BINARY_RELEASE="YES" + echo "use a WABT binary release instead of compiling from source code" + ;; + t) + echo "set compile type of wamr " ${OPTARG} + if [[ ${OPTARG} != "classic-interp" && ${OPTARG} != "fast-interp" \ + && ${OPTARG} != "jit" && ${OPTARG} != "aot" ]]; then + echo "*----- please varify a type of compile when using -t! -----*" + help + exit 1 + fi + + TYPE=(${OPTARG}) + ;; + 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 + ;; + M) + echo "enable multi module feature" + ENABLE_MULTI_MODULE=1 + ;; + C) + echo "enable code coverage" + COLLECT_CODE_COVERAGE=1 + ;; + p) + echo "enable multi thread feature" + ENABLE_MULTI_THREAD=1 + # Disable reference-types when multi-thread is enabled + echo "disable reference-types for multi thread" + ENABLE_REF_TYPES=0 + ;; + S) + echo "enable SIMD feature" + ENABLE_SIMD=1 + ;; + x) + echo "test SGX" + SGX_OPT="--sgx" + ;; + ?) + help + exit 1;; + esac +done + +# Parameters are not allowed, use options instead +if [ -z "$OPT_PARSED" ]; +then + if [ ! -z "$1" ]; + then + help + exit 1 + fi +fi + +mkdir -p workspace +cd workspace + +readonly WORK_DIR=$PWD + +readonly DATE=$(date +%Y-%m-%d_%H:%M:%S) +readonly REPORT_DIR=${WORK_DIR}/report/${DATE} +mkdir -p ${REPORT_DIR} + +# TODO: a strong assumation about a link to the WAMR project +readonly WAMR_DIR=${WORK_DIR}/../../.. + +if [[ ${SGX_OPT} == "--sgx" ]];then + readonly IWASM_LINUX_ROOT_DIR="${WAMR_DIR}/product-mini/platforms/linux-sgx" + readonly IWASM_CMD="${WAMR_DIR}/product-mini/platforms/linux-sgx/enclave-sample/iwasm" +else + readonly IWASM_LINUX_ROOT_DIR="${WAMR_DIR}/product-mini/platforms/${PLATFORM}" + readonly IWASM_CMD="${WAMR_DIR}/product-mini/platforms/${PLATFORM}/build/iwasm" +fi + +readonly WAMRC_CMD="${WAMR_DIR}/wamr-compiler/build/wamrc" + +readonly CLASSIC_INTERP_COMPILE_FLAGS="\ + -DWAMR_BUILD_TARGET=${TARGET} \ + -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=0 \ + -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=0 \ + -DWAMR_BUILD_SPEC_TEST=1 \ + -DWAMR_BUILD_MULTI_MODULE=${ENABLE_MULTI_MODULE} \ + -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + +readonly FAST_INTERP_COMPILE_FLAGS="\ + -DWAMR_BUILD_TARGET=${TARGET} \ + -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=1 \ + -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=0 \ + -DWAMR_BUILD_SPEC_TEST=1 \ + -DWAMR_BUILD_MULTI_MODULE=${ENABLE_MULTI_MODULE} \ + -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + +# jit: report linking error if set COLLECT_CODE_COVERAGE, +# now we don't collect code coverage of jit type +readonly JIT_COMPILE_FLAGS="\ + -DWAMR_BUILD_TARGET=${TARGET} \ + -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_INTERP=0 \ + -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_AOT=1 \ + -DWAMR_BUILD_SPEC_TEST=1 \ + -DWAMR_BUILD_MULTI_MODULE=${ENABLE_MULTI_MODULE}" + +readonly AOT_COMPILE_FLAGS="\ + -DWAMR_BUILD_TARGET=${TARGET} \ + -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_INTERP=0 \ + -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=1 \ + -DWAMR_BUILD_SPEC_TEST=1 \ + -DWAMR_BUILD_MULTI_MODULE=${ENABLE_MULTI_MODULE} \ + -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}" + +readonly COMPILE_FLAGS=( + "${CLASSIC_INTERP_COMPILE_FLAGS}" + "${FAST_INTERP_COMPILE_FLAGS}" + "${JIT_COMPILE_FLAGS}" + "${AOT_COMPILE_FLAGS}" + ) + +# TODO: with libiwasm.so only +function unit_test() +{ + echo "Now start unit tests" + + cd ${WORK_DIR} + readonly UNIT_CASES="wasm-vm host-tool utils" + + echo "Build unit test" + touch ${REPORT_DIR}/unit_test_report.txt + + for compile_flag in "${COMPILE_FLAGS[@]}"; do + echo "Build unit test with compile flags with " ${compile_flag} + + # keep going and do not care if it is success or not + make -ki clean | true + cmake ${compile_flag} ${WORK_DIR}/../../unit && make + if [ "$?" != 0 ];then + echo -e "\033[31mbuild unit test failed, you may need to change wamr into dev/aot branch and ensure llvm is built \033[0m" + exit 1 + fi + + echo ${compile_flag} >> ${REPORT_DIR}/unit_test_report.txt + + for case in ${UNIT_CASES} + do + echo "run ${case} ..." + cd ./${case}/ + ./${case/-/_}"_test" | tee -a ${REPORT_DIR}/unit_test_report.txt + cd - + echo "finish ${case}" + done + done + + echo "Finish unit tests" +} + +function sightglass_test() +{ + echo "Now start sightglass benchmark tests" + + cd ${WORK_DIR}/../sightglass/benchmarks + + # build iwasm first + if [[ $1 == "classic-interp" || $1 == "fast-interp" ]];then + ./test_interp.sh ${SGX_OPT} + cp report.txt ${REPORT_DIR}/sightglass_$1_test_report.txt + fi + + if [[ $1 == "aot" ]];then + ./test_aot.sh ${SGX_OPT} + cp report.txt ${REPORT_DIR}/sightglass_aot_test_report.txt + fi + + if [[ $1 == "jit" ]];then + [[ $TEST_ALL_AOT_RUNTIME ]] && ./test_aot.sh ${TEST_ALL_AOT_RUNTIME} ${SGX_OPT} \ + || ./test_aot.sh jit ${SGX_OPT} + cp report.txt ${REPORT_DIR}/sightglass_jit_test_report.txt + fi + + echo "Finish sightglass benchmark tests" +} + +# TODO: with iwasm only +function spec_test() +{ + echo "Now start spec tests" + touch ${REPORT_DIR}/spec_test_report.txt + + cd ${WORK_DIR} + if [ ! -d "spec" ];then + echo "spec not exist, clone it from github" + git clone -b master --single-branch https://github.com/WebAssembly/spec + fi + + pushd spec + + # restore and clean everything + git reset --hard HEAD + + # update basic test cases + echo "update spec test cases" + git fetch origin master + # restore from XX_ignore_cases.patch + # resotre branch + git checkout -B master + git reset --hard 397399a70565609bf142d211891724e21bffd01f + git apply ../../spec-test-script/ignore_cases.patch + + # udpate thread cases + if [ ${ENABLE_MULTI_THREAD} == 1 ]; then + echo "checkout spec for threads proposal" + if [[ -z $(git remote -v | grep "\") ]]; then + git remote add threads https://github.com/WebAssembly/threads + fi + + # fetch spec for threads proposal + git fetch threads + git reset --hard HEAD + git checkout threads/main + + git apply ../../spec-test-script/thread_proposal_ignore_cases.patch + fi + + # udpate SIMD cases + if [[ ${ENABLE_SIMD} == 1 ]]; then + echo "checkout spec for SIMD proposal" + # check spec test cases for simd + if [[ -z $(git remote | grep "\") ]]; then + git remote add simd https://github.com/WebAssembly/simd.git + fi + + git fetch simd + git checkout simd/main -- test/core/simd + git checkout simd/main -- interpreter + + echo "compile the reference intepreter" + pushd interpreter + make opt + popd + + git apply ../../spec-test-script/simd_ignore_cases.patch + fi + + popd + echo $(pwd) + + if [ ${WABT_BINARY_RELEASE} == "YES" ]; then + echo "download a binary release and install" + local WAT2WASM=${WORK_DIR}/wabt/out/gcc/Release/wat2wasm + if [ ! -f ${WAT2WASM} ]; then + case ${PLATFORM} in + linux) + WABT_PLATFORM=ubuntu + ;; + darwin) + WABT_PLATFORM=macos + ;; + *) + echo "wabt platform for ${PLATFORM} in unknown" + exit 1 + ;; + esac + if [ ! -f /tmp/wabt-1.0.24-${WABT_PLATFORM}.tar.gz ]; then + wget \ + https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-${WABT_PLATFORM}.tar.gz \ + -P /tmp + fi + + cd /tmp \ + && tar zxf wabt-1.0.24-${WABT_PLATFORM}.tar.gz \ + && mkdir -p ${WORK_DIR}/wabt/out/gcc/Release/ \ + && install wabt-1.0.24/bin/wa* ${WORK_DIR}/wabt/out/gcc/Release/ \ + && cd - + fi + else + echo "download source code and compile and install" + if [ ! -d "wabt" ];then + echo "wabt not exist, clone it from github" + git clone --recursive https://github.com/WebAssembly/wabt + fi + echo "upate wabt" + cd wabt + git pull + git reset --hard origin/main + cd .. + make -C wabt gcc-release + fi + + ln -sf ${WORK_DIR}/../spec-test-script/all.sh . + ln -sf ${WORK_DIR}/../spec-test-script/runtest.py . + + local ARGS_FOR_SPEC_TEST="" + + # multi-module only enable in interp mode + if [[ 1 == ${ENABLE_MULTI_MODULE} ]]; then + if [[ $1 == 'classic-interp' || $1 == 'fast-interp' ]]; then + ARGS_FOR_SPEC_TEST+="-M " + fi + fi + + # sgx only enable in interp mode and aot mode + if [[ ${SGX_OPT} == "--sgx" ]];then + if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' ]]; then + ARGS_FOR_SPEC_TEST+="-x " + fi + fi + + # simd only enable in jit mode and aot mode + if [[ ${ENABLE_SIMD} == 1 ]]; then + if [[ $1 == 'jit' || $1 == 'aot' ]]; then + ARGS_FOR_SPEC_TEST+="-S " + fi + fi + + # reference type in all mode + if [[ ${ENABLE_REF_TYPES} == 1 ]]; then + ARGS_FOR_SPEC_TEST+="-r " + fi + + # require warmc only in aot mode + if [[ $1 == 'aot' ]]; then + ARGS_FOR_SPEC_TEST+="-t -m ${TARGET} " + fi + + cd ${WORK_DIR} + ./all.sh ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt + [[ ${PIPESTATUS[0]} -ne 0 ]] && exit 1 + cd - + + echo -e "\nFinish spec tests" | tee -a ${REPORT_DIR}/spec_test_report.txt +} + +function wasi_test() +{ + echo "Now start wasi tests" + touch ${REPORT_DIR}/wasi_test_report.txt + + cd ${WORK_DIR}/../../wasi + [[ $1 != "aot" ]] && \ + python wasi_test.py --interpreter ${IWASM_CMD} ${SGX_OPT}\ + | tee ${REPORT_DIR}/wasi_test_report.txt \ + || \ + python wasi_test.py --aot --aot-compiler ${WAMRC_CMD} ${SGX_OPT}\ + --interpreter ${IWASM_CMD} \ + | tee ${REPORT_DIR}/wasi_test_report.txt + echo "Finish wasi tests" +} + +function polybench_test() +{ + echo "Now start polybench tests" + + cd ${WORK_DIR}/../polybench + if [[ $1 == "aot" || $1 == "jit" ]];then + ./build.sh AOT ${SGX_OPT} + ./test_aot.sh $1 ${SGX_OPT} + + else + ./build.sh + ./test_interp.sh ${SGX_OPT} + fi + cp report.txt ${REPORT_DIR}/polybench_$1_test_report.txt + + echo "Finish polybench tests" +} + +function malformed_test() +{ + # build iwasm firstly + cd ${WORK_DIR}/../../malformed + ./malformed_test.py --run ${IWASM_CMD} | tee ${REPORT_DIR}/malfomed_$1_test_report.txt +} + +function standalone_test() +{ + cd ${WORK_DIR}/../../standalone + + args="" + + [[ $1 == "aot" ]] && args="$args --aot" || args="$args --no-aot" + [[ ${SGX_OPT} == "--sgx" ]] && args="$args --sgx" || args="$args --no-sgx" + + if [[ ${ENABLE_MULTI_THREAD} == 1 ]];then + args="$args --thread" + fi + + ./standalone.sh $args | tee ${REPORT_DIR}/standalone_$1_test_report.txt +} + +function build_iwasm_with_cfg() +{ + echo "Build iwasm with compile flags with " $* " for spec test" \ + | tee -a ${REPORT_DIR}/spec_test_report.txt + + if [[ ${SGX_OPT} == "--sgx" ]];then + cd ${WAMR_DIR}/product-mini/platforms/linux-sgx \ + && if [ -d build ]; then rm -rf build/*; else mkdir build; fi \ + && cd build \ + && cmake $* .. \ + && make + cd ${WAMR_DIR}/product-mini/platforms/linux-sgx/enclave-sample \ + && make clean \ + && make SPEC_TEST=1 + else + cd ${WAMR_DIR}/product-mini/platforms/${PLATFORM} \ + && if [ -d build ]; then rm -rf build/*; else mkdir build; fi \ + && cd build \ + && cmake $* .. \ + && make + fi + + if [ "$?" != 0 ];then + echo -e "\033[31mbuild iwasm failed \033[0m" + exit 1 + fi +} + +function build_wamrc() +{ + if [[ $TARGET == "ARMV7_VFP" || $TARGET == "THUMBV7_VFP" + || $TARGET == "RISCV64" || $TARGET == "RISCV64_LP64D" + || $TARGET == "RISCV64_LP64" ]];then + echo "suppose wamrc is already built" + return + fi + + echo "Build wamrc for spec test under aot compile type" + cd ${WAMR_DIR}/wamr-compiler \ + && ./build_llvm.sh \ + && if [ -d build ]; then rm -r build/*; else mkdir build; fi \ + && cd build \ + && cmake .. \ + && make +} + +### Need to add a test suite? +### The function name should be ${suite_name}_test +# function xxx_test() +# { +# +# } + +function collect_coverage() +{ + if [[ ${COLLECT_CODE_COVERAGE} == 1 ]];then + cd ${IWASM_LINUX_ROOT_DIR}/build + lcov -t "iwasm code coverage" -o iwasm.info -c -d . + genhtml -o iwasm-gcov iwasm.info + [[ -d iwasm-gcov ]] && \ + cp -r iwasm-gcov ${REPORT_DIR}/$1_iwasm_gcov || \ + echo "generate code coverage html failed" + else + echo "will not collect code coverage" + fi +} + +function trigger() +{ + local EXTRA_COMPILE_FLAGS="" + if [[ ${ENABLE_MULTI_THREAD} == 1 ]];then + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_PTHREAD=1" + fi + + if [[ ${ENABLE_SIMD} == 1 ]]; then + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_SIMD=1" + fi + + if [[ ${ENABLE_REF_TYPES} == 1 ]]; then + # spec test cases for reference type depends on + # multi-module and bulk memory + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_REF_TYPES=1" + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MULTI_MODULE=1" + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_BULK_MEMORY=1" + fi + + for t in "${TYPE[@]}"; do + case $t in + "classic-interp") + if [[ ${ENABLE_SIMD} == 1 ]]; then + echo "does not support SIMD in interp mode, bypass" + continue + fi + + echo "work in classic-interp mode" + # classic-interp + BUILD_FLAGS="$CLASSIC_INTERP_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" + build_iwasm_with_cfg $BUILD_FLAGS + for suite in "${TEST_CASE_ARR[@]}"; do + $suite"_test" classic-interp + done + collect_coverage classic-interp + ;; + + "fast-interp") + if [[ ${ENABLE_SIMD} == 1 ]]; then + echo "does not support SIMD in interp mode, bypass" + continue + fi + + echo "work in fast-interp mode" + # fast-interp + BUILD_FLAGS="$FAST_INTERP_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" + build_iwasm_with_cfg $BUILD_FLAGS + for suite in "${TEST_CASE_ARR[@]}"; do + $suite"_test" fast-interp + done + collect_coverage fast-interp + ;; + + "jit") + echo "work in jit mode" + # jit + BUILD_FLAGS="$JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" + build_iwasm_with_cfg $BUILD_FLAGS + build_wamrc + for suite in "${TEST_CASE_ARR[@]}"; do + $suite"_test" jit + done + ;; + + "aot") + echo "work in aot mode" + # aot + BUILD_FLAGS="$AOT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" + build_iwasm_with_cfg $BUILD_FLAGS + build_wamrc + for suite in "${TEST_CASE_ARR[@]}"; do + $suite"_test" aot + done + collect_coverage aot + ;; + + *) + echo "unexpected mode, do nothing" + ;; + esac + done +} + +# if collect code coverage, ignore -s, test all test cases. +if [[ $TEST_CASE_ARR && $COLLECT_CODE_COVERAGE != 1 ]];then + trigger || (echo "TEST FAILED"; exit 1) +else + # test all suite, ignore polybench because of long time cost + TEST_CASE_ARR=("sightglass" "spec" "wasi" "malformed" "standalone") + trigger || (echo "TEST FAILED"; exit 1) + # Add more suites here +fi + +echo -e "\033[32mTest finish. Reports are under ${REPORT_DIR} \033[0m" +DEBUG set +xEevuo pipefail +echo "TEST SUCCESSFUL" +exit 0 diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index c1c8c97f79..70e59ed5d5 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -50,6 +50,10 @@ if (NOT WAMR_BUILD_TARGET) if (("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")) set (WAMR_BUILD_TARGET "X86_32") endif() + elseif (WAMR_BUILD_PLATFORM STREQUAL "darwin") + if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64") + set (WAMR_BUILD_TARGET "AARCH64") + endif () endif() endif () @@ -68,6 +72,14 @@ elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*") elseif (WAMR_BUILD_TARGET MATCHES "ARM.*") add_definitions(-DBUILD_TARGET_ARM) add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") +elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64" OR WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64D") + add_definitions(-DBUILD_TARGET_RISCV64_LP64D) +elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64") + add_definitions(-DBUILD_TARGET_RISCV64_LP64) +elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32D") + add_definitions(-DBUILD_TARGET_RISCV32_ILP32D) +elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32") + add_definitions(-DBUILD_TARGET_RISCV32_ILP32) else () message (FATAL_ERROR "-- Build target isn't set") endif () @@ -75,7 +87,8 @@ endif () message ("-- Build as target ${WAMR_BUILD_TARGET}") if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*") + if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" + OR WAMR_BUILD_TARGET MATCHES "AARCH64.*" OR WAMR_BUILD_TARGET MATCHES "RISCV64.*") if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") # Add -fPIC flag if build as 64-bit set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") @@ -96,19 +109,24 @@ message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) if (CMAKE_BUILD_TYPE STREQUAL "Debug") add_definitions(-DBH_DEBUG=1) endif () +if (WAMR_BUILD_DEBUG_AOT EQUAL 1) + add_definitions(-DWASM_ENABLE_DEBUG_AOT=1) +endif() # Enable LLVM -set (LLVM_SRC_ROOT "${PROJECT_SOURCE_DIR}/../core/deps/llvm") -if (WAMR_BUILD_PLATFORM STREQUAL "windows") - if (NOT EXISTS "${LLVM_SRC_ROOT}/win32build") - message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/win32build") - endif () - set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/win32build;${CMAKE_PREFIX_PATH}") -else() - if (NOT EXISTS "${LLVM_SRC_ROOT}/build") - message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +if (NOT WAMR_BUILD_WITH_CUSTOM_LLVM) + set (LLVM_SRC_ROOT "${PROJECT_SOURCE_DIR}/../core/deps/llvm") + if (WAMR_BUILD_PLATFORM STREQUAL "windows") + if (NOT EXISTS "${LLVM_SRC_ROOT}/win32build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/win32build") + endif () + set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/win32build;${CMAKE_PREFIX_PATH}") + else() + if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") + endif () + set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") endif () - set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") endif () find_package(LLVM REQUIRED CONFIG) @@ -118,6 +136,16 @@ add_definitions(${LLVM_DEFINITIONS}) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") +if (WAMR_BUILD_DEBUG_AOT EQUAL 1) + if(LLVM_BUILD_MAIN_SRC_DIR) + include_directories(${LLVM_BUILD_MAIN_SRC_DIR}/../lldb/include) + include_directories(${LLVM_BUILD_BINARY_DIR}/tools/lldb/include) + endif() + link_directories(${LLVM_LIBRARY_DIRS}) + find_library(lib_lldb NAMES lldb HINTS ${LLVM_LIBRARY_DIRS}) + message(STATUS "find lldb ${LLDB_ALL_PLUGINS} in: ${LLVM_LIBRARY_DIRS}") +endif() + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) if(NOT MSVC) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") @@ -197,7 +225,7 @@ add_library (aotclib ${IWASM_COMPL_SOURCE}) add_executable (wamrc main.c) if (NOT MSVC) - target_link_libraries (wamrc aotclib vmlib LLVMDemangle ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread) + target_link_libraries (wamrc aotclib vmlib LLVMDemangle ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread ${lib_lldb}) else() - target_link_libraries (wamrc aotclib vmlib ${LLVM_AVAILABLE_LIBS}) + target_link_libraries (wamrc aotclib vmlib ${lib_lldb} ${LLVM_AVAILABLE_LIBS}) endif() diff --git a/wamr-compiler/build_llvm.py b/wamr-compiler/build_llvm.py index 34ae7b03f5..dd181b81a9 100644 --- a/wamr-compiler/build_llvm.py +++ b/wamr-compiler/build_llvm.py @@ -1,98 +1,14 @@ +#!/usr/bin/env python3 # # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # -#!/usr/bin/env python3 -import os +import pathlib +import subprocess import sys -from pathlib import Path - -def clone_llvm(): - llvm_dir = Path("llvm") - if(llvm_dir.exists() == False): - print("Clone llvm to core/deps/ ..") - for line in os.popen("git clone --branch release/11.x https://github.com/llvm/llvm-project.git llvm"): - print(line) - else: - print("llvm source codes already existed") - return llvm_dir - -""" def detect_VS_version(): - program_dirs = [os.environ['ProgramFiles(x86)'], os.environ['ProgramFiles']] - for dir in program_dirs: - vswhere = Path("{}\\Microsoft Visual Studio\\Installer\\vswhere.exe".format(dir)) - if (vswhere.exists()): - print('"{}" -version 14.0,16.0'.format(vswhere)) - for line in os.popen('"{}" -version 14.0,16.0'.format(vswhere)): - keyvalue = line.split(':', maxsplit=1) - if(keyvalue[0] == "installationPath"): - value = keyvalue[1].strip() - for line in os.popen('"{}\\VC\\Auxiliary\\Build\\vcvars32.bat"'.format(value)): - print(line) - break """ - - -def main(): - current_os = sys.platform - print("current OS is ", current_os) - - current_dir = Path.cwd() - deps_dir = current_dir.joinpath( "../core/deps") - - os.chdir(deps_dir) - llvm_dir = clone_llvm() - os.chdir(llvm_dir) - - if(current_os == "linux"): - build_dir_name = "build" - llvm_file = "bin/llvm-lto" - # generator = '"Unix Makefiles"' - elif(current_os == "win32"): - build_dir_name = "win32build" - llvm_file = "LLVM.sln" - # generator = '"Visual Studio 15 2017"' - else: - build_dir_name = "build" - # generator = '""' - - Path(build_dir_name).mkdir(exist_ok = True) - build_dir = Path(build_dir_name) - os.chdir(build_dir) - - if ( not Path(llvm_file).exists()): - core_number = os.cpu_count() - print("Build llvm with", core_number, " cores") - cmd = 'cmake ../llvm \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_BUILD_TYPE:STRING="Release" \ - -DLLVM_TARGETS_TO_BUILD:STRING="X86;ARM;AArch64;Mips" \ - -DLLVM_INCLUDE_GO_TESTS=OFF \ - -DLLVM_INCLUDE_TOOLS=OFF \ - -DLLVM_INCLUDE_UTILS=OFF \ - -DLLVM_ENABLE_TERMINFO=OFF \ - -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ - -DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \ - -DLLVM_ENABLE_ZLIB:BOOL=OFF \ - -DLLVM_INCLUDE_DOCS:BOOL=OFF \ - -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \ - -DLLVM_INCLUDE_TESTS:BOOL=OFF \ - -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \ - -DLLVM_APPEND_VC_REV:BOOL=OFF' - print(cmd) - for line in os.popen(cmd): - print(line) - else: - print("llvm has already been Cmaked") - - if(current_os == "linux"): - for line in os.popen("make -j {}".format(core_number)): - print(line) - elif(current_os == "win32"): - print("Please open LLVM.sln in {} to build *Release* version".format(build_dir.absolute())) - - os.chdir(current_dir) - -if __name__ == "__main__": - main() +script = ( + pathlib.Path(__file__).parent.joinpath("../build-scripts/build_llvm.py").resolve() +) +subprocess.check_call([sys.executable, script.name]) diff --git a/wamr-compiler/build_llvm.sh b/wamr-compiler/build_llvm.sh index 7960e36462..089e48b2b5 100755 --- a/wamr-compiler/build_llvm.sh +++ b/wamr-compiler/build_llvm.sh @@ -3,44 +3,4 @@ # Copyright (C) 2020 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -DEPS_DIR=${PWD}/../core/deps - -cd ${DEPS_DIR} -if [ ! -d "llvm" ]; then - echo "Clone llvm to core/deps/ .." - git clone --depth 1 --branch release/11.x https://github.com/llvm/llvm-project.git llvm -fi - -cd llvm -mkdir -p build -cd build - -if [ ! -f bin/llvm-lto ]; then - - CORE_NUM=$(nproc --all) - if [ -z "${CORE_NUM}" ]; then - CORE_NUM=1 - fi - - echo "Build llvm with" ${CORE_NUM} "cores" - - cmake ../llvm \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_BUILD_TYPE:STRING="Release" \ - -DLLVM_TARGETS_TO_BUILD:STRING="X86;ARM;AArch64;Mips" \ - -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ - -DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \ - -DLLVM_ENABLE_ZLIB:BOOL=OFF \ - -DLLVM_INCLUDE_DOCS:BOOL=OFF \ - -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \ - -DLLVM_INCLUDE_TESTS:BOOL=OFF \ - -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \ - -DLLVM_APPEND_VC_REV:BOOL=OFF - make -j ${CORE_NUM} - -else - echo "llvm has already been built" -fi - -cd ${PWD} - +/usr/bin/env python3 ../build-scripts/build_llvm.py diff --git a/wamr-compiler/build_llvm_arc.sh b/wamr-compiler/build_llvm_arc.sh new file mode 100755 index 0000000000..c48c30959d --- /dev/null +++ b/wamr-compiler/build_llvm_arc.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# Copyright (C) 2020 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +/usr/bin/env python3 ../build-scripts/build_llvm.py --platform arc diff --git a/wamr-compiler/build_llvm_xtensa.sh b/wamr-compiler/build_llvm_xtensa.sh index c8bb9b83db..8277f9ca05 100755 --- a/wamr-compiler/build_llvm_xtensa.sh +++ b/wamr-compiler/build_llvm_xtensa.sh @@ -1,47 +1,6 @@ #!/bin/sh -# Copyright (C) 2019 Intel Corporation. All rights reserved. +# Copyright (C) 2020 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -DEPS_DIR=${PWD}/../core/deps - -cd ${DEPS_DIR} -if [ ! -d "llvm" ]; then - echo "Clone llvm Xtensa to core/deps/ .." - git clone --depth 1 --branch xtensa_release_10.0.1 https://github.com/espressif/llvm-project.git llvm -fi - -cd llvm -mkdir -p build -cd build - -if [ ! -f bin/llvm-lto ]; then - - CORE_NUM=$(nproc --all) - if [ -z "${CORE_NUM}" ]; then - CORE_NUM=1 - fi - - echo "Build llvm with" ${CORE_NUM} "cores" - - cmake ../llvm \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCMAKE_BUILD_TYPE:STRING="Release" \ - -DLLVM_TARGETS_TO_BUILD:STRING="X86;ARM;AArch64;Mips" \ - -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="Xtensa" \ - -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ - -DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \ - -DLLVM_ENABLE_ZLIB:BOOL=OFF \ - -DLLVM_INCLUDE_DOCS:BOOL=OFF \ - -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \ - -DLLVM_INCLUDE_TESTS:BOOL=OFF \ - -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \ - -DLLVM_APPEND_VC_REV:BOOL=OFF - make -j ${CORE_NUM} - -else - echo "llvm has already been built" -fi - -cd ${PWD} - +/usr/bin/env python3 ../build-scripts/build_llvm.py --platform xtensa diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 4ced209b06..c57eff2d62 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -20,11 +20,14 @@ print_help() { printf("Usage: wamrc [options] -o output_file wasm_file\n"); printf(" --target= Set the target arch, which has the general format: \n"); - printf(" = x86_64, i386, aarch64, arm, thumb, xtensa, mips.\n"); + printf(" = x86_64, i386, aarch64, arm, thumb, xtensa, mips,\n"); + printf(" riscv64, riscv32.\n"); printf(" Default is host arch, e.g. x86_64\n"); printf(" = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc.\n"); printf(" Use --target=help to list supported targets\n"); - printf(" --target-abi= Set the target ABI, e.g. gnu, eabi, gnueabihf, etc. (default: gnu)\n"); + printf(" --target-abi= Set the target ABI, e.g. gnu, eabi, gnueabihf, msvc, etc.\n"); + printf(" Default is gnu if target isn't riscv64 or riscv32\n"); + printf(" For target riscv64 and riscv32, default is lp64d and ilp32d\n"); printf(" Use --target-abi=help to list all the ABI supported\n"); printf(" --cpu= Set the target CPU (default: host CPU, e.g. skylake)\n"); printf(" Use --cpu=help to list all the CPU supported\n"); @@ -57,6 +60,8 @@ print_help() printf(" --disable-aux-stack-check Disable auxiliary stack overflow/underflow check\n"); printf(" --enable-dump-call-stack Enable stack trace feature\n"); printf(" --enable-perf-profiling Enable function performance profiling\n"); + printf(" --enable-indirect-mode Enalbe call function through symbol table but not direct call\n"); + printf(" --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n"); printf(" -v=n Set log verbose level (0 to 5, default is 2), larger with more log\n"); printf("Examples: wamrc -o test.aot test.wasm\n"); printf(" wamrc --target=i386 -o test.aot test.wasm\n"); @@ -185,6 +190,12 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0], "--enable-perf-profiling")) { option.enable_aux_stack_frame = true; } + else if (!strcmp(argv[0], "--enable-indirect-mode")) { + option.is_indirect_mode = true; + } + else if (!strcmp(argv[0], "--disable-llvm-intrinsics")) { + option.disable_llvm_intrinsics = true; + } else return print_help(); } @@ -237,6 +248,12 @@ main(int argc, char *argv[]) goto fail3; } +#if WASM_ENABLE_DEBUG_AOT != 0 + if (!create_dwarf_extractor(comp_data, wasm_file_name)) { + printf("%s:create dwarf extractor failed\n", wasm_file_name); + } +#endif + bh_print_time("Begin to create compile context"); if (!(comp_ctx = aot_create_comp_context(comp_data, diff --git a/wamr-sdk/README.md b/wamr-sdk/README.md index f9d143c7e1..c161a69a4a 100644 --- a/wamr-sdk/README.md +++ b/wamr-sdk/README.md @@ -84,7 +84,7 @@ The folder “**app-sdk**” under the profile output directory contains all the -Refer to [build WASM applications](./doc/build_wasm_app.md) for the details. +Refer to [build WASM applications](../doc/build_wasm_app.md) for the details. diff --git a/zephyr/module.yml b/zephyr/module.yml new file mode 100644 index 0000000000..059c7368fa --- /dev/null +++ b/zephyr/module.yml @@ -0,0 +1,5 @@ +name: wasm-micro-runtime + +build: + cmake-ext: True + kconfig-ext: True