diff --git a/.github/workflows/codeing_guildelines.yml b/.github/workflows/codeing_guildelines.yml index de1364f28..f06892631 100644 --- a/.github/workflows/codeing_guildelines.yml +++ b/.github/workflows/codeing_guildelines.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Workflow Action - uses: styfle/cancel-workflow-action@0.6.0 + uses: styfle/cancel-workflow-action@0.9.1 with: access_token: ${{ github.token }} @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 diff --git a/.github/workflows/compilation_on_android_ubuntu_macos.yml b/.github/workflows/compilation_on_android_ubuntu.yml similarity index 75% rename from .github/workflows/compilation_on_android_ubuntu_macos.yml rename to .github/workflows/compilation_on_android_ubuntu.yml index d15d0649e..5ae14156b 100644 --- a/.github/workflows/compilation_on_android_ubuntu_macos.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -1,7 +1,7 @@ # 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 +name: compilation on android, ubuntu-18.04, ubuntu-20.04 on: # will be triggered on PR events @@ -11,7 +11,7 @@ on: - "ci/**" - "doc/**" - "test-tools/**" - - ".github/workflows/compilation_on_android_ubuntu_macos.yml" + - ".github/workflows/compilation_on_android_ubuntu.yml" # will be triggered on push events push: paths-ignore: @@ -19,7 +19,7 @@ on: - "ci/**" - "doc/**" - "test-tools/**" - - ".github/workflows/compilation_on_android_ubuntu_macos.yml" + - ".github/workflows/compilation_on_android_ubuntu.yml" # allow to be triggered manually workflow_dispatch: @@ -30,12 +30,20 @@ concurrency: cancel-in-progress: true env: + # For BUILD 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" 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" MC_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" + # LLVM LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex" + # For Spec Test + DEFAULT_TEST_OPTIONS: "-s spec -P" + MULTI_MODULES_TEST_OPTIONS: "-s spec -M -P" + SIMD_TEST_OPTIONS: "-s spec -S -P" + THREADS_TEST_OPTIONS: "-s spec -p -P" + X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P" jobs: # Cancel any in-flight jobs for the same PR/branch so there's only one active @@ -44,25 +52,25 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + os: [ubuntu-18.04, ubuntu-20.04] steps: - name: Cancel Workflow Action - uses: styfle/cancel-workflow-action@0.6.0 + uses: styfle/cancel-workflow-action@0.9.1 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 + # it is used to separate between the public repo and the private repo check_repo: needs: cancel_previous runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + os: [ubuntu-18.04, ubuntu-20.04] 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 @@ -84,41 +92,29 @@ jobs: 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] + os: [ubuntu-18.04, ubuntu-20.04] 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 + uses: actions/checkout@v3 - name: Cache LLVM libraries id: cache_llvm if: ${{ matrix.light == 'green' }} - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ./core/deps/llvm/build/bin @@ -128,43 +124,35 @@ jobs: ./core/deps/llvm/build/share key: ${{ 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' }} + - name: Build llvm and clang from source + id: build_llvm + if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }} 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 - build_wamrc: needs: [build_llvm_libraries, check_repo] runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + os: [ubuntu-18.04, ubuntu-20.04] 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 + uses: actions/checkout@v3 - name: Get LLVM libraries id: cache_llvm if: ${{ matrix.light == 'green' }} - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ./core/deps/llvm/build/bin @@ -193,11 +181,11 @@ jobs: matrix: make_options_run_mode: [ # Running mode + $AOT_BUILD_OPTIONS, $CLASSIC_INTERP_BUILD_OPTIONS, $FAST_INTERP_BUILD_OPTIONS, $LAZY_JIT_BUILD_OPTIONS, $MC_JIT_BUILD_OPTIONS, - $AOT_BUILD_OPTIONS, ] make_options_feature: [ # Features @@ -206,6 +194,7 @@ jobs: "-DWAMR_BUILD_DEBUG_INTERP=1", "-DWAMR_BUILD_DUMP_CALL_STACK=1", "-DWAMR_BUILD_LIB_PTHREAD=1", + "-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1", "-DWAMR_BUILD_MINI_LOADER=1", "-DWAMR_BUILD_MEMORY_PROFILING=1", "-DWAMR_BUILD_MULTI_MODULE=1", @@ -215,23 +204,10 @@ jobs: "-DWAMR_BUILD_TAIL_CALL=1", "-DWAMR_DISABLE_HW_BOUND_CHECK=1", ] - os: [ubuntu-18.04, ubuntu-20.04, macos-latest] - platform: [android, linux, darwin] + os: [ubuntu-18.04, ubuntu-20.04] + platform: [android, linux] 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" # uncompatiable mode and feature # MULTI_MODULE only on INTERP mode - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS @@ -276,20 +252,19 @@ jobs: 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 + uses: actions/checkout@v3 + # only download llvm cache when needed - name: Get LLVM libraries id: cache_llvm - if: ${{ matrix.light == 'green' }} - uses: actions/cache@v2 + if: (matrix.light == 'green') && (endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')) + uses: actions/cache@v3 with: path: | ./core/deps/llvm/build/bin @@ -300,7 +275,7 @@ jobs: key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} - name: Quit if cache miss - if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }} + if: (matrix.light == 'green') && (endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true') run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: Build iwasm @@ -324,7 +299,7 @@ jobs: $MC_JIT_BUILD_OPTIONS, $AOT_BUILD_OPTIONS, ] - os: [ubuntu-18.04, ubuntu-20.04, macos-latest] + os: [ubuntu-18.04, ubuntu-20.04] include: - os: ubuntu-18.04 light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }} @@ -334,30 +309,18 @@ jobs: 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: $LAZY_JIT_BUILD_OPTIONS - - os: macos-latest - make_options: $AOT_BUILD_OPTIONS - - os: macos-latest - make_options: $MC_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 + uses: actions/checkout@v3 - name: Get LLVM libraries id: cache_llvm - if: ${{ matrix.light == 'green' }} - uses: actions/cache@v2 + if: (matrix.light == 'green') && (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) + uses: actions/cache@v3 with: path: | ./core/deps/llvm/build/bin @@ -368,7 +331,7 @@ jobs: key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} - name: Quit if cache miss - if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }} + if: (matrix.light == 'green') && (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true') run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: download and install wabt @@ -380,7 +343,7 @@ jobs: sudo mv wabt-1.0.24 wabt - name: Build wamrc - if: ${{ matrix.light == 'green' }} + if: (matrix.light == 'green') && (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) run: | mkdir build && cd build cmake .. @@ -406,7 +369,7 @@ jobs: working-directory: samples/wasm-c-api build_samples_others: - needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo] + needs: [build_iwasm, check_repo] runs-on: ${{ matrix.os }} strategy: matrix: @@ -419,34 +382,13 @@ jobs: 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/bin - ./core/deps/llvm/build/include - ./core/deps/llvm/build/lib - ./core/deps/llvm/build/libexec - ./core/deps/llvm/build/share - key: ${{ 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 + uses: actions/checkout@v3 - name: download and install wasi-sdk if: ${{ matrix.light == 'green' }} @@ -464,14 +406,6 @@ jobs: 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: | @@ -514,3 +448,110 @@ jobs: cmake .. cmake --build . --config Release --parallel 4 ./hello + + spec_test_default: + needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo] + runs-on: ubuntu-20.04 + strategy: + matrix: + test_option: [$DEFAULT_TEST_OPTIONS, $SIMD_TEST_OPTIONS] + steps: + - name: checkout + uses: actions/checkout@v3 + + - name: Get LLVM libraries + id: cache_llvm + uses: actions/cache@v3 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: 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: 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 + + spec_test_extra: + if: ${{ endsWith(github.repository, 'wasm-micro-runtime') }} + needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo] + runs-on: ubuntu-20.04 + strategy: + matrix: + test_option: [$MULTI_MODULES_TEST_OPTIONS, $THREADS_TEST_OPTIONS] + steps: + - name: checkout + uses: actions/checkout@v3 + + - name: Get LLVM libraries + id: cache_llvm + uses: actions/cache@v3 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: 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: 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 + + spec_test_x86_32: + if: ${{ endsWith(github.repository, 'wasm-micro-runtime') }} + needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo] + runs-on: ubuntu-20.04 + strategy: + matrix: + test_option: [$DEFAULT_TEST_OPTIONS, $THREADS_TEST_OPTIONS] + steps: + - name: checkout + uses: actions/checkout@v3 + + - name: Get LLVM libraries + id: cache_llvm + uses: actions/cache@v3 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: 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: install Ninja and x32 support libraries + run: + # Add another apt repository as some packages cannot + # be downloaded with the github default repository + sudo curl -sSL https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc && + sudo apt-add-repository https://packages.microsoft.com/ubuntu/20.04/prod && + sudo apt-get update && + sudo apt install -y g++-multilib lib32gcc-9-dev ninja-build + + - name: run spec tests + run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} + working-directory: ./tests/wamr-test-suites diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml new file mode 100644 index 000000000..9afbb8444 --- /dev/null +++ b/.github/workflows/compilation_on_macos.yml @@ -0,0 +1,393 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +name: compilation on macos-latest + +on: + # will be triggered on PR events + pull_request: + paths-ignore: + - "assembly-script/**" + - "ci/**" + - "doc/**" + - "test-tools/**" + - ".github/workflows/compilation_on_macos.yml" + # will be triggered on push events + push: + paths-ignore: + - "assembly-script/**" + - "ci/**" + - "doc/**" + - "test-tools/**" + - ".github/workflows/compilation_on_macos.yml" + # 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" + 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" + MC_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" + 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: [macos-latest] + steps: + - name: Cancel Workflow Action + uses: styfle/cancel-workflow-action@0.9.1 + 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: [macos-latest] + outputs: + traffic_light: ${{ steps.do_check.outputs.light }} + steps: + - name: do_check + id: do_check + 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: [macos-latest] + include: + - os: macos-latest + light: ${{ needs.check_repo.outputs.traffic_light }} + steps: + - name: light status + run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}" + + - name: checkout + if: ${{ matrix.light == 'green' }} + uses: actions/checkout@v3 + + - name: Cache LLVM libraries + id: cache_llvm + if: ${{ matrix.light == 'green' }} + uses: actions/cache@v3 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + + - name: Build llvm and clang from source + id: build_llvm + if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }} + run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly + working-directory: build-scripts + + build_wamrc: + needs: [build_llvm_libraries, check_repo] + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest] + include: + - os: macos-latest + light: ${{ needs.check_repo.outputs.traffic_light }} + steps: + - name: light status + run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}" + + - name: checkout + if: ${{ matrix.light == 'green' }} + uses: actions/checkout@v3 + + - name: Get LLVM libraries + id: cache_llvm + if: ${{ matrix.light == 'green' }} + uses: actions/cache@v3 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: ${{ matrix.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: 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 + $AOT_BUILD_OPTIONS, + $CLASSIC_INTERP_BUILD_OPTIONS, + $FAST_INTERP_BUILD_OPTIONS, + $LAZY_JIT_BUILD_OPTIONS, + $MC_JIT_BUILD_OPTIONS, + ] + make_options_feature: [ + # Features + "-DWAMR_BUILD_CUSTOM_NAME_SECTION=1", + # doesn't support + #"-DWAMR_BUILD_DEBUG_AOT=1", + "-DWAMR_BUILD_DEBUG_INTERP=1", + "-DWAMR_BUILD_DUMP_CALL_STACK=1", + "-DWAMR_BUILD_LIB_PTHREAD=1", + "-DWAMR_BUILD_LOAD_CUSTOM_SECTION=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: [macos-latest] + platform: [darwin] + exclude: + # uncompatiable feature and platform + # uncompatiable mode and feature + # MULTI_MODULE only on INTERP mode + - make_options_run_mode: $LAZY_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: $MC_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: $LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1" + - make_options_run_mode: $MC_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: $LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" + - make_options_run_mode: $MC_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: $LAZY_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" + - make_options_run_mode: $MC_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" + include: + - os: macos-latest + light: ${{ needs.check_repo.outputs.traffic_light }} + steps: + - name: light status + run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}" + + - name: checkout + if: ${{ matrix.light == 'green' }} + uses: actions/checkout@v3 + + # only download llvm cache when needed + - name: Get LLVM libraries + id: cache_llvm + if: (matrix.light == 'green') && (endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')) + uses: actions/cache@v3 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + + - name: Quit if cache miss + if: (matrix.light == 'green') && (endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true') + run: echo "::error::can not get prebuilt llvm libraries" && exit 1 + + - 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, check_repo] + runs-on: ${{ matrix.os }} + strategy: + matrix: + make_options: [ + # Running mode + $CLASSIC_INTERP_BUILD_OPTIONS, + $FAST_INTERP_BUILD_OPTIONS, + # doesn't support + #$LAZY_JIT_BUILD_OPTIONS, + #$MC_JIT_BUILD_OPTIONS, + #$AOT_BUILD_OPTIONS, + ] + os: [macos-latest] + include: + - os: macos-latest + light: ${{ needs.check_repo.outputs.traffic_light }} + 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@v3 + + - 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 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, check_repo] + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: macos-latest + light: ${{ needs.check_repo.outputs.traffic_light }} + 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@v3 + + - 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 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_sgx.yml b/.github/workflows/compilation_on_sgx.yml index 621ed953d..f21b618ce 100644 --- a/.github/workflows/compilation_on_sgx.yml +++ b/.github/workflows/compilation_on_sgx.yml @@ -1,7 +1,7 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -name: CI on SGX +name: compilation on SGX on: # will be triggered on PR events @@ -47,7 +47,7 @@ jobs: os: [ubuntu-20.04] steps: - name: Cancel Workflow Action - uses: styfle/cancel-workflow-action@0.6.0 + uses: styfle/cancel-workflow-action@0.9.1 with: access_token: ${{ github.token }} @@ -87,12 +87,12 @@ jobs: - name: checkout if: ${{ matrix.light == 'green' }} - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache LLVM libraries id: cache_llvm if: ${{ matrix.light == 'green' }} - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ./core/deps/llvm/build/bin @@ -103,24 +103,24 @@ jobs: key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} - name: Build llvm and clang from source - id: build_llvm_ubuntu + id: build_llvm if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }} run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly --project clang lldb working-directory: build-scripts build_iwasm: - needs: [build_llvm_libraries, check_repo] + needs: [check_repo] runs-on: ${{ matrix.os }} strategy: matrix: make_options_run_mode: [ # Running mode + $AOT_BUILD_OPTIONS, $CLASSIC_INTERP_BUILD_OPTIONS, $FAST_INTERP_BUILD_OPTIONS, # doesn't support # $LAZY_JIT_BUILD_OPTIONS, # $MC_JIT_BUILD_OPTIONS, - $AOT_BUILD_OPTIONS, ] make_options_feature: [ # Features @@ -130,6 +130,7 @@ jobs: # "-DWAMR_BUILD_DEBUG_INTERP=1", "-DWAMR_BUILD_DUMP_CALL_STACK=1", "-DWAMR_BUILD_LIB_PTHREAD=1", + "-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1", "-DWAMR_BUILD_MINI_LOADER=1", "-DWAMR_BUILD_MEMORY_PROFILING=1", "-DWAMR_BUILD_MULTI_MODULE=1", @@ -160,7 +161,7 @@ jobs: - name: install SGX SDK and necessary libraries if: ${{ matrix.light == 'green' }} run: | - mkdir -p /opt/intel + mkdir -p /opt/intel cd /opt/intel wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin chmod +x sgx_linux_x64_sdk_2.15.100.3.bin @@ -173,12 +174,51 @@ jobs: - name: checkout if: ${{ matrix.light == 'green' }} - uses: actions/checkout@v2 + uses: actions/checkout@v3 + + - 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_wamrc: + needs: [build_llvm_libraries, check_repo] + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-20.04] + include: + - os: ubuntu-20.04 + light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }} + steps: + - name: light status + run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}" + + - name: install SGX SDK and necessary libraries + if: ${{ matrix.light == 'green' }} + run: | + mkdir -p /opt/intel + cd /opt/intel + wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin + chmod +x sgx_linux_x64_sdk_2.15.100.3.bin + echo 'yes' | ./sgx_linux_x64_sdk_2.15.100.3.bin + echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu focal main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list + wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo apt-key add - + sudo apt update + sudo apt install -y libsgx-launch libsgx-urts + source /opt/intel/sgxsdk/environment + + - name: checkout + if: ${{ matrix.light == 'green' }} + uses: actions/checkout@v3 - name: Get LLVM libraries id: cache_llvm if: ${{ matrix.light == 'green' }} - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ./core/deps/llvm/build/bin @@ -192,16 +232,16 @@ jobs: if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }} run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - - name: Build iwasm + - name: Build wamrc if: ${{ matrix.light == 'green' }} run: | mkdir build && cd build - cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} + cmake .. cmake --build . --config Release --parallel 4 - working-directory: product-mini/platforms/${{ matrix.platform }} + working-directory: wamr-compiler build_samples_wasm_c_api: - needs: [build_iwasm, build_llvm_libraries, check_repo] + needs: [build_iwasm, check_repo] runs-on: ${{ matrix.os }} strategy: matrix: @@ -226,24 +266,7 @@ jobs: - 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/bin - ./core/deps/llvm/build/include - ./core/deps/llvm/build/lib - ./core/deps/llvm/build/libexec - ./core/deps/llvm/build/share - key: ${{ 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 + uses: actions/checkout@v3 - name: download and install wabt if: ${{ matrix.light == 'green' }} @@ -256,7 +279,7 @@ jobs: - name: install SGX SDK and necessary libraries if: ${{ matrix.light == 'green' }} run: | - mkdir -p /opt/intel + mkdir -p /opt/intel cd /opt/intel wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin chmod +x sgx_linux_x64_sdk_2.15.100.3.bin @@ -267,14 +290,6 @@ jobs: sudo apt install -y libsgx-launch libsgx-urts source /opt/intel/sgxsdk/environment - - 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: | @@ -294,7 +309,7 @@ jobs: working-directory: samples/wasm-c-api build_samples_others: - needs: [build_iwasm, build_llvm_libraries, check_repo] + needs: [build_iwasm, check_repo] runs-on: ${{ matrix.os }} strategy: matrix: @@ -309,24 +324,7 @@ jobs: - 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/bin - ./core/deps/llvm/build/include - ./core/deps/llvm/build/lib - ./core/deps/llvm/build/libexec - ./core/deps/llvm/build/share - key: ${{ 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 + uses: actions/checkout@v3 - name: download and install wasi-sdk if: ${{ matrix.light == 'green' }} @@ -347,7 +345,7 @@ jobs: - name: install SGX SDK and necessary libraries if: ${{ matrix.light == 'green' }} run: | - mkdir -p /opt/intel + mkdir -p /opt/intel cd /opt/intel wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin chmod +x sgx_linux_x64_sdk_2.15.100.3.bin @@ -358,14 +356,6 @@ jobs: sudo apt install -y libsgx-launch libsgx-urts source /opt/intel/sgxsdk/environment - - 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: | @@ -410,7 +400,7 @@ jobs: ./hello spec_test_default: - needs: [build_iwasm, build_llvm_libraries, check_repo] + needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo] runs-on: ubuntu-20.04 strategy: matrix: @@ -422,12 +412,12 @@ jobs: steps: - name: checkout if: ${{ matrix.light == 'green' }} - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Get LLVM libraries if: ${{ matrix.light == 'green' }} id: cache_llvm - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ./core/deps/llvm/build/bin @@ -437,6 +427,10 @@ jobs: ./core/deps/llvm/build/share key: ubuntu-20.04-${{ 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: install Ninja if: ${{ matrix.light == 'green' }} run: sudo apt install -y ninja-build @@ -444,7 +438,7 @@ jobs: - name: install SGX SDK and necessary libraries if: ${{ matrix.light == 'green' }} run: | - mkdir -p /opt/intel + mkdir -p /opt/intel cd /opt/intel wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin chmod +x sgx_linux_x64_sdk_2.15.100.3.bin diff --git a/.github/workflows/compilation_on_windows.yml b/.github/workflows/compilation_on_windows.yml index 5306f784b..408bdc25e 100644 --- a/.github/workflows/compilation_on_windows.yml +++ b/.github/workflows/compilation_on_windows.yml @@ -36,7 +36,7 @@ jobs: runs-on: windows-latest steps: - name: Cancel Workflow Action - uses: styfle/cancel-workflow-action@0.6.0 + uses: styfle/cancel-workflow-action@0.9.1 with: access_token: ${{ github.token }} @@ -44,7 +44,7 @@ jobs: needs: cancel_previous runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: clone uvwasi library run: | diff --git a/.github/workflows/spec_test.yml b/.github/workflows/spec_test.yml deleted file mode 100644 index 336d19379..000000000 --- a/.github/workflows/spec_test.yml +++ /dev/null @@ -1,155 +0,0 @@ -# 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/**" - - "tests/wamr-test-suites/spec-test-script/**" - - "tests/wamr-test-suites/test_wamr.sh" - - ".github/workflows/spec_test.yml" - # will be triggered on push events - push: - paths: - - "core/config.h" - - "core/iwasm/**" - - "core/shared/**" - - "wamr-compiler/**" - - "product-mini/**" - - "tests/wamr-test-suites/spec-test-script/**" - - "tests/wamr-test-suites/test_wamr.sh" - - ".github/workflows/spec_test.yml" - # 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: - DEFAULT_TEST_OPTIONS: "-s spec -P" - LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex" - MULTI_MODULES_TEST_OPTIONS: "-s spec -M -P" - SIMD_TEST_OPTIONS: "-s spec -S -P" - THREADS_TEST_OPTIONS: "-s spec -p -P" - X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P" - -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 }} - - spec_test_default: - needs: cancel_previous - runs-on: ubuntu-20.04 - strategy: - matrix: - test_option: [$DEFAULT_TEST_OPTIONS, $SIMD_TEST_OPTIONS] - steps: - - name: checkout - uses: actions/checkout@v2 - - - name: Get LLVM libraries - id: cache_llvm - uses: actions/cache@v2 - with: - path: | - ./core/deps/llvm/build/bin - ./core/deps/llvm/build/include - ./core/deps/llvm/build/lib - ./core/deps/llvm/build/libexec - ./core/deps/llvm/build/share - key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }} - - - 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 - - spec_test_extra: - needs: cancel_previous - if: ${{ endsWith(github.repository, 'wasm-micro-runtime') }} - runs-on: ubuntu-20.04 - strategy: - matrix: - test_option: [$MULTI_MODULES_TEST_OPTIONS, $THREADS_TEST_OPTIONS] - steps: - - name: checkout - uses: actions/checkout@v2 - - - name: Get LLVM libraries - id: cache_llvm - uses: actions/cache@v2 - with: - path: | - ./core/deps/llvm/build/bin - ./core/deps/llvm/build/include - ./core/deps/llvm/build/lib - ./core/deps/llvm/build/libexec - ./core/deps/llvm/build/share - key: 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: 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 - - spec_test_x86_32: - if: ${{ endsWith(github.repository, 'wasm-micro-runtime') }} - needs: cancel_previous - runs-on: ubuntu-20.04 - strategy: - matrix: - test_option: [$DEFAULT_TEST_OPTIONS, $THREADS_TEST_OPTIONS] - steps: - - name: checkout - uses: actions/checkout@v2 - - - name: Get LLVM libraries - id: cache_llvm - uses: actions/cache@v2 - with: - path: | - ./core/deps/llvm/build/bin - ./core/deps/llvm/build/include - ./core/deps/llvm/build/lib - ./core/deps/llvm/build/libexec - ./core/deps/llvm/build/share - key: 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: install Ninja and x32 support libraries - run: - # Add another apt repository as some packages cannot - # be downloaded with the github default repository - sudo curl -sSL https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc && - sudo apt-add-repository https://packages.microsoft.com/ubuntu/20.04/prod && - sudo apt-get update && - sudo apt install -y g++-multilib lib32gcc-9-dev ninja-build - - - name: run spec tests - run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} - working-directory: ./tests/wamr-test-suites diff --git a/README.md b/README.md index 4645bc4f7..dac63583a 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Getting started ================== - [Build iwasm VM core](./doc/build_wamr.md) on [Linux](./doc/build_wamr.md#linux), [SGX](./doc/linux_sgx.md), [MacOS](./doc/build_wamr.md#macos) and [Windows](./doc/build_wamr.md#windows), and [Build wamrc AOT compiler](./README.md#build-wamrc-aot-compiler) - [Embed WAMR into host applications](./doc/embed_wamr.md) + - [Embed into C/C++](./doc/embed_wamr.md), [Embed into Python](./language-bindings/python), [Embed into Go](./language-bindings/go) + - [Register native APIs for WASM applications](./doc/export_native_api.md) - [Build WASM applications](./doc/build_wasm_app.md) - [Port WAMR to a new platform](./doc/port_wamr.md) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 191487bf9..b01bd93ef 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -259,3 +259,7 @@ endif () if (WAMR_BUILD_DEBUG_AOT EQUAL 1) message (" Debug AOT enabled") endif () +if (WAMR_BUILD_LOAD_CUSTOM_SECTION EQUAL 1) + add_definitions (-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1) + message (" Load custom section enabled") +endif () diff --git a/core/config.h b/core/config.h index 98ff51cb2..cf49d95f4 100644 --- a/core/config.h +++ b/core/config.h @@ -176,6 +176,11 @@ #define WASM_ENABLE_DEBUG_AOT 0 #endif +/* Custom sections */ +#ifndef WASM_ENABLE_LOAD_CUSTOM_SECTION +#define WASM_ENABLE_LOAD_CUSTOM_SECTION 0 +#endif + /* WASM log system */ #ifndef WASM_ENABLE_LOG #define WASM_ENABLE_LOG 1 diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index d7728707f..d6560cccb 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -14,6 +14,7 @@ #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" @@ -151,7 +152,7 @@ GET_U64_FROM_ADDR(uint32 *addr) #define read_byte_array(p, p_end, addr, len) \ do { \ CHECK_BUF(p, p_end, len); \ - memcpy(addr, p, len); \ + bh_memcpy_s(addr, len, p, len); \ p += len; \ } while (0) @@ -674,6 +675,36 @@ load_custom_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module, error_buf, error_buf_size)) goto fail; break; +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 + case AOT_CUSTOM_SECTION_RAW: + { + const char *section_name; + WASMCustomSection *section; + + if (p >= p_end) { + set_error_buf(error_buf, error_buf_size, "unexpected end"); + goto fail; + } + + read_string(p, p_end, section_name); + + section = loader_malloc(sizeof(WASMCustomSection), error_buf, + error_buf_size); + if (!section) { + goto fail; + } + + section->name_addr = (char *)section_name; + section->name_len = strlen(section_name); + section->content_addr = (uint8 *)p; + section->content_len = p_end - p; + + section->next = module->custom_section_list; + module->custom_section_list = section; + LOG_VERBOSE("Load custom section [%s] success.", section_name); + break; + } +#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */ default: break; } @@ -1816,7 +1847,7 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group, return false; } } - memcpy(symbol, relocation->symbol_name, symbol_len); + bh_memcpy_s(symbol, symbol_len, relocation->symbol_name, symbol_len); symbol[symbol_len] = '\0'; if (!strncmp(symbol, AOT_FUNC_PREFIX, strlen(AOT_FUNC_PREFIX))) { @@ -3261,6 +3292,10 @@ aot_unload(AOTModule *module) } #endif +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 + wasm_runtime_destroy_custom_sections(module->custom_section_list); +#endif + wasm_runtime_free(module); } @@ -3269,3 +3304,24 @@ aot_get_plt_table_size() { return get_plt_table_size(); } + +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 +const uint8 * +aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len) +{ + WASMCustomSection *section = module->custom_section_list; + + while (section) { + if (strcmp(section->name_addr, name) == 0) { + if (len) { + *len = section->content_len; + } + return section->content_addr; + } + + section = section->next; + } + + return NULL; +} +#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION */ diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index bab053fc1..606ffa05c 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1837,7 +1837,7 @@ aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, uint32 size, if (memory_inst->heap_handle.ptr) { addr = mem_allocator_realloc( memory_inst->heap_handle.ptr, - (uint8 *)memory_inst->memory_data.ptr + ptr, size); + ptr ? (uint8 *)memory_inst->memory_data.ptr + ptr : NULL, size); } /* Only support realloc in WAMR's app heap */ diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 1ab325c3d..0aa4edeae 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -50,6 +50,7 @@ typedef enum AOTSectionType { } AOTSectionType; typedef enum AOTCustomSectionType { + AOT_CUSTOM_SECTION_RAW = 0, AOT_CUSTOM_SECTION_NATIVE_SYMBOL = 1, AOT_CUSTOM_SECTION_ACCESS_CONTROL = 2, AOT_CUSTOM_SECTION_NAME = 3, @@ -268,6 +269,9 @@ typedef struct AOTModule { uint32 *aux_func_indexes; uint32 aux_func_name_count; #endif +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 + WASMCustomSection *custom_section_list; +#endif } AOTModule; typedef union { @@ -733,6 +737,9 @@ aot_dump_call_stack(WASMExecEnv *exec_env); void aot_dump_perf_profiling(const AOTModuleInstance *module_inst); +const uint8 * +aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/aot/arch/aot_reloc_arc.c b/core/iwasm/aot/arch/aot_reloc_arc.c index 63267201d..c4fcb176e 100644 --- a/core/iwasm/aot/arch/aot_reloc_arc.c +++ b/core/iwasm/aot/arch/aot_reloc_arc.c @@ -13,6 +13,7 @@ #define R_ARC_32_ME 27 /* clang-format off */ +#ifndef __CCAC__ void __st_r13_to_r15(); void __st_r13_to_r16(); void __st_r13_to_r17(); @@ -41,29 +42,86 @@ 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(); +#else +void __ac_push_13_to_13(); +void __ac_push_13_to_14(); +void __ac_push_13_to_15(); +void __ac_push_13_to_16(); +void __ac_push_13_to_17(); +void __ac_push_13_to_18(); +void __ac_push_13_to_19(); +void __ac_push_13_to_20(); +void __ac_push_13_to_21(); +void __ac_push_13_to_22(); +void __ac_push_13_to_23(); +void __ac_push_13_to_24(); +void __ac_push_13_to_25(); +void __ac_push_13_to_26(); +void __ac_push_none(); +void __ac_pop_13_to_26(); +void __ac_pop_13_to_26v(); +void __ac_pop_13_to_25(); +void __ac_pop_13_to_25v(); +void __ac_pop_13_to_24(); +void __ac_pop_13_to_24v(); +void __ac_pop_13_to_23(); +void __ac_pop_13_to_23v(); +void __ac_pop_13_to_22(); +void __ac_pop_13_to_22v(); +void __ac_pop_13_to_21(); +void __ac_pop_13_to_21v(); +void __ac_pop_13_to_20(); +void __ac_pop_13_to_20v(); +void __ac_pop_13_to_19(); +void __ac_pop_13_to_19v(); +void __ac_pop_13_to_18(); +void __ac_pop_13_to_18v(); +void __ac_pop_13_to_17(); +void __ac_pop_13_to_17v(); +void __ac_pop_13_to_16(); +void __ac_pop_13_to_16v(); +void __ac_pop_13_to_15(); +void __ac_pop_13_to_15v(); +void __ac_pop_13_to_14(); +void __ac_pop_13_to_14v(); +void __ac_pop_13_to_13(); +void __ac_pop_13_to_13v(); +void __ac_pop_none(); +void __ac_pop_nonev(); +void __eqdf2(); +void __nedf2(); +void __ltsf2(); +void __nesf2(); +void __gesf2(); +void __gtsf2(); +void __unordsf2(); +void __truncdfhf2(); +void __truncsfhf2(); +#endif /* end of __CCAC__ */ + +void __ledf2(); +void __ltdf2(); +void __gedf2(); +void __gtdf2(); +void __eqsf2(); +void __lesf2(); void __unorddf2(); /* clang-format on */ static SymbolMap target_sym_map[] = { /* clang-format off */ REG_COMMON_SYMBOLS +#ifndef __CCAC__ 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), @@ -91,22 +149,80 @@ static SymbolMap target_sym_map[] = { 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), +#else + REG_SYM(__ac_push_13_to_13), + REG_SYM(__ac_push_13_to_14), + REG_SYM(__ac_push_13_to_15), + REG_SYM(__ac_push_13_to_16), + REG_SYM(__ac_push_13_to_17), + REG_SYM(__ac_push_13_to_18), + REG_SYM(__ac_push_13_to_19), + REG_SYM(__ac_push_13_to_20), + REG_SYM(__ac_push_13_to_21), + REG_SYM(__ac_push_13_to_22), + REG_SYM(__ac_push_13_to_23), + REG_SYM(__ac_push_13_to_24), + REG_SYM(__ac_push_13_to_25), + REG_SYM(__ac_push_13_to_26), + REG_SYM(__ac_push_none), + REG_SYM(__ac_pop_13_to_26), + REG_SYM(__ac_pop_13_to_26v), + REG_SYM(__ac_pop_13_to_25), + REG_SYM(__ac_pop_13_to_25v), + REG_SYM(__ac_pop_13_to_24), + REG_SYM(__ac_pop_13_to_24v), + REG_SYM(__ac_pop_13_to_23), + REG_SYM(__ac_pop_13_to_23v), + REG_SYM(__ac_pop_13_to_22), + REG_SYM(__ac_pop_13_to_22v), + REG_SYM(__ac_pop_13_to_21), + REG_SYM(__ac_pop_13_to_21v), + REG_SYM(__ac_pop_13_to_20), + REG_SYM(__ac_pop_13_to_20v), + REG_SYM(__ac_pop_13_to_19), + REG_SYM(__ac_pop_13_to_19v), + REG_SYM(__ac_pop_13_to_18), + REG_SYM(__ac_pop_13_to_18v), + REG_SYM(__ac_pop_13_to_17), + REG_SYM(__ac_pop_13_to_17v), + REG_SYM(__ac_pop_13_to_16), + REG_SYM(__ac_pop_13_to_16v), + REG_SYM(__ac_pop_13_to_15), + REG_SYM(__ac_pop_13_to_15v), + REG_SYM(__ac_pop_13_to_14), + REG_SYM(__ac_pop_13_to_14v), + REG_SYM(__ac_pop_13_to_13), + REG_SYM(__ac_pop_13_to_13v), + REG_SYM(__ac_pop_none), + REG_SYM(__ac_pop_nonev), + REG_SYM(__eqdf2), + REG_SYM(__nedf2), + REG_SYM(__ltsf2), + REG_SYM(__nesf2), + REG_SYM(__gesf2), + REG_SYM(__gtsf2), + REG_SYM(__unordsf2), + REG_SYM(__truncdfhf2), + REG_SYM(__truncsfhf2), +#endif /* end of __CCAC__ */ + + REG_SYM(__ledf2), + REG_SYM(__ltdf2), + REG_SYM(__gedf2), + REG_SYM(__gtdf2), + REG_SYM(__eqsf2), + REG_SYM(__lesf2), REG_SYM(__unorddf2), + /* clang-format on */ }; static void @@ -168,6 +284,45 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, int32 symbol_index, char *error_buf, uint32 error_buf_size) { switch (reloc_type) { + case R_ARC_S25H_PCREL: + { + uint32 insn = LOAD_I32(target_section_addr + reloc_offset); + int32 addend, value; + uintptr_t S, P; + intptr_t A; + + 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 << 10; + /* Extract the remaining 10 bits from Position 17 to 26 in insn */ + addend |= ((insn << 5) >> 22); + /* Fill in 1 bits to get the 25 bit Offset Value */ + addend = addend << 1; + + /* (S + A) - P */ + S = (uintptr_t)(uint8 *)symbol_addr; + A = (intptr_t)reloc_addend; + P = (uintptr_t)(target_section_addr + reloc_offset); + P &= (uintptr_t)~1; + value = (int32)(S + A + addend - P); + + insn = insn & 0xf8010030; + insn |= ((((value >> 1) & 0x3ff) << 17) + | (((value >> 1) & 0xffc00) >> 3) + | (((value >> 1) & 0xf00000) >> 19)); + + /* Convert to middle endian */ + insn = middle_endian_convert(insn); + + STORE_U32(target_section_addr + reloc_offset, insn); + break; + } case R_ARC_S25W_PCREL: { uint32 insn = LOAD_I32(target_section_addr + reloc_offset); diff --git a/core/iwasm/aot/arch/aot_reloc_xtensa.c b/core/iwasm/aot/arch/aot_reloc_xtensa.c index 5e1a34c4e..b5b262a5a 100644 --- a/core/iwasm/aot/arch/aot_reloc_xtensa.c +++ b/core/iwasm/aot/arch/aot_reloc_xtensa.c @@ -22,6 +22,26 @@ void __modsi3(); void __divdi3(); +void __udivdi3(); +void __unorddf2(); +void __adddf3(); +void __eqdf2(); +void __muldf3(); +void __gedf2(); +void __ledf2(); +void __fixunsdfsi(); +void __floatunsidf(); +void __subdf3(); +void __nedf2(); +void __fixdfsi(); +void __moddi3(); +void __extendsfdf2(); +void __truncdfsf2(); +void __gtdf2(); +void __umoddi3(); +void __floatdidf(); +void __divsf3(); + static SymbolMap target_sym_map[] = { REG_COMMON_SYMBOLS @@ -40,6 +60,28 @@ static SymbolMap target_sym_map[] = { REG_SYM(__modsi3), REG_SYM(__divdi3), + + REG_SYM(__udivdi3), + REG_SYM(__unorddf2), + REG_SYM(__adddf3), + REG_SYM(__eqdf2), + REG_SYM(__muldf3), + REG_SYM(__gedf2), + REG_SYM(__ledf2), + REG_SYM(__fixunsdfsi), + REG_SYM(__floatunsidf), + REG_SYM(__subdf3), + REG_SYM(__nedf2), + REG_SYM(__fixdfsi), + REG_SYM(__moddi3), + REG_SYM(__extendsfdf2), + REG_SYM(__truncdfsf2), + REG_SYM(__gtdf2), + REG_SYM(__umoddi3), + REG_SYM(__floatdidf), + REG_SYM(__divsf3), + REG_SYM(sqrt), + REG_SYM(sqrtf), }; /* clang-format on */ @@ -130,6 +172,16 @@ static union { #define is_little_endian() (__ue.b == 1) +#if !defined(__packed) +/* + * Note: This version check is a bit relaxed. + * The __packed__ attribute has been there since gcc 2 era. + */ +#if __GNUC__ >= 3 +#define __packed __attribute__((__packed__)) +#endif +#endif + typedef union { struct l32r_le { int8 other; diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index a139d1f4e..c3393eac4 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -485,7 +485,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name, u.ieee.ieee_little_endian.negative = 1; else u.ieee.ieee_big_endian.negative = 1; - memcpy(&f32, &u.f, sizeof(float)); + bh_memcpy_s(&f32, sizeof(float), &u.f, sizeof(float)); } if (endptr[0] == ':') { uint32 sig; @@ -496,10 +496,11 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name, u.ieee.ieee_little_endian.mantissa = sig; else u.ieee.ieee_big_endian.mantissa = sig; - memcpy(&f32, &u.f, sizeof(float)); + bh_memcpy_s(&f32, sizeof(float), &u.f, sizeof(float)); } } - memcpy(&argv1[p++], &f32, sizeof(float)); + bh_memcpy_s(&argv1[p], total_size - p, &f32, sizeof(float)); + p++; break; } case VALUE_TYPE_F64: @@ -517,7 +518,8 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name, ud.ieee.ieee_little_endian.negative = 1; else ud.ieee.ieee_big_endian.negative = 1; - memcpy(&u.val, &ud.d, sizeof(double)); + bh_memcpy_s(&u.val, sizeof(double), &ud.d, + sizeof(double)); } if (endptr[0] == ':') { uint64 sig; @@ -532,7 +534,8 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name, ud.ieee.ieee_big_endian.mantissa0 = sig >> 32; ud.ieee.ieee_big_endian.mantissa1 = (uint32)sig; } - memcpy(&u.val, &ud.d, sizeof(double)); + bh_memcpy_s(&u.val, sizeof(double), &ud.d, + sizeof(double)); } } argv1[p++] = u.parts[0]; @@ -755,7 +758,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, } #endif -#if WAMR_ENABLE_PERF_PROFILING != 0 +#if WASM_ENABLE_PERF_PROFILING != 0 wasm_runtime_dump_perf_profiling(module_inst); #endif diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index d5e4f02b2..ebc4e79c7 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -464,7 +464,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_t error_buf_size) + char *error_buf, uint32 error_buf_size) { WASMRegisteredModule *node = NULL; @@ -519,7 +519,7 @@ wasm_runtime_register_module_internal(const char *module_name, bool wasm_runtime_register_module(const char *module_name, WASMModuleCommon *module, - char *error_buf, uint32_t error_buf_size) + char *error_buf, uint32 error_buf_size) { if (!error_buf || !error_buf_size) { LOG_ERROR("error buffer is required"); @@ -842,7 +842,7 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf, WASMModuleCommon * wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, - char *error_buf, uint32_t error_buf_size) + char *error_buf, uint32 error_buf_size) { WASMModuleCommon *module_common; @@ -999,6 +999,23 @@ wasm_runtime_destroy_thread_env(void) #endif } +bool +wasm_runtime_thread_env_inited(void) +{ +#ifdef BH_PLATFORM_WINDOWS + if (!os_thread_env_inited()) + return false; +#endif + +#if WASM_ENABLE_AOT != 0 +#ifdef OS_ENABLE_HW_BOUND_CHECK + if (!os_thread_signal_inited()) + return false; +#endif +#endif + return true; +} + #if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_MEMORY_TRACING != 0) void wasm_runtime_dump_module_mem_consumption(const WASMModuleCommon *module) @@ -1241,8 +1258,85 @@ wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst, return NULL; } +uint32 +wasm_func_get_param_count(WASMFunctionInstanceCommon *const func_inst, + WASMModuleInstanceCommon *const module_inst) +{ + WASMType *type = + wasm_runtime_get_function_type(func_inst, module_inst->module_type); + bh_assert(type); + + return type->param_count; +} + +uint32 +wasm_func_get_result_count(WASMFunctionInstanceCommon *const func_inst, + WASMModuleInstanceCommon *const module_inst) +{ + WASMType *type = + wasm_runtime_get_function_type(func_inst, module_inst->module_type); + bh_assert(type); + + return type->result_count; +} + +static uint8 +val_type_to_val_kind(uint8 value_type) +{ + switch (value_type) { + 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_FUNCREF: + return WASM_FUNCREF; + case VALUE_TYPE_EXTERNREF: + return WASM_ANYREF; + default: + bh_assert(0); + return 0; + } +} + +void +wasm_func_get_param_types(WASMFunctionInstanceCommon *const func_inst, + WASMModuleInstanceCommon *const module_inst, + wasm_valkind_t *param_types) +{ + WASMType *type = + wasm_runtime_get_function_type(func_inst, module_inst->module_type); + uint32 i; + + bh_assert(type); + + for (i = 0; i < type->param_count; i++) { + param_types[i] = val_type_to_val_kind(type->types[i]); + } +} + +void +wasm_func_get_result_types(WASMFunctionInstanceCommon *const func_inst, + WASMModuleInstanceCommon *const module_inst, + wasm_valkind_t *result_types) +{ + WASMType *type = + wasm_runtime_get_function_type(func_inst, module_inst->module_type); + uint32 i; + + bh_assert(type); + + for (i = 0; i < type->result_count; i++) { + result_types[i] = + val_type_to_val_kind(type->types[type->param_count + i]); + } +} + #if WASM_ENABLE_REF_TYPES != 0 -/* (uintptr_t)externref -> (uint32_t)index */ +/* (uintptr_t)externref -> (uint32)index */ /* argv -> *ret_argv */ static bool wasm_runtime_prepare_call_function(WASMExecEnv *exec_env, @@ -1340,7 +1434,7 @@ wasm_runtime_prepare_call_function(WASMExecEnv *exec_env, return true; } -/* (uintptr_t)externref <- (uint32_t)index */ +/* (uintptr_t)externref <- (uint32)index */ /* argv <- new_argv */ static bool wasm_runtime_finalize_call_function(WASMExecEnv *exec_env, @@ -2776,6 +2870,24 @@ wasm_exec_env_get_module(WASMExecEnv *exec_env) return NULL; } +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 +const uint8 * +wasm_runtime_get_custom_section(WASMModuleCommon *const module_comm, + const char *name, uint32 *len) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_comm->module_type == Wasm_Module_Bytecode) + return wasm_loader_get_custom_section((WASMModule *)module_comm, name, + len); +#endif +#if WASM_ENABLE_AOT != 0 + if (module_comm->module_type == Wasm_Module_AoT) + return aot_get_custom_section((AOTModule *)module_comm, name, len); +#endif + return NULL; +} +#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */ + static union { int a; char b; @@ -3971,8 +4083,8 @@ fail: || defined(BUILD_TARGET_RISCV64_LP64) */ bool -wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32_t element_indices, - uint32_t argc, uint32_t argv[]) +wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices, + uint32 argc, uint32 argv[]) { if (!wasm_runtime_exec_env_check(exec_env)) { LOG_ERROR("Invalid exec env stack info."); @@ -4820,3 +4932,16 @@ wasm_runtime_show_app_heap_corrupted_prompt() "compiled by asc, please add --exportRuntime to " "export the runtime helpers."); } + +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 +void +wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list) +{ + WASMCustomSection *section = section_list, *next; + while (section) { + next = section->next; + wasm_runtime_free(section); + section = next; + } +} +#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION */ diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index cc172f99c..7ef8f69c1 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -303,6 +303,11 @@ typedef struct WASMModuleCommon { Wasm_Module_AoT, and this structure should be treated as AOTModule structure. */ uint32 module_type; + + /* The following uint8[1] member is a dummy just to indicate + some module_type dependent members follow. + Typically it should be accessed by casting to the corresponding + actual module_type dependent structure, not via this member. */ uint8 module_data[1]; } WASMModuleCommon; @@ -314,6 +319,11 @@ typedef struct WASMModuleInstanceCommon { Wasm_Module_AoT, and this structure should be treated as AOTModuleInstance structure. */ uint32 module_type; + + /* The following uint8[1] member is a dummy just to indicate + some module_type dependent members follow. + Typically it should be accessed by casting to the corresponding + actual module_type dependent structure, not via this member. */ uint8 module_inst_data[1]; } WASMModuleInstanceCommon; @@ -377,6 +387,11 @@ typedef struct WASMRegisteredModule { typedef struct WASMMemoryInstanceCommon { uint32 module_type; + + /* The following uint8[1] member is a dummy just to indicate + some module_type dependent members follow. + Typically it should be accessed by casting to the corresponding + actual module_type dependent structure, not via this member. */ uint8 memory_inst_data[1]; } WASMMemoryInstanceCommon; @@ -456,6 +471,28 @@ WASMType * wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function, uint32 module_type); +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN uint32 +wasm_func_get_param_count(WASMFunctionInstanceCommon *const func_inst, + WASMModuleInstanceCommon *const module_inst); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN uint32 +wasm_func_get_result_count(WASMFunctionInstanceCommon *const func_inst, + WASMModuleInstanceCommon *const module_inst); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN void +wasm_func_get_param_types(WASMFunctionInstanceCommon *const func_inst, + WASMModuleInstanceCommon *const module_inst, + wasm_valkind_t *param_types); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN void +wasm_func_get_result_types(WASMFunctionInstanceCommon *const func_inst, + WASMModuleInstanceCommon *const module_inst, + wasm_valkind_t *result_types); + /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN WASMExecEnv * wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst, @@ -621,6 +658,11 @@ wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst, uint8 **p_native_start_addr, uint8 **p_native_end_addr); +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN const uint8 * +wasm_runtime_get_custom_section(WASMModuleCommon *const module_comm, + const char *name, uint32 *len); + uint32 wasm_runtime_get_temp_ret(WASMModuleInstanceCommon *module_inst); @@ -842,6 +884,11 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst, void wasm_runtime_show_app_heap_corrupted_prompt(); +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 +void +wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list); +#endif + #ifdef __cplusplus } #endif diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h index 78dc78e20..a94bf6469 100644 --- a/core/iwasm/compilation/aot.h +++ b/core/iwasm/compilation/aot.h @@ -15,7 +15,9 @@ extern "C" { #endif +#ifndef AOT_FUNC_PREFIX #define AOT_FUNC_PREFIX "aot_func#" +#endif typedef InitializerExpression AOTInitExpr; typedef WASMType AOTFuncType; diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index d1bb081ad..09c3be273 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -2886,6 +2886,36 @@ aot_compile_wasm(AOTCompContext *comp_ctx) return true; } +#if !(defined(_WIN32) || defined(_WIN32_)) +char * +aot_generate_tempfile_name(const char *prefix, const char *extension, + char *buffer, uint32 len) +{ + int fd, name_len; + + name_len = snprintf(buffer, len, "%s-XXXXXX", prefix); + + if ((fd = mkstemp(buffer)) <= 0) { + aot_set_last_error("make temp file failed."); + return NULL; + } + + /* close and remove temp file */ + close(fd); + unlink(buffer); + + /* Check if buffer length is enough */ + /* name_len + '.' + extension + '\0' */ + if (name_len + 1 + strlen(extension) + 1 > len) { + aot_set_last_error("temp file name too long."); + return NULL; + } + + snprintf(buffer + name_len, len - name_len, ".%s", extension); + return buffer; +} +#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */ + #if WASM_ENABLE_LAZY_JIT == 0 bool aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name) @@ -2915,6 +2945,83 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name) bh_print_time("Begin to emit object file"); +#if !(defined(_WIN32) || defined(_WIN32_)) + if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) { + char cmd[1024]; + int ret; + + if (comp_ctx->external_llc_compiler) { + char bc_file_name[64]; + + if (!aot_generate_tempfile_name("wamrc-bc", "bc", bc_file_name, + sizeof(bc_file_name))) { + return false; + } + + if (LLVMWriteBitcodeToFile(comp_ctx->module, bc_file_name) != 0) { + aot_set_last_error("emit llvm bitcode file failed."); + return false; + } + + snprintf(cmd, sizeof(cmd), "%s %s -o %s %s", + comp_ctx->external_llc_compiler, + comp_ctx->llc_compiler_flags ? comp_ctx->llc_compiler_flags + : "-O3 -c", + file_name, bc_file_name); + LOG_VERBOSE("invoking external LLC compiler:\n\t%s", cmd); + + ret = system(cmd); + /* remove temp bitcode file */ + unlink(bc_file_name); + + if (ret != 0) { + aot_set_last_error("failed to compile LLVM bitcode to obj file " + "with external LLC compiler."); + return false; + } + } + else if (comp_ctx->external_asm_compiler) { + char asm_file_name[64]; + + if (!aot_generate_tempfile_name("wamrc-asm", "s", asm_file_name, + sizeof(asm_file_name))) { + return false; + } + + if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine, + comp_ctx->module, asm_file_name, + LLVMAssemblyFile, &err) + != 0) { + if (err) { + LLVMDisposeMessage(err); + err = NULL; + } + aot_set_last_error("emit elf to assembly file failed."); + return false; + } + + snprintf(cmd, sizeof(cmd), "%s %s -o %s %s", + comp_ctx->external_asm_compiler, + comp_ctx->asm_compiler_flags ? comp_ctx->asm_compiler_flags + : "-O3 -c", + file_name, asm_file_name); + LOG_VERBOSE("invoking external ASM compiler:\n\t%s", cmd); + + ret = system(cmd); + /* remove temp assembly file */ + unlink(asm_file_name); + + if (ret != 0) { + aot_set_last_error("failed to compile Assembly file to obj " + "file with external ASM compiler."); + return false; + } + } + + return true; + } +#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */ + if (!strncmp(LLVMGetTargetName(target), "arc", 3)) /* Emit to assmelby file instead for arc target as it cannot emit to object file */ diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h index 4efd1bfb0..d5e45f28b 100644 --- a/core/iwasm/compilation/aot_compiler.h +++ b/core/iwasm/compilation/aot_compiler.h @@ -371,6 +371,10 @@ aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data, bool aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name); +char * +aot_generate_tempfile_name(const char *prefix, const char *extension, + char *buffer, uint32 len); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index dacb59c69..2a46ff9be 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -877,11 +877,15 @@ get_native_symbol_list_size(AOTCompContext *comp_ctx) static uint32 get_name_section_size(AOTCompData *comp_data); +static uint32 +get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data); + static uint32 get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data, AOTObjectData *obj_data) { uint32 size = 0; + uint32 size_custom_section = 0; /* aot file header */ size += get_file_header_size(); @@ -939,6 +943,12 @@ get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data, get_name_section_size(comp_data)); } + size_custom_section = get_custom_sections_size(comp_ctx, comp_data); + if (size_custom_section > 0) { + size = align_uint(size, 4); + size += size_custom_section; + } + return size; } @@ -1274,6 +1284,40 @@ fail: return 0; } +static uint32 +get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data) +{ +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 + uint32 size = 0, i; + + for (i = 0; i < comp_ctx->custom_sections_count; i++) { + const char *section_name = comp_ctx->custom_sections_wp[i]; + const uint8 *content = NULL; + uint32 length = 0; + + content = wasm_loader_get_custom_section(comp_data->wasm_module, + section_name, &length); + if (!content) { + LOG_WARNING("Can't find custom section [%s], ignore it", + section_name); + continue; + } + + size = align_uint(size, 4); + /* section id + section size + sub section id */ + size += (uint32)sizeof(uint32) * 3; + /* section name and len */ + size += get_string_size(comp_ctx, section_name); + /* section content */ + size += length; + } + + return size; +#else + return 0; +#endif +} + static bool aot_emit_file_header(uint8 *buf, uint8 *buf_end, uint32 *p_offset, AOTCompData *comp_data, AOTObjectData *obj_data) @@ -1897,6 +1941,43 @@ aot_emit_name_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, return true; } +static bool +aot_emit_custom_sections(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTCompContext *comp_ctx) +{ +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 + uint32 offset = *p_offset, i; + + for (i = 0; i < comp_ctx->custom_sections_count; i++) { + const char *section_name = comp_ctx->custom_sections_wp[i]; + const uint8 *content = NULL; + uint32 length = 0; + + content = wasm_loader_get_custom_section(comp_data->wasm_module, + section_name, &length); + if (!content) { + /* Warning has been reported during calculating size */ + continue; + } + + offset = align_uint(offset, 4); + EMIT_U32(AOT_SECTION_TYPE_CUSTOM); + /* sub section id + content */ + EMIT_U32(sizeof(uint32) * 1 + get_string_size(comp_ctx, section_name) + + length); + EMIT_U32(AOT_CUSTOM_SECTION_RAW); + EMIT_STR(section_name); + bh_memcpy_s((uint8 *)(buf + offset), (uint32)(buf_end - buf), content, + length); + offset += length; + } + + *p_offset = offset; +#endif + + return true; +} + typedef uint32 U32; typedef int32 I32; typedef uint16 U16; @@ -2611,8 +2692,41 @@ aot_obj_data_create(AOTCompContext *comp_ctx) memset(obj_data, 0, sizeof(AOTObjectData)); bh_print_time("Begin to emit object file"); + if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) { +#if defined(_WIN32) || defined(_WIN32_) + aot_set_last_error("external toolchain not supported on Windows"); + goto fail; +#else + /* Generate a temp file name */ + int ret; + char obj_file_name[64]; - if (!strncmp(LLVMGetTargetName(target), "arc", 3)) { + if (!aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name, + sizeof(obj_file_name))) { + goto fail; + } + + if (!aot_emit_object_file(comp_ctx, obj_file_name)) { + goto fail; + } + + /* create memory buffer from object file */ + ret = LLVMCreateMemoryBufferWithContentsOfFile( + obj_file_name, &obj_data->mem_buf, &err); + /* remove temp object file */ + unlink(obj_file_name); + + 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 (!strncmp(LLVMGetTargetName(target), "arc", 3)) { #if defined(_WIN32) || defined(_WIN32_) aot_set_last_error("emit object file on Windows is unsupported."); goto fail; @@ -2751,7 +2865,9 @@ aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data, || !aot_emit_relocation_section(buf, buf_end, &offset, comp_ctx, comp_data, obj_data) || !aot_emit_native_symbol(buf, buf_end, &offset, comp_ctx) - || !aot_emit_name_section(buf, buf_end, &offset, comp_data, comp_ctx)) + || !aot_emit_name_section(buf, buf_end, &offset, comp_data, comp_ctx) + || !aot_emit_custom_sections(buf, buf_end, &offset, comp_data, + comp_ctx)) goto fail2; #if 0 diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 9252fc2ab..f4449afd3 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -1587,6 +1587,9 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) comp_ctx->opt_level = option->opt_level; comp_ctx->size_level = option->size_level; + comp_ctx->custom_sections_wp = option->custom_sections; + comp_ctx->custom_sections_count = option->custom_sections_count; + if (option->is_jit_mode) { char *triple_jit = NULL; @@ -1657,6 +1660,51 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) opt_level = option->opt_level; size_level = option->size_level; + /* verify external llc compiler */ + comp_ctx->external_llc_compiler = getenv("WAMRC_LLC_COMPILER"); + if (comp_ctx->external_llc_compiler) { +#if defined(_WIN32) || defined(_WIN32_) + comp_ctx->external_llc_compiler = NULL; + LOG_WARNING("External LLC compiler not supported on Windows."); +#else + if (access(comp_ctx->external_llc_compiler, X_OK) != 0) { + LOG_WARNING("WAMRC_LLC_COMPILER [%s] not found, fallback to " + "default pipeline", + comp_ctx->external_llc_compiler); + comp_ctx->external_llc_compiler = NULL; + } + else { + comp_ctx->llc_compiler_flags = getenv("WAMRC_LLC_FLAGS"); + LOG_VERBOSE("Using external LLC compiler [%s]", + comp_ctx->external_llc_compiler); + } +#endif + } + + /* verify external asm compiler */ + if (!comp_ctx->external_llc_compiler) { + comp_ctx->external_asm_compiler = getenv("WAMRC_ASM_COMPILER"); + if (comp_ctx->external_asm_compiler) { +#if defined(_WIN32) || defined(_WIN32_) + comp_ctx->external_asm_compiler = NULL; + LOG_WARNING("External ASM compiler not supported on Windows."); +#else + if (access(comp_ctx->external_asm_compiler, X_OK) != 0) { + LOG_WARNING( + "WAMRC_ASM_COMPILER [%s] not found, fallback to " + "default pipeline", + comp_ctx->external_asm_compiler); + comp_ctx->external_asm_compiler = NULL; + } + else { + comp_ctx->asm_compiler_flags = getenv("WAMRC_ASM_FLAGS"); + LOG_VERBOSE("Using external ASM compiler [%s]", + comp_ctx->external_asm_compiler); + } +#endif + } + } + if (arch) { /* Add default sub-arch if not specified */ if (!strcmp(arch, "arm")) diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 1cb8d3b75..3e321f45d 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -14,6 +14,7 @@ #include "llvm-c/Object.h" #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Analysis.h" +#include "llvm-c/BitWriter.h" #include "llvm-c/Transforms/Utils.h" #include "llvm-c/Transforms/Scalar.h" #include "llvm-c/Transforms/Vectorize.h" @@ -348,6 +349,22 @@ typedef struct AOTCompContext { /* Function contexts */ AOTFuncContext **func_ctxes; uint32 func_ctx_count; + char **custom_sections_wp; + uint32 custom_sections_count; + + /* 3rd-party toolchains */ + /* External llc compiler, if specified, wamrc will emit the llvm-ir file and + * invoke the llc compiler to generate object file. + * This can be used when we want to benefit from the optimization of other + * LLVM based toolchains */ + const char *external_llc_compiler; + const char *llc_compiler_flags; + /* External asm compiler, if specified, wamrc will emit the text-based + * assembly file (.s) and invoke the llc compiler to generate object file. + * This will be useful when the upstream LLVM doesn't support to emit object + * file for some architecture (such as arc) */ + const char *external_asm_compiler; + const char *asm_compiler_flags; } AOTCompContext; enum { @@ -378,6 +395,8 @@ typedef struct AOTCompOption { uint32 size_level; uint32 output_format; uint32 bounds_checks; + char **custom_sections; + uint32 custom_sections_count; } AOTCompOption, *aot_comp_option_t; AOTCompContext * diff --git a/core/iwasm/include/aot_export.h b/core/iwasm/include/aot_export.h index e0ee89668..b60454398 100644 --- a/core/iwasm/include/aot_export.h +++ b/core/iwasm/include/aot_export.h @@ -59,6 +59,8 @@ typedef struct AOTCompOption { uint32_t size_level; uint32_t output_format; uint32_t bounds_checks; + char **custom_sections; + uint32_t custom_sections_count; } AOTCompOption, *aot_comp_option_t; aot_comp_context_t diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index d21a6cabf..9b1481d72 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -133,11 +133,12 @@ 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 + + /* Debug settings, only used when + WASM_ENABLE_DEBUG_INTERP != 0 */ char ip_addr[128]; int platform_port; int instance_port; -#endif } RuntimeInitArgs; #ifndef WASM_VALKIND_T_DEFINED @@ -406,6 +407,54 @@ WASM_RUNTIME_API_EXTERN wasm_function_inst_t wasm_runtime_lookup_function(wasm_module_inst_t const module_inst, const char *name, const char *signature); +/** + * Get parameter count of the function instance + * + * @param func_inst the function instance + * @param module_inst the module instance the function instance belongs to + * + * @return the parameter count of the function instance + */ +WASM_RUNTIME_API_EXTERN uint32_t +wasm_func_get_param_count(wasm_function_inst_t const func_inst, + wasm_module_inst_t const module_inst); + +/** + * Get result count of the function instance + * + * @param func_inst the function instance + * @param module_inst the module instance the function instance belongs to + * + * @return the result count of the function instance + */ +WASM_RUNTIME_API_EXTERN uint32_t +wasm_func_get_result_count(wasm_function_inst_t const func_inst, + wasm_module_inst_t const module_inst); + +/** + * Get parameter types of the function instance + * + * @param func_inst the function instance + * @param module_inst the module instance the function instance belongs to + * @param param_types the parameter types returned + */ +WASM_RUNTIME_API_EXTERN void +wasm_func_get_param_types(wasm_function_inst_t const func_inst, + wasm_module_inst_t const module_inst, + wasm_valkind_t *param_types); + +/** + * Get result types of the function instance + * + * @param func_inst the function instance + * @param module_inst the module instance the function instance belongs to + * @param result_types the result types returned + */ +WASM_RUNTIME_API_EXTERN void +wasm_func_get_result_types(wasm_function_inst_t const func_inst, + wasm_module_inst_t const module_inst, + wasm_valkind_t *result_types); + /** * Create execution environment for a WASM module instance. * @@ -448,7 +497,7 @@ WASM_RUNTIME_API_EXTERN uint32_t wasm_runtime_start_debug_instance(wasm_exec_env_t exec_env); /** - * Initialize thread environment. + * Initialize the thread environment. * Note: * If developer creates a child thread by himself to call the * the wasm function in that thread, he should call this API @@ -463,11 +512,17 @@ WASM_RUNTIME_API_EXTERN bool wasm_runtime_init_thread_env(void); /** - * Destroy thread environment + * Destroy the thread environment */ WASM_RUNTIME_API_EXTERN void wasm_runtime_destroy_thread_env(void); +/** + * Whether the thread environment is initialized + */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_thread_env_inited(void); + /** * Get WASM module instance from execution environment * @@ -998,6 +1053,20 @@ wasm_externref_retain(uint32_t externref_idx); WASM_RUNTIME_API_EXTERN void wasm_runtime_dump_call_stack(wasm_exec_env_t exec_env); +/** + * Get a custom section by name + * + * @param module_comm the module to find + * @param name name of the custom section + * @param len return the length of the content if found + * + * @return Custom section content (not including the name length + * and name string) if found, NULL otherwise + */ +WASM_RUNTIME_API_EXTERN const uint8_t * +wasm_runtime_get_custom_section(wasm_module_t const module_comm, + const char *name, uint32_t *len); + /* clang-format on */ #ifdef __cplusplus diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 20478c586..49961b089 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -346,6 +346,19 @@ typedef struct WASMFastOPCodeNode { } WASMFastOPCodeNode; #endif +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 +typedef struct WASMCustomSection { + struct WASMCustomSection *next; + /* Start address of the section name */ + char *name_addr; + /* Length of the section name decoded from leb */ + uint32 name_len; + /* Start address of the content (name len and name skipped) */ + uint8 *content_addr; + uint32 content_len; +} WASMCustomSection; +#endif + struct WASMModule { /* Module type, for module loaded from WASM bytecode binary, this field is Wasm_Module_Bytecode; @@ -468,6 +481,10 @@ struct WASMModule { const uint8 *name_section_buf_end; #endif +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 + WASMCustomSection *custom_section_list; +#endif + #if WASM_ENABLE_FAST_JIT != 0 /* point to JITed functions */ void **fast_jit_func_ptrs; diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 5dfdcbd78..d66fd36e9 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -14,6 +14,7 @@ #endif #if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 #include "../libraries/thread-mgr/thread_manager.h" +#include "../libraries/debug-engine/debug_engine.h" #endif #if WASM_ENABLE_FAST_JIT != 0 #include "../fast-jit/jit_compiler.h" @@ -947,6 +948,9 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst, #if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0 #define HANDLE_OP_END() \ do { \ + /* Record the current frame_ip, so when exception occurs, \ + debugger can know the exact opcode who caused the exception */ \ + frame_ip_orig = frame_ip; \ while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \ && exec_env->current_status->step_count++ == 1) { \ exec_env->current_status->step_count = 0; \ @@ -1024,6 +1028,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 cache_index, type_index, param_cell_num, cell_num; uint8 value_type; +#if WASM_ENABLE_DEBUG_INTERP != 0 + uint8 *frame_ip_orig = NULL; +#endif + #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op DEFINE_GOTO_TABLE(const void *, handle_table); @@ -3751,6 +3759,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, wasm_set_exception(module, "out of bounds memory access"); got_exception: +#if WASM_ENABLE_DEBUG_INTERP != 0 + if (wasm_exec_env_get_instance(exec_env) != NULL) { + uint8 *frame_ip_temp = frame_ip; + frame_ip = frame_ip_orig; + wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP); + CHECK_SUSPEND_FLAGS(); + frame_ip = frame_ip_temp; + } +#endif SYNC_ALL_TO_FRAME(); return; diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index f5393150d..814445106 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -2815,7 +2815,8 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, uint32 error_buf_size) { const uint8 *p = buf, *p_end = buf_end; - uint32 name_len; + char section_name[32]; + uint32 name_len, buffer_len; if (p >= p_end) { set_error_buf(error_buf, error_buf_size, "unexpected end"); @@ -2834,6 +2835,16 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } + buffer_len = sizeof(section_name); + memset(section_name, 0, buffer_len); + if (name_len < buffer_len) { + bh_memcpy_s(section_name, buffer_len, p, name_len); + } + else { + bh_memcpy_s(section_name, buffer_len, p, buffer_len - 4); + memset(section_name + buffer_len - 4, '.', 3); + } + #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 if (memcmp(p, "name", 4) == 0) { module->name_section_buf = buf; @@ -2841,9 +2852,34 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, p += name_len; handle_name_section(p, p_end, module, is_load_from_file_buf, error_buf, error_buf_size); + LOG_VERBOSE("Load custom name section success."); + return true; } #endif - LOG_VERBOSE("Load custom section success.\n"); + +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 + { + WASMCustomSection *section = + loader_malloc(sizeof(WASMCustomSection), error_buf, error_buf_size); + + if (!section) { + return false; + } + + section->name_addr = (char *)p; + section->name_len = name_len; + section->content_addr = (uint8 *)(p + name_len); + section->content_len = p_end - p - name_len; + + section->next = module->custom_section_list; + module->custom_section_list = section; + LOG_VERBOSE("Load custom section [%s] success.", section_name); + return true; + } +#endif + + LOG_VERBOSE("Ignore custom section [%s].", section_name); + return true; fail: return false; @@ -3792,6 +3828,10 @@ wasm_loader_unload(WASMModule *module) os_mutex_destroy(&module->ref_count_lock); #endif +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 + wasm_runtime_destroy_custom_sections(module->custom_section_list); +#endif + #if WASM_ENABLE_FAST_JIT != 0 if (module->fast_jit_func_ptrs) { for (i = 0; i < module->function_count; i++) { @@ -6493,6 +6533,29 @@ get_table_seg_elem_type(const WASMModule *module, uint32 table_seg_idx, } #endif +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 +const uint8 * +wasm_loader_get_custom_section(WASMModule *module, const char *name, + uint32 *len) +{ + WASMCustomSection *section = module->custom_section_list; + + while (section) { + if ((section->name_len == strlen(name)) + && (memcmp(section->name_addr, name, section->name_len) == 0)) { + if (len) { + *len = section->content_len; + } + return section->content_addr; + } + + section = section->next; + } + + return false; +} +#endif + static bool wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 cur_func_idx, char *error_buf, @@ -6540,6 +6603,16 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } #if WASM_ENABLE_FAST_INTERP != 0 + /* For the first traverse, the initial value of preserved_local_offset has + * not been determined, we use the INT16_MAX to represent that a slot has + * been copied to preserve space. For second traverse, this field will be + * set to the appropriate value in wasm_loader_ctx_reinit. + * This is for Issue #1230, + * https://github.com/bytecodealliance/wasm-micro-runtime/issues/1230, the + * drop opcodes need to know which slots are preserved, so those slots will + * not be treated as dynamically allocated slots */ + loader_ctx->preserved_local_offset = INT16_MAX; + re_scan: if (loader_ctx->code_compiled_size > 0) { if (!wasm_loader_ctx_reinit(loader_ctx)) { @@ -7197,8 +7270,10 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); loader_ctx->frame_offset--; - if (*(loader_ctx->frame_offset) - > loader_ctx->start_dynamic_offset) + if ((*(loader_ctx->frame_offset) + > loader_ctx->start_dynamic_offset) + && (*(loader_ctx->frame_offset) + < loader_ctx->max_dynamic_offset)) loader_ctx->dynamic_offset--; #endif } @@ -7211,8 +7286,10 @@ re_scan: #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->frame_offset) + < loader_ctx->max_dynamic_offset)) loader_ctx->dynamic_offset -= 2; #endif } diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index e6a100d0b..cf81eb5cb 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -4901,6 +4901,16 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, } #if WASM_ENABLE_FAST_INTERP != 0 + /* For the first traverse, the initial value of preserved_local_offset has + * not been determined, we use the INT16_MAX to represent that a slot has + * been copied to preserve space. For second traverse, this field will be + * set to the appropriate value in wasm_loader_ctx_reinit. + * This is for Issue #1230, + * https://github.com/bytecodealliance/wasm-micro-runtime/issues/1230, the + * drop opcodes need to know which slots are preserved, so those slots will + * not be treated as dynamically allocated slots */ + loader_ctx->preserved_local_offset = INT16_MAX; + re_scan: if (loader_ctx->code_compiled_size > 0) { if (!wasm_loader_ctx_reinit(loader_ctx)) { @@ -5477,8 +5487,10 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 skip_label(); loader_ctx->frame_offset--; - if (*(loader_ctx->frame_offset) - > loader_ctx->start_dynamic_offset) + if ((*(loader_ctx->frame_offset) + > loader_ctx->start_dynamic_offset) + && (*(loader_ctx->frame_offset) + < loader_ctx->max_dynamic_offset)) loader_ctx->dynamic_offset--; #endif } @@ -5491,8 +5503,10 @@ re_scan: #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->frame_offset) + < loader_ctx->max_dynamic_offset)) loader_ctx->dynamic_offset -= 2; #endif } diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index e85217715..6c804cb05 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1935,8 +1935,8 @@ wasm_module_realloc(WASMModuleInstance *module_inst, uint32 ptr, uint32 size, } if (memory->heap_handle) { - addr = mem_allocator_realloc(memory->heap_handle, - memory->memory_data + ptr, size); + addr = mem_allocator_realloc( + memory->heap_handle, ptr ? memory->memory_data + ptr : NULL, size); } /* Only support realloc in WAMR's app heap */ diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 5284115a6..a2242fe52 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -458,6 +458,10 @@ void wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env); #endif +const uint8 * +wasm_loader_get_custom_section(WASMModule *module, const char *name, + uint32 *len); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/libraries/debug-engine/debug_engine.c b/core/iwasm/libraries/debug-engine/debug_engine.c index a20d19669..31f45a1f8 100644 --- a/core/iwasm/libraries/debug-engine/debug_engine.c +++ b/core/iwasm/libraries/debug-engine/debug_engine.c @@ -456,7 +456,7 @@ wasm_debug_instance_destroy(WASMCluster *cluster) } } -static WASMExecEnv * +WASMExecEnv * wasm_debug_instance_get_current_env(WASMDebugInstance *instance) { WASMExecEnv *exec_env = NULL; @@ -829,7 +829,10 @@ WASMDebugInstance * wasm_exec_env_get_instance(WASMExecEnv *exec_env) { WASMDebugInstance *instance = NULL; - bh_assert(g_debug_engine); + + if (!g_debug_engine) { + return NULL; + } os_mutex_lock(&g_debug_engine->instance_list_lock); instance = bh_list_first_elem(&g_debug_engine->debug_instance_list); diff --git a/core/iwasm/libraries/debug-engine/debug_engine.h b/core/iwasm/libraries/debug-engine/debug_engine.h index 6057b0ce3..015f20d7b 100644 --- a/core/iwasm/libraries/debug-engine/debug_engine.h +++ b/core/iwasm/libraries/debug-engine/debug_engine.h @@ -128,6 +128,9 @@ wasm_debug_set_engine_active(bool active); bool wasm_debug_get_engine_active(void); +WASMExecEnv * +wasm_debug_instance_get_current_env(WASMDebugInstance *instance); + uint64 wasm_debug_instance_get_pid(WASMDebugInstance *instance); diff --git a/core/iwasm/libraries/debug-engine/handler.c b/core/iwasm/libraries/debug-engine/handler.c index 1b9bd8de4..0772b48ac 100644 --- a/core/iwasm/libraries/debug-engine/handler.c +++ b/core/iwasm/libraries/debug-engine/handler.c @@ -334,6 +334,8 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid) char pc_string[17]; uint32 tids_count, i = 0; uint32 gdb_status = status; + WASMExecEnv *exec_env; + const char *exception; if (status == 0) { os_mutex_lock(&tmpbuf_lock); @@ -370,20 +372,43 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid) mem2hex((void *)&pc, pc_string, 8); pc_string[8 * 2] = '\0'; - if (status == WAMR_SIG_TRAP) { - len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, - "thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc, - pc_string, "breakpoint"); + exec_env = wasm_debug_instance_get_current_env( + (WASMDebugInstance *)server->thread->debug_instance); + bh_assert(exec_env); + + exception = + wasm_runtime_get_exception(wasm_runtime_get_module_inst(exec_env)); + if (exception) { + /* When exception occurs, use reason:exception so the description can be + * correctly processed by LLDB */ + uint32 exception_len = strlen(exception); + len += + snprintf(tmpbuf + len, sizeof(tmpbuf) - len, + "thread-pcs:%" PRIx64 ";00:%s;reason:%s;description:", pc, + pc_string, "exception"); + /* The description should be encoded as HEX */ + for (i = 0; i < exception_len; i++) { + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, "%02x", + exception[i]); + } + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, ";"); } - else if (status == WAMR_SIG_SINGSTEP) { - len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, - "thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc, - pc_string, "trace"); - } - else if (status > 0) { - len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, - "thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc, - pc_string, "signal"); + else { + if (status == WAMR_SIG_TRAP) { + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, + "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc, + pc_string, "breakpoint"); + } + else if (status == WAMR_SIG_SINGSTEP) { + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, + "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc, + pc_string, "trace"); + } + else if (status > 0) { + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, + "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc, + pc_string, "signal"); + } } write_packet(server, tmpbuf); os_mutex_unlock(&tmpbuf_lock); diff --git a/core/shared/platform/common/math/math.c b/core/shared/platform/common/math/math.c index e3b1a7a48..a1679f256 100644 --- a/core/shared/platform/common/math/math.c +++ b/core/shared/platform/common/math/math.c @@ -1091,7 +1091,7 @@ static float freebsd_fminf(float x, float y) { if (is_little_endian()) { - IEEEf2bits_L u[2]; + IEEEf2bits_L u[2] = { 0 }; u[0].f = x; u[1].f = y; @@ -1107,7 +1107,7 @@ freebsd_fminf(float x, float y) return (u[u[1].bits.sign].f); } else { - IEEEf2bits_B u[2]; + IEEEf2bits_B u[2] = { 0 }; u[0].f = x; u[1].f = y; @@ -1130,7 +1130,7 @@ static float freebsd_fmaxf(float x, float y) { if (is_little_endian()) { - IEEEf2bits_L u[2]; + IEEEf2bits_L u[2] = { 0 }; u[0].f = x; u[1].f = y; @@ -1146,7 +1146,7 @@ freebsd_fmaxf(float x, float y) return (u[u[0].bits.sign].f); } else { - IEEEf2bits_B u[2]; + IEEEf2bits_B u[2] = { 0 }; u[0].f = x; u[1].f = y; diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 8513d7943..c13b68f50 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -107,6 +107,12 @@ os_thread_env_init(); void os_thread_env_destroy(); +/** + * Whether the thread environment is initialized + */ +bool +os_thread_env_inited(); + /** * Suspend execution of the calling thread for (at least) * usec microseconds diff --git a/core/shared/platform/linux-sgx/platform_internal.h b/core/shared/platform/linux-sgx/platform_internal.h index 4ce7ee356..3d782ca1c 100644 --- a/core/shared/platform/linux-sgx/platform_internal.h +++ b/core/shared/platform/linux-sgx/platform_internal.h @@ -28,6 +28,7 @@ #include "sgx_time.h" #include "sgx_socket.h" #include "sgx_signal.h" +#include "sgx_trts.h" #ifdef __cplusplus extern "C" { diff --git a/core/shared/platform/linux-sgx/sgx_file.c b/core/shared/platform/linux-sgx/sgx_file.c index 240c4a780..f71249fcc 100644 --- a/core/shared/platform/linux-sgx/sgx_file.c +++ b/core/shared/platform/linux-sgx/sgx_file.c @@ -116,10 +116,6 @@ int ocall_getopt(int *p_ret, int argc, char *argv_buf, unsigned int argv_buf_len, const char *optstring); int -ocall_getrandom(ssize_t *p_ret, void *buf, size_t buflen, unsigned int flags); -int -ocall_getentropy(int *p_ret, void *buffer, size_t length); -int ocall_sched_yield(int *p_ret); /** struct iovec **/ @@ -891,29 +887,124 @@ sched_yield(void) ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) { - ssize_t ret; + sgx_status_t ret; - if (ocall_getrandom(&ret, buf, buflen, flags) != SGX_SUCCESS) { - TRACE_OCALL_FAIL(); + if (!buf || buflen > INT32_MAX || flags != 0) { + errno = EINVAL; return -1; } - if (ret == -1) - errno = get_errno(); - return ret; + + ret = sgx_read_rand(buf, buflen); + if (ret != SGX_SUCCESS) { + errno = EFAULT; + return -1; + } + + return (ssize_t)buflen; +} + +#define RDRAND_RETRIES 3 + +static int +rdrand64_step(uint64 *seed) +{ + uint8 ok; + __asm__ volatile("rdseed %0; setc %1" : "=r"(*seed), "=qm"(ok)); + return (int)ok; +} + +static int +rdrand64_retry(uint64 *rand, uint32 retries) +{ + uint32 count = 0; + + while (count++ <= retries) { + if (rdrand64_step(rand)) { + return -1; + } + } + return 0; +} + +static uint32 +rdrand_get_bytes(uint8 *dest, uint32 n) +{ + uint8 *head_start = dest, *tail_start = NULL; + uint64 *block_start; + uint32 count, ltail, lhead, lblock; + uint64 i, temp_rand; + + /* Get the address of the first 64-bit aligned block in the + destination buffer. */ + if (((uintptr_t)head_start & (uintptr_t)7) == 0) { + /* already 8-byte aligned */ + block_start = (uint64 *)head_start; + lhead = 0; + lblock = n & ~7; + } + else { + /* next 8-byte aligned */ + block_start = (uint64 *)(((uintptr_t)head_start + 7) & ~(uintptr_t)7); + lhead = (uint32)((uintptr_t)block_start - (uintptr_t)head_start); + lblock = (n - lhead) & ~7; + } + + /* Compute the number of 64-bit blocks and the remaining number + of bytes (the tail) */ + ltail = n - lblock - lhead; + if (ltail > 0) { + tail_start = (uint8 *)block_start + lblock; + } + + /* Populate the starting, mis-aligned section (the head) */ + if (lhead > 0) { + if (!rdrand64_retry(&temp_rand, RDRAND_RETRIES)) { + return 0; + } + memcpy(head_start, &temp_rand, lhead); + } + + /* Populate the central, aligned blocks */ + count = lblock / 8; + for (i = 0; i < count; i++, block_start++) { + if (!rdrand64_retry(block_start, RDRAND_RETRIES)) { + return i * 8 + lhead; + } + } + + /* Populate the tail */ + if (ltail > 0) { + if (!rdrand64_retry(&temp_rand, RDRAND_RETRIES)) { + return count * 8 + lhead; + } + + memcpy(tail_start, &temp_rand, ltail); + } + + return n; } int getentropy(void *buffer, size_t length) { - int ret; + uint32 size; - if (ocall_getentropy(&ret, buffer, length) != SGX_SUCCESS) { - TRACE_OCALL_FAIL(); + if (!buffer || length > INT32_MAX) { + errno = EINVAL; return -1; } - if (ret == -1) - errno = get_errno(); - return ret; + + if (length == 0) { + return 0; + } + + size = rdrand_get_bytes(buffer, (uint32)length); + if (size != length) { + errno = EFAULT; + return -1; + } + + return 0; } int diff --git a/core/shared/platform/linux-sgx/sgx_file.h b/core/shared/platform/linux-sgx/sgx_file.h index 83be395bf..c35c22469 100644 --- a/core/shared/platform/linux-sgx/sgx_file.h +++ b/core/shared/platform/linux-sgx/sgx_file.h @@ -250,6 +250,7 @@ sched_yield(void); ssize_t getrandom(void *buf, size_t buflen, unsigned int flags); + int getentropy(void *buffer, size_t length); diff --git a/core/shared/platform/linux-sgx/sgx_wamr.edl b/core/shared/platform/linux-sgx/sgx_wamr.edl index a5ce1897d..3e16aaf8b 100644 --- a/core/shared/platform/linux-sgx/sgx_wamr.edl +++ b/core/shared/platform/linux-sgx/sgx_wamr.edl @@ -77,9 +77,6 @@ enclave { [in, size=argv_buf_len]char *argv_buf, unsigned int argv_buf_len, [in, string]const char *optstring); - ssize_t ocall_getrandom([out, size=buflen]void *buf, size_t buflen, - unsigned int flags); - int ocall_getentropy([out, size=length]void *buffer, size_t length); ssize_t ocall_readv(int fd, [in, out, size=buf_size]char *iov_buf, unsigned int buf_size, int iovcnt, diff --git a/core/shared/platform/linux-sgx/untrusted/file.c b/core/shared/platform/linux-sgx/untrusted/file.c index 4da4be2d3..22abe7d88 100644 --- a/core/shared/platform/linux-sgx/untrusted/file.c +++ b/core/shared/platform/linux-sgx/untrusted/file.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -303,18 +302,6 @@ ocall_getopt(int argc, char *argv_buf, unsigned int argv_buf_len, return getopt(argc, argv, optstring); } -ssize_t -ocall_getrandom(void *buf, size_t buflen, unsigned int flags) -{ - return getrandom(buf, buflen, flags); -} - -int -ocall_getentropy(void *buffer, size_t length) -{ - return getentropy(buffer, length); -} - int ocall_sched_yield() { diff --git a/core/shared/platform/nuttx/nuttx_platform.c b/core/shared/platform/nuttx/nuttx_platform.c index 160147cca..8b8d6d85a 100644 --- a/core/shared/platform/nuttx/nuttx_platform.c +++ b/core/shared/platform/nuttx/nuttx_platform.c @@ -6,6 +6,10 @@ #include "platform_api_extension.h" #include "platform_api_vmcore.h" +#if defined(CONFIG_ARCH_USE_TEXT_HEAP) +#include +#endif + int bh_platform_init() { @@ -37,6 +41,12 @@ os_free(void *ptr) void * os_mmap(void *hint, size_t size, int prot, int flags) { +#if defined(CONFIG_ARCH_USE_TEXT_HEAP) + if ((prot & MMAP_PROT_EXEC) != 0) { + return up_textheap_memalign(sizeof(void *), size); + } +#endif + if ((uint64)size >= UINT32_MAX) return NULL; return malloc((uint32)size); @@ -45,6 +55,12 @@ os_mmap(void *hint, size_t size, int prot, int flags) void os_munmap(void *addr, size_t size) { +#if defined(CONFIG_ARCH_USE_TEXT_HEAP) + if (up_textheap_heapmember(addr)) { + up_textheap_free(addr); + return; + } +#endif return free(addr); } @@ -57,3 +73,75 @@ os_mprotect(void *addr, size_t size, int prot) void os_dcache_flush() {} + +/* If AT_FDCWD is provided, maybe we have openat family */ +#if !defined(AT_FDCWD) + +int +openat(int fd, const char *path, int oflags, ...) +{ + errno = ENOSYS; + return -1; +} + +int +fstatat(int fd, const char *path, struct stat *buf, int flag) +{ + errno = ENOSYS; + return -1; +} + +int +mkdirat(int fd, const char *path, mode_t mode) +{ + errno = ENOSYS; + return -1; +} + +ssize_t +readlinkat(int fd, const char *path, char *buf, size_t bufsize) +{ + errno = ENOSYS; + return -1; +} + +int +linkat(int fd1, const char *path1, int fd2, const char *path2, int flag) +{ + errno = ENOSYS; + return -1; +} + +int +renameat(int fromfd, const char *from, int tofd, const char *to) +{ + errno = ENOSYS; + return -1; +} +int +symlinkat(const char *target, int fd, const char *path) +{ + errno = ENOSYS; + return -1; +} +int +unlinkat(int fd, const char *path, int flag) +{ + errno = ENOSYS; + return -1; +} +int +utimensat(int fd, const char *path, const struct timespec ts[2], int flag) +{ + errno = ENOSYS; + return -1; +} + +#endif /* !defined(AT_FDCWD) */ + +DIR * +fdopendir(int fd) +{ + errno = ENOSYS; + return NULL; +} diff --git a/core/shared/platform/nuttx/platform_internal.h b/core/shared/platform/nuttx/platform_internal.h index 7acfc7305..54c8d7445 100644 --- a/core/shared/platform/nuttx/platform_internal.h +++ b/core/shared/platform/nuttx/platform_internal.h @@ -8,15 +8,21 @@ #include #include +#include #include +#include #include #include +#include #include #include #include #include #include +#include #include +#include +#include #include #include @@ -50,6 +56,63 @@ typedef pthread_t korp_thread; /* On NuttX, time_t is uint32_t */ #define BH_TIME_T_MAX 0xffffffff +/* + * NuttX doesn't have O_DIRECTORY or directory open. + * REVISIT: maybe this is safer to be disabled at higher level. + */ +#if !defined(O_DIRECTORY) +#define O_DIRECTORY 0 +#endif + +#if !defined(O_NOFOLLOW) +#define O_NOFOLLOW 0 +#endif + +#undef CONFIG_HAS_ISATTY +#ifdef CONFIG_SERIAL_TERMIOS +#define CONFIG_HAS_ISATTY 1 +#else +#define CONFIG_HAS_ISATTY 0 +#endif + +/* + * NuttX doesn't have openat family. + */ + +/* If AT_FDCWD is provided, maybe we have openat family */ +#if !defined(AT_FDCWD) + +int +openat(int fd, const char *path, int oflags, ...); +int +fstatat(int fd, const char *path, struct stat *buf, int flag); +int +mkdirat(int fd, const char *path, mode_t mode); +ssize_t +readlinkat(int fd, const char *path, char *buf, size_t bufsize); +int +linkat(int fd1, const char *path1, int fd2, const char *path2, int flag); +int +renameat(int fromfd, const char *from, int tofd, const char *to); +int +symlinkat(const char *target, int fd, const char *path); +int +unlinkat(int fd, const char *path, int flag); +int +utimensat(int fd, const char *path, const struct timespec ts[2], int flag); +#define AT_SYMLINK_NOFOLLOW 0 +#define AT_SYMLINK_FOLLOW 0 +#define AT_REMOVEDIR 0 + +#endif /* !defined(AT_FDCWD) */ + +/* + * NuttX doesn't have fdopendir. + */ + +DIR * +fdopendir(int fd); + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/windows/win_thread.c b/core/shared/platform/windows/win_thread.c index 7d3f60b02..d5a32b530 100644 --- a/core/shared/platform/windows/win_thread.c +++ b/core/shared/platform/windows/win_thread.c @@ -360,6 +360,13 @@ os_thread_env_destroy() } } +bool +os_thread_env_inited() +{ + os_thread_data *thread_data = TlsGetValue(thread_data_key); + return thread_data ? true : false; +} + int os_sem_init(korp_sem *sem) { diff --git a/core/shared/utils/bh_vector.c b/core/shared/utils/bh_vector.c index ea91bec6a..e484661bb 100644 --- a/core/shared/utils/bh_vector.c +++ b/core/shared/utils/bh_vector.c @@ -23,6 +23,10 @@ alloc_vector_data(size_t length, size_t size_elem) return data; } +/** + * every caller of `extend_vector` must provide + * a thread-safe environment. + */ static bool extend_vector(Vector *vector, size_t length) { @@ -38,15 +42,12 @@ extend_vector(Vector *vector, size_t length) return false; } - if (vector->lock) - os_mutex_lock(vector->lock); - memcpy(data, vector->data, vector->size_elem * vector->max_elems); + bh_memcpy_s(data, vector->size_elem * length, vector->data, + vector->size_elem * vector->max_elems); BH_FREE(vector->data); vector->data = data; vector->max_elems = length; - if (vector->lock) - os_mutex_unlock(vector->lock); return true; } @@ -109,8 +110,8 @@ bh_vector_set(Vector *vector, uint32 index, const void *elem_buf) if (vector->lock) os_mutex_lock(vector->lock); - memcpy(vector->data + vector->size_elem * index, elem_buf, - vector->size_elem); + bh_memcpy_s(vector->data + vector->size_elem * index, vector->size_elem, + elem_buf, vector->size_elem); if (vector->lock) os_mutex_unlock(vector->lock); return true; @@ -131,8 +132,8 @@ bh_vector_get(Vector *vector, uint32 index, void *elem_buf) if (vector->lock) os_mutex_lock(vector->lock); - memcpy(elem_buf, vector->data + vector->size_elem * index, - vector->size_elem); + bh_memcpy_s(elem_buf, vector->size_elem, + vector->data + vector->size_elem * index, vector->size_elem); if (vector->lock) os_mutex_unlock(vector->lock); return true; @@ -143,58 +144,73 @@ bh_vector_insert(Vector *vector, uint32 index, const void *elem_buf) { size_t i; uint8 *p; + bool ret = false; if (!vector || !elem_buf) { LOG_ERROR("Insert vector elem failed: vector or elem buf is NULL.\n"); - return false; + goto just_return; } if (index >= vector->num_elems) { LOG_ERROR("Insert vector elem failed: invalid elem index.\n"); - return false; - } - - if (!extend_vector(vector, vector->num_elems + 1)) { - LOG_ERROR("Insert vector elem failed: extend vector failed.\n"); - return false; + goto just_return; } if (vector->lock) os_mutex_lock(vector->lock); + + if (!extend_vector(vector, vector->num_elems + 1)) { + LOG_ERROR("Insert vector elem failed: extend vector failed.\n"); + goto unlock_return; + } + p = vector->data + vector->size_elem * vector->num_elems; for (i = vector->num_elems - 1; i > index; i--) { - memcpy(p, p - vector->size_elem, vector->size_elem); + bh_memcpy_s(p, vector->size_elem, p - vector->size_elem, + vector->size_elem); p -= vector->size_elem; } - memcpy(p, elem_buf, vector->size_elem); + bh_memcpy_s(p, vector->size_elem, elem_buf, vector->size_elem); vector->num_elems++; + ret = true; + +unlock_return: if (vector->lock) os_mutex_unlock(vector->lock); - return true; +just_return: + return ret; } bool bh_vector_append(Vector *vector, const void *elem_buf) { + bool ret = false; + if (!vector || !elem_buf) { LOG_ERROR("Append vector elem failed: vector or elem buf is NULL.\n"); - return false; + goto just_return; } + /* make sure one more slot is used by the thread who allocas it */ + if (vector->lock) + os_mutex_lock(vector->lock); + if (!extend_vector(vector, vector->num_elems + 1)) { LOG_ERROR("Append ector elem failed: extend vector failed.\n"); - return false; + goto unlock_return; } - if (vector->lock) - os_mutex_lock(vector->lock); - memcpy(vector->data + vector->size_elem * vector->num_elems, elem_buf, - vector->size_elem); + bh_memcpy_s(vector->data + vector->size_elem * vector->num_elems, + vector->size_elem, elem_buf, vector->size_elem); vector->num_elems++; + ret = true; + +unlock_return: if (vector->lock) os_mutex_unlock(vector->lock); - return true; +just_return: + return ret; } bool @@ -218,11 +234,12 @@ bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf) p = vector->data + vector->size_elem * index; if (old_elem_buf) { - memcpy(old_elem_buf, p, vector->size_elem); + bh_memcpy_s(old_elem_buf, vector->size_elem, p, vector->size_elem); } for (i = index; i < vector->num_elems - 1; i++) { - memcpy(p, p + vector->size_elem, vector->size_elem); + bh_memcpy_s(p, vector->size_elem, p + vector->size_elem, + vector->size_elem); p += vector->size_elem; } diff --git a/doc/build_wamr.md b/doc/build_wamr.md index d3fe5a683..f57d6678d 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -148,6 +148,15 @@ Currently we only profile the memory consumption of module, module_instance and - **WAMR_BUILD_DEBUG_INTERP**=1/0, default to 0 if not set > Note: There are some other setup required by source debugging, please refer to [source_debugging.md](./source_debugging.md) for more details. +#### **Enable load wasm custom sections** +- **WAMR_BUILD_LOAD_CUSTOM_SECTION**=1/0, default to disable if not set + +> Note: By default, the custom sections are ignored. If the embedder wants to get custom sections from `wasm_module_t`, then `WAMR_BUILD_LOAD_CUSTOM_SECTION` should be enabled, and then `wasm_runtime_get_custom_section` can be used to get a custom section by name. + +> Note: If `WAMR_BUILD_CUSTOM_NAME_SECTION` is enabled, then the `custom name section` will be treated as a special section and consumed by the runtime, not available to the embedder. + +> For AoT file, must use `--emit-custom-sections` to specify which sections need to be emitted into AoT file, otherwise all custom sections (except custom name section) will be ignored. + **Combination of configurations:** We can combine the configurations. For example, if we want to disable interpreter, enable AOT and WASI, we can run command: @@ -216,7 +225,7 @@ To run an AOT file, firstly please refer to [Build wamrc AOT compiler](../README wamrc -o iwasm ``` - + To enable the `JIT` mode, firstly we should build LLVM: ``` Bash @@ -246,7 +255,7 @@ cd build cmake .. -DWAMR_BUILD_FAST_INTERP=0 make ``` - + Linux SGX (Intel Software Guard Extension) ------------------------- @@ -546,14 +555,14 @@ WAMR is intergrated with NuttX, just enable the WAMR in Kconfig option (Applicat ESP-IDF ------------------------- -WAMR integrates with ESP-IDF both for the XTENSA and RISC-V chips (esp32x and esp32c3 respectively). +WAMR integrates with ESP-IDF both for the XTENSA and RISC-V chips (esp32x and esp32c3 respectively). In order to use this, you need at least version 4.3.1 of ESP-IDF. If you don't have it installed, follow the instructions [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/#get-started-get-prerequisites). ESP-IDF also installs the toolchains needed for compiling WAMR and ESP-IDF. A small demonstration of how to use WAMR and ESP-IDF can be found under [product_mini](/product-mini/platforms/esp-idf). -The demo builds WAMR for ESP-IDF and runs a small wasm program. -In order to run it for your specific Espressif chip, edit the ['build.sh'](/product-mini/platforms/esp-idf/build.sh) file and put the correct toolchain file (see #Cross-compilation) and `IDF_TARGET`. +The demo builds WAMR for ESP-IDF and runs a small wasm program. +In order to run it for your specific Espressif chip, edit the ['build_and_run.sh'](/product-mini/platforms/esp-idf/build_and_run.sh) file and put the correct toolchain file (see #Cross-compilation) and `IDF_TARGET`. Before compiling it is also necessary to call ESP-IDF's `export.sh` script to bring all compile time relevant information in scope. Docker diff --git a/doc/build_wasm_app.md b/doc/build_wasm_app.md index a8698e11f..4034b1f5e 100644 --- a/doc/build_wasm_app.md +++ b/doc/build_wasm_app.md @@ -330,6 +330,36 @@ Examples: wamrc -o test.aot test.wasm wamrc --target=i386 --format=object -o test.o test.wasm ``` +## AoT compilation with 3rd-party toolchains + +`wamrc` uses LLVM to compile wasm bytecode to AoT file, this works for most of the architectures, but there may be circumstances where you want to use 3rd-party toolchains to take over some steps of the compilation pipeline, e.g. + +1. The upstream LLVM doesn't support generating object file for your CPU architecture (such as ARC), then we may need some other assembler to do such things. +2. You may get some other LLVM-based toolchains which may have better optimizations for the specific target, then you may want your toolchain to take over all optimization steps. + +`wamrc` provides two environment variables to achieve these: +- `WAMRC_LLC_COMPILER` + + When specified, `wamrc` will emit the optimized LLVM-IR (.bc) to a file, and invoke `$WAMRC_LLC_COMPILER` with ` -c -O3 ` to generate the object file. + + Optionally, you can use environment variable `WAMRC_LLC_FLAGS` to overwrite the default flags. + +- `WAMRC_ASM_COMPILER` + + When specified, `wamrc` will emit the text based assembly file (.s), and invoke `$WAMRC_ASM_COMPILER` with ` -c -O3 ` to generate the object file. + + Optionally, you can use environment variable `WAMRC_ASM_FLAGS` to overwrite the default flags. + +### Usage example +``` bash +WAMRC_LLC_COMPILER= ./wamrc -o test.aot test.wasm +``` + +> Note: `wamrc` will verify whether the specified file exists and executable. If verification failed, `wamrc` will report a warning and fallback to normal pipeline. Since the verification is based on file, you **must specify the absolute path to the binary** even if it's in `$PATH` + +> Note: `WAMRC_LLC_COMPILER` has higher priority than `WAMRC_ASM_COMPILER`, if `WAMRC_LLC_COMPILER` is set and verified, then `WAMRC_ASM_COMPILER` will be ignored. + +> Note: the `LLC` and `ASM` in the env name just means this compiler will be used to compile the `LLVM IR file`/`assembly file` to object file, usually passing the compiler driver is the simplest way. (e.g. for LLVM toolchain, you don't need to pass `/usr/bin/llc`, using `/usr/bin/clang` is OK) Run WASM app in WAMR mini product build ======================================= diff --git a/doc/embed_wamr.md b/doc/embed_wamr.md index b78a0be64..ae3fe4181 100644 --- a/doc/embed_wamr.md +++ b/doc/embed_wamr.md @@ -1,7 +1,9 @@ Embedding WAMR guideline ===================================== -**Note**: All the embedding APIs supported by the runtime are defined under folder [core/iwasm/include](../core/iwasm/include). The API details are available in the header files. +**Note**: This document is about how to embed WAMR into C/C++ host applications, for other languages, please refer to: [Embed WAMR into Python](../language-bindings/go), [Embed WAMR into Go](../language-bindings/go). + +All the embedding APIs supported by the runtime are defined under folder [core/iwasm/include](../core/iwasm/include). The API details are available in the header files. ## Embed WAMR into developer's project @@ -109,7 +111,7 @@ There are several ways to call WASM function: 1. Function call with parameters in an array of 32 bits elements and size: ```c - unit32 argv[2]; + uint32 argv[2]; /* arguments are always transferred in 32-bit element */ argv[0] = 8; @@ -128,11 +130,11 @@ There are several ways to call WASM function: The parameters are transferred in an array of 32 bits elements. For parameters that occupy 4 or fewer bytes, each parameter can be a single array element. For parameters in types like double or int64, each parameter will take two array elements. The function return value will be sent back in the first one or two elements of the array according to the value type. See the sample code below: ```c - unit32 argv[6]; + uint32 argv[6]; char arg1 = 'a'; int arg2 = 10; double arg3 = 1.0; - int 64 arg4 = 100; + int64 arg4 = 100; double ret; argv[0] = arg1; @@ -160,7 +162,7 @@ The parameters are transferred in an array of 32 bits elements. For parameters t 2. Function call with results and arguments both in `wasm_val_t` struct and size: ```c - unit32 num_args = 1, num_results = 1; + uint32 num_args = 1, num_results = 1; wasm_val_t args[1], results[1]; /* set the argument type and value */ @@ -181,7 +183,7 @@ The parameters are transferred in an array of 32 bits elements. For parameters t 3. Function call with variant argument support: ```c - unit32 num_args = 1, num_results = 1; + uint32 num_args = 1, num_results = 1; wasm_val_t results[1]; /* call the WASM function */ @@ -238,7 +240,7 @@ uint32_t buffer_for_wasm; buffer_for_wasm = wasm_runtime_module_malloc(module_inst, 100, &buffer); if (buffer_for_wasm != 0) { - unit32 argv[2]; + uint32 argv[2]; strncpy(buffer, "hello", 100); /* use native address for accessing in runtime */ argv[0] = buffer_for_wasm; /* pass the buffer address for WASM space */ argv[1] = 100; /* the size of buffer */ diff --git a/language-bindings/go/README.md b/language-bindings/go/README.md new file mode 100644 index 000000000..34baf2181 --- /dev/null +++ b/language-bindings/go/README.md @@ -0,0 +1,104 @@ +WAMR Go binding: Embedding WAMR in Go guideline +=============================================== + +This Go library uses CGO to consume the runtime APIs of the WAMR project which are defined in [core/iwasm/include/wasm_export.h](../../core/iwasm/include/wasm_export.h). The API details are available in the header files. + +## Installation + +### Installing from the source code + +Installing from local source tree is in _development mode_. + +Run `./build.sh` in this folder to build the package, which builds the WAMR runtime library firstly and then builds the Go binding library. + +Run `./build.sh` under `samples` folder to build and test the sample. + +```bash +cd samples +./build.sh +``` + +## Supported APIs + +All the embedding APIs supported are defined under folder [wamr](./wamr). + +### Runtime APIs + +```Go +func Runtime() *_Runtime +func (self *_Runtime) FullInit(alloc_with_pool bool, heap_buf []byte, + max_thread_num uint) error +func (self *_Runtime) Init() error +func (self *_Runtime) Destroy() +func (self *_Runtime) SetLogLevel(level LogLevel) +func (self *_Runtime) Malloc(size uint32) *uint8 +func (self *_Runtime) Free(ptr *uint8) +``` + +### Module APIs + +```Go +func NewModule(wasmBytes []byte) (*Module, error) +func (self *Module) Destroy() +func (self *Module) SetWasiArgs(dirList [][]byte, mapDirList [][]byte, + env [][]byte, argv[][]byte) +func (self *Module) SetWasiArgsEx(dirList [][]byte, mapDirList [][]byte, + env [][]byte, argv[][]byte, + stdinfd int, stdoutfd int, stderrfd int) +func (self *Module) SetWasiAddrPool(addrPool [][]byte) +``` + +### Instance APIs + +```Go +func NewInstance(module *Module, + stackSize uint, heapSize uint) (*Instance, error) +func (self *Instance) Destroy() +func (self *Instance) CallFunc(funcName string, + argc uint32, args []uint32) error +func (self *Instance) CallFuncV(funcName string, + num_results uint32, results []interface{}, + args ... interface{}) error +func (self *Instance) GetException() string +func (self Instance) ModuleMalloc(size uint32) (uint32, *uint8) +func (self Instance) ModuleFree(offset uint32) +func (self Instance) ValidateAppAddr(app_offset uint32, size uint32) bool +func (self Instance) ValidateNativeAddr(native_ptr *uint8, size uint32) bool +func (self Instance) AddrAppToNative(app_offset uint32) *uint8 +func (self Instance) AddrNativeToApp(native_ptr *uint8) uint32 +func (self Instance) GetAppAddrRange(app_offset uint32) (bool, uint32, uint32) +func (self Instance) GetNativeAddrRange(native_ptr *uint8) (bool, *uint8, *uint8) +func (self Instance) DumpMemoryConsumption() +func (self Instance) DumpCallStack() +``` + +## Sample codes + +```Go + var module *wamr.Module + var instance *wamr.Instance + var results []interface{} + var err error + + /* Runtime initialization */ + err = wamr.Runtime().FullInit(false, nil, 1) + + /* Read WASM/AOT file into a memory buffer */ + wasmBytes := read_wasm_binary_to_buffer(...) + + /* Load WASM/AOT module from the memory buffer */ + module, err = wamr.NewModule(wasmBytes) + + /* Create WASM/AOT instance from the module */ + instance, err = wamr.NewInstance(module, 16384, 16384) + + /* Call the `fib` function */ + results = make([]interface{}, 1, 1) + err = instance.CallFuncV("fib", 1, results, (int32)32) + fmt.Printf("fib(32) return: %d\n", results[0].(int32)); + + /* Destroy runtime */ + wamr.Runtime().Destroy() +``` + +More samples can be found in [test.go](./samples/test.go) diff --git a/language-bindings/go/build.sh b/language-bindings/go/build.sh new file mode 100755 index 000000000..1540c6640 --- /dev/null +++ b/language-bindings/go/build.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +PLATFORM=$(uname -s | tr A-Z a-z) +CUR_DIR=$PWD +WAMR_DIR=$PWD/../.. +WAMR_GO_DIR=$PWD/wamr + +cp -a ${WAMR_DIR}/core/iwasm/include/*.h ${WAMR_GO_DIR}/packaged/include + +mkdir -p build && cd build +cmake ${WAMR_DIR}/product-mini/platforms/${PLATFORM} \ + -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 \ + -DWAMR_BUILD_MEMORY_PROFILING=1 +make -j ${nproc} +cp -a libvmlib.a ${WAMR_GO_DIR}/packaged/lib/${PLATFORM}-amd64 + +cd ${WAMR_GO_DIR} +go test diff --git a/language-bindings/go/go.mod b/language-bindings/go/go.mod new file mode 100644 index 000000000..60afebbff --- /dev/null +++ b/language-bindings/go/go.mod @@ -0,0 +1,5 @@ +module gitlab.alipay-inc.com/TNT_Runtime/ant-runtime/bindings/go + +go 1.15 + +require github.com/stretchr/testify v1.7.0 diff --git a/language-bindings/go/go.sum b/language-bindings/go/go.sum new file mode 100644 index 000000000..b380ae445 --- /dev/null +++ b/language-bindings/go/go.sum @@ -0,0 +1,10 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/language-bindings/go/samples/build.sh b/language-bindings/go/samples/build.sh new file mode 100755 index 000000000..1b0a80719 --- /dev/null +++ b/language-bindings/go/samples/build.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +PLATFORM=$(uname -s | tr A-Z a-z) +CUR_DIR=$PWD +WAMR_DIR=$PWD/../../.. +WAMR_GO_DIR=$PWD/../wamr + +cp -a ${WAMR_DIR}/core/iwasm/include/*.h ${WAMR_GO_DIR}/packaged/include + +mkdir -p build && cd build +cmake ${WAMR_DIR}/product-mini/platforms/${PLATFORM} \ + -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 \ + -DWAMR_BUILD_MEMORY_PROFILING=1 +make -j ${nproc} +cp -a libvmlib.a ${WAMR_GO_DIR}/packaged/lib/${PLATFORM}-amd64 + +cd ${CUR_DIR} +rm -f test +go build test.go +./test diff --git a/language-bindings/go/samples/run.sh b/language-bindings/go/samples/run.sh new file mode 100755 index 000000000..a57da7f5f --- /dev/null +++ b/language-bindings/go/samples/run.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +go build test.go +./test diff --git a/language-bindings/go/samples/test.go b/language-bindings/go/samples/test.go new file mode 100644 index 000000000..aacb4a950 --- /dev/null +++ b/language-bindings/go/samples/test.go @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package main + +import ( + "gitlab.alipay-inc.com/TNT_Runtime/ant-runtime/bindings/go/wamr" + "fmt" +) + +var wasmBytes = []byte { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x29, 0x07, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x01, + 0x7F, 0x00, 0x60, 0x04, 0x7F, 0x7E, 0x7D, 0x7C, 0x00, 0x60, 0x02, 0x7E, + 0x7E, 0x01, 0x7E, 0x60, 0x02, 0x7C, 0x7F, 0x01, 0x7D, 0x60, 0x02, 0x7D, + 0x7C, 0x01, 0x7C, 0x02, 0x31, 0x04, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x70, + 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x04, + 0x70, 0x75, 0x74, 0x73, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, + 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x04, + 0x66, 0x72, 0x65, 0x65, 0x00, 0x02, 0x03, 0x07, 0x06, 0x00, 0x03, 0x04, + 0x06, 0x05, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x13, 0x03, 0x7F, + 0x01, 0x41, 0x90, 0x29, 0x0B, 0x7F, 0x00, 0x41, 0x90, 0x09, 0x0B, 0x7F, + 0x00, 0x41, 0x90, 0x29, 0x0B, 0x07, 0x5F, 0x09, 0x06, 0x6D, 0x65, 0x6D, + 0x6F, 0x72, 0x79, 0x02, 0x00, 0x04, 0x66, 0x69, 0x62, 0x32, 0x00, 0x04, + 0x05, 0x74, 0x65, 0x73, 0x74, 0x31, 0x00, 0x05, 0x05, 0x74, 0x65, 0x73, + 0x74, 0x32, 0x00, 0x06, 0x05, 0x74, 0x65, 0x73, 0x74, 0x33, 0x00, 0x07, + 0x05, 0x74, 0x65, 0x73, 0x74, 0x34, 0x00, 0x08, 0x10, 0x5F, 0x5F, 0x6D, + 0x61, 0x69, 0x6E, 0x5F, 0x61, 0x72, 0x67, 0x63, 0x5F, 0x61, 0x72, 0x67, + 0x76, 0x00, 0x09, 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x65, + 0x6E, 0x64, 0x03, 0x01, 0x0B, 0x5F, 0x5F, 0x68, 0x65, 0x61, 0x70, 0x5F, + 0x62, 0x61, 0x73, 0x65, 0x03, 0x02, 0x0A, 0xA5, 0x03, 0x06, 0x37, 0x01, + 0x01, 0x7F, 0x41, 0x01, 0x21, 0x01, 0x20, 0x00, 0x41, 0x02, 0x4F, 0x04, + 0x7F, 0x41, 0x00, 0x21, 0x01, 0x03, 0x40, 0x20, 0x00, 0x41, 0x02, 0x6B, + 0x10, 0x04, 0x20, 0x01, 0x6A, 0x21, 0x01, 0x20, 0x00, 0x41, 0x01, 0x6B, + 0x22, 0x00, 0x41, 0x01, 0x4B, 0x0D, 0x00, 0x0B, 0x20, 0x01, 0x41, 0x01, + 0x6A, 0x05, 0x41, 0x01, 0x0B, 0x0B, 0x3F, 0x01, 0x01, 0x7F, 0x23, 0x00, + 0x41, 0x20, 0x6B, 0x22, 0x04, 0x24, 0x00, 0x20, 0x04, 0x41, 0x18, 0x6A, + 0x20, 0x03, 0x39, 0x03, 0x00, 0x20, 0x04, 0x41, 0x10, 0x6A, 0x20, 0x02, + 0xBB, 0x39, 0x03, 0x00, 0x20, 0x04, 0x20, 0x01, 0x37, 0x03, 0x08, 0x20, + 0x04, 0x20, 0x00, 0x36, 0x02, 0x00, 0x41, 0xD0, 0x08, 0x20, 0x04, 0x10, + 0x00, 0x1A, 0x20, 0x04, 0x41, 0x20, 0x6A, 0x24, 0x00, 0x0B, 0x3B, 0x01, + 0x01, 0x7F, 0x23, 0x00, 0x41, 0x20, 0x6B, 0x22, 0x02, 0x24, 0x00, 0x20, + 0x02, 0x20, 0x00, 0x37, 0x03, 0x00, 0x20, 0x02, 0x20, 0x01, 0x37, 0x03, + 0x08, 0x20, 0x02, 0x41, 0x10, 0x6A, 0x20, 0x00, 0x20, 0x01, 0x7C, 0x22, + 0x00, 0x37, 0x03, 0x00, 0x41, 0xF6, 0x08, 0x20, 0x02, 0x10, 0x00, 0x1A, + 0x20, 0x02, 0x41, 0x20, 0x6A, 0x24, 0x00, 0x20, 0x00, 0x0B, 0x40, 0x02, + 0x01, 0x7F, 0x01, 0x7C, 0x23, 0x00, 0x41, 0x20, 0x6B, 0x22, 0x02, 0x24, + 0x00, 0x20, 0x02, 0x20, 0x01, 0x39, 0x03, 0x08, 0x20, 0x02, 0x20, 0x00, + 0xBB, 0x22, 0x03, 0x39, 0x03, 0x00, 0x20, 0x02, 0x41, 0x10, 0x6A, 0x20, + 0x03, 0x20, 0x01, 0xA2, 0x22, 0x01, 0x39, 0x03, 0x00, 0x41, 0xB4, 0x08, + 0x20, 0x02, 0x10, 0x00, 0x1A, 0x20, 0x02, 0x41, 0x20, 0x6A, 0x24, 0x00, + 0x20, 0x01, 0x0B, 0x3D, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x20, 0x6B, + 0x22, 0x02, 0x24, 0x00, 0x20, 0x02, 0x20, 0x00, 0x39, 0x03, 0x00, 0x20, + 0x02, 0x20, 0x01, 0x36, 0x02, 0x08, 0x20, 0x02, 0x41, 0x10, 0x6A, 0x20, + 0x00, 0x20, 0x01, 0xB7, 0xA3, 0x22, 0x00, 0x39, 0x03, 0x00, 0x41, 0xC2, + 0x08, 0x20, 0x02, 0x10, 0x00, 0x1A, 0x20, 0x02, 0x41, 0x20, 0x6A, 0x24, + 0x00, 0x20, 0x00, 0xB6, 0x0B, 0x70, 0x00, 0x23, 0x00, 0x41, 0x20, 0x6B, + 0x22, 0x00, 0x24, 0x00, 0x41, 0x9A, 0x08, 0x10, 0x01, 0x1A, 0x02, 0x7F, + 0x41, 0x80, 0x08, 0x10, 0x02, 0x22, 0x01, 0x45, 0x04, 0x40, 0x41, 0x88, + 0x08, 0x10, 0x01, 0x1A, 0x41, 0x7F, 0x0C, 0x01, 0x0B, 0x20, 0x00, 0x20, + 0x01, 0x36, 0x02, 0x10, 0x41, 0xA7, 0x08, 0x20, 0x00, 0x41, 0x10, 0x6A, + 0x10, 0x00, 0x1A, 0x20, 0x01, 0x41, 0x04, 0x6A, 0x41, 0x8E, 0x09, 0x2F, + 0x00, 0x00, 0x3B, 0x00, 0x00, 0x20, 0x01, 0x41, 0x8A, 0x09, 0x28, 0x00, + 0x00, 0x36, 0x00, 0x00, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x00, 0x41, + 0x80, 0x08, 0x20, 0x00, 0x10, 0x00, 0x1A, 0x20, 0x01, 0x10, 0x03, 0x41, + 0x00, 0x0B, 0x20, 0x00, 0x41, 0x20, 0x6A, 0x24, 0x00, 0x0B, 0x0B, 0x97, + 0x01, 0x01, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x8F, 0x01, 0x62, 0x75, 0x66, + 0x3A, 0x20, 0x25, 0x73, 0x00, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x20, + 0x62, 0x75, 0x66, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x00, 0x48, + 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00, + 0x62, 0x75, 0x66, 0x20, 0x70, 0x74, 0x72, 0x3A, 0x20, 0x25, 0x70, 0x0A, + 0x00, 0x25, 0x66, 0x20, 0x2A, 0x20, 0x25, 0x66, 0x20, 0x3D, 0x20, 0x25, + 0x66, 0x0A, 0x00, 0x25, 0x66, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x20, 0x3D, + 0x20, 0x25, 0x66, 0x0A, 0x00, 0x69, 0x33, 0x32, 0x3A, 0x20, 0x25, 0x64, + 0x2C, 0x20, 0x69, 0x36, 0x34, 0x3A, 0x20, 0x25, 0x6C, 0x6C, 0x64, 0x2C, + 0x20, 0x66, 0x33, 0x32, 0x3A, 0x20, 0x25, 0x66, 0x2C, 0x20, 0x66, 0x36, + 0x34, 0x3A, 0x20, 0x25, 0x66, 0x0A, 0x00, 0x25, 0x6C, 0x6C, 0x64, 0x20, + 0x2B, 0x20, 0x25, 0x6C, 0x6C, 0x64, 0x20, 0x3D, 0x20, 0x25, 0x6C, 0x6C, + 0x64, 0x0A, 0x00, 0x31, 0x32, 0x33, 0x34, 0x0A } + +var global_heap []byte = make([]byte, 128 * 1024, 128 * 1024) + +func main() { + var module *wamr.Module + var instance *wamr.Instance + var argv []uint32 + var results []interface{} + var offset uint32 + var native_addr *uint8 + var err error + + fmt.Print("Init wasm runtime with global heap buf\n"); + err = wamr.Runtime().FullInit(true, global_heap, 1) + if err != nil { + return + } + fmt.Print("Destroy runtime\n"); + wamr.Runtime().Destroy() + + fmt.Print("Init wasm runtime without global heap buf\n"); + err = wamr.Runtime().FullInit(false, nil, 1) + if err != nil { + return + } + + wamr.Runtime().SetLogLevel(wamr.LOG_LEVEL_WARNING) + + fmt.Print("Load wasm module\n"); + module, err = wamr.NewModule(wasmBytes) + if err != nil { + fmt.Println(err) + goto fail + } + + fmt.Print("Instantiate wasm module\n"); + instance, err = wamr.NewInstance(module, 16384, 16384) + if err != nil { + fmt.Println(err) + goto fail + } + + results = make([]interface{}, 8, 8) + argv = make([]uint32, 8) + + fmt.Print("\nCall func __main_argc_argv with CallFunc:\n"); + err = instance.CallFunc("__main_argc_argv", 2, argv) + if err != nil { + fmt.Println(err) + goto fail + } + + fmt.Print("\nCall func __main_argc_argv with CallFuncV:\n"); + err = instance.CallFuncV("__main_argc_argv", 2, results, + (int32)(0), (int32)(0)) + if err != nil { + fmt.Println(err) + goto fail + } + + fmt.Print("\nCall func `i32 fib2(i32)` with CallFunc:\n"); + argv[0] = 32 + err = instance.CallFunc("fib2", 1, argv) + if err != nil { + fmt.Println(err) + goto fail + } + fmt.Printf("fib2(32) return: %d\n", argv[0]); + + fmt.Print("\nCall func `void test1(i32, i64, f32, f64)` with CallFuncV:\n"); + err = instance.CallFuncV("test1", 0, nil, + (int32)(12345678), + (int64)(3344556677889900), + (float32)(5678.1234), + (float64)(987654321.5678)) + if err != nil { + fmt.Println(err) + goto fail + } + + fmt.Print("\nCall func `i64 test2(i64, i64)` with CallFuncV:\n"); + err = instance.CallFuncV("test2", 1, results, + (int64)(3344556677889900), + (int64)(1122331122110099)) + if err != nil { + fmt.Println(err) + goto fail + } + fmt.Printf("test2(3344556677889900, 1122331122110099) return: %d\n", + results[0].(int64)) + + fmt.Print("\nCall func `f64 test3(f32, f64)` with CallFuncV:\n"); + err = instance.CallFuncV("test3", 1, results, + (float32)(3456.1234), + (float64)(7890.4567)) + if err != nil { + fmt.Println(err) + goto fail + } + fmt.Printf("test3(3456.1234, 7890.4567) return: %f\n", + results[0].(float64)) + + fmt.Print("\nCall func `f32 test4(f64, i32)` with CallFuncV:\n"); + err = instance.CallFuncV("test4", 1, results, + (float64)(8912.3456), + (int32)(123)) + if err != nil { + fmt.Println(err) + goto fail + } + fmt.Printf("test4(8912.3456, 123) return: %f\n", + results[0].(float32)) + + fmt.Print("\nTest ModuleMalloc") + offset, native_addr = instance.ModuleMalloc(1024) + fmt.Printf("ModuleMalloc(%d) return offset: %d, native addr: %p\n", + 1024, offset, native_addr) + + if (!instance.ValidateAppAddr(offset, 1024)) { + fmt.Print("Validate app addr failed\n") + } + if (!instance.ValidateNativeAddr(native_addr, 1024)) { + fmt.Print("Validate native addr failed\n") + } + if (native_addr != instance.AddrAppToNative(offset)) { + fmt.Print("Convert app addr to native addr failed\n") + } + if (offset != instance.AddrNativeToApp(native_addr)) { + fmt.Print("Convert app addr to native addr failed\n") + } + + instance.ModuleFree(offset) + + /* + instance.DumpMemoryConsumption() + instance.DumpCallStack() + */ + + fmt.Print("\n"); + +fail: + if (instance != nil) { + fmt.Print("Destroy instance\n"); + instance.Destroy() + } + + if (module != nil) { + fmt.Print("Destroy module\n"); + module.Destroy() + } + + fmt.Print("Destroy wasm runtime\n"); + wamr.Runtime().Destroy() +} diff --git a/language-bindings/go/samples/wasm-app/build.sh b/language-bindings/go/samples/wasm-app/build.sh new file mode 100755 index 000000000..1d0cc833c --- /dev/null +++ b/language-bindings/go/samples/wasm-app/build.sh @@ -0,0 +1,32 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +WAMR_DIR=${PWD}/../../.. + +echo "Build wasm app .." +/opt/wasi-sdk/bin/clang -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -o test.wasm main.c \ + -Wl,--export=main -Wl,--export=__main_argc_argv \ + -Wl,--export=fib2 \ + -Wl,--export=test1 \ + -Wl,--export=test2 \ + -Wl,--export=test3 \ + -Wl,--export=test4 \ + -Wl,--export=__data_end -Wl,--export=__heap_base \ + -Wl,--strip-all,--no-entry \ + -Wl,--allow-undefined \ + -nostdlib \ + +echo "Build binarydump tool .." +rm -fr build && mkdir build && cd build +cmake ../../../../../test-tools/binarydump-tool +make +cd .. + +echo "Generate test_wasm.h .." +./build/binarydump -o test_wasm.h -n wasm_test_file test.wasm + +rm -fr build + +echo "Done" diff --git a/language-bindings/go/samples/wasm-app/main.c b/language-bindings/go/samples/wasm-app/main.c new file mode 100644 index 000000000..8d1f91242 --- /dev/null +++ b/language-bindings/go/samples/wasm-app/main.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include + +unsigned +fib2(unsigned n) +{ + if (n < 2) { + return 1; + } + return fib2(n - 2) + fib2(n - 1); +} + +void +test1(int32_t i32, int64_t i64, float f32, double f64) +{ + printf("i32: %d, i64: %lld, f32: %f, f64: %f\n", i32, i64, f32, f64); +} + +int64_t +test2(int64_t x, int64_t y) +{ + printf("%lld + %lld = %lld\n", x, y, x + y); + return x + y; +} + +double +test3(float x, double y) +{ + printf("%f * %f = %f\n", x, y, x * y); + return x * y; +} + +float +test4(double x, int32_t y) +{ + printf("%f / %d = %f\n", x, y, x / y); + return x / y; +} + +int +main(int argc, char **argv) +{ + char *buf; + + printf("Hello world!\n"); + + buf = malloc(1024); + if (!buf) { + printf("malloc buf failed\n"); + return -1; + } + + printf("buf ptr: %p\n", buf); + + snprintf(buf, 1024, "%s", "1234\n"); + printf("buf: %s", buf); + + free(buf); + return 0; +} diff --git a/language-bindings/go/wamr/cgo.go b/language-bindings/go/wamr/cgo.go new file mode 100644 index 000000000..74766c301 --- /dev/null +++ b/language-bindings/go/wamr/cgo.go @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package wamr + +// #cgo CFLAGS: -I${SRCDIR}/packaged/include +// #cgo LDFLAGS: -lvmlib -lm +// +// #cgo linux,amd64 LDFLAGS: -Wl,-rpath,${SRCDIR}/packaged/lib/linux-amd64 -L${SRCDIR}/packaged/lib/linux-amd64 +// #cgo linux,arm64 LDFLAGS: -Wl,-rpath,${SRCDIR}/packaged/lib/linux-aarch64 -L${SRCDIR}/packaged/lib/linux-aarch64 +// #cgo darwin,amd64 LDFLAGS: -Wl,-rpath,${SRCDIR}/packaged/lib/darwin-amd64 -L${SRCDIR}/packaged/lib/darwin-amd64 +// #cgo darwin,arm64 LDFLAGS: -Wl,-rpath,${SRCDIR}/packaged/lib/darwin-aarch64 -L${SRCDIR}/packaged/lib/darwin-aarch64 +// +// #include +import "C" + +import ( +) diff --git a/language-bindings/go/wamr/instance.go b/language-bindings/go/wamr/instance.go new file mode 100644 index 000000000..08757f4dc --- /dev/null +++ b/language-bindings/go/wamr/instance.go @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package wamr + +/* +#include +#include + +static inline void +PUT_I64_TO_ADDR(uint32_t *addr, int64_t value) +{ + union { + int64_t val; + uint32_t parts[2]; + } u; + u.val = value; + addr[0] = u.parts[0]; + addr[1] = u.parts[1]; +} + +static inline void +PUT_F64_TO_ADDR(uint32_t *addr, double value) +{ + union { + double val; + uint32_t parts[2]; + } u; + u.val = value; + addr[0] = u.parts[0]; + addr[1] = u.parts[1]; +} + +static inline int64_t +GET_I64_FROM_ADDR(uint32_t *addr) +{ + union { + int64_t val; + uint32_t parts[2]; + } u; + u.parts[0] = addr[0]; + u.parts[1] = addr[1]; + return u.val; +} + +static inline double +GET_F64_FROM_ADDR(uint32_t *addr) +{ + union { + double val; + uint32_t parts[2]; + } u; + u.parts[0] = addr[0]; + u.parts[1] = addr[1]; + return u.val; +} +*/ +import "C" + +import ( + "runtime" + "unsafe" + "fmt" +) + +type Instance struct { + _instance C.wasm_module_inst_t + _exec_env C.wasm_exec_env_t + _module *Module + _exportsCache map[string]C.wasm_function_inst_t +} + +/* Create instance from the module */ +func NewInstance(module *Module, + stackSize uint, heapSize uint) (*Instance, error) { + if (module == nil) { + return nil, fmt.Errorf("NewInstance error: invalid input") + } + + errorBytes := make([]byte, 128) + errorPtr := (*C.char)(unsafe.Pointer(&errorBytes[0])) + errorLen := C.uint(len(errorBytes)) + + instance := C.wasm_runtime_instantiate(module.module, C.uint(stackSize), + C.uint(heapSize), errorPtr, errorLen) + if (instance == nil) { + return nil, fmt.Errorf("NewInstance Error: %s", string(errorBytes)) + } + + exec_env := C.wasm_runtime_create_exec_env(instance, C.uint(stackSize)) + if (exec_env == nil) { + C.wasm_runtime_deinstantiate(instance) + return nil, fmt.Errorf("NewInstance Error: create exec_env failed") + } + + self := &Instance{ + _instance: instance, + _exec_env: exec_env, + _module: module, + _exportsCache: make(map[string]C.wasm_function_inst_t), + } + + runtime.SetFinalizer(self, func(self *Instance) { + self.Destroy() + }) + + return self, nil +} + +/* Destroy the instance */ +func (self *Instance) Destroy() { + runtime.SetFinalizer(self, nil) + if (self._instance != nil) { + C.wasm_runtime_deinstantiate(self._instance) + } + if (self._exec_env != nil) { + C.wasm_runtime_destroy_exec_env(self._exec_env) + } +} + +/* Call the wasm function with argument in the uint32 array, and store + the return values back into the array */ +func (self *Instance) CallFunc(funcName string, + argc uint32, args []uint32) error { + _func := self._exportsCache[funcName] + if _func == nil { + cName := C.CString(funcName) + defer C.free(unsafe.Pointer(cName)) + + _func = C.wasm_runtime_lookup_function(self._instance, + cName, (*C.char)(C.NULL)) + if _func == nil { + return fmt.Errorf("CallFunc error: lookup function failed") + } + self._exportsCache[funcName] = _func + } + + thread_env_inited := Runtime().ThreadEnvInited() + if (!thread_env_inited) { + Runtime().InitThreadEnv() + } + + var args_C *C.uint32_t + if (argc > 0) { + args_C = (*C.uint32_t)(unsafe.Pointer(&args[0])) + } + if (!C.wasm_runtime_call_wasm(self._exec_env, _func, + C.uint(argc), args_C)) { + if (!thread_env_inited) { + Runtime().DestroyThreadEnv() + } + return fmt.Errorf("CallFunc error: %s", string(self.GetException())) + } + + if (!thread_env_inited) { + Runtime().DestroyThreadEnv() + } + return nil +} + +/* Call the wasm function with variant arguments, and store the return + values back into the results array */ +func (self *Instance) CallFuncV(funcName string, + num_results uint32, results []interface{}, + args ... interface{}) error { + _func := self._exportsCache[funcName] + if _func == nil { + cName := C.CString(funcName) + defer C.free(unsafe.Pointer(cName)) + + _func = C.wasm_runtime_lookup_function(self._instance, + cName, (*C.char)(C.NULL)) + if _func == nil { + return fmt.Errorf("CallFunc error: lookup function failed") + } + self._exportsCache[funcName] = _func + } + + param_count := uint32(C.wasm_func_get_param_count(_func, self._instance)) + result_count := uint32(C.wasm_func_get_result_count(_func, self._instance)) + + if (num_results < result_count) { + str := "CallFunc error: invalid result count %d, " + + "must be no smaller than %d" + return fmt.Errorf(str, num_results, result_count) + } + + param_types := make([]C.uchar, param_count, param_count) + result_types := make([]C.uchar, result_count, result_count) + if (param_count > 0) { + C.wasm_func_get_param_types(_func, self._instance, + (*C.uchar)(unsafe.Pointer(¶m_types[0]))) + } + if (result_count > 0) { + C.wasm_func_get_result_types(_func, self._instance, + (*C.uchar)(unsafe.Pointer(&result_types[0]))) + } + + argv_size := param_count * 2 + if (result_count > param_count) { + argv_size = result_count * 2 + } + argv := make([]uint32, argv_size, argv_size) + + var i, argc uint32 + for _, arg := range args { + if (i >= param_count) { + break; + } + switch arg.(type) { + case int32: + if (param_types[i] != C.WASM_I32 && + param_types[i] != C.WASM_FUNCREF && + param_types[i] != C.WASM_ANYREF) { + str := "CallFunc error: invalid param type %d, " + + "expect i32 but got other" + return fmt.Errorf(str, param_types[i]) + } + argv[argc] = (uint32)(arg.(int32)) + argc++ + break + case int64: + if (param_types[i] != C.WASM_I64) { + str := "CallFunc error: invalid param type %d, " + + "expect i64 but got other" + return fmt.Errorf(str, param_types[i]) + } + addr := (*C.uint32_t)(unsafe.Pointer(&argv[argc])) + C.PUT_I64_TO_ADDR(addr, (C.int64_t)(arg.(int64))) + argc += 2 + break + case float32: + if (param_types[i] != C.WASM_F32) { + str := "CallFunc error: invalid param type %d, " + + "expect f32 but got other" + return fmt.Errorf(str, param_types[i]) + } + *(*C.float)(unsafe.Pointer(&argv[argc])) = (C.float)(arg.(float32)) + argc++ + break + case float64: + if (param_types[i] != C.WASM_F64) { + str := "CallFunc error: invalid param type %d, " + + "expect f64 but got other" + return fmt.Errorf(str, param_types[i]) + } + addr := (*C.uint32_t)(unsafe.Pointer(&argv[argc])) + C.PUT_F64_TO_ADDR(addr, (C.double)(arg.(float64))) + argc += 2 + break + default: + return fmt.Errorf("CallFunc error: unknown param type %d", + param_types[i]) + } + i++ + } + + if (i < param_count) { + str := "CallFunc error: invalid param count, " + + "must be no smaller than %d" + return fmt.Errorf(str, param_count) + } + + err := self.CallFunc(funcName, argc, argv) + if (err != nil) { + return err + } + + argc = 0 + for i = 0; i < result_count; i++ { + switch result_types[i] { + case C.WASM_I32: + case C.WASM_FUNCREF: + case C.WASM_ANYREF: + i32 := (int32)(argv[argc]) + results[i] = i32 + argc++ + break + case C.WASM_I64: + addr := (*C.uint32_t)(unsafe.Pointer(&argv[argc])) + results[i] = (int64)(C.GET_I64_FROM_ADDR(addr)) + argc += 2 + break + case C.WASM_F32: + addr := (*C.float)(unsafe.Pointer(&argv[argc])) + results[i] = (float32)(*addr) + argc++ + break + case C.WASM_F64: + addr := (*C.uint32_t)(unsafe.Pointer(&argv[argc])) + results[i] = (float64)(C.GET_F64_FROM_ADDR(addr)) + argc += 2 + break + } + } + + return nil +} + +/* Get exception info of the instance */ +func (self *Instance) GetException() string { + cStr := C.wasm_runtime_get_exception(self._instance) + goStr := C.GoString(cStr) + return goStr +} + +/* Allocate memory from the heap of the instance */ +func (self Instance) ModuleMalloc(size uint32) (uint32, *uint8) { + var offset C.uint32_t + native_addrs := make([]*uint8, 1, 1) + ptr := unsafe.Pointer(&native_addrs[0]) + offset = C.wasm_runtime_module_malloc(self._instance, (C.uint32_t)(size), + (*unsafe.Pointer)(ptr)) + return (uint32)(offset), native_addrs[0] +} + +/* Free memory to the heap of the instance */ +func (self Instance) ModuleFree(offset uint32) { + C.wasm_runtime_module_free(self._instance, (C.uint32_t)(offset)) +} + +func (self Instance) ValidateAppAddr(app_offset uint32, size uint32) bool { + ret := C.wasm_runtime_validate_app_addr(self._instance, + (C.uint32_t)(app_offset), + (C.uint32_t)(size)) + return (bool)(ret) +} + +func (self Instance) ValidateStrAddr(app_str_offset uint32) bool { + ret := C.wasm_runtime_validate_app_str_addr(self._instance, + (C.uint32_t)(app_str_offset)) + return (bool)(ret) +} + +func (self Instance) ValidateNativeAddr(native_ptr *uint8, size uint32) bool { + native_ptr_C := (unsafe.Pointer)(native_ptr) + ret := C.wasm_runtime_validate_native_addr(self._instance, + native_ptr_C, + (C.uint32_t)(size)) + return (bool)(ret) +} + +func (self Instance) AddrAppToNative(app_offset uint32) *uint8 { + native_ptr := C.wasm_runtime_addr_app_to_native(self._instance, + (C.uint32_t)(app_offset)) + return (*uint8)(native_ptr) +} + +func (self Instance) AddrNativeToApp(native_ptr *uint8) uint32 { + native_ptr_C := (unsafe.Pointer)(native_ptr) + offset := C.wasm_runtime_addr_native_to_app(self._instance, + native_ptr_C) + return (uint32)(offset) +} + +func (self Instance) GetAppAddrRange(app_offset uint32) (bool, + uint32, + uint32) { + var start_offset, end_offset C.uint32_t + ret := C.wasm_runtime_get_app_addr_range(self._instance, + (C.uint32_t)(app_offset), + &start_offset, &end_offset) + return (bool)(ret), (uint32)(start_offset), (uint32)(end_offset) +} + +func (self Instance) GetNativeAddrRange(native_ptr *uint8) (bool, + *uint8, + *uint8) { + var start_addr, end_addr *C.uint8_t + native_ptr_C := (*C.uint8_t)((unsafe.Pointer)(native_ptr)) + ret := C.wasm_runtime_get_native_addr_range(self._instance, + native_ptr_C, + &start_addr, &end_addr) + return (bool)(ret), (*uint8)(start_addr), (*uint8)(end_addr) +} + +func (self Instance) DumpMemoryConsumption() { + C.wasm_runtime_dump_mem_consumption(self._exec_env) +} + +func (self Instance) DumpCallStack() { + C.wasm_runtime_dump_call_stack(self._exec_env) +} diff --git a/language-bindings/go/wamr/instance_test.go b/language-bindings/go/wamr/instance_test.go new file mode 100644 index 000000000..ad679e2c6 --- /dev/null +++ b/language-bindings/go/wamr/instance_test.go @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package wamr + +import ( + //"github.com/stretchr/testify/assert" + "testing" +) + +func TestInstance(t *testing.T) { + /* TODO */ +} + +func TestCallFunc(t *testing.T) { + /* TODO */ +} diff --git a/language-bindings/go/wamr/module.go b/language-bindings/go/wamr/module.go new file mode 100644 index 000000000..a637e0844 --- /dev/null +++ b/language-bindings/go/wamr/module.go @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package wamr + +// #include +import "C" +import ( + "unsafe" + "runtime" + "fmt" +) + +type Module struct { + module C.wasm_module_t +} + +/* Create WASM/AOT module from the memory buffer */ +func NewModule(wasmBytes []byte) (*Module, error) { + if (wasmBytes == nil || len(wasmBytes) == 0) { + return nil, fmt.Errorf("NewModule error: invalid input") + } + + wasmPtr := (*C.uint8_t)(unsafe.Pointer(&wasmBytes[0])) + wasmLen := C.uint(len(wasmBytes)) + + errorBytes := make([]byte, 128) + errorPtr := (*C.char)(unsafe.Pointer(&errorBytes[0])) + errorLen := C.uint(len(errorBytes)) + + m := C.wasm_runtime_load(wasmPtr, wasmLen, errorPtr, errorLen) + if (m == nil) { + return nil, fmt.Errorf("NewModule error: %s", string(errorBytes)) + } + + self := &Module{ + module: m, + } + + runtime.SetFinalizer(self, func(self *Module) { + self.Destroy() + }) + + return self, nil +} + +/* Destroy the module */ +func (self *Module) Destroy() { + runtime.SetFinalizer(self, nil) + if (self.module != nil) { + C.wasm_runtime_unload(self.module) + } +} + +/* Set module's wasi arguments */ +func (self *Module) SetWasiArgs(dirList [][]byte, mapDirList [][]byte, + env [][]byte, argv[][]byte) { + var dirPtr, mapDirPtr, envPtr, argvPtr **C.char + var dirCount, mapDirCount, envCount C.uint + var argc C.int + + if (dirList != nil) { + dirPtr = (**C.char)(unsafe.Pointer(&dirList[0])) + dirCount = C.uint(len(dirList)) + } + + if (mapDirList != nil) { + mapDirPtr = (**C.char)(unsafe.Pointer(&mapDirList[0])) + mapDirCount = C.uint(len(mapDirList)) + } + + if (env != nil) { + envPtr = (**C.char)(unsafe.Pointer(&env[0])) + envCount = C.uint(len(env)) + } + + if (argv != nil) { + argvPtr = (**C.char)(unsafe.Pointer(&argv[0])) + argc = C.int(len(argv)) + } + + C.wasm_runtime_set_wasi_args(self.module, dirPtr, dirCount, + mapDirPtr, mapDirCount, + envPtr, envCount, argvPtr, argc) +} + +/* Set module's wasi arguments */ +func (self *Module) SetWasiArgsEx(dirList [][]byte, mapDirList [][]byte, + env [][]byte, argv[][]byte, + stdinfd int, stdoutfd int, stderrfd int) { + var dirPtr, mapDirPtr, envPtr, argvPtr **C.char + var dirCount, mapDirCount, envCount C.uint + var argc C.int + + if (dirList != nil) { + dirPtr = (**C.char)(unsafe.Pointer(&dirList[0])) + dirCount = C.uint(len(dirList)) + } + + if (mapDirList != nil) { + mapDirPtr = (**C.char)(unsafe.Pointer(&mapDirList[0])) + mapDirCount = C.uint(len(mapDirList)) + } + + if (env != nil) { + envPtr = (**C.char)(unsafe.Pointer(&env[0])) + envCount = C.uint(len(env)) + } + + if (argv != nil) { + argvPtr = (**C.char)(unsafe.Pointer(&argv[0])) + argc = C.int(len(argv)) + } + + C.wasm_runtime_set_wasi_args_ex(self.module, dirPtr, dirCount, + mapDirPtr, mapDirCount, + envPtr, envCount, argvPtr, argc, + C.int(stdinfd), C.int(stdoutfd), + C.int(stderrfd)) +} + +/* Set module's wasi network address pool */ +func (self *Module) SetWasiAddrPool(addrPool [][]byte) { + var addrPoolPtr **C.char + var addrPoolSize C.uint + + if (addrPool != nil) { + addrPoolPtr = (**C.char)(unsafe.Pointer(&addrPool[0])) + addrPoolSize = C.uint(len(addrPool)) + } + C.wasm_runtime_set_wasi_addr_pool(self.module, addrPoolPtr, addrPoolSize) +} diff --git a/language-bindings/go/wamr/module_test.go b/language-bindings/go/wamr/module_test.go new file mode 100644 index 000000000..8abeccbaa --- /dev/null +++ b/language-bindings/go/wamr/module_test.go @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package wamr + +import ( + //"github.com/stretchr/testify/assert" + "testing" +) + +func TestModule(t *testing.T) { + /* TODO */ +} diff --git a/language-bindings/go/wamr/packaged/include/dummy.go b/language-bindings/go/wamr/packaged/include/dummy.go new file mode 100644 index 000000000..271e5c167 --- /dev/null +++ b/language-bindings/go/wamr/packaged/include/dummy.go @@ -0,0 +1,6 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package include diff --git a/language-bindings/go/wamr/packaged/lib/darwin-amd64/dummy.go b/language-bindings/go/wamr/packaged/lib/darwin-amd64/dummy.go new file mode 100644 index 000000000..fa8096ad6 --- /dev/null +++ b/language-bindings/go/wamr/packaged/lib/darwin-amd64/dummy.go @@ -0,0 +1,6 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package darwin_amd64 diff --git a/language-bindings/go/wamr/packaged/lib/dummy.go b/language-bindings/go/wamr/packaged/lib/dummy.go new file mode 100644 index 000000000..20dfca801 --- /dev/null +++ b/language-bindings/go/wamr/packaged/lib/dummy.go @@ -0,0 +1,6 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package lib diff --git a/language-bindings/go/wamr/packaged/lib/linux-amd64/dummy.go b/language-bindings/go/wamr/packaged/lib/linux-amd64/dummy.go new file mode 100644 index 000000000..8a7c15a7d --- /dev/null +++ b/language-bindings/go/wamr/packaged/lib/linux-amd64/dummy.go @@ -0,0 +1,6 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package linux_amd64 diff --git a/language-bindings/go/wamr/runtime.go b/language-bindings/go/wamr/runtime.go new file mode 100644 index 000000000..2c48a92ad --- /dev/null +++ b/language-bindings/go/wamr/runtime.go @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package wamr + +/* +#include +#include + +#include + +void +bh_log_set_verbose_level(uint32_t level); + +bool +init_wamr_runtime(bool alloc_with_pool, uint8_t *heap_buf, + uint32_t heap_size, uint32_t max_thread_num) +{ + RuntimeInitArgs init_args; + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + if (alloc_with_pool) { + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = heap_buf; + init_args.mem_alloc_option.pool.heap_size = heap_size; + } + else { + init_args.mem_alloc_type = Alloc_With_System_Allocator; + } + + return wasm_runtime_full_init(&init_args); +} +*/ +import "C" +import ( + "fmt" + "unsafe" +) + +type LogLevel uint32 +const ( + LOG_LEVEL_FATAL LogLevel = 0 + LOG_LEVEL_ERROR LogLevel = 1 + LOG_LEVEL_WARNING LogLevel = 2 + LOG_LEVEL_DEBUG LogLevel = 3 + LOG_LEVEL_VERBOSE LogLevel = 4 +) + +/* +type NativeSymbol struct { + symbol string + func_ptr *uint8 + signature string +} +*/ + +type _Runtime struct { + initialized bool +} + +var _runtime_singleton *_Runtime + +/* Return the runtime singleton */ +func Runtime() *_Runtime { + if (_runtime_singleton == nil) { + self := &_Runtime{} + _runtime_singleton = self + } + return _runtime_singleton; +} + +/* Initialize the WASM runtime environment */ +func (self *_Runtime) FullInit(alloc_with_pool bool, heap_buf []byte, + max_thread_num uint) error { + var heap_buf_C *C.uchar + + if (self.initialized) { + return nil + } + + if (alloc_with_pool) { + if (heap_buf == nil) { + return fmt.Errorf("Failed to init WAMR runtime") + } + heap_buf_C = (*C.uchar)(unsafe.Pointer(&heap_buf[0])) + } + + if (!C.init_wamr_runtime((C.bool)(alloc_with_pool), heap_buf_C, + (C.uint)(len(heap_buf)), + (C.uint)(max_thread_num))) { + return fmt.Errorf("Failed to init WAMR runtime") + } + + self.initialized = true + return nil +} + +/* Initialize the WASM runtime environment */ +func (self *_Runtime) Init() error { + return self.FullInit(false, nil, 1) +} + +/* Destroy the WASM runtime environment */ +func (self *_Runtime) Destroy() { + if (self.initialized) { + C.wasm_runtime_destroy() + self.initialized = false + } +} + +/* Set log verbose level (0 to 5, default is 2), + larger level with more log */ +func (self *_Runtime) SetLogLevel(level LogLevel) { + C.bh_log_set_verbose_level(C.uint32_t(level)) +} + +/* +func (self *_Runtime) RegisterNatives(moduleName string, + nativeSymbols []NativeSymbol) { +} +*/ /* TODO */ + +func (self *_Runtime) InitThreadEnv() bool { + if (!C.wasm_runtime_init_thread_env()) { + return false + } + return true +} + +func (self *_Runtime) DestroyThreadEnv() { + C.wasm_runtime_destroy_thread_env(); +} + +func (self *_Runtime) ThreadEnvInited() bool { + if (!C.wasm_runtime_thread_env_inited()) { + return false + } + return true +} + +/* Allocate memory from runtime memory environment */ +func (self *_Runtime) Malloc(size uint32) *uint8 { + ptr := C.wasm_runtime_malloc((C.uint32_t)(size)) + return (*uint8)(ptr) +} + +/* Free memory to runtime memory environment */ +func (self *_Runtime) Free(ptr *uint8) { + C.wasm_runtime_free((unsafe.Pointer)(ptr)) +} diff --git a/language-bindings/go/wamr/runtime_test.go b/language-bindings/go/wamr/runtime_test.go new file mode 100644 index 000000000..66fdf65e5 --- /dev/null +++ b/language-bindings/go/wamr/runtime_test.go @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +package wamr + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestRuntime(t *testing.T) { + res := false + if (Runtime() != nil) { + res = true; + } + assert.Equal(t, res, true) + + err := Runtime().Init() + assert.NoError(t, err) + Runtime().Destroy() + + err = Runtime().FullInit(false, nil, 6) + assert.NoError(t, err) + Runtime().Destroy() + + err = Runtime().FullInit(false, nil, 0) + assert.NoError(t, err) + Runtime().Destroy() + + heap_buf := make([]byte, 128 * 1024) + err = Runtime().FullInit(true, heap_buf, 4) + assert.NoError(t, err) + Runtime().Destroy() + + Runtime().FullInit(false, nil, 0) + err = Runtime().FullInit(false, nil, 0) + assert.NoError(t, err) + Runtime().Destroy() + Runtime().Destroy() +} diff --git a/language-bindings/python/.gitignore b/language-bindings/python/.gitignore new file mode 100644 index 000000000..65efaeda8 --- /dev/null +++ b/language-bindings/python/.gitignore @@ -0,0 +1,160 @@ +# Refer to https://github.com/github/gitignore/blob/main/Python.gitignore +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# virtual environment +Pipfile + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# VSCode settings +.vscode/ + diff --git a/language-bindings/python/LICENSE b/language-bindings/python/LICENSE new file mode 120000 index 000000000..30cff7403 --- /dev/null +++ b/language-bindings/python/LICENSE @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/language-bindings/python/README.md b/language-bindings/python/README.md new file mode 100644 index 000000000..2698a059e --- /dev/null +++ b/language-bindings/python/README.md @@ -0,0 +1,31 @@ +# wamr-python + +## Installation + +### Installing from the source code + +Installing from local source tree is in _development mode_. The package appears to be installed but still is editable from the source tree. + +```bash +$ python -m pip install -e /path/to/wamr-root/binding/python +``` + +## Usage + +```python +import wamr.ffi as ffi +``` + +### Preparation + +The binding will load the shared library _libiwasm.so_ from the WAMR repo. So before running the binding, you need to build the library yourself. + +The default compile options are good enough. + +Please be aware that `wasm_frame_xxx` and `wasm_trap_xxx` only work well when enabling `WAMR_BUILD_DUMP_CALL_STACK`. + +### Examples + +There is a [simple example](./samples/hello_procedural.py) to show how to use bindings. Actually, the python binding follows C-APIs. There it should be easy if be familiar with _programming with wasm-c-api_. + +Unit test cases under _./tests_ could be another but more complete references. diff --git a/language-bindings/python/docs/design.md b/language-bindings/python/docs/design.md new file mode 100644 index 000000000..6c3bc9168 --- /dev/null +++ b/language-bindings/python/docs/design.md @@ -0,0 +1,708 @@ +# how to implement a python binding of WAMR + +A python language binding of Wasm runtime allows its users to call a set of APIs of +the runtime from the python world. Those APIs maybe implemented in C, C++, or Rust. + +In the WAMR case, a python binding allows APIs in `core/iwasm/include/wasm_c_api.h` +to be used in the python scripts. To achieve that, we will create two kinds +of stuff: wrappers of structured data types and wrappers of functions under the +help of _ctypes_. + +Cyptes is a tool in the standard library for creating Python bindings. It +provides a low-level toolset for loading shared libraries and marshaling +data between Python and C. Other options include _cffi_, _pybind11_, +_cpython_ and so on. Because we tend to make the binding depending on least +items. The built-in module, _ctypes_, is a good choice. + +## General rules to marshal + +The core of the idea of a language binding is how to translate different +representations of types in different language. + +### load libraries + +The `ctypes` supports locating a dynamic link library in a way similar to the +compiler does. + +Currently, `ctypes.LoadLibrary` supports: + +- `CDLL`. Those libraries use the standard C calling conversion. +- `OleDLL` and `WinDLL`. Those libraries use the `stdcall` calling conversion on + Windows only + +### fundamental datatypes + +_ctypes_ provides [primitive C compatiable data types](https://docs.python.org/3/library/ctypes.html#fundamental-data-types). +Like `c_bool`, `c_byte`, `c_int`, `c_long` and so on. + +> `c_int` represents the _C_ `signed int` datatype. On platforms where +> `sizeof(int) == sizeof(long)` it is an alias to `c_long`. + +| c datatypes | ctypes | +| ------------------- | ----------------------- | +| bool | c_bool | +| byte_t | c_ubyte | +| char | c_char | +| float32_t | c_float | +| float64_t | c_double | +| int32_t | c_int32 | +| int64_t | c_int64 | +| intptr_t | c_void_p | +| size_t | c_size_t | +| uint8_t | c_uint8 | +| uint32_t | c_uint32 | +| void | None | +| wasm_byte_t | c_ubyte | +| wasm_externkind_t | c_uint8 | +| wasm_memory_pages_t | c_uint32 | +| wasm_mutability_t | c_bool | +| wasm_table_size_t | c_uint32 | +| wasm_valkind_t | c_uint8 | +| wasm_data_type\* | POINTER(wasm_data_type) | + +- `c_void_p` only represents `void *` only +- `None` represents `void` in function parameter lists and return lists + +### structured datatypes + +Create a corresponding concept for every native structured data type includes +`enum`, `struct` and `union`, in the python world. + +#### Enum types + +For example, if there is a `enum wams_mutability_enum` in native. + +```c +typedef uint8_t wams_mutability_t; +enum wams_mutability_enum { + WASM_CONST, + WASM_VAR +}; +``` + +Use `ctypes.int`(or any integer types in ctypes) to represents its value directly. + +```python +# represents enum wams_mutability_enum +wasm_mutability_t = c_uint8 + +WASM_CONST = 0 +WASM_VAR = 1 +``` + +> C standard only requires "Each enumerated type shall be compatible with char, +> a signed integer type, or an unsigned integer type. The choice of the integer +> type is implementation-defined, but shall be capable of representing the +> values of all the members of the enumeration. + +#### Struct types + +If there is a `struct wasm_byte_vec_t` in native(in C). + +```c +typedef struct wasm_byte_vec_t { + size_t size; + wasm_byte_t *data; + size_t num_elems; + size_t size_of_elem; +} wasm_byte_vec_t; +``` + +Use `ctypes.Structure` to create its corresponding data type in python. + +```python +class wasm_byte_vec_t(ctypes.Structure): + _fileds_ = [ + ("size", ctypes.c_size_t), + ("data", ctypes.POINTER(c_ubyte)), + ("num_elems", ctypes.c_size_t), + ("size_of_elem", ctypes.c_size_t), + ] +``` + +a list of `Structures` + +| name | +| ----------------- | +| wasm_engine_t | +| wasm_store_t | +| wasm_limits_t | +| wasm_valtype_t | +| wasm_functype_t | +| wasm_globaltype_t | +| wasm_tabletype_t | +| wasm_memorytype_t | +| wasm_externtype_t | +| wasm_importtype_t | +| wasm_exporttype_t | +| wasm_ref_t | +| wasm_ref_t | +| wasm_frame_t | +| wasm_trap_t | +| wasm_foreign_t | +| WASMModuleCommon | +| WASMModuleCommon | +| wasm_func_t | +| wasm_global_t | +| wasm_table_t | +| wasm_memory_t | +| wasm_extern_t | +| wasm_instance_t | + +not supported `struct` + +- wasm_config_t + +If there is an anonymous `union` in native. + +```c +typedef struct wasm_val_t { + wasm_valkind_t kind; + union { + int32_t i32; + int64_t i64; + float32_t f32; + float64_t f64; + } of; +} wasm_val_t; +``` + +Use `ctypes.Union` to create its corresponding data type in python. + +```python +class _OF(ctypes.Union): + _fields_ = [ + ("i32", ctypes.c_int32), + ("i64", ctypes.c_int64), + ("f32", ctypes.c_float), + ("f64", ctypes.c_double), + ] + +class wasm_val_t(ctypes.Structure): + _anonymous_ = ("of",) + _fields_ = [ + ("kind", ctypes.c_uint8) + ("of", _OF) + ] +``` + +### wrappers of functions + +Foreign functions (C functions) can be accessed as attributes of loaded shared +libraries or an instance of function prototypes. Callback functions(python +functions) can only be accessed by instantiating function prototypes. + +For example, + +```c +void wasm_name_new(wasm_name_t* out, size_t len, wasm_byte_t [] data); +``` + +Assume there are: + +- `class wasm_name_t` of python represents `wasm_name_t` of C +- `libiwasm` represents loaded _libiwasm.so_ + +If to access a c function like an attribute, + +```python +def wasm_name_new(out, len, data): + _wasm_name_new = libiwasm.wasm_name_new + _wasm_name_new.argtypes = (ctypes.POINTER(wasm_name_t), ctypes.c_size_t, ctypes.POINTER(ctypes.c_ubyte)) + _wasm_name_new.restype = None + return _wasm_name_new(out, len, data) +``` + +Or to instantiate a function prototype, + +```python +def wasm_name_new(out, len, data): + return ctypes.CFUNCTYPE(None, (ctypes.POINTER(wasm_name_t), ctypes.c_size_t, ctypes.POINTER(ctypes.c_ubyte)))( + ("wasm_name_new", libiwasm), out, len, data) +``` + +Now it is able to create a `wasm_name_t` with `wasm_name_new()` in python. + +Sometimes, need to create a python function as a callback of c. + +```c +wasm_trap_t* (*wasm_func_callback_t)(wasm_val_vec_t* args, wasm_val_vec_t *results); +``` + +Use `cyptes.CFUNCTYPE` to create a _pointer of function_ + +```python +def hello(args, results): + print("hello from a callback") + +wasm_func_callback_t = ctypes.CFUNCTYPE(c_size_t, POINTER(wasm_val_vec_t), POINTER(wasm_val_vec_t)) +hello_callback = wasm_func_callback_t(hello) +``` + +or with a decorator + +```python +def wasm_func_cb_decl(func): + return @ctypes.CFUNCTYPE(ctypes.POINTER(wasm_trap_t), (ctypes.POINTER(wasm_val_vec_t), ctypes.POINTER(wasm_val_vec_t)))(func) + +@wasm_func_cb_decl +def hello(args, results): + print("hello from a callback") +``` + +### programming tips + +#### `struct` and `ctypes.Structure` + +There are two kinds of `cytes.Structure` in `binding.py`. + +- has `__field__` definition. like `class wasm_byte_vec_t(Structure)` +- doesn't have `__field__` definition. like `class wasm_config_t(Structure)` + +Since, `ctypes` will create its C world _mirror_ variable according to `__field__` +information, `wasm_config_t()` will only create a python instance without binding +to any C variable. `wasm_byte_vec_t()` will return a python instance with an internal +C variable. + +That is why `pointer(wasm_config_t())` is a NULL pointer which can not be dereferenced. + +#### deal with pointers + +`byref()` and `pointer()` are two functions can return a pointer. + +```python +x = ctypes.c_int(2) + +# use pointer() to creates a new pointer instance which would later be used in Python +x_ptr = ctypes.pointer(x) +... +struct_use_pointer = Mystruct() +struct_use_pointer.ptr = x_ptr + +# use byref() pass a pointer to an object to a foreign function call +func(ctypes.byref(x)) +``` + +The main difference is that `pointer()` does a lot more work since it +constructs a real pointer object. It is faster to use `byref(`) if don't need +the pointer object in Python itself(e.g. only use it as an argument to pass +to a function). + +There is no doubt that `wasm_xxx_new()` which return type is `ctypes.POINTER` +can return a pointer. Plus, the return value of `wasm_xxx_t()` can also be +used as a pointer without casting by `byref` or `pointer`. + +#### array + +In [ctypes document](https://docs.python.org/3/library/ctypes.html#arrays), +it states that "The recommended way to create array types is by multiplying a +data type with a positive integer". So _multiplying a data type_ should be a +better way to create arrays + +```python +from ctypes import * + +class POINT(Structure): + _fields_ = ("x", c_int), ("y", c_int) + +# multiplying a data type +# type(TenPointsArrayType) is +TenPointsArrayType = POINT * 10 + +# Instances are created in the usual way, by calling the class: +arr = TenPointsArrayType() +arr[0] = POINT(3,2) +for pt in arr: + print(pt.x, pt.y) +``` + +On both sides, it is OK to assign an array to a pointer. + +```c +char buf[128] = {0}; +char *ptr = buf; +``` + +```python +binary = wasm_byte_vec_t() +binary.data = (ctypes.c_ubyte * len(wasm)).from_buffer_copy(wasm) +``` + +#### exceptions and traps + +Interfaces of _wasm-c-api_ have their return values to represent failures. +The python binding should just keep and transfer them to callers instead of +raising any additional exception. + +The python binding should raise exceptions when the python partial is failed. + +#### readonly buffer + +```python +with open("hello.wasm", "rb") as f: + wasm = f.read() + binary = wasm_byte_vec_t() + wasm_byte_vec_new_uninitialized(byref(binary), len(wasm)) + # create a ctypes instance (byte[] in c) and copy the content + # from wasm(bytearray in python) + binary.data = (ctypes.c_ubyte * len(wasm)).from_buffer_copy(wasm) +``` + +in the above example, `wasm` is a python-created readable buffer. It is not +writable and needs to be copied into a ctype array. + +#### variable arguments + +A function with _variable arugments_ makes it hard to specify the required +argument types for the function prototype. It leaves us one way to call it +directly without any arguments type checking. + +```python +libc.printf(b"Hello, an int %d, a float %f, a string %s\n", c_int(1), c_doulbe(3.14), "World!") +``` + +#### Use `c_bool` to represent `wasm_mutability_t ` + +- `True` for `WASM_CONST` +- `False` for `WASM_VALUE` + +#### customize class builtins + +- `__eq__` for comparation. +- `__repr__` for printing. + +### bindgen.py + +`bindge.py` is a tool to create WAMR python binding automatically. `binding.py` +is generated. We should avoid modification on it. Additional helpers should go +to `ffi.py`. + +`bindgen.py` uses _pycparser_. Visit the AST of `core/iwasm/include/wasm_c_api.h` +created by _gcc_ and generate necessary wrappers. + +```python +from pycparser import c_ast + +class Visitor(c_ast.NodeVisitor): + def visit_Struct(self, node): + pass + + def visit_Union(self, node): + pass + + def visit_TypeDef(self, node): + pass + + def visit_FuncDecl(self, node): + pass + +ast = parse_file(...) +v = Visitor() +v.visit(ast) +``` + +Before running _bindgen.py_, the shared library _libiwasm.so_ should be generated. + +```bash +$ cd /path/to/wamr/repo +$ # if it is in linux +$ pushd product-mini/platforms/linux/ +$ cmake -S . -B build .. +$ cmake --build build --target iwasm +$ popd +$ cd binding/python +$ python utils/bindgen.py +``` + +`wasm_frame_xxx` and `wasm_trap_xxx` only work well when enabling `WAMR_BUILD_DUMP_CALL_STACK`. + +```bash +$ cmake -S . -B build -DWAMR_BUILD_DUMP_CALL_STACK=1 .. +``` + +## OOP wrappers + +Based on the above general rules, there will be corresponding python +APIs for every C API in `wasm_c_api.h` with same name. Users can do procedural +programming with those. + +In next phase, we will create OOP APIs. Almost follow the +[C++ version of wasm_c_api](https://github.com/WebAssembly/wasm-c-api/blob/master/include/wasm.hh) + +## A big list + +| WASM Concept | Procedural APIs | OOP APIs | OOP APIs methods | +| ------------ | ------------------------------ | ---------- | ---------------- | +| XXX_vec | wasm_xxx_vec_new | | list | +| | wasm_xxx_vec_new_uninitialized | | | +| | wasm_xxx_vec_new_empty | | | +| | wasm_xxx_vec_copy | | | +| | wasm_xxx_vec_delete | | | +| valtype | wasm_valtype_new | valtype | \_\_init\_\_ | +| | wasm_valtype_delete | | \_\_del\_\_ | +| | wasm_valtype_kind | | \_\_eq\_\_ | +| | wasm_valtype_copy | | | +| | _vector methods_ | | | +| functype | wasm_functype_new | functype | | +| | wasm_functype_delete | | | +| | wasm_functype_params | | | +| | wasm_functype_results | | | +| | wasm_functype_copy | | | +| | _vector methods_ | | | +| globaltype | wasm_globaltype_new | globaltype | \_\_init\_\_ | +| | wasm_globaltype_delete | | \_\_del\_\_ | +| | wasm_globaltype_content | | \_\_eq\_\_ | +| | wasm_globaltype_mutability | | | +| | wasm_globaltype_copy | | | +| | _vector methods_ | | | +| tabletype | wasm_tabletype_new | tabletype | \_\_init\_\_ | +| | wasm_tabletype_delete | | \_\_del\_\_ | +| | wasm_tabletype_element | | \_\_eq\_\_ | +| | wasm_tabletype_limits | | | +| | wasm_tabletype_copy | | | +| | _vector methods_ | | | +| memorytype | wasm_memorytype_new | memorytype | \_\_init\_\_ | +| | wasm_memorytype_delete | | \_\_del\_\_ | +| | wasm_memorytype_limits | | \_\_eq\_\_ | +| | wasm_memorytype_copy | | | +| | _vector methods_ | | | +| externtype | wasm_externtype_as_XXX | externtype | | +| | wasm_XXX_as_externtype | | | +| | wasm_externtype_copy | | | +| | wasm_externtype_delete | | | +| | wasm_externtype_kind | | | +| | _vector methods_ | | | +| importtype | wasm_importtype_new | importtype | | +| | wasm_importtype_delete | | | +| | wasm_importtype_module | | | +| | wasm_importtype_name | | | +| | wasm_importtype_type | | | +| | wasm_importtype_copy | | | +| | _vector methods_ | | | +| exportype | wasm_exporttype_new | exporttype | | +| | wasm_exporttype_delete | | | +| | wasm_exporttype_name | | | +| | wasm_exporttype_type | | | +| | wasm_exporttype_copy | | | +| | _vector methods_ | | | +| val | wasm_val_delete | val | | +| | wasm_val_copy | | | +| | _vector methods_ | | | +| frame | wasm_frame_delete | frame | | +| | wasm_frame_instance | | | +| | wasm_frame_func_index | | | +| | wasm_frame_func_offset | | | +| | wasm_frame_module_offset | | | +| | wasm_frame_copy | | | +| | _vector methods_ | | | +| trap | wasm_trap_new | trap | | +| | wasm_trap_delete | | | +| | wasm_trap_message | | | +| | wasm_trap_origin | | | +| | wasm_trap_trace | | | +| | _vector methods_ | | | +| foreign | wasm_foreign_new | foreign | | +| | wasm_foreign_delete | | | +| | _vector methods_ | | | +| engine | wasm_engine_new | engine | | +| | wasm_engine_new_with_args\* | | | +| | wasm_engine_new_with_config | | | +| | wasm_engine_delete | | | +| store | wasm_store_new | store | | +| | wasm_store_delete | | | +| | _vector methods_ | | | +| module | wasm_module_new | module | | +| | wasm_module_delete | | | +| | wasm_module_validate | | | +| | wasm_module_imports | | | +| | wasm_module_exports | | | +| instance | wasm_instance_new | instance | | +| | wasm_instance_delete | | | +| | wasm_instance_new_with_args\* | | | +| | wasm_instance_exports | | | +| | _vector methods_ | | | +| func | wasm_func_new | func | | +| | wasm_func_new_with_env | | | +| | wasm_func_delete | | | +| | wasm_func_type | | | +| | wasm_func_call | | | +| | wasm_func_param_arity | | | +| | wasm_func_result_arity | | | +| | _vector methods_ | | | +| global | wasm_global_new | global | | +| | wasm_global_delete | | | +| | wasm_global_type | | | +| | wasm_global_get | | | +| | wasm_global_set | | | +| | _vector methods_ | | | +| table | wasm_table_new | table | | +| | wasm_table_delete | | | +| | wasm_table_type | | | +| | wasm_table_get | | | +| | wasm_table_set | | | +| | wasm_table_size | | | +| | _vector methods_ | | | +| memory | wasm_memory_new | memory | | +| | wasm_memory_delete | | | +| | wasm_memory_type | | | +| | wasm_memory_data | | | +| | wasm_memory_data_size | | | +| | wasm_memory_size | | | +| | _vector methods_ | | | +| extern | wasm_extern_delete | extern | | +| | wasm_extern_as_XXX | | | +| | wasm_XXX_as_extern | | | +| | wasm_extern_kind | | | +| | wasm_extern_type | | | +| | _vector methods_ | | | + +not supported _functions_ + +- wasm_config_XXX +- wasm_module_deserialize +- wasm_module_serialize +- wasm_ref_XXX +- wasm_XXX_as_ref +- wasm_XXX_as_ref_const +- wasm_XXX_copy +- wasm_XXX_get_host_info +- wasm_XXX_set_host_info + +## test + +there will be two kinds of tests in the project + +- unit test. located in `./tests`. driven by _unittest_. run by + `$ python -m unittest` or `$ make test`. +- integration test. located in `./samples`. + +The whole project is under test-driven development. Every wrapper function will +have two kinds of test cases. The first kind is a positive case. It checks a +wrapper function with expected and safe arguments combinations. Its goal is the +function should work well with expected inputs. Another kind is a negative +case. It feeds unexpected arguments combinations into a wrapper function. Arguments +should include but not be limited to `None`. It ensures that the function will +gracefully handle invalid input or unexpected behaviors. + +## distribution + +### package + +Create a python package named `wamr`. Users should import it after installation +just like any other python module. + +```python +from wamr import * +``` + +### PyPI + +Refer to [tutorial provided by PyPA](https://packaging.python.org/en/latest/tutorials/packaging-projects/). +Steps to publish WAMR Python library: + +1. Creating `pyproject.toml` tells build tools (like pip and build) what is + required to build a project. An example .toml file uses _setuptools_ + + ```toml + [build-system] + requires = [ + "setuptools>=42", + "wheel" + ] + build-backend = "setuptools.build_meta" + ``` + +2. Configuring metadata tells build tools about a package (such as the name + and the version), as well as which code files to include + + - Static metadata (`setup.cfg`): guaranteed to be the same every time. + It is simpler, easier to read, and avoids many common errors, like + encoding errors. + + - Dynamic metadata (`setup.py`): possibly non-deterministic. Any items that + are dynamic or determined at install-time, as well as extension modules + or extensions to setuptools, need to go into setup.py. + + **_Static metadata should be preferred_**. Dynamic metadata should be used + only as an escape hatch when necessary. setup.py used to be + required, but can be omitted with newer versions of setuptools and pip. + +3. Including other files in the distribution + + - For [source distribution](https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist): + + It's usually generated using `python setup.py sdist`, providing metadata + and the essential source files needed for installing by a tool like pip, + or for generating a Built Distribution. + + It includes our Python modules, pyproject.toml, metadata, README.md, + LICENSE. If you want to control what goes in this explicitly, + see [Including files in source distributions with MANIFEST.in](https://packaging.python.org/en/latest/guides/using-manifest-in/#using-manifest-in). + + - For [final built distribution](https://packaging.python.org/en/latest/glossary/#term-Built-Distribution) + + A Distribution format containing files and metadata that only need to be + moved to the correct location on the target system, to be installed. + e.g. `Wheel` + + It will have the Python files in the discovered or listed Python packages. + If you want to control what goes here, such as to add data files, + see [Including Data Files](https://setuptools.pypa.io/en/latest/userguide/datafiles.html) from the [setuptools docs](https://setuptools.pypa.io/en/latest/index.html). + +4. Generating distribution archives. These are archives that are uploaded to + the Python Package Index and can be installed by pip. + + example using `setuptools` + + ```shell + python3 -m pip install --upgrade build + python3 -m build + ``` + + generated files: + + ```shell + dist/ + WAMR-package-0.0.1-py3-none-any.whl + WAMR-package-0.0.1.tar.gz + ``` + + The `tar.gz` file is a _source archive_ whereas the `.whl file` is a + _built distribution_. Newer pip versions preferentially install built + distributions but will fall back to source archives if needed. You should + always upload a source archive and provide built archives for compatibility + reasons. + +5. Uploading the distribution archives + + - Register an account on https://pypi.org. + - To securely upload your project, you’ll need a + [PyPI API token](https://pypi.org/help/#apitoken). It can create at + [here](https://pypi.org/manage/account/#api-tokens), and the “Scope” + the setting needs to be “Entire account”. + - After registration, now twine can be used to upload the distribution packages. + + ```shell + # install twine + python3 -m pip install --upgrade twine + # --repository is https://pypi.org/ by default. + # You will be prompted for a username and password. For the username, use __token__. For the password, use the token value, including the pypi- prefix. + twine upload dist/* + ``` + +after all, the python binding will be installed with + +```shell +$ pip install wamr +``` + +PS: A example lifecycle of a python package +![python-package-lifecycle](images/python_package_life_cycle.png) + +## CI + +There are several parts: + +- code format check. +- test. include running all unit test cases and examples. +- publish built distribution. diff --git a/language-bindings/python/docs/images/python_package_life_cycle.png b/language-bindings/python/docs/images/python_package_life_cycle.png new file mode 100644 index 000000000..90856e181 Binary files /dev/null and b/language-bindings/python/docs/images/python_package_life_cycle.png differ diff --git a/language-bindings/python/docs/setup_dev_env.md b/language-bindings/python/docs/setup_dev_env.md new file mode 100644 index 000000000..6612748f6 --- /dev/null +++ b/language-bindings/python/docs/setup_dev_env.md @@ -0,0 +1,12 @@ +Use a python virtual environment tool to create an environment for development. All necessary packages are in _../requirements.txt_. + +python code formatter is provided by _black_. + +python code linter is provided by _pylint_ and default configuration. + +Unit tests are driven by _unittest_. + +```bash +$ python -m unittest -v tests/test_basics.py +$ python -m unittest -v tests/test_advanced.py +``` diff --git a/language-bindings/python/pyproject.toml b/language-bindings/python/pyproject.toml new file mode 100644 index 000000000..b0f076532 --- /dev/null +++ b/language-bindings/python/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools>=42"] +build-backend = "setuptools.build_meta" diff --git a/language-bindings/python/requirements.txt b/language-bindings/python/requirements.txt new file mode 100644 index 000000000..7bb68ba6c --- /dev/null +++ b/language-bindings/python/requirements.txt @@ -0,0 +1,5 @@ +black +nose +pycparser +pylint + diff --git a/language-bindings/python/samples/hello.wat b/language-bindings/python/samples/hello.wat new file mode 100644 index 000000000..1c56c5582 --- /dev/null +++ b/language-bindings/python/samples/hello.wat @@ -0,0 +1,4 @@ +(module + (func $hello (import "" "hello")) + (func (export "run") (call $hello)) +) diff --git a/language-bindings/python/samples/hello_oop.py b/language-bindings/python/samples/hello_oop.py new file mode 100644 index 000000000..666f63cd8 --- /dev/null +++ b/language-bindings/python/samples/hello_oop.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +import ctypes +from wamr import * + + +def hello_callback(): + print("Calling back...") + print("> Hello World!") + + +def main(): + print("Initializing...") + engine = Engine() + store = Store(engine) + + print("Loading binary...") + print("Compiling module...") + module = Module.from_file(engine, "./hello.wasm") + + print("Creating callback...") + hello = Func(store, FuncType([], []), hello_callback) + + print("Instantiating module...") + instance = Instance(store, module, [hello]) + + print("Extracting export...") + run = instance.exports(store)["run"] + + print("Calling export...") + run(store) + + print("Shutting down...") + print("Done.") + + +if __name__ == "__main__": + main() diff --git a/language-bindings/python/samples/hello_procedural.py b/language-bindings/python/samples/hello_procedural.py new file mode 100644 index 000000000..ed3002d5b --- /dev/null +++ b/language-bindings/python/samples/hello_procedural.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +import ctypes +import wamr.ffi as ffi + +WAMS_BINARY_CONTENT = ( + b"\x00asm\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01`\x00\x00\x02\x8a\x80" + b"\x80\x80\x00\x01\x00\x05hello\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00" + b"\x07\x87\x80\x80\x80\x00\x01\x03run\x00\x01\n\x8a\x80\x80\x80\x00\x01" + b"\x84\x80\x80\x80\x00\x00\x10\x00\x0b" +) + + +@ffi.wasm_func_cb_decl +def hello_callback(args, results): + print("Calling back...") + print("> Hello World!") + + +def main(): + print("Initializing...") + engine = ffi.wasm_engine_new() + store = ffi.wasm_store_new(engine) + + print("Loading binary...") + + # for convenience, use binary content instead of open file + # with open("./hello.wasm", "rb") as f: + # wasm = f.read() + wasm = WAMS_BINARY_CONTENT + binary = ffi.wasm_byte_vec_t() + ffi.wasm_byte_vec_new_uninitialized(binary, len(wasm)) + # underlying buffer is not writable + binary.data = (ctypes.c_ubyte * len(wasm)).from_buffer_copy(wasm) + + print("Compiling module...") + module = ffi.wasm_module_new(store, binary) + if not module: + raise RuntimeError("Compiling module failed") + + binary.data = None + ffi.wasm_byte_vec_delete(binary) + + print("Creating callback...") + hello_type = ffi.wasm_functype_new_0_0() + hello_func = ffi.wasm_func_new( + store, + hello_type, + hello_callback, + ) + + ffi.wasm_functype_delete(hello_type) + + print("Instantiating module...") + + imports = ffi.wasm_extern_vec_t() + ffi.wasm_extern_vec_new((imports), 1, ffi.wasm_func_as_extern(hello_func)) + instance = ffi.wasm_instance_new(store, module, imports, None) + + ffi.wasm_func_delete(hello_func) + + print("Extracting export...") + exports = ffi.wasm_extern_vec_t() + ffi.wasm_instance_exports(instance, exports) + + run_func = ffi.wasm_extern_as_func(exports.data[0]) + if not run_func: + raise RuntimeError("can not extract exported function") + + ffi.wasm_instance_delete(instance) + ffi.wasm_module_delete(module) + + print("Calling export...") + args = ffi.wasm_val_vec_t() + results = ffi.wasm_val_vec_t() + + ffi.wasm_val_vec_new_empty(args) + ffi.wasm_val_vec_new_empty(results) + ffi.wasm_func_call(run_func, args, results) + + print("Shutting down...") + ffi.wasm_store_delete(store) + ffi.wasm_engine_delete(engine) + + print("Done.") + + +if __name__ == "__main__": + main() diff --git a/language-bindings/python/setup.py b/language-bindings/python/setup.py new file mode 100755 index 000000000..c7868187b --- /dev/null +++ b/language-bindings/python/setup.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# pylint: disable=missing-class-docstring +# pylint: disable=missing-function-docstring +# pylint: disable=missing-module-docstring + +from setuptools import setup, find_packages + + +with open("README.md") as f: + readme = f.read() + +with open("LICENSE") as f: + license = f.read() + +setup( + name="wamr-python", + version="0.1.0", + description="A WebAssembly runtime powered by WAMR", + long_description=readme, + author="The WAMR Project Developers", + author_email="hello@bytecodealliance.org", + url="https://github.com/bytecodealliance/wamr-python", + license=license, + packages=["wamr"], +) diff --git a/language-bindings/python/tests/__init__.py b/language-bindings/python/tests/__init__.py new file mode 100644 index 000000000..fd913c63c --- /dev/null +++ b/language-bindings/python/tests/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +__all__ = ["test_basic", "test_advanced"] diff --git a/language-bindings/python/tests/context.py b/language-bindings/python/tests/context.py new file mode 100644 index 000000000..15c30087c --- /dev/null +++ b/language-bindings/python/tests/context.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import os + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + +import wamr diff --git a/language-bindings/python/tests/test_advanced.py b/language-bindings/python/tests/test_advanced.py new file mode 100644 index 000000000..ad074f2b3 --- /dev/null +++ b/language-bindings/python/tests/test_advanced.py @@ -0,0 +1,525 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# pylint: disable=missing-class-docstring +# pylint: disable=missing-function-docstring +# pylint: disable=missing-module-docstring + +import ctypes as c +import math +import unittest + +import wamr.ffi as ffi + + +# It is a module likes: +# (module +# (import "mod" "g0" (global i32)) +# (import "mod" "f0" (func (param f32) (result f64))) +# +# (func (export "f1") (param i32 i64)) +# (global (export "g1") (mut f32) (f32.const 3.14)) +# (memory (export "m1") 1 2) +# (table (export "t1") 1 funcref) +# +# (func (export "f2") (unreachable)) +# ) +MODULE_BINARY = ( + b"\x00asm\x01\x00\x00\x00\x01\x0e\x03`\x01}\x01|`\x02\x7f~\x00`\x00" + b"\x00\x02\x14\x02\x03mod\x02g0\x03\x7f\x00\x03mod\x02f0\x00\x00\x03\x03" + b"\x02\x01\x02\x04\x04\x01p\x00\x01\x05\x04\x01\x01\x01\x02\x06\t\x01}\x01C" + b"\xc3\xf5H@\x0b\x07\x1a\x05\x02f1\x00\x01\x02g1\x03\x01\x02m1\x02\x00\x02t1" + b"\x01\x00\x02f2\x00\x02\n\x08\x02\x02\x00\x0b\x03\x00\x00\x0b" +) + +# False -> True when testing with a library enabling WAMR_BUILD_DUMP_CALL_STACK flag +TEST_WITH_WAMR_BUILD_DUMP_CALL_STACK = False + + +@ffi.wasm_func_cb_decl +def callback(args, results): + args = ffi.dereference(args) + results = ffi.dereference(results) + + arg_v = args.data[0] + + result_v = ffi.wasm_f64_val(arg_v.of.f32 * 2.0) + ffi.wasm_val_copy(results.data[0], result_v) + results.num_elems = 1 + + print(f"\nIn callback: {arg_v} --> {result_v}\n") + + +@ffi.wasm_func_with_env_cb_decl +def callback_with_env(env, args, results): + # pylint: disable=unused-argument + print("summer") + + +class AdvancedTestSuite(unittest.TestCase): + @classmethod + def setUpClass(cls): + print("Initializing...") + cls._wasm_engine = ffi.wasm_engine_new() + cls._wasm_store = ffi.wasm_store_new(cls._wasm_engine) + + def assertIsNullPointer(self, pointer): + # pylint: disable=invalid-name + if not ffi.is_null_pointer(pointer): + self.fail("not a non-null pointer") + + def assertIsNotNullPointer(self, pointer): + # pylint: disable=invalid-name + if ffi.is_null_pointer(pointer): + self.fail("not a non-null pointer") + + def load_binary(self, binary_string): + print("Load binary...") + binary = ffi.load_module_file(binary_string) + binary = c.pointer(binary) + self.assertIsNotNullPointer(binary) + return binary + + def compile(self, binary): + print("Compile...") + module = ffi.wasm_module_new(self._wasm_store, binary) + self.assertIsNotNullPointer(module) + return module + + def prepare_imports_local(self): + print("Prepare imports...") + func_type = ffi.wasm_functype_new_1_1( + ffi.wasm_valtype_new(ffi.WASM_F32), + ffi.wasm_valtype_new(ffi.WASM_F64), + ) + func = ffi.wasm_func_new(self._wasm_store, func_type, callback) + self.assertIsNotNullPointer(func) + ffi.wasm_functype_delete(func_type) + + glbl_type = ffi.wasm_globaltype_new(ffi.wasm_valtype_new(ffi.WASM_I32), True) + init = ffi.wasm_i32_val(1024) + glbl = ffi.wasm_global_new(self._wasm_store, glbl_type, init) + self.assertIsNotNullPointer(glbl) + ffi.wasm_globaltype_delete(glbl_type) + + imports = ffi.wasm_extern_vec_t() + data = ffi.list_to_carray( + c.POINTER(ffi.wasm_extern_t), + ffi.wasm_func_as_extern(func), + ffi.wasm_global_as_extern(glbl), + ) + ffi.wasm_extern_vec_new(imports, 2, data) + imports = c.pointer(imports) + self.assertIsNotNullPointer(imports) + return imports + + def instantiate(self, module, imports): + print("Instantiate module...") + instance = ffi.wasm_instance_new( + self._wasm_store, module, imports, ffi.create_null_pointer(ffi.wasm_trap_t) + ) + self.assertIsNotNone(instance) + self.assertIsNotNullPointer(instance) + return instance + + def extract_exports(self, instance): + print("Extracting exports...") + exports = ffi.wasm_extern_vec_t() + ffi.wasm_instance_exports(instance, exports) + exports = c.pointer(exports) + self.assertIsNotNullPointer(exports) + return exports + + def setUp(self): + binary = self.load_binary(MODULE_BINARY) + self.module = self.compile(binary) + self.imports = self.prepare_imports_local() + self.instance = self.instantiate(self.module, self.imports) + self.exports = self.extract_exports(self.instance) + + ffi.wasm_byte_vec_delete(binary) + + def tearDown(self): + if self.imports: + ffi.wasm_extern_vec_delete(self.imports) + + if self.exports: + ffi.wasm_extern_vec_delete(self.exports) + + ffi.wasm_instance_delete(self.instance) + ffi.wasm_module_delete(self.module) + + def test_wasm_func_call_wasm(self): + export_list = ffi.wasm_vec_to_list(self.exports) + print(export_list) + + func = ffi.wasm_extern_as_func(export_list[0]) + self.assertIsNotNullPointer(func) + + # make a call + params = ffi.wasm_val_vec_t() + data = ffi.list_to_carray( + ffi.wasm_val_t, + ffi.wasm_i32_val(1024), + ffi.wasm_i64_val(1024 * 1024), + ) + ffi.wasm_val_vec_new(params, 2, data) + + results = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new_empty(results) + + ffi.wasm_func_call(func, params, results) + + def test_wasm_func_call_native(self): + import_list = ffi.wasm_vec_to_list(self.imports) + + func = ffi.wasm_extern_as_func(import_list[0]) + self.assertIsNotNullPointer(func) + + params = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new( + params, 1, ffi.list_to_carray(ffi.wasm_val_t, ffi.wasm_f32_val(3.14)) + ) + results = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new_uninitialized(results, 1) + ffi.wasm_func_call(func, params, results) + self.assertEqual(params.data[0].of.f32 * 2, results.data[0].of.f64) + + def test_wasm_func_call_wrong_params(self): + export_list = ffi.wasm_vec_to_list(self.exports) + func = ffi.wasm_extern_as_func(export_list[0]) + # make a call + params = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new_empty(params) + results = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new_empty(results) + trap = ffi.wasm_func_call(func, params, results) + + self.assertIsNotNullPointer(trap) + + def test_wasm_func_call_unlinked(self): + ft = ffi.wasm_functype_new_0_0() + func = ffi.wasm_func_new(self._wasm_store, ft, callback) + params = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new_empty(params) + results = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new_empty(results) + trap = ffi.wasm_func_call(func, params, results) + ffi.wasm_func_delete(func) + + def test_wasm_global_get_wasm(self): + export_list = ffi.wasm_vec_to_list(self.exports) + glb = ffi.wasm_extern_as_global(export_list[1]) + self.assertIsNotNullPointer(glb) + + # access the global + val = ffi.wasm_val_t() + ffi.wasm_global_get(glb, val) + self.assertAlmostEqual(val.of.f32, 3.14, places=3) + + def test_wasm_global_get_native(self): + import_list = ffi.wasm_vec_to_list(self.imports) + + glb = ffi.wasm_extern_as_global(import_list[1]) + self.assertIsNotNullPointer(glb) + + val = ffi.wasm_val_t() + ffi.wasm_global_get(glb, val) + self.assertEqual(val.of.i32, 1024) + + def test_wasm_global_get_unlinked(self): + gt = ffi.wasm_globaltype_new(ffi.wasm_valtype_new(ffi.WASM_I32), True) + init = ffi.wasm_i32_val(32) + glbl = ffi.wasm_global_new(self._wasm_store, gt, init) + val_ret = ffi.wasm_f32_val(3.14) + ffi.wasm_global_get(glbl, val_ret) + ffi.wasm_global_delete(glbl) + + # val_ret wasn't touched, keep the original value + self.assertAlmostEqual(val_ret.of.f32, 3.14, 3) + + def test_wasm_global_get_null_val(self): + export_list = ffi.wasm_vec_to_list(self.exports) + glb = ffi.wasm_extern_as_global(export_list[1]) + ffi.wasm_global_get(glb, ffi.create_null_pointer(ffi.wasm_val_t)) + + def test_wasm_global_get_null_global(self): + val = ffi.wasm_val_t() + ffi.wasm_global_get(ffi.create_null_pointer(ffi.wasm_global_t), val) + + def test_wasm_global_set_wasm(self): + export_list = ffi.wasm_vec_to_list(self.exports) + glb = ffi.wasm_extern_as_global(export_list[1]) + self.assertIsNotNullPointer(glb) + + # access the global + new_val = ffi.wasm_f32_val(math.e) + ffi.wasm_global_set(glb, new_val) + + val = ffi.wasm_val_t() + ffi.wasm_global_get(glb, val) + self.assertNotEqual(val.of.f32, 3.14) + + def test_wasm_global_set_native(self): + import_list = ffi.wasm_vec_to_list(self.imports) + + glb = ffi.wasm_extern_as_global(import_list[1]) + self.assertIsNotNullPointer(glb) + + new_val = ffi.wasm_i32_val(2048) + ffi.wasm_global_set(glb, new_val) + + val = ffi.wasm_val_t() + ffi.wasm_global_get(glb, val) + self.assertEqual(val, new_val) + + def test_wasm_global_set_unlinked(self): + gt = ffi.wasm_globaltype_new(ffi.wasm_valtype_new(ffi.WASM_I32), True) + init = ffi.wasm_i32_val(32) + glbl = ffi.wasm_global_new(self._wasm_store, gt, init) + val_ret = ffi.wasm_f32_val(3.14) + ffi.wasm_global_set(glbl, val_ret) + ffi.wasm_global_delete(glbl) + + def test_wasm_global_set_null_v(self): + export_list = ffi.wasm_vec_to_list(self.exports) + glb = ffi.wasm_extern_as_global(export_list[1]) + # access the global + ffi.wasm_global_set(glb, ffi.create_null_pointer(ffi.wasm_val_t)) + + def test_wasm_global_set_null_global(self): + # access the global + new_val = ffi.wasm_f32_val(math.e) + ffi.wasm_global_set(ffi.create_null_pointer(ffi.wasm_global_t), new_val) + + def test_wasm_table_size(self): + export_list = ffi.wasm_vec_to_list(self.exports) + tbl = ffi.wasm_extern_as_table(export_list[3]) + self.assertIsNotNullPointer(tbl) + + tbl_sz = ffi.wasm_table_size(tbl) + self.assertEqual(tbl_sz, 1) + + def test_wasm_table_size_unlink(self): + vt = ffi.wasm_valtype_new(ffi.WASM_FUNCREF) + limits = ffi.wasm_limits_new(10, 15) + tt = ffi.wasm_tabletype_new(vt, limits) + tbl = ffi.wasm_table_new( + self._wasm_store, tt, ffi.create_null_pointer(ffi.wasm_ref_t) + ) + tbl_sz = ffi.wasm_table_size(tbl) + ffi.wasm_table_delete(tbl) + + def test_wasm_table_size_null_table(self): + ffi.wasm_table_size(ffi.create_null_pointer(ffi.wasm_table_t)) + + def test_wasm_table_get(self): + export_list = ffi.wasm_vec_to_list(self.exports) + tbl = ffi.wasm_extern_as_table(export_list[3]) + self.assertIsNotNullPointer(tbl) + + ref = ffi.wasm_table_get(tbl, 0) + self.assertIsNullPointer(ref) + + ref = ffi.wasm_table_get(tbl, 4096) + self.assertIsNullPointer(ref) + + def test_wasm_table_get_unlinked(self): + vt = ffi.wasm_valtype_new(ffi.WASM_FUNCREF) + limits = ffi.wasm_limits_new(10, 15) + tt = ffi.wasm_tabletype_new(vt, limits) + tbl = ffi.wasm_table_new( + self._wasm_store, tt, ffi.create_null_pointer(ffi.wasm_ref_t) + ) + ffi.wasm_table_get(tbl, 0) + ffi.wasm_table_delete(tbl) + + def test_wasm_table_get_null_table(self): + ffi.wasm_table_get(ffi.create_null_pointer(ffi.wasm_table_t), 0) + + def test_wasm_table_get_out_of_bounds(self): + export_list = ffi.wasm_vec_to_list(self.exports) + tbl = ffi.wasm_extern_as_table(export_list[3]) + ffi.wasm_table_get(tbl, 1_000_000_000) + + def test_wasm_ref(self): + export_list = ffi.wasm_vec_to_list(self.exports) + func = ffi.wasm_extern_as_func(export_list[0]) + self.assertIsNotNullPointer(func) + + ref = ffi.wasm_func_as_ref(func) + self.assertIsNotNullPointer(ref) + + func_from_ref = ffi.wasm_ref_as_func(ref) + self.assertEqual( + ffi.dereference(ffi.wasm_func_type(func)), + ffi.dereference(ffi.wasm_func_type(func_from_ref)), + ) + + def test_wasm_table_set(self): + export_list = ffi.wasm_vec_to_list(self.exports) + tbl = ffi.wasm_extern_as_table(export_list[3]) + self.assertIsNotNullPointer(tbl) + + func = ffi.wasm_extern_as_func(export_list[0]) + ref = ffi.wasm_func_as_ref(func) + + ffi.wasm_table_set(tbl, 0, ref) + + ref_ret = ffi.wasm_table_get(tbl, 0) + self.assertIsNotNullPointer(ref_ret) + func_ret = ffi.wasm_ref_as_func(ref_ret) + self.assertEqual( + ffi.dereference(ffi.wasm_func_type(func)), + ffi.dereference(ffi.wasm_func_type(func_ret)), + ) + + def test_wasm_table_set_unlinked(self): + vt = ffi.wasm_valtype_new(ffi.WASM_FUNCREF) + limits = ffi.wasm_limits_new(10, 15) + tt = ffi.wasm_tabletype_new(vt, limits) + tbl = ffi.wasm_table_new( + self._wasm_store, tt, ffi.create_null_pointer(ffi.wasm_ref_t) + ) + export_list = ffi.wasm_vec_to_list(self.exports) + func = ffi.wasm_extern_as_func(export_list[0]) + ref = ffi.wasm_func_as_ref(func) + ffi.wasm_table_set(tbl, 0, ref) + ffi.wasm_table_delete(tbl) + + def test_wasm_table_set_null_table(self): + export_list = ffi.wasm_vec_to_list(self.exports) + func = ffi.wasm_extern_as_func(export_list[0]) + ref = ffi.wasm_func_as_ref(func) + ffi.wasm_table_set(ffi.create_null_pointer(ffi.wasm_table_t), 0, ref) + + def test_wasm_table_set_null_ref(self): + export_list = ffi.wasm_vec_to_list(self.exports) + tbl = ffi.wasm_extern_as_table(export_list[3]) + ffi.wasm_table_set(tbl, 0, ffi.create_null_pointer(ffi.wasm_ref_t)) + + def test_wasm_table_set_out_of_bounds(self): + export_list = ffi.wasm_vec_to_list(self.exports) + tbl = ffi.wasm_extern_as_table(export_list[3]) + func = ffi.wasm_extern_as_func(export_list[0]) + ref = ffi.wasm_func_as_ref(func) + ffi.wasm_table_set(tbl, 1_000_000_000, ref) + + def test_wasm_memory_size(self): + export_list = ffi.wasm_vec_to_list(self.exports) + mem = ffi.wasm_extern_as_memory(export_list[2]) + self.assertIsNotNullPointer(mem) + + pg_sz = ffi.wasm_memory_size(mem) + self.assertEqual(pg_sz, 1) + + def test_wasm_memory_size_unlinked(self): + limits = ffi.wasm_limits_new(10, 12) + mt = ffi.wasm_memorytype_new(limits) + mem = ffi.wasm_memory_new(self._wasm_store, mt) + ffi.wasm_memory_size(mem) + ffi.wasm_memory_delete(mem) + + def test_wasm_memory_data(self): + export_list = ffi.wasm_vec_to_list(self.exports) + mem = ffi.wasm_extern_as_memory(export_list[2]) + self.assertIsNotNullPointer(mem) + + data_base = ffi.wasm_memory_data(mem) + self.assertIsNotNone(data_base) + + def test_wasm_memory_data_unlinked(self): + limits = ffi.wasm_limits_new(10, 12) + mt = ffi.wasm_memorytype_new(limits) + mem = ffi.wasm_memory_new(self._wasm_store, mt) + ffi.wasm_memory_data(mem) + ffi.wasm_memory_delete(mem) + + def test_wasm_memory_data_size(self): + export_list = ffi.wasm_vec_to_list(self.exports) + mem = ffi.wasm_extern_as_memory(export_list[2]) + self.assertIsNotNullPointer(mem) + + mem_sz = ffi.wasm_memory_data_size(mem) + self.assertGreater(mem_sz, 0) + + def test_wasm_memory_data_size_unlinked(self): + limits = ffi.wasm_limits_new(10, 12) + mt = ffi.wasm_memorytype_new(limits) + mem = ffi.wasm_memory_new(self._wasm_store, mt) + ffi.wasm_memory_data_size(mem) + ffi.wasm_memory_delete(mem) + + def test_wasm_trap(self): + export_list = ffi.wasm_vec_to_list(self.exports) + func = ffi.wasm_extern_as_func(export_list[0]) + # make a call + params = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new_empty(params) + results = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new_empty(results) + + trap = ffi.wasm_func_call(func, params, results) + self.assertIsNotNullPointer(trap) + + message = ffi.wasm_message_t() + ffi.wasm_trap_message(trap, message) + self.assertIsNotNullPointer(c.pointer(message)) + + # not a function internal exception + frame = ffi.wasm_trap_origin(trap) + self.assertIsNullPointer(frame) + + @unittest.skipUnless( + TEST_WITH_WAMR_BUILD_DUMP_CALL_STACK, + "need to enable WAMR_BUILD_DUMP_CALL_STACK", + ) + # assertions only works if enabling WAMR_BUILD_DUMP_CALL_STACK + def test_wasm_frame(self): + export_list = ffi.wasm_vec_to_list(self.exports) + func = ffi.wasm_extern_as_func(export_list[4]) + # make a call + params = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new_empty(params) + results = ffi.wasm_val_vec_t() + ffi.wasm_val_vec_new_empty(results) + + print("Making a call...") + trap = ffi.wasm_func_call(func, params, results) + + message = ffi.wasm_message_t() + ffi.wasm_trap_message(trap, message) + self.assertIsNotNullPointer(c.pointer(message)) + print(message) + + frame = ffi.wasm_trap_origin(trap) + self.assertIsNotNullPointer(frame) + print(ffi.dereference(frame)) + + traces = ffi.wasm_frame_vec_t() + ffi.wasm_trap_trace(trap, traces) + self.assertIsNotNullPointer(c.pointer(frame)) + + instance = ffi.wasm_frame_instance(frame) + self.assertIsNotNullPointer(instance) + + module_offset = ffi.wasm_frame_module_offset(frame) + + func_index = ffi.wasm_frame_func_index(frame) + self.assertEqual(func_index, 2) + + func_offset = ffi.wasm_frame_func_offset(frame) + self.assertGreater(func_offset, 0) + + @classmethod + def tearDownClass(cls): + print("Shutting down...") + ffi.wasm_store_delete(cls._wasm_store) + ffi.wasm_engine_delete(cls._wasm_engine) + + +if __name__ == "__main__": + unittest.main() diff --git a/language-bindings/python/tests/test_basic.py b/language-bindings/python/tests/test_basic.py new file mode 100644 index 000000000..556162bde --- /dev/null +++ b/language-bindings/python/tests/test_basic.py @@ -0,0 +1,1588 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# pylint: disable=missing-class-docstring +# pylint: disable=missing-function-docstring +# pylint: disable=missing-module-docstring + +import ctypes as c +import unittest +from venv import create + +from wamr.ffi import * + +# It is a module likes: +# (module +# (import "mod" "g0" (global i32)) +# (import "mod" "f0" (func (param f32) (result f64))) +# +# (func (export "f1") (param i32 i64)) +# (global (export "g1") (mut f32) (f32.const 3.14)) +# (memory 1 2) +# (table 1 funcref) +# ) +MODULE_BINARY = ( + b"\x00asm\x01\x00\x00\x00\x01\x0b\x02`\x01}\x01|`\x02\x7f~\x00" + b"\x02\x14\x02\x03mod\x02g0\x03\x7f\x00\x03mod\x02f0\x00\x00\x03" + b"\x02\x01\x01\x04\x04\x01p\x00\x01\x05\x04\x01\x01\x01\x02\x06\t" + b"\x01}\x01C\xc3\xf5H@\x0b\x07\x0b\x02\x02f1\x00\x01\x02g1\x03\x01\n" + b"\x04\x01\x02\x00\x0b" +) + + +@wasm_func_cb_decl +def callback(args, results): + # pylint: disable=unused-argument + print("summer") + + +@wasm_func_with_env_cb_decl +def callback_with_env(env, args, results): + # pylint: disable=unused-argument + print("summer") + + +class BasicTestSuite(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls._wasm_engine = wasm_engine_new() + cls._wasm_store = wasm_store_new(cls._wasm_engine) + + def assertIsNullPointer(self, c_pointer): + if not is_null_pointer(c_pointer): + self.fail("not a null pointer") + + def assertIsNotNullPointer(self, c_pointer): + if is_null_pointer(c_pointer): + self.fail("not a non-null pointer") + + def test_wasm_valkind(self): + self.assertEqual( + [WASM_I32, WASM_I64, WASM_F32, WASM_F64, WASM_ANYREF, WASM_FUNCREF], + [0, 1, 2, 3, 128, 129], + ) + + def test_wasm_valtype_new_pos(self): + vt = wasm_valtype_new(WASM_I32) + self.assertIsNotNullPointer(vt) + wasm_valtype_delete(vt) + + def test_wasm_valtype_new_neg(self): + vt = wasm_valtype_new(37) + self.assertIsNullPointer(vt) + wasm_valtype_delete(vt) + + def test_wasm_valtype_kind_pos(self): + vt = wasm_valtype_new(WASM_I64) + self.assertEqual(wasm_valtype_kind(vt), WASM_I64) + wasm_valtype_delete(vt) + + def test_wasm_valtype_kind_neg(self): + wasm_valtype_kind(create_null_pointer(wasm_valtype_t)) + + def test_wasm_valtype_delete_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + wasm_valtype_delete(vt) + + def test_wasm_valtype_delete_neg(self): + wasm_valtype_delete(create_null_pointer(wasm_valtype_t)) + + def test_wasm_valtype_copy_pos(self): + vt1 = wasm_valtype_new(WASM_FUNCREF) + vt2 = wasm_valtype_copy(vt1) + + self.assertIsNotNone(vt1) + self.assertIsNotNullPointer(vt1) + self.assertEqual(dereference(vt1), dereference(vt2)) + + wasm_valtype_delete(vt1) + wasm_valtype_delete(vt2) + + def test_wasm_valtype_copy_neg(self): + vt = wasm_valtype_copy(create_null_pointer(wasm_valtype_t)) + self.assertIsNotNone(vt) + self.assertIsNullPointer(vt) + + def test_list_to_carray(self): + v1 = wasm_valtype_new(WASM_I64) + v2 = wasm_valtype_new(WASM_F32) + v3 = wasm_valtype_new(WASM_FUNCREF) + data = list_to_carray(c.POINTER(wasm_valtype_t), v1, v2, v3) + + self.assertIsNotNone(data) + self.assertTrue(isinstance(data, c.Array)) + self.assertEqual(data._length_, 3) + self.assertEqual(dereference(data[0]), dereference(v1)) + self.assertEqual(dereference(data[1]), dereference(v2)) + self.assertEqual(dereference(data[2]), dereference(v3)) + + wasm_valtype_delete(v1) + wasm_valtype_delete(v2) + wasm_valtype_delete(v3) + + def test_wasm_valtype_vec_new_pos(self): + def_vt_list = [ + wasm_valtype_new(WASM_I32), + wasm_valtype_new(WASM_F64), + wasm_valtype_new(WASM_FUNCREF), + ] + data = list_to_carray(c.POINTER(wasm_valtype_t), *def_vt_list) + vt_vec = wasm_valtype_vec_t() + wasm_valtype_vec_new(vt_vec, 3, data) + + self.assertEqual(vt_vec.size, 3) + self.assertEqual(vt_vec.num_elems, 3) + self.assertIsNotNullPointer(vt_vec.data) + + ret_vt_list = wasm_vec_to_list(vt_vec) + ret_vt_list = [dereference(vt) for vt in ret_vt_list] + def_vt_list = [dereference(vt) for vt in def_vt_list] + self.assertEqual(ret_vt_list, def_vt_list) + + wasm_valtype_vec_delete(vt_vec) + + def test_wasm_valtype_vec_new_neg(self): + data = list_to_carray( + c.POINTER(wasm_valtype_t), + wasm_valtype_new(WASM_I32), + wasm_valtype_new(WASM_F64), + wasm_valtype_new(WASM_FUNCREF), + ) + vt_vec = wasm_valtype_vec_t() + wasm_valtype_vec_new(vt_vec, 1_000_000_000, data) + + self.assertEqual(vt_vec.size, 0) + self.assertIsNullPointer(vt_vec.data) + + wasm_valtype_vec_delete(vt_vec) + + def test_wasm_valtype_vec_new_null_out(self): + data = list_to_carray( + c.POINTER(wasm_valtype_t), + wasm_valtype_new(WASM_I32), + wasm_valtype_new(WASM_F64), + wasm_valtype_new(WASM_FUNCREF), + ) + wasm_valtype_vec_new(create_null_pointer(wasm_valtype_vec_t), 10, data) + + def test_wasm_valtype_vec_new_null_data(self): + vt_vec = wasm_valtype_vec_t() + wasm_valtype_vec_new(vt_vec, 3, create_null_pointer(wasm_valtype_t)) + self.assertIsNotNone(vt_vec) + self.assertIsNotNullPointer(c.pointer(vt_vec)) + + def test_wasm_valtype_vec_new_uninitialized_pos(self): + vt_vec = wasm_valtype_vec_t() + wasm_valtype_vec_new_uninitialized((vt_vec), 2) + self.assertEqual(2, vt_vec.size) + wasm_valtype_vec_delete(vt_vec) + + def test_wasm_valtype_vec_new_uninitialized_neg(self): + vt_vec = wasm_valtype_vec_t() + wasm_valtype_vec_new_uninitialized(vt_vec, 1_000_000_000) + self.assertEqual(vt_vec.size, 0) + self.assertIsNullPointer(vt_vec.data) + wasm_valtype_vec_delete(vt_vec) + + def test_wasm_valtype_vec_new_uninitialized_null_out(self): + wasm_valtype_vec_new_uninitialized(create_null_pointer(wasm_valtype_vec_t), 2) + + def test_wasm_valtype_vec_new_empty_pos(self): + vt_vec = wasm_valtype_vec_t() + wasm_valtype_vec_new_empty(vt_vec) + self.assertEqual(0, vt_vec.size) + self.assertIsNullPointer(vt_vec.data) + wasm_valtype_vec_delete(vt_vec) + + def test_wasm_valtype_vec_new_empty_neg(self): + wasm_valtype_vec_new_empty(create_null_pointer(wasm_valtype_vec_t)) + + def test_wasm_valtype_vec_copy_pos(self): + vt_vec1 = wasm_valtype_vec_t() + vt1 = wasm_valtype_new(WASM_F32) + vt2 = wasm_valtype_new(WASM_I32) + data = list_to_carray(c.POINTER(wasm_valtype_t), vt1, vt2) + wasm_valtype_vec_new(vt_vec1, 2, data) + + vt_vec2 = wasm_valtype_vec_t() + wasm_valtype_vec_copy(vt_vec2, vt_vec1) + + print(f"{vt_vec1} --> {vt_vec2}") + + self.assertEqual(vt_vec2.size, 2) + self.assertEqual(vt_vec2.num_elems, 2) + self.assertEqual(dereference(vt_vec2.data[0]), dereference(vt1)) + self.assertEqual(dereference(vt_vec2.data[1]), dereference(vt2)) + + wasm_valtype_vec_delete(vt_vec1) + wasm_valtype_vec_delete(vt_vec2) + + def test_wasm_valtype_vec_copy_null_src(self): + dst = wasm_valtype_vec_t() + wasm_valtype_vec_copy(dst, create_null_pointer(wasm_valtype_vec_t)) + self.assertIsNotNullPointer(c.pointer(dst)) + self.assertIsNullPointer(dst.data) + + def test_wasm_valtype_vec_copy_null_dst(self): + src = wasm_valtype_vec_t() + wasm_valtype_vec_new_empty(src) + wasm_valtype_vec_copy(create_null_pointer(wasm_valtype_vec_t), src) + wasm_valtype_vec_delete(src) + + def test_wasm_valtype_vec_delete_pos(self): + vt_vec = wasm_valtype_vec_t() + wasm_valtype_vec_new_uninitialized(vt_vec, 10) + wasm_valtype_vec_delete(vt_vec) + + vt_vec = wasm_valtype_vec_t() + wasm_valtype_vec_new_empty(vt_vec) + wasm_valtype_vec_delete(vt_vec) + + def test_wasm_valtype_vec_delete_neg(self): + wasm_valtype_vec_delete(create_null_pointer(wasm_valtype_vec_t)) + + def test_wasm_functype_new_0_0(self): + ft = wasm_functype_new_0_0() + + self.assertIsNotNullPointer(ft) + self.assertEqual(0, dereference(wasm_functype_params(ft)).size) + self.assertEqual(0, dereference(wasm_functype_results(ft)).size) + + wasm_functype_delete(ft) + + def test_wasm_functype_new_1_0(self): + vt = wasm_valtype_new(WASM_I64) + ft = wasm_functype_new_1_0(vt) + + self.assertIsNotNullPointer(ft) + params = wasm_vec_to_list(wasm_functype_params(ft)) + self.assertEqual([dereference(p) for p in params], [dereference(vt)]) + + wasm_functype_delete(ft) + + def test_wasm_functype_new_2_0(self): + vt1 = wasm_valtype_new(WASM_I64) + vt2 = wasm_valtype_new(WASM_F64) + ft = wasm_functype_new_2_0(vt1, vt2) + + self.assertIsNotNullPointer(ft) + self.assertEqual(2, dereference(wasm_functype_params(ft)).size) + self.assertEqual(0, dereference(wasm_functype_results(ft)).size) + + wasm_functype_delete(ft) + + def test_wasm_functype_new_3_0(self): + vt_list = [ + wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_F64), + wasm_valtype_new(WASM_I64), + ] + ft = wasm_functype_new_3_0(*vt_list) + + params = wasm_vec_to_list(wasm_functype_params(ft)) + self.assertEqual( + [dereference(p) for p in params], + [dereference(vt) for vt in vt_list], + ) + + wasm_functype_delete(ft) + + def test_wasm_functype_new_0_1(self): + vt1 = wasm_valtype_new(WASM_I64) + ft = wasm_functype_new_0_1(vt1) + + self.assertIsNotNullPointer(ft) + self.assertEqual(0, dereference(wasm_functype_params(ft)).size) + self.assertEqual(1, dereference(wasm_functype_results(ft)).size) + + wasm_functype_delete(ft) + + def test_wasm_functype_new_1_1(self): + vt1 = wasm_valtype_new(WASM_I64) + vt2 = wasm_valtype_new(WASM_F64) + ft = wasm_functype_new_1_1(vt1, vt2) + + params = wasm_vec_to_list(wasm_functype_params(ft)) + self.assertEqual(dereference(params[0]), dereference(vt1)) + + results = wasm_vec_to_list(wasm_functype_results(ft)) + self.assertEqual(dereference(results[0]), dereference(vt2)) + + wasm_functype_delete(ft) + + def test_wasm_functype_new_2_1(self): + vt_list = [ + wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_F64), + wasm_valtype_new(WASM_I64), + ] + ft = wasm_functype_new_2_1(*vt_list) + + self.assertIsNotNullPointer(ft) + self.assertEqual(2, dereference(wasm_functype_params(ft)).size) + self.assertEqual(1, dereference(wasm_functype_results(ft)).size) + + wasm_functype_delete(ft) + + def test_wasm_functype_new_3_1(self): + vt_list = [ + wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_F64), + wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_I32), + ] + ft = wasm_functype_new_3_1(*vt_list) + + params = wasm_vec_to_list(wasm_functype_params(ft)) + self.assertEqual( + [dereference(p) for p in params], [dereference(vt) for vt in vt_list[:3]] + ) + + results = wasm_vec_to_list(wasm_functype_results(ft)) + self.assertEqual(dereference(results[0]), dereference(vt_list[-1])) + + wasm_functype_delete(ft) + + def test_wasm_functype_new_neg(self): + ft = wasm_functype_new( + create_null_pointer(wasm_valtype_vec_t), + create_null_pointer(wasm_valtype_vec_t), + ) + + self.assertIsNotNullPointer(ft) + + wasm_functype_delete(ft) + + def test_wasm_functype_delete_pos(self): + ft = wasm_functype_new_0_0() + wasm_functype_delete(ft) + + def test_wasm_functype_delete_neg(self): + wasm_functype_delete(create_null_pointer(wasm_functype_t)) + + def test_wasm_functype_params_pos(self): + vt_list = [ + wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_F64), + wasm_valtype_new(WASM_I64), + ] + ft = wasm_functype_new_3_0(*vt_list) + params = wasm_vec_to_list(wasm_functype_params(ft)) + + self.assertEqual( + [dereference(p) for p in params], + [dereference(vt) for vt in vt_list], + ) + + wasm_functype_delete(ft) + + def test_wasm_functype_params_neg(self): + params = wasm_functype_params(create_null_pointer(wasm_functype_t)) + self.assertIsNullPointer(params) + + def test_wasm_functype_results_pos(self): + vt1 = wasm_valtype_new(WASM_I64) + ft = wasm_functype_new_0_1(vt1) + results = wasm_vec_to_list(wasm_functype_results(ft)) + + self.assertEqual(dereference(results[0]), dereference(vt1)) + + wasm_functype_delete(ft) + + def test_wasm_functype_results_neg(self): + results = wasm_functype_results(create_null_pointer(wasm_functype_t)) + self.assertIsNullPointer(results) + + def test_wasm_functype_copy_pos(self): + ft1 = wasm_functype_new_2_1( + wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_F64), + wasm_valtype_new(WASM_I64), + ) + ft2 = wasm_functype_copy(ft1) + + self.assertIsNotNullPointer(ft2) + self.assertEqual(2, dereference(wasm_functype_params(ft1)).size) + self.assertEqual(1, dereference(wasm_functype_results(ft2)).size) + + wasm_functype_delete(ft1) + wasm_functype_delete(ft2) + + def test_wasm_functype_copy_neg(self): + ft2 = wasm_functype_copy(create_null_pointer(wasm_functype_t)) + self.assertIsNullPointer(ft2) + wasm_functype_delete(ft2) + + def test_wasm_globaltype_new_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + gt = wasm_globaltype_new(vt, True) + + self.assertIsNotNullPointer(gt) + + wasm_globaltype_delete(gt) + + def test_wasm_globaltype_new_neg(self): + gt = wasm_globaltype_new(create_null_pointer(wasm_valtype_t), True) + self.assertIsNullPointer(gt) + wasm_globaltype_delete(gt) + + def test_wasm_globaltype_delete_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + gt = wasm_globaltype_new(vt, False) + wasm_globaltype_delete(gt) + + def test_wasm_globaltype_delete_neg(self): + wasm_globaltype_delete(create_null_pointer(wasm_globaltype_t)) + + def test_wasm_globaltype_content_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + gt = wasm_globaltype_new(vt, True) + gt_ret = wasm_globaltype_content(gt) + + self.assertEqual(dereference(vt), dereference(gt_ret)) + + wasm_globaltype_delete(gt) + + def test_wasm_globaltype_content_neg(self): + gt_ret = wasm_globaltype_content(create_null_pointer(wasm_globaltype_t)) + self.assertIsNullPointer(gt_ret) + + def test_wasm_globaltype_mutability_pos(self): + vt1 = wasm_valtype_new(WASM_F32) + gt1 = wasm_globaltype_new(vt1, False) + vt2 = wasm_valtype_new(WASM_F32) + gt2 = wasm_globaltype_new(vt2, True) + + self.assertFalse(wasm_globaltype_mutability(gt1)) + self.assertTrue(wasm_globaltype_mutability(gt2)) + + wasm_globaltype_delete(gt1) + wasm_globaltype_delete(gt2) + + def test_wasm_globaltype_mutability_neg(self): + self.assertFalse( + wasm_globaltype_mutability(create_null_pointer(wasm_globaltype_t)) + ) + + def test_wasm_globaltype_copy_pos(self): + vt = wasm_valtype_new(WASM_I32) + gt1 = wasm_globaltype_new(vt, True) + gt2 = wasm_globaltype_copy(gt1) + + self.assertEqual(dereference(gt1), dereference(gt2)) + + wasm_globaltype_delete(gt1) + wasm_globaltype_delete(gt2) + + def test_wasm_globaltype_copy_neg(self): + gt2 = wasm_globaltype_copy(create_null_pointer(wasm_globaltype_t)) + + self.assertIsNullPointer(gt2) + wasm_globaltype_delete(gt2) + + def test_wasm_limit_new(self): + limit = wasm_limits_new(10, 20) + self.assertIsNotNullPointer(limit) + self.assertEqual(dereference(limit).min, 10) + self.assertEqual(dereference(limit).max, 20) + + def test_wasm_tabletype_new_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + limit = wasm_limits_new(0, 0xFF) + tt = wasm_tabletype_new(vt, limit) + + self.assertIsNotNullPointer(tt) + wasm_tabletype_delete(tt) + + def test_wasm_tabletype_new_null_val_type(self): + limit = wasm_limits_new(0, 0xFFFFFFFF) + tt = wasm_tabletype_new(create_null_pointer(wasm_valtype_t), limit) + + self.assertIsNullPointer(tt) + wasm_tabletype_delete(tt) + + def test_wasm_tabletype_new_null_limits(self): + vt = wasm_valtype_new(WASM_FUNCREF) + tt = wasm_tabletype_new(vt, create_null_pointer(wasm_limits_t)) + + self.assertIsNullPointer(tt) + wasm_tabletype_delete(tt) + + def test_wasm_tabletype_delete_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + limit = wasm_limits_new(0, 0xFFFFFFFF) + tt = wasm_tabletype_new(vt, limit) + wasm_tabletype_delete(tt) + + def test_wasm_tabletype_delete_neg(self): + wasm_tabletype_delete(create_null_pointer(wasm_tabletype_t)) + + def test_wasm_tabletype_element_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + limit = wasm_limits_new(0, 0xFFFFFFFF) + tt = wasm_tabletype_new(vt, limit) + vt_ret = wasm_tabletype_element(tt) + + self.assertEqual(dereference(vt), dereference(vt_ret)) + + wasm_tabletype_delete(tt) + + def test_wasm_tabletype_element_neg(self): + vt_ret = wasm_tabletype_element(create_null_pointer(wasm_tabletype_t)) + self.assertIsNullPointer(vt_ret) + + def test_wasm_tabletype_limits_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + limit = wasm_limits_new(100, 256) + tt = wasm_tabletype_new(vt, limit) + limit_ret = wasm_tabletype_limits(tt) + + self.assertEqual(dereference(limit), dereference(limit_ret)) + + wasm_tabletype_delete(tt) + + def test_wasm_tabletype_limits_neg(self): + limit_ret = wasm_tabletype_limits(create_null_pointer(wasm_tabletype_t)) + self.assertIsNullPointer(limit_ret) + + def test_wasm_tabletype_copy_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + limit = wasm_limits_new(13, 19) + tt1 = wasm_tabletype_new(vt, limit) + tt2 = wasm_tabletype_copy(tt1) + + self.assertEqual(dereference(tt1), dereference(tt2)) + + wasm_tabletype_delete(tt1) + wasm_tabletype_delete(tt2) + + def test_wasm_tabletype_copy_neg(self): + tt2 = wasm_tabletype_copy(create_null_pointer(wasm_tabletype_t)) + self.assertIsNullPointer(tt2) + wasm_tabletype_delete(tt2) + + def test_wasm_memorytype_new_pos(self): + limit = wasm_limits_new(0, 3) + mt = wasm_memorytype_new(limit) + + self.assertIsNotNullPointer(mt) + + wasm_memorytype_delete(mt) + + def test_wasm_memorytype_new_neg(self): + mt = wasm_memorytype_new(None) + + self.assertIsNullPointer(mt) + + wasm_memorytype_delete(mt) + + def test_wasm_memorytype_delete_pos(self): + limit = wasm_limits_new(1, 2) + mt = wasm_memorytype_new(limit) + wasm_memorytype_delete(mt) + + def test_wasm_memorytype_delete_neg(self): + wasm_memorytype_delete(create_null_pointer(wasm_memorytype_t)) + + def test_wasm_memorytype_limits_pos(self): + limit = wasm_limits_new(3, 8) + mt = wasm_memorytype_new(limit) + limit_ret = wasm_memorytype_limits(mt) + + self.assertEqual(dereference(limit), dereference(limit_ret)) + + wasm_memorytype_delete(mt) + + def test_wasm_memorytype_limits_neg(self): + wasm_memorytype_limits(create_null_pointer(wasm_memorytype_t)) + + def test_wasm_memorytype_copy_pos(self): + limit = wasm_limits_new(7, 13) + mt1 = wasm_memorytype_new(limit) + mt2 = wasm_memorytype_copy(mt1) + + self.assertEqual( + dereference(mt1), + dereference(mt2), + ) + + wasm_memorytype_delete(mt1) + wasm_memorytype_delete(mt2) + + def test_wasm_memorytype_copy_neg(self): + mt2 = wasm_memorytype_copy(create_null_pointer(wasm_memorytype_t)) + + self.assertIsNullPointer(mt2) + + wasm_memorytype_delete(mt2) + + def test_wasm_externtype_kind_pos(self): + ft = wasm_functype_new_0_0() + gt = wasm_globaltype_new(wasm_valtype_new(WASM_FUNCREF), True) + mt = wasm_memorytype_new(wasm_limits_new(1, 2)) + tt = wasm_tabletype_new(wasm_valtype_new(WASM_FUNCREF), wasm_limits_new(10, 20)) + ets = [ + wasm_functype_as_externtype(ft), + wasm_globaltype_as_externtype(gt), + wasm_memorytype_as_externtype(mt), + wasm_tabletype_as_externtype(tt), + ] + type_kinds = [wasm_externtype_kind(et) for et in ets] + + self.assertEqual( + type_kinds, + [ + WASM_EXTERN_FUNC, + WASM_EXTERN_GLOBAL, + WASM_EXTERN_MEMORY, + WASM_EXTERN_TABLE, + ], + ) + + [wasm_externtype_delete(et) for et in ets] + + def test_wasm_externtype_kind_neg(self): + et = wasm_memorytype_as_externtype(create_null_pointer(wasm_memorytype_t)) + self.assertIsNullPointer(et) + + def test_wasm_externtype_delete_pos(self): + mt = wasm_memorytype_new(wasm_limits_new(10, 20)) + et = wasm_memorytype_as_externtype(mt) + wasm_externtype_delete(et) + + def test_wasm_externtype_delete_neg(self): + et = wasm_globaltype_as_externtype(create_null_pointer(wasm_globaltype_t)) + wasm_externtype_delete(et) + + def test_wasm_externtype_copy_pos(self): + tt1 = wasm_tabletype_new( + wasm_valtype_new(WASM_FUNCREF), wasm_limits_new(10, 20) + ) + et1 = wasm_tabletype_as_externtype(tt1) + et2 = wasm_externtype_copy(et1) + + tt2 = wasm_externtype_as_tabletype(et2) + self.assertEqual(dereference(tt1), dereference(tt2)) + + wasm_externtype_delete(et2) + wasm_externtype_delete(et1) + + def test_wasm_externtype_copy_neg(self): + et1 = create_null_pointer(wasm_externtype_t) + et2 = wasm_externtype_copy(et1) + wasm_externtype_delete(et2) + wasm_externtype_delete(et1) + + def test_wasm_name_new_from_string(self): + s = "let the stars shine upon you" + name = wasm_name_new_from_string(s) + + name_data = c.cast(name.data, c.c_char_p) + name_data = bytes.decode(name_data.value) + self.assertEqual(name_data, s) + + def test_wasm_importtype_new_pos(self): + module_name = "mA" + field_name = "func#1" + module_name = wasm_name_new_from_string(module_name) + field_name = wasm_name_new_from_string(field_name) + ft = wasm_functype_new_0_0() + et = wasm_functype_as_externtype(ft) + it = wasm_importtype_new(module_name, field_name, et) + + self.assertIsNotNullPointer(it) + self.assertEqual(dereference(wasm_importtype_module(it)), module_name) + self.assertEqual(dereference(wasm_importtype_name(it)), field_name) + self.assertEqual(dereference(wasm_importtype_type(it)), dereference(et)) + + wasm_importtype_delete(it) + + def test_wasm_importtype_new_null_ext_type(self): + module_name = "mA" + field_name = "func#1" + module_name = wasm_name_new_from_string(module_name) + field_name = wasm_name_new_from_string(field_name) + it = wasm_importtype_new( + module_name, + field_name, + create_null_pointer(wasm_externtype_t), + ) + + self.assertIsNullPointer(it) + + wasm_importtype_delete(it) + + def test_wasm_importtype_new_null_module(self): + field_name = "func#1" + field_name = wasm_name_new_from_string(field_name) + ft = wasm_functype_new_0_0() + et = wasm_functype_as_externtype(ft) + it = wasm_importtype_new(create_null_pointer(wasm_name_t), field_name, et) + + self.assertIsNullPointer(it) + + wasm_importtype_delete(it) + + def test_wasm_importtype_new_null_field(self): + module_name = "mA" + module_name = wasm_name_new_from_string(module_name) + ft = wasm_functype_new_0_0() + et = wasm_functype_as_externtype(ft) + it = wasm_importtype_new(module_name, create_null_pointer(wasm_name_t), et) + + self.assertIsNullPointer(it) + + wasm_importtype_delete(it) + + def test_wasm_importtype_copy_pos(self): + module_name = "mA" + field_name = "memory#1" + module_name = wasm_name_new_from_string(module_name) + field_name = wasm_name_new_from_string(field_name) + mt = wasm_memorytype_new(wasm_limits_new(10, 20)) + et = wasm_memorytype_as_externtype(mt) + it1 = wasm_importtype_new(module_name, field_name, et) + it2 = wasm_importtype_copy(it1) + + self.assertEqual(dereference(it1), dereference(it2)) + + wasm_importtype_delete(it1) + wasm_importtype_delete(it2) + + def test_wasm_importtype_copy_neg(self): + it1 = create_null_pointer(wasm_importtype_t) + it2 = wasm_importtype_copy(it1) + wasm_importtype_delete(it1) + wasm_importtype_delete(it2) + + def test_wasm_importtype_delete_pos(self): + module_name = "mA" + field_name = "memory#1" + module_name = wasm_name_new_from_string(module_name) + field_name = wasm_name_new_from_string(field_name) + tt = wasm_tabletype_new(wasm_valtype_new(WASM_FUNCREF), wasm_limits_new(10, 20)) + et = wasm_tabletype_as_externtype(tt) + it = wasm_importtype_new(module_name, field_name, et) + wasm_importtype_delete(it) + + def test_wasm_importtype_delete_neg(self): + wasm_importtype_delete(create_null_pointer(wasm_importtype_t)) + + def test_wasm_importtype_module_pos(self): + module_name = "mA" + field_name = "func#1" + module_name = wasm_name_new_from_string(module_name) + field_name = wasm_name_new_from_string(field_name) + ft = wasm_functype_new_0_0() + et = wasm_functype_as_externtype(ft) + it = wasm_importtype_new(module_name, field_name, et) + module_name_ret = wasm_importtype_module(it) + + self.assertEqual(dereference(module_name_ret), module_name) + + wasm_importtype_delete(it) + + def test_wasm_importtype_module_neg(self): + it = create_null_pointer(wasm_importtype_t) + wasm_importtype_module(it) + wasm_importtype_delete(it) + + def test_wasm_importtype_name_pos(self): + module_name = "mA" + field_name = "func#1" + module_name = wasm_name_new_from_string(module_name) + field_name = wasm_name_new_from_string(field_name) + ft = wasm_functype_new_0_0() + et = wasm_functype_as_externtype(ft) + it = wasm_importtype_new(module_name, field_name, et) + field_name_ret = wasm_importtype_name(it) + + self.assertEqual(dereference(field_name_ret), field_name) + + wasm_importtype_delete(it) + + def test_wasm_importtype_name_neg(self): + it = create_null_pointer(wasm_importtype_t) + wasm_importtype_name(it) + wasm_importtype_delete(it) + + def test_wasm_importtype_type_pos(self): + module_name = "mA" + field_name = "func#1" + module_name = wasm_name_new_from_string(module_name) + field_name = wasm_name_new_from_string(field_name) + ft = wasm_functype_new_0_0() + et = wasm_functype_as_externtype(ft) + it = wasm_importtype_new(module_name, field_name, et) + et_ret = wasm_importtype_type(it) + + self.assertEqual(dereference(et_ret), dereference(et)) + + wasm_importtype_delete(it) + + def test_wasm_importtype_type_neg(self): + it = create_null_pointer(wasm_importtype_t) + wasm_importtype_type(it) + wasm_importtype_delete(it) + + def test_wasm_exporttype_new_pos(self): + name = "hello" + name = wasm_name_new_from_string(name) + ft = wasm_functype_new_0_0() + ft = wasm_functype_as_externtype(ft) + et = wasm_exporttype_new(name, ft) + + self.assertIsNotNullPointer(et) + + wasm_exporttype_delete(et) + + def test_wasm_exporttype_new_null_name(self): + name = create_null_pointer(wasm_name_t) + ft = wasm_functype_new_0_0() + ft = wasm_functype_as_externtype(ft) + et = wasm_exporttype_new(name, ft) + + self.assertIsNullPointer(et) + + wasm_exporttype_delete(et) + + def test_wasm_exporttype_new_null_ext_type(self): + name = "hello" + name = wasm_name_new_from_string(name) + ext_type = create_null_pointer(wasm_externtype_t) + et = wasm_exporttype_new(name, ext_type) + + self.assertIsNullPointer(et) + + wasm_exporttype_delete(et) + + def test_wasm_exporttype_copy_pos(self): + name = "hello" + name = wasm_name_new_from_string(name) + gt = wasm_globaltype_new(wasm_valtype_new(WASM_F32), True) + gt = wasm_globaltype_as_externtype(gt) + et1 = wasm_exporttype_new(name, gt) + et2 = wasm_exporttype_copy(et1) + + self.assertEqual( + dereference(et1), + dereference(et2), + ) + + wasm_exporttype_delete(et1) + wasm_exporttype_delete(et2) + + def test_wasm_exporttype_copy_neg(self): + et1 = create_null_pointer(wasm_exporttype_t) + et2 = wasm_exporttype_copy(et1) + + wasm_exporttype_delete(et1) + wasm_exporttype_delete(et2) + + def test_wasm_exporttype_delete_pos(self): + name = "hello" + name = wasm_name_new_from_string(name) + mt = wasm_memorytype_new(wasm_limits_new(10, 20)) + mt = wasm_memorytype_as_externtype(mt) + et = wasm_exporttype_new(name, mt) + + wasm_exporttype_delete(et) + + def test_wasm_exporttype_delete_neg(self): + et = create_null_pointer(wasm_exporttype_t) + wasm_exporttype_delete(et) + + def test_wasm_exporttype_name_pos(self): + name = "hello" + name = wasm_name_new_from_string(name) + tt = wasm_tabletype_new(wasm_valtype_new(WASM_FUNCREF), wasm_limits_new(10, 20)) + tt = wasm_tabletype_as_externtype(tt) + et = wasm_exporttype_new(name, tt) + name_ret = wasm_exporttype_name(et) + + self.assertEqual(dereference(name_ret), name) + + wasm_exporttype_delete(et) + + def test_wasm_exporttype_name_neg(self): + et = create_null_pointer(wasm_exporttype_t) + wasm_exporttype_name(et) + wasm_exporttype_delete(et) + + def test_wasm_exporttype_type_pos(self): + name = "hello" + name = wasm_name_new_from_string(name) + tt = wasm_tabletype_new(wasm_valtype_new(WASM_FUNCREF), wasm_limits_new(10, 20)) + tt = wasm_tabletype_as_externtype(tt) + et = wasm_exporttype_new(name, tt) + tt_ret = wasm_exporttype_type(et) + + self.assertEqual(dereference(tt_ret), dereference(tt)) + + wasm_exporttype_delete(et) + + def test_wasm_exporttype_type_neg(self): + et = create_null_pointer(wasm_exporttype_t) + wasm_exporttype_type(et) + wasm_exporttype_delete(et) + + def test_wasm_i32_val(self): + val = wasm_i32_val(100) + + self.assertEqual(val.kind, WASM_I32) + self.assertEqual(val.of.i32, 100) + + # can not use wasm_val_delete() because it is not malloced + + def test_wasm_i64_val(self): + val = wasm_i64_val(-100) + + self.assertEqual(val.kind, WASM_I64) + self.assertEqual(val.of.i64, -100) + + # can not use wasm_val_delete() because it is not malloced + + def test_wasm_f32_val(self): + val = wasm_f32_val(100) + + self.assertEqual(val.kind, WASM_F32) + self.assertEqual(val.of.f32, 100.0) + + # can not use wasm_val_delete() because it is not malloced + + def test_wasm_f64_val(self): + val = wasm_f64_val(-100) + + self.assertEqual(val.kind, WASM_F64) + self.assertEqual(val.of.f64, -100.0) + + # can not use wasm_val_delete() because it is not malloced + + # there is no wasm_val_new() to malloc a wasm_val_t + def test_wasm_val_delete(self): + pass + + def test_wasm_val_copy(self): + v1 = wasm_f32_val(3.14) + v2 = wasm_val_t() + wasm_val_copy(v1, v2) + + self.assertEqual(v1, v2) + # can not use wasm_val_delete() because it is not malloced + + def test_wasm_ref_delete_neg(self): + ref = create_null_pointer(wasm_ref_t) + wasm_ref_delete(ref) + + ref = wasm_ref_t() + wasm_ref_delete(ref) + + def test_wasm_trap_new_pos(self): + # can't create a trap with traces(wasm_frame_vec_t) + msg = wasm_name_new_from_string("a fake trap") + trap = wasm_trap_new(self._wasm_store, msg) + + self.assertIsNotNone(trap) + + wasm_trap_delete(trap) + + def test_wasm_trap_new_null_msg(self): + trap = wasm_trap_new(self._wasm_store, create_null_pointer(wasm_name_t)) + + self.assertIsNotNone(trap) + self.assertIsNotNullPointer(trap) + + wasm_trap_delete(trap) + + def test_wasm_trap_message_pos(self): + msg = wasm_name_new_from_string("a fake trap") + trap = wasm_trap_new(self._wasm_store, msg) + msg_in_trap = wasm_message_t() + wasm_trap_message(trap, msg_in_trap) + + self.assertEqual( + msg, + msg_in_trap, + ) + + wasm_trap_delete(trap) + + def test_wasm_trap_message_null_trap(self): + msg = wasm_name_new_from_string("a fake trap") + wasm_trap_message(create_null_pointer(wasm_trap_t), msg) + + def test_wasm_trap_message_null_out(self): + msg = wasm_name_new_from_string("a fake trap") + trap = wasm_trap_new(self._wasm_store, msg) + wasm_trap_message(trap, create_null_pointer(wasm_message_t)) + wasm_trap_delete(trap) + + # test those APIs in advance: + # wasm_trap_origin + # wasm_trap_trace + # wasm_frame_delete + # wasm_frame_copy + # wasm_frame_module_offset + # wasm_frame_instance + # wasm_frame_func_index + # wasm_frame_func_offset + + def test_wasm_foreign_new_pos(self): + foreign = wasm_foreign_new(self._wasm_store) + + self.assertIsNotNone(foreign) + self.assertIsNotNullPointer(foreign) + + wasm_foreign_delete(foreign) + + def test_wasm_foreign_new_neg(self): + foreign = wasm_foreign_new(create_null_pointer(wasm_store_t)) + + self.assertIsNotNone(foreign) + self.assertIsNullPointer(foreign) + + wasm_foreign_delete(foreign) + + def test_wasm_foreign_delete_pos(self): + foreign = wasm_foreign_new(self._wasm_store) + wasm_foreign_delete(foreign) + + def test_wasm_foreign_delete_neg(self): + wasm_foreign_delete(create_null_pointer(wasm_foreign_t)) + + # wasm_egnine_new()/wasm_engine_delete() + # wasm_store_new()/wasm_store_delete() + # used in setUpClass() and tearDownClass + + def test_wasm_module_new_pos(self): + binary = load_module_file(MODULE_BINARY) + module = wasm_module_new(self._wasm_store, binary) + + self.assertIsNotNone(module) + self.assertIsNotNullPointer(module) + + wasm_byte_vec_delete(binary) + wasm_module_delete(module) + + def test_wasm_module_new_neg(self): + module = wasm_module_new(self._wasm_store, create_null_pointer(wasm_byte_vec_t)) + + self.assertIsNotNone(module) + self.assertIsNullPointer(module) + + wasm_module_delete(module) + + def test_wasm_module_delete_pos(self): + binary = load_module_file(MODULE_BINARY) + module = wasm_module_new(self._wasm_store, binary) + wasm_byte_vec_delete(binary) + wasm_module_delete(module) + + def test_wasm_module_delete_neg(self): + module = wasm_module_new(self._wasm_store, create_null_pointer(wasm_byte_vec_t)) + wasm_module_delete(module) + + def test_wasm_module_validate_pos(self): + binary = load_module_file(MODULE_BINARY) + validation = wasm_module_validate(self._wasm_store, binary) + + self.assertTrue(validation) + + wasm_byte_vec_delete(binary) + + def test_wasm_module_validate_neg(self): + tmp = (1024).to_bytes(2, byteorder="big") + binary = load_module_file(tmp) + validation = wasm_module_validate(self._wasm_store, binary) + + self.assertFalse(validation) + + wasm_byte_vec_delete(binary) + + def test_wasm_module_imports_pos(self): + binary = load_module_file(MODULE_BINARY) + module = wasm_module_new(self._wasm_store, binary) + imports = wasm_importtype_vec_t() + wasm_module_imports(module, imports) + + imports_list = wasm_vec_to_list(imports) + self.assertEqual(len(imports_list), 2) + + func_type = wasm_functype_new_1_1( + wasm_valtype_new(WASM_F32), + wasm_valtype_new(WASM_F64), + ) + ext_type = wasm_functype_as_externtype(func_type) + self.assertEqual( + dereference(wasm_importtype_type(imports_list[0])), dereference(ext_type) + ) + + wasm_externtype_delete(ext_type) + wasm_importtype_vec_delete(imports) + wasm_byte_vec_delete(binary) + wasm_module_delete(module) + + def test_wasm_module_imports_null_module(self): + imports = wasm_importtype_vec_t() + wasm_module_imports(create_null_pointer(wasm_module_t), imports) + + self.assertEqual(imports.size, 0) + + wasm_importtype_vec_delete(imports) + + def test_wasm_module_imports_null_out(self): + binary = load_module_file(MODULE_BINARY) + module = wasm_module_new(self._wasm_store, binary) + wasm_module_imports(module, create_null_pointer(wasm_importtype_vec_t)) + wasm_byte_vec_delete(binary) + wasm_module_delete(module) + + def test_wasm_module_exports_pos(self): + binary = load_module_file(MODULE_BINARY) + module = wasm_module_new(self._wasm_store, binary) + exports = wasm_exporttype_vec_t() + wasm_module_exports(module, exports) + + exports_list = wasm_vec_to_list(exports) + self.assertEqual(len(exports_list), 2) + + glbl_type = wasm_globaltype_new(wasm_valtype_new(WASM_F32), True) + ext_type = wasm_globaltype_as_externtype(glbl_type) + self.assertEqual( + dereference(wasm_exporttype_type(exports_list[1])), dereference(ext_type) + ) + + wasm_exporttype_vec_delete(exports) + wasm_byte_vec_delete(binary) + wasm_module_delete(module) + + def test_wasm_module_exports_null_module(self): + exports = wasm_exporttype_vec_t() + wasm_module_exports(create_null_pointer(wasm_module_t), exports) + + self.assertEqual(exports.size, 0) + + wasm_exporttype_vec_delete(exports) + + def test_wasm_module_exports_null_out(self): + binary = load_module_file(MODULE_BINARY) + module = wasm_module_new(self._wasm_store, binary) + wasm_module_exports(module, create_null_pointer(wasm_exporttype_vec_t)) + wasm_byte_vec_delete(binary) + wasm_module_delete(module) + + def test_wasm_instance_new_pos_empty_imports(self): + binary = load_module_file(MODULE_BINARY) + module = wasm_module_new(self._wasm_store, binary) + imports = wasm_extern_vec_t() + wasm_extern_vec_new_empty(imports) + instance = wasm_instance_new( + self._wasm_store, module, imports, create_null_pointer(wasm_trap_t) + ) + + wasm_instance_delete(instance) + wasm_module_delete(module) + + def test_wasm_instance_new_pos(self): + binary = load_module_file(MODULE_BINARY) + module = wasm_module_new(self._wasm_store, binary) + + ft = wasm_functype_new_1_1( + wasm_valtype_new(WASM_F32), + wasm_valtype_new(WASM_F64), + ) + func = wasm_func_new(self._wasm_store, ft, callback) + + gt = wasm_globaltype_new(wasm_valtype_new(WASM_I32), True) + init = wasm_i32_val(100) + gb = wasm_global_new(self._wasm_store, gt, init) + + imports = wasm_extern_vec_t() + data = list_to_carray( + c.POINTER(wasm_extern_t), + wasm_func_as_extern(func), + wasm_global_as_extern(gb), + ) + wasm_extern_vec_new(imports, 2, data) + + instance = wasm_instance_new( + self._wasm_store, module, imports, create_null_pointer(wasm_trap_t) + ) + + self.assertIsNotNone(instance) + + wasm_instance_delete(instance) + wasm_module_delete(module) + + def test_wasm_instance_new_neg_null_imports(self): + binary = load_module_file(MODULE_BINARY) + module = wasm_module_new(self._wasm_store, binary) + instance = wasm_instance_new( + self._wasm_store, + module, + create_null_pointer(wasm_extern_vec_t), + create_null_pointer(wasm_trap_t), + ) + + wasm_instance_delete(instance) + wasm_module_delete(module) + + # test those APIs in advanced: + # wasm_instance_delete + # wasm_instance_exports + + def test_wasm_func_new_pos(self): + vt1 = wasm_valtype_new(WASM_F32) + vt2 = wasm_valtype_new(WASM_FUNCREF) + ft = wasm_functype_new_1_1(vt1, vt2) + func = wasm_func_new(self._wasm_store, ft, callback) + + self.assertIsNotNone(func) + self.assertIsNotNullPointer(func) + + wasm_func_delete(func) + + def test_wasm_func_new_null_type(self): + func = wasm_func_new( + self._wasm_store, create_null_pointer(wasm_functype_t), callback + ) + + self.assertIsNotNone(func) + self.assertIsNullPointer(func) + + wasm_func_delete(func) + + def test_wasm_func_new_null_callback(self): + vt1 = wasm_valtype_new(WASM_F32) + vt2 = wasm_valtype_new(WASM_FUNCREF) + ft = wasm_functype_new_1_1(vt1, vt2) + func = wasm_func_new(self._wasm_store, ft, wasm_func_callback_t()) + + self.assertIsNotNone(func) + self.assertIsNullPointer(func) + + wasm_func_delete(func) + + def test_wasm_func_new_with_env_pos(self): + ft = wasm_functype_new_3_1( + wasm_valtype_new(WASM_I32), + wasm_valtype_new(WASM_F32), + wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_I64), + ) + func = wasm_func_new_with_env( + self._wasm_store, + ft, + callback_with_env, + c.c_void_p(0), + wasm_finalizer(0), + ) + + self.assertIsNotNone(func) + self.assertIsNotNullPointer(func) + + wasm_func_delete(func) + + def test_wasm_func_new_with_env_null_type(self): + func = wasm_func_new_with_env( + self._wasm_store, + create_null_pointer(wasm_functype_t), + callback_with_env, + c.c_void_p(0), + wasm_finalizer(0), + ) + + self.assertIsNotNone(func) + self.assertIsNullPointer(func) + + wasm_func_delete(func) + + def test_wasm_func_new_with_env_null_callback(self): + ft = wasm_functype_new_3_1( + wasm_valtype_new(WASM_I32), + wasm_valtype_new(WASM_F32), + wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_I64), + ) + func = wasm_func_new_with_env( + self._wasm_store, + ft, + wasm_func_callback_with_env_t(), + c.c_void_p(0), + wasm_finalizer(0), + ) + + self.assertIsNotNone(func) + self.assertIsNullPointer(func) + + wasm_func_delete(func) + + def test_wasm_func_delete_pos(self): + ft = wasm_functype_new_0_0() + func = wasm_func_new(self._wasm_store, ft, callback) + wasm_func_delete(func) + + def test_wasm_func_delete_neg(self): + wasm_func_delete(create_null_pointer(wasm_func_t)) + + def test_wasm_func_type_pos(self): + ft = wasm_functype_new_2_0( + wasm_valtype_new(WASM_F32), + wasm_valtype_new(WASM_FUNCREF), + ) + func = wasm_func_new(self._wasm_store, ft, callback) + ft_ret = wasm_func_type(func) + + self.assertEqual( + dereference(ft), + dereference(ft_ret), + ) + + wasm_functype_delete(ft_ret) + wasm_func_delete(func) + + def test_wasm_func_type_neg(self): + ft_ret = wasm_func_type(create_null_pointer(wasm_func_t)) + wasm_functype_delete(ft_ret) + + def test_wasm_func_copy_pos(self): + vt1 = wasm_valtype_new(WASM_F32) + ft = wasm_functype_new_0_1(vt1) + func1 = wasm_func_new(self._wasm_store, ft, callback) + func2 = wasm_func_copy(func1) + + self.assertEqual( + dereference(wasm_func_type(func1)), dereference(wasm_func_type(func2)) + ) + + wasm_func_delete(func2) + wasm_func_delete(func1) + + def test_wasm_func_copy_neg(self): + func1 = wasm_func_new( + self._wasm_store, create_null_pointer(wasm_functype_t), callback + ) + func2 = wasm_func_copy(func1) + + wasm_func_delete(func2) + wasm_func_delete(func1) + + # test wasm_func_call in advanced + + def test_wasm_global_new_pos(self): + vt = wasm_valtype_new(WASM_F32) + gt = wasm_globaltype_new(vt, False) + v = wasm_f32_val(3.14) + g = wasm_global_new(self._wasm_store, gt, v) + + self.assertIsNotNone(g) + self.assertIsNotNullPointer(g) + + wasm_globaltype_delete(gt) + wasm_global_delete(g) + + def test_wasm_global_new_null_type(self): + v = wasm_f32_val(3.14) + g = wasm_global_new(self._wasm_store, create_null_pointer(wasm_globaltype_t), v) + + self.assertIsNotNone(g) + self.assertIsNullPointer(g) + + wasm_global_delete(g) + + def test_wasm_global_new_null_init(self): + vt = wasm_valtype_new(WASM_F32) + gt = wasm_globaltype_new(vt, False) + g = wasm_global_new(self._wasm_store, gt, create_null_pointer(wasm_val_t)) + + self.assertIsNotNone(g) + self.assertIsNullPointer(g) + + wasm_globaltype_delete(gt) + wasm_global_delete(g) + + def test_wasm_global_delete_pos(self): + vt = wasm_valtype_new(WASM_I32) + gt = wasm_globaltype_new(vt, True) + v = wasm_i32_val(3) + g = wasm_global_new(self._wasm_store, gt, v) + wasm_globaltype_delete(gt) + wasm_global_delete(g) + + def test_wasm_global_delete_neg(self): + wasm_global_delete(create_null_pointer(wasm_global_t)) + + def test_wasm_global_type_pos(self): + vt = wasm_valtype_new(WASM_I64) + gt = wasm_globaltype_new(vt, False) + v = wasm_i32_val(3) + g = wasm_global_new(self._wasm_store, gt, v) + gt_ret = wasm_global_type(g) + + self.assertEqual(dereference(gt), dereference(gt_ret)) + + wasm_globaltype_delete(gt) + wasm_globaltype_delete(gt_ret) + wasm_global_delete(g) + + def test_wasm_global_type_neg(self): + gt = wasm_global_type(create_null_pointer(wasm_global_t)) + wasm_globaltype_delete(gt) + + # test wasm_global_get and wasm_global_set in advanced + + def test_wasm_table_new_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + limits = wasm_limits_new(10, 15) + tt = wasm_tabletype_new(vt, limits) + t = wasm_table_new(self._wasm_store, tt, create_null_pointer(wasm_ref_t)) + + self.assertIsNotNone(t) + self.assertIsNotNullPointer(t) + + wasm_table_delete(t) + + def test_wasm_table_new_null_type(self): + t = wasm_table_new( + self._wasm_store, + create_null_pointer(wasm_tabletype_t), + create_null_pointer(wasm_ref_t), + ) + + self.assertIsNotNone(t) + self.assertIsNullPointer(t) + + wasm_table_delete(t) + + def test_wasm_table_delete_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + limits = wasm_limits_new(10, 15) + tt = wasm_tabletype_new(vt, limits) + t = wasm_table_new(self._wasm_store, tt, create_null_pointer(wasm_ref_t)) + wasm_table_delete(t) + + def test_wasm_table_delete_neg(self): + wasm_table_delete(create_null_pointer(wasm_table_t)) + + def test_wasm_table_type_pos(self): + vt = wasm_valtype_new(WASM_FUNCREF) + limits = wasm_limits_new(1, 2) + tt = wasm_tabletype_new(vt, limits) + t = wasm_table_new(self._wasm_store, tt, create_null_pointer(wasm_ref_t)) + tt_ret = wasm_table_type(t) + + self.assertEqual( + dereference(tt), + dereference(tt_ret), + ) + + wasm_table_delete(t) + + def test_wasm_table_type_neg(self): + t = wasm_table_new( + self._wasm_store, + create_null_pointer(wasm_tabletype_t), + create_null_pointer(wasm_ref_t), + ) + tt_ret = wasm_table_type(t) + wasm_table_delete(t) + + # test wasm_table_size, wasm_table_get, wasm_table_set in advanced + + def test_wasm_memory_new_pos(self): + limits = wasm_limits_new(10, 12) + mt = wasm_memorytype_new(limits) + m = wasm_memory_new(self._wasm_store, mt) + + self.assertIsNotNullPointer(m) + + wasm_memory_delete(m) + + def test_wasm_memory_new_null_type(self): + m = wasm_memory_new(self._wasm_store, create_null_pointer(wasm_memorytype_t)) + + self.assertIsNullPointer(m) + + wasm_memory_delete(m) + + def test_wasm_memory_delete_pos(self): + limits = wasm_limits_new(10, 21) + mt = wasm_memorytype_new(limits) + m = wasm_memory_new(self._wasm_store, mt) + wasm_memory_delete(m) + + def test_wasm_memory_delete_neg(self): + wasm_memory_delete(create_null_pointer(wasm_memory_t)) + + def test_wasm_memory_type_pos(self): + limits = wasm_limits_new(10, 21) + mt = wasm_memorytype_new(limits) + m = wasm_memory_new(self._wasm_store, mt) + mt_ret = wasm_memory_type(m) + + self.assertEqual(dereference(mt), dereference(mt_ret)) + + wasm_memory_delete(m) + + def test_wasm_memory_type_neg(self): + mt = wasm_memory_type(create_null_pointer(wasm_memory_t)) + + self.assertIsNullPointer(mt) + wasm_memorytype_delete(mt) + + # test wasm_memory_size, wasm_memory_data, wasm_memory_data_size in advanced + + def test_wasm_extern_delete_pos(self): + vt = wasm_valtype_new(WASM_I64) + gt = wasm_globaltype_new(vt, False) + v = wasm_i64_val(128) + glb = wasm_global_new(self._wasm_store, gt, v) + etrn = wasm_global_as_extern(glb) + wasm_extern_delete(etrn) + + def test_wasm_extern_delete_neg(self): + etrn = wasm_global_as_extern(create_null_pointer(wasm_global_t)) + wasm_extern_delete(etrn) + + def test_wasm_extern_type_pos(self): + vt = wasm_valtype_new(WASM_I64) + gt = wasm_globaltype_new(vt, False) + v = wasm_i64_val(128) + glb = wasm_global_new(self._wasm_store, gt, v) + etrn = wasm_global_as_extern(glb) + + tp = wasm_extern_type(etrn) + gt_ret = wasm_externtype_as_globaltype(tp) + self.assertEqual( + dereference(gt), + dereference(gt_ret), + ) + wasm_extern_delete(etrn) + + def test_wasm_extern_type_neg(self): + wasm_extern_type(create_null_pointer(wasm_extern_t)) + + def test_wasm_extern_kind_pos(self): + ft = wasm_functype_new_0_0() + func = wasm_func_new(self._wasm_store, ft, callback) + etrn = wasm_func_as_extern(func) + kind = wasm_extern_kind(etrn) + + self.assertEqual(WASM_EXTERN_FUNC, kind) + + wasm_extern_delete(etrn) + + def test_wasm_extern_kind_neg(self): + wasm_extern_kind(create_null_pointer(wasm_extern_t)) + + @classmethod + def tearDownClass(cls): + wasm_store_delete(cls._wasm_store) + wasm_engine_delete(cls._wasm_engine) + + +if __name__ == "__main__": + unittest.main() diff --git a/language-bindings/python/utils/bindgen.py b/language-bindings/python/utils/bindgen.py new file mode 100644 index 000000000..6371ca657 --- /dev/null +++ b/language-bindings/python/utils/bindgen.py @@ -0,0 +1,386 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# pylint: disable=missing-class-docstring +# pylint: disable=missing-function-docstring +# pylint: disable=missing-module-docstring + +""" +- Need to run *download_wamr.py* firstly. +- Parse *./wasm-micro-runtime/core/iwasm/include/wasm_c_api.h* and generate + *wamr/binding.py* +""" +import os +import pathlib +import shutil +import sys + +from pycparser import c_ast, parse_file + +WASM_C_API_HEADER = "core/iwasm/include/wasm_c_api.h" +BINDING_PATH = "wamr/binding.py" +# 4 spaces as default indent +INDENT = " " + +IGNORE_SYMOLS = ( + "wasm_engine_new_with_args", + "wasm_valkind_is_num", + "wasm_valkind_is_ref", + "wasm_valtype_is_num", + "wasm_valtype_is_ref", + "wasm_valtype_new_i32", + "wasm_valtype_new_i64", + "wasm_valtype_new_f32", + "wasm_valtype_new_f64", + "wasm_valtype_new_anyref", + "wasm_valtype_new_funcref", + "wasm_functype_new_0_0", + "wasm_functype_new_0_0", + "wasm_functype_new_1_0", + "wasm_functype_new_2_0", + "wasm_functype_new_3_0", + "wasm_functype_new_0_1", + "wasm_functype_new_1_1", + "wasm_functype_new_2_1", + "wasm_functype_new_3_1", + "wasm_functype_new_0_2", + "wasm_functype_new_1_2", + "wasm_functype_new_2_2", + "wasm_functype_new_3_2", + "wasm_val_init_ptr", + "wasm_val_ptr", + "wasm_val_t", + "wasm_ref_t", + "wasm_name_new_from_string", + "wasm_name_new_from_string_nt", +) + + +class Visitor(c_ast.NodeVisitor): + def __init__(self): + self.type_map = { + "_Bool": "c_bool", + "byte_t": "c_ubyte", + "char": "c_char", + "errno_t": "c_int", + "int": "c_int", + "long": "c_long", + "size_t": "c_size_t", + "uint32_t": "c_uint32", + "uint8_t": "c_uint8", + "void": "None", + } + self.ret = ( + "# -*- coding: utf-8 -*-\n" + "#!/usr/bin/env python3\n" + "#\n" + "# Copyright (C) 2019 Intel Corporation. All rights reserved.\n" + "# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n" + "#\n" + "#It is a generated file. DO NOT EDIT.\n" + "#\n" + "from ctypes import *\n" + "\n" + "from .ffi import dereference, libiwasm, wasm_ref_t, wasm_val_t\n" + "\n" + "\n" + ) + + def get_type_name(self, c_type): + if isinstance(c_type, c_ast.TypeDecl): + return self.get_type_name(c_type.type) + elif isinstance(c_type, c_ast.PtrDecl): + pointed_type = self.get_type_name(c_type.type) + + if isinstance(c_type.type, c_ast.FuncDecl): + # CFUCNTYPE is a pointer of function + return pointed_type + + if "None" == pointed_type: + return "c_void_p" + + return f"POINTER({pointed_type})" + + elif isinstance(c_type, c_ast.ArrayDecl): + return f"POINTER({self.get_type_name(c_type.type)})" + elif isinstance(c_type, c_ast.IdentifierType): + if len(c_type.names) > 1: + raise RuntimeError(f"unexpected type with a long names: {c_type}") + + type_name = c_type.names[0] + + if type_name.startswith("wasm_"): + return type_name + + if not type_name in self.type_map: + raise RuntimeError(f"a new type should be in type_map: {type_name}") + + return self.type_map.get(type_name) + elif isinstance(c_type, c_ast.Union): + if not c_type.name: + raise RuntimeError(f"found an anonymous union {c_type}") + + return c_type.name + elif isinstance(c_type, c_ast.Struct): + if not c_type.name: + raise RuntimeError(f"found an anonymous union {c_type}") + + return c_type.name + elif isinstance(c_type, c_ast.FuncDecl): + content = "CFUNCTYPE(" + if isinstance(c_type.type, c_ast.PtrDecl): + # there is a bug in CFUNCTYPE if the result type is a pointer + content += "c_void_p" + else: + content += f"{self.get_type_name(c_type.type)}" + content += f",{self.get_type_name(c_type.args)}" if c_type.args else "" + content += ")" + return content + elif isinstance(c_type, c_ast.Decl): + return self.get_type_name(c_type.type) + elif isinstance(c_type, c_ast.ParamList): + content = ",".join( + [self.get_type_name(param.type) for param in c_type.params] + ) + return content + else: + raise RuntimeError(f"unexpected type: {c_type.show()}") + + def visit_Struct(self, node): + # pylint: disable=invalid-name + def gen_fields(info, indent): + content = "" + for k, v in info.items(): + content += f'{indent}("{k}", {v}),\n' + return content[:-1] + + def gen_equal(info, indent): + content = f"{indent}return" + for k, v in info.items(): + # not compare pointer value in __eq__ + if v.startswith("POINTER") or v.startswith("c_void_p"): + continue + + content += f" self.{k} == other.{k} and" + return content[:-4] + + def gen_repr(info, indent): + content = f'{indent}return f"{{{{' + for k, _ in info.items(): + content += f"{k}={{self.{k}}}, " + content = content[:-2] + '}}"' + return content + + def gen_vector_repr(info, indent): + content = f'{indent}ret = ""\n' + content += f"{indent}for i in range(self.num_elems):\n" + + if 1 == info["data"].count("POINTER"): + # pointer + content += f"{2*indent}ret += str(self.data[i])\n" + else: + # pointer of pointer + content += f"{2*indent}ret += str(dereference(self.data[i]))\n" + + content += f'{2*indent}ret += " "\n' + content += f"{indent}return ret\n" + return content + + if not node.name or not node.name.lower().startswith("wasm"): + return + + if node.name in IGNORE_SYMOLS: + return + + name = node.name + + info = {} + if node.decls: + for decl in node.decls: + info[decl.name] = self.get_type_name(decl.type) + + if info: + self.ret += ( + f"class {name}(Structure):\n" + f"{INDENT}_fields_ = [\n" + f"{gen_fields(info, INDENT*2)}\n" + f"{INDENT}]\n" + f"\n" + f"{INDENT}def __eq__(self, other):\n" + f"{INDENT*2}if not isinstance(other, {name}):\n" + f"{INDENT*3}return False\n" + f"{gen_equal(info, INDENT*2)}\n" + f"\n" + f"{INDENT}def __repr__(self):\n" + ) + self.ret += ( + f"{gen_vector_repr(info, INDENT*2)}\n" + if name.endswith("_vec_t") + else f"{gen_repr(info, INDENT*2)}\n" + ) + self.ret += "\n" + + else: + self.ret += f"class {name}(Structure):\n{INDENT}pass\n" + + self.ret += "\n" + + def visit_Union(self, node): + # pylint: disable=invalid-name + print(f"Union: {node.show()}") + + def visit_Typedef(self, node): + # pylint: disable=invalid-name + # system defined + if not node.name: + return + + if not node.name.startswith("wasm_"): + return + + if node.name in IGNORE_SYMOLS: + return + + self.visit(node.type) + + if node.name == self.get_type_name(node.type): + return + else: + self.ret += f"{node.name} = {self.get_type_name(node.type)}\n" + self.ret += "\n" + + def visit_FuncDecl(self, node): + # pylint: disable=invalid-name + restype = self.get_type_name(node.type) + + if isinstance(node.type, c_ast.TypeDecl): + func_name = node.type.declname + elif isinstance(node.type, c_ast.PtrDecl): + func_name = node.type.type.declname + else: + raise RuntimeError(f"unexpected type in FuncDecl: {type}") + + if not func_name.startswith("wasm_") or func_name.endswith("_t"): + return + + if func_name in IGNORE_SYMOLS: + return + + params_len = 0 + for arg in node.args.params: + # ignore void but not void* + if isinstance(arg.type, c_ast.TypeDecl): + type_name = self.get_type_name(arg.type) + if "None" == type_name: + continue + + params_len += 1 + + args = ( + "" if not params_len else ",".join([f"arg{i}" for i in range(params_len)]) + ) + argtypes = f"[{self.get_type_name(node.args)}]" if params_len else "None" + + self.ret += ( + f"def {func_name}({args}):\n" + f"{INDENT}_{func_name} = libiwasm.{func_name}\n" + f"{INDENT}_{func_name}.restype = {restype}\n" + f"{INDENT}_{func_name}.argtypes = {argtypes}\n" + f"{INDENT}return _{func_name}({args})\n" + ) + self.ret += "\n" + + def visit_Enum(self, node): + # pylint: disable=invalid-name + elem_value = 0 + # generate enum elementes directly as consts with values + for i, elem in enumerate(node.values.enumerators): + self.ret += f"{elem.name}" + + if elem.value: + elem_value = int(elem.value.value) + else: + if 0 == i: + elem_value = 0 + else: + elem_value += 1 + + self.ret += f" = {elem_value}\n" + + self.ret += "\n" + + +def preflight_check(workspace): + wamr_repo = workspace.joinpath("wasm-micro-runtime") + file_check_list = [ + wamr_repo.exists(), + wamr_repo.joinpath(WASM_C_API_HEADER).exists(), + ] + + if not all(file_check_list): + print( + "please run utils/download_wamr.py to download the repo, or re-download the repo" + ) + return False + + if not shutil.which("gcc"): + print("please install gcc") + return False + + return True + + +def do_parse(workspace): + filename = workspace.joinpath(WASM_C_API_HEADER) + filename = str(filename) + + ast = parse_file( + filename, + use_cpp=True, + cpp_path="gcc", + cpp_args=[ + "-E", + "-D__attribute__(x)=", + "-D__asm__(x)=", + "-D__asm(x)=", + "-D__builtin_va_list=int", + "-D__extension__=", + "-D__inline__=", + "-D__restrict=", + "-D__restrict__=", + "-D_Static_assert(x, y)=", + "-D__signed=", + "-D__volatile__(x)=", + "-Dstatic_assert(x, y)=", + ], + ) + + ast_visitor = Visitor() + ast_visitor.visit(ast) + return ast_visitor.ret + + +def main(): + current_file = pathlib.Path(__file__) + if current_file.is_symlink(): + current_file = pathlib.Path(os.readlink(current_file)) + + current_dir = current_file.parent.resolve() + root_dir = current_dir.joinpath("..").resolve() + + if not preflight_check(root_dir): + return False + + wamr_repo = root_dir.joinpath("wasm-micro-runtime") + binding_file_path = root_dir.joinpath(BINDING_PATH) + with open(binding_file_path, "wt", encoding="utf-8") as binding_file: + binding_file.write(do_parse(wamr_repo)) + + return True + + +if __name__ == "__main__": + sys.exit(0 if main() else 1) diff --git a/language-bindings/python/wamr/__init__.py b/language-bindings/python/wamr/__init__.py new file mode 100644 index 000000000..8d7404ad8 --- /dev/null +++ b/language-bindings/python/wamr/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +__all__ = ["ffi"] diff --git a/language-bindings/python/wamr/binding.py b/language-bindings/python/wamr/binding.py new file mode 100644 index 000000000..dd7adadf6 --- /dev/null +++ b/language-bindings/python/wamr/binding.py @@ -0,0 +1,2020 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +#It is a generated file. DO NOT EDIT. +# +from ctypes import * + +from .ffi import dereference, libiwasm, wasm_ref_t, wasm_val_t + + +wasm_byte_t = c_ubyte + +class wasm_byte_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(wasm_byte_t)), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_byte_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(self.data[i]) + ret += " " + return ret + + + +def wasm_byte_vec_new_empty(arg0): + _wasm_byte_vec_new_empty = libiwasm.wasm_byte_vec_new_empty + _wasm_byte_vec_new_empty.restype = None + _wasm_byte_vec_new_empty.argtypes = [POINTER(wasm_byte_vec_t)] + return _wasm_byte_vec_new_empty(arg0) + +def wasm_byte_vec_new_uninitialized(arg0,arg1): + _wasm_byte_vec_new_uninitialized = libiwasm.wasm_byte_vec_new_uninitialized + _wasm_byte_vec_new_uninitialized.restype = None + _wasm_byte_vec_new_uninitialized.argtypes = [POINTER(wasm_byte_vec_t),c_size_t] + return _wasm_byte_vec_new_uninitialized(arg0,arg1) + +def wasm_byte_vec_new(arg0,arg1,arg2): + _wasm_byte_vec_new = libiwasm.wasm_byte_vec_new + _wasm_byte_vec_new.restype = None + _wasm_byte_vec_new.argtypes = [POINTER(wasm_byte_vec_t),c_size_t,POINTER(wasm_byte_t)] + return _wasm_byte_vec_new(arg0,arg1,arg2) + +def wasm_byte_vec_copy(arg0,arg1): + _wasm_byte_vec_copy = libiwasm.wasm_byte_vec_copy + _wasm_byte_vec_copy.restype = None + _wasm_byte_vec_copy.argtypes = [POINTER(wasm_byte_vec_t),POINTER(wasm_byte_vec_t)] + return _wasm_byte_vec_copy(arg0,arg1) + +def wasm_byte_vec_delete(arg0): + _wasm_byte_vec_delete = libiwasm.wasm_byte_vec_delete + _wasm_byte_vec_delete.restype = None + _wasm_byte_vec_delete.argtypes = [POINTER(wasm_byte_vec_t)] + return _wasm_byte_vec_delete(arg0) + +wasm_name_t = wasm_byte_vec_t + +class wasm_config_t(Structure): + pass + +def wasm_config_delete(arg0): + _wasm_config_delete = libiwasm.wasm_config_delete + _wasm_config_delete.restype = None + _wasm_config_delete.argtypes = [POINTER(wasm_config_t)] + return _wasm_config_delete(arg0) + +def wasm_config_new(): + _wasm_config_new = libiwasm.wasm_config_new + _wasm_config_new.restype = POINTER(wasm_config_t) + _wasm_config_new.argtypes = None + return _wasm_config_new() + +class wasm_engine_t(Structure): + pass + +def wasm_engine_delete(arg0): + _wasm_engine_delete = libiwasm.wasm_engine_delete + _wasm_engine_delete.restype = None + _wasm_engine_delete.argtypes = [POINTER(wasm_engine_t)] + return _wasm_engine_delete(arg0) + +def wasm_engine_new(): + _wasm_engine_new = libiwasm.wasm_engine_new + _wasm_engine_new.restype = POINTER(wasm_engine_t) + _wasm_engine_new.argtypes = None + return _wasm_engine_new() + +def wasm_engine_new_with_config(arg0): + _wasm_engine_new_with_config = libiwasm.wasm_engine_new_with_config + _wasm_engine_new_with_config.restype = POINTER(wasm_engine_t) + _wasm_engine_new_with_config.argtypes = [POINTER(wasm_config_t)] + return _wasm_engine_new_with_config(arg0) + +class wasm_store_t(Structure): + pass + +def wasm_store_delete(arg0): + _wasm_store_delete = libiwasm.wasm_store_delete + _wasm_store_delete.restype = None + _wasm_store_delete.argtypes = [POINTER(wasm_store_t)] + return _wasm_store_delete(arg0) + +def wasm_store_new(arg0): + _wasm_store_new = libiwasm.wasm_store_new + _wasm_store_new.restype = POINTER(wasm_store_t) + _wasm_store_new.argtypes = [POINTER(wasm_engine_t)] + return _wasm_store_new(arg0) + +wasm_mutability_t = c_uint8 + +WASM_CONST = 0 +WASM_VAR = 1 + +class wasm_limits_t(Structure): + _fields_ = [ + ("min", c_uint32), + ("max", c_uint32), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_limits_t): + return False + return self.min == other.min and self.max == other.max + + def __repr__(self): + return f"{{min={self.min}, max={self.max}}}" + + +class wasm_valtype_t(Structure): + pass + +def wasm_valtype_delete(arg0): + _wasm_valtype_delete = libiwasm.wasm_valtype_delete + _wasm_valtype_delete.restype = None + _wasm_valtype_delete.argtypes = [POINTER(wasm_valtype_t)] + return _wasm_valtype_delete(arg0) + +class wasm_valtype_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_valtype_t))), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_valtype_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(dereference(self.data[i])) + ret += " " + return ret + + + +def wasm_valtype_vec_new_empty(arg0): + _wasm_valtype_vec_new_empty = libiwasm.wasm_valtype_vec_new_empty + _wasm_valtype_vec_new_empty.restype = None + _wasm_valtype_vec_new_empty.argtypes = [POINTER(wasm_valtype_vec_t)] + return _wasm_valtype_vec_new_empty(arg0) + +def wasm_valtype_vec_new_uninitialized(arg0,arg1): + _wasm_valtype_vec_new_uninitialized = libiwasm.wasm_valtype_vec_new_uninitialized + _wasm_valtype_vec_new_uninitialized.restype = None + _wasm_valtype_vec_new_uninitialized.argtypes = [POINTER(wasm_valtype_vec_t),c_size_t] + return _wasm_valtype_vec_new_uninitialized(arg0,arg1) + +def wasm_valtype_vec_new(arg0,arg1,arg2): + _wasm_valtype_vec_new = libiwasm.wasm_valtype_vec_new + _wasm_valtype_vec_new.restype = None + _wasm_valtype_vec_new.argtypes = [POINTER(wasm_valtype_vec_t),c_size_t,POINTER(POINTER(wasm_valtype_t))] + return _wasm_valtype_vec_new(arg0,arg1,arg2) + +def wasm_valtype_vec_copy(arg0,arg1): + _wasm_valtype_vec_copy = libiwasm.wasm_valtype_vec_copy + _wasm_valtype_vec_copy.restype = None + _wasm_valtype_vec_copy.argtypes = [POINTER(wasm_valtype_vec_t),POINTER(wasm_valtype_vec_t)] + return _wasm_valtype_vec_copy(arg0,arg1) + +def wasm_valtype_vec_delete(arg0): + _wasm_valtype_vec_delete = libiwasm.wasm_valtype_vec_delete + _wasm_valtype_vec_delete.restype = None + _wasm_valtype_vec_delete.argtypes = [POINTER(wasm_valtype_vec_t)] + return _wasm_valtype_vec_delete(arg0) + +def wasm_valtype_copy(arg0): + _wasm_valtype_copy = libiwasm.wasm_valtype_copy + _wasm_valtype_copy.restype = POINTER(wasm_valtype_t) + _wasm_valtype_copy.argtypes = [POINTER(wasm_valtype_t)] + return _wasm_valtype_copy(arg0) + +wasm_valkind_t = c_uint8 + +WASM_I32 = 0 +WASM_I64 = 1 +WASM_F32 = 2 +WASM_F64 = 3 +WASM_ANYREF = 128 +WASM_FUNCREF = 129 + +def wasm_valtype_new(arg0): + _wasm_valtype_new = libiwasm.wasm_valtype_new + _wasm_valtype_new.restype = POINTER(wasm_valtype_t) + _wasm_valtype_new.argtypes = [wasm_valkind_t] + return _wasm_valtype_new(arg0) + +def wasm_valtype_kind(arg0): + _wasm_valtype_kind = libiwasm.wasm_valtype_kind + _wasm_valtype_kind.restype = wasm_valkind_t + _wasm_valtype_kind.argtypes = [POINTER(wasm_valtype_t)] + return _wasm_valtype_kind(arg0) + +class wasm_functype_t(Structure): + pass + +def wasm_functype_delete(arg0): + _wasm_functype_delete = libiwasm.wasm_functype_delete + _wasm_functype_delete.restype = None + _wasm_functype_delete.argtypes = [POINTER(wasm_functype_t)] + return _wasm_functype_delete(arg0) + +class wasm_functype_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_functype_t))), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_functype_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(dereference(self.data[i])) + ret += " " + return ret + + + +def wasm_functype_vec_new_empty(arg0): + _wasm_functype_vec_new_empty = libiwasm.wasm_functype_vec_new_empty + _wasm_functype_vec_new_empty.restype = None + _wasm_functype_vec_new_empty.argtypes = [POINTER(wasm_functype_vec_t)] + return _wasm_functype_vec_new_empty(arg0) + +def wasm_functype_vec_new_uninitialized(arg0,arg1): + _wasm_functype_vec_new_uninitialized = libiwasm.wasm_functype_vec_new_uninitialized + _wasm_functype_vec_new_uninitialized.restype = None + _wasm_functype_vec_new_uninitialized.argtypes = [POINTER(wasm_functype_vec_t),c_size_t] + return _wasm_functype_vec_new_uninitialized(arg0,arg1) + +def wasm_functype_vec_new(arg0,arg1,arg2): + _wasm_functype_vec_new = libiwasm.wasm_functype_vec_new + _wasm_functype_vec_new.restype = None + _wasm_functype_vec_new.argtypes = [POINTER(wasm_functype_vec_t),c_size_t,POINTER(POINTER(wasm_functype_t))] + return _wasm_functype_vec_new(arg0,arg1,arg2) + +def wasm_functype_vec_copy(arg0,arg1): + _wasm_functype_vec_copy = libiwasm.wasm_functype_vec_copy + _wasm_functype_vec_copy.restype = None + _wasm_functype_vec_copy.argtypes = [POINTER(wasm_functype_vec_t),POINTER(wasm_functype_vec_t)] + return _wasm_functype_vec_copy(arg0,arg1) + +def wasm_functype_vec_delete(arg0): + _wasm_functype_vec_delete = libiwasm.wasm_functype_vec_delete + _wasm_functype_vec_delete.restype = None + _wasm_functype_vec_delete.argtypes = [POINTER(wasm_functype_vec_t)] + return _wasm_functype_vec_delete(arg0) + +def wasm_functype_copy(arg0): + _wasm_functype_copy = libiwasm.wasm_functype_copy + _wasm_functype_copy.restype = POINTER(wasm_functype_t) + _wasm_functype_copy.argtypes = [POINTER(wasm_functype_t)] + return _wasm_functype_copy(arg0) + +def wasm_functype_new(arg0,arg1): + _wasm_functype_new = libiwasm.wasm_functype_new + _wasm_functype_new.restype = POINTER(wasm_functype_t) + _wasm_functype_new.argtypes = [POINTER(wasm_valtype_vec_t),POINTER(wasm_valtype_vec_t)] + return _wasm_functype_new(arg0,arg1) + +def wasm_functype_params(arg0): + _wasm_functype_params = libiwasm.wasm_functype_params + _wasm_functype_params.restype = POINTER(wasm_valtype_vec_t) + _wasm_functype_params.argtypes = [POINTER(wasm_functype_t)] + return _wasm_functype_params(arg0) + +def wasm_functype_results(arg0): + _wasm_functype_results = libiwasm.wasm_functype_results + _wasm_functype_results.restype = POINTER(wasm_valtype_vec_t) + _wasm_functype_results.argtypes = [POINTER(wasm_functype_t)] + return _wasm_functype_results(arg0) + +class wasm_globaltype_t(Structure): + pass + +def wasm_globaltype_delete(arg0): + _wasm_globaltype_delete = libiwasm.wasm_globaltype_delete + _wasm_globaltype_delete.restype = None + _wasm_globaltype_delete.argtypes = [POINTER(wasm_globaltype_t)] + return _wasm_globaltype_delete(arg0) + +class wasm_globaltype_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_globaltype_t))), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_globaltype_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(dereference(self.data[i])) + ret += " " + return ret + + + +def wasm_globaltype_vec_new_empty(arg0): + _wasm_globaltype_vec_new_empty = libiwasm.wasm_globaltype_vec_new_empty + _wasm_globaltype_vec_new_empty.restype = None + _wasm_globaltype_vec_new_empty.argtypes = [POINTER(wasm_globaltype_vec_t)] + return _wasm_globaltype_vec_new_empty(arg0) + +def wasm_globaltype_vec_new_uninitialized(arg0,arg1): + _wasm_globaltype_vec_new_uninitialized = libiwasm.wasm_globaltype_vec_new_uninitialized + _wasm_globaltype_vec_new_uninitialized.restype = None + _wasm_globaltype_vec_new_uninitialized.argtypes = [POINTER(wasm_globaltype_vec_t),c_size_t] + return _wasm_globaltype_vec_new_uninitialized(arg0,arg1) + +def wasm_globaltype_vec_new(arg0,arg1,arg2): + _wasm_globaltype_vec_new = libiwasm.wasm_globaltype_vec_new + _wasm_globaltype_vec_new.restype = None + _wasm_globaltype_vec_new.argtypes = [POINTER(wasm_globaltype_vec_t),c_size_t,POINTER(POINTER(wasm_globaltype_t))] + return _wasm_globaltype_vec_new(arg0,arg1,arg2) + +def wasm_globaltype_vec_copy(arg0,arg1): + _wasm_globaltype_vec_copy = libiwasm.wasm_globaltype_vec_copy + _wasm_globaltype_vec_copy.restype = None + _wasm_globaltype_vec_copy.argtypes = [POINTER(wasm_globaltype_vec_t),POINTER(wasm_globaltype_vec_t)] + return _wasm_globaltype_vec_copy(arg0,arg1) + +def wasm_globaltype_vec_delete(arg0): + _wasm_globaltype_vec_delete = libiwasm.wasm_globaltype_vec_delete + _wasm_globaltype_vec_delete.restype = None + _wasm_globaltype_vec_delete.argtypes = [POINTER(wasm_globaltype_vec_t)] + return _wasm_globaltype_vec_delete(arg0) + +def wasm_globaltype_copy(arg0): + _wasm_globaltype_copy = libiwasm.wasm_globaltype_copy + _wasm_globaltype_copy.restype = POINTER(wasm_globaltype_t) + _wasm_globaltype_copy.argtypes = [POINTER(wasm_globaltype_t)] + return _wasm_globaltype_copy(arg0) + +def wasm_globaltype_new(arg0,arg1): + _wasm_globaltype_new = libiwasm.wasm_globaltype_new + _wasm_globaltype_new.restype = POINTER(wasm_globaltype_t) + _wasm_globaltype_new.argtypes = [POINTER(wasm_valtype_t),wasm_mutability_t] + return _wasm_globaltype_new(arg0,arg1) + +def wasm_globaltype_content(arg0): + _wasm_globaltype_content = libiwasm.wasm_globaltype_content + _wasm_globaltype_content.restype = POINTER(wasm_valtype_t) + _wasm_globaltype_content.argtypes = [POINTER(wasm_globaltype_t)] + return _wasm_globaltype_content(arg0) + +def wasm_globaltype_mutability(arg0): + _wasm_globaltype_mutability = libiwasm.wasm_globaltype_mutability + _wasm_globaltype_mutability.restype = wasm_mutability_t + _wasm_globaltype_mutability.argtypes = [POINTER(wasm_globaltype_t)] + return _wasm_globaltype_mutability(arg0) + +class wasm_tabletype_t(Structure): + pass + +def wasm_tabletype_delete(arg0): + _wasm_tabletype_delete = libiwasm.wasm_tabletype_delete + _wasm_tabletype_delete.restype = None + _wasm_tabletype_delete.argtypes = [POINTER(wasm_tabletype_t)] + return _wasm_tabletype_delete(arg0) + +class wasm_tabletype_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_tabletype_t))), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_tabletype_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(dereference(self.data[i])) + ret += " " + return ret + + + +def wasm_tabletype_vec_new_empty(arg0): + _wasm_tabletype_vec_new_empty = libiwasm.wasm_tabletype_vec_new_empty + _wasm_tabletype_vec_new_empty.restype = None + _wasm_tabletype_vec_new_empty.argtypes = [POINTER(wasm_tabletype_vec_t)] + return _wasm_tabletype_vec_new_empty(arg0) + +def wasm_tabletype_vec_new_uninitialized(arg0,arg1): + _wasm_tabletype_vec_new_uninitialized = libiwasm.wasm_tabletype_vec_new_uninitialized + _wasm_tabletype_vec_new_uninitialized.restype = None + _wasm_tabletype_vec_new_uninitialized.argtypes = [POINTER(wasm_tabletype_vec_t),c_size_t] + return _wasm_tabletype_vec_new_uninitialized(arg0,arg1) + +def wasm_tabletype_vec_new(arg0,arg1,arg2): + _wasm_tabletype_vec_new = libiwasm.wasm_tabletype_vec_new + _wasm_tabletype_vec_new.restype = None + _wasm_tabletype_vec_new.argtypes = [POINTER(wasm_tabletype_vec_t),c_size_t,POINTER(POINTER(wasm_tabletype_t))] + return _wasm_tabletype_vec_new(arg0,arg1,arg2) + +def wasm_tabletype_vec_copy(arg0,arg1): + _wasm_tabletype_vec_copy = libiwasm.wasm_tabletype_vec_copy + _wasm_tabletype_vec_copy.restype = None + _wasm_tabletype_vec_copy.argtypes = [POINTER(wasm_tabletype_vec_t),POINTER(wasm_tabletype_vec_t)] + return _wasm_tabletype_vec_copy(arg0,arg1) + +def wasm_tabletype_vec_delete(arg0): + _wasm_tabletype_vec_delete = libiwasm.wasm_tabletype_vec_delete + _wasm_tabletype_vec_delete.restype = None + _wasm_tabletype_vec_delete.argtypes = [POINTER(wasm_tabletype_vec_t)] + return _wasm_tabletype_vec_delete(arg0) + +def wasm_tabletype_copy(arg0): + _wasm_tabletype_copy = libiwasm.wasm_tabletype_copy + _wasm_tabletype_copy.restype = POINTER(wasm_tabletype_t) + _wasm_tabletype_copy.argtypes = [POINTER(wasm_tabletype_t)] + return _wasm_tabletype_copy(arg0) + +def wasm_tabletype_new(arg0,arg1): + _wasm_tabletype_new = libiwasm.wasm_tabletype_new + _wasm_tabletype_new.restype = POINTER(wasm_tabletype_t) + _wasm_tabletype_new.argtypes = [POINTER(wasm_valtype_t),POINTER(wasm_limits_t)] + return _wasm_tabletype_new(arg0,arg1) + +def wasm_tabletype_element(arg0): + _wasm_tabletype_element = libiwasm.wasm_tabletype_element + _wasm_tabletype_element.restype = POINTER(wasm_valtype_t) + _wasm_tabletype_element.argtypes = [POINTER(wasm_tabletype_t)] + return _wasm_tabletype_element(arg0) + +def wasm_tabletype_limits(arg0): + _wasm_tabletype_limits = libiwasm.wasm_tabletype_limits + _wasm_tabletype_limits.restype = POINTER(wasm_limits_t) + _wasm_tabletype_limits.argtypes = [POINTER(wasm_tabletype_t)] + return _wasm_tabletype_limits(arg0) + +class wasm_memorytype_t(Structure): + pass + +def wasm_memorytype_delete(arg0): + _wasm_memorytype_delete = libiwasm.wasm_memorytype_delete + _wasm_memorytype_delete.restype = None + _wasm_memorytype_delete.argtypes = [POINTER(wasm_memorytype_t)] + return _wasm_memorytype_delete(arg0) + +class wasm_memorytype_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_memorytype_t))), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_memorytype_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(dereference(self.data[i])) + ret += " " + return ret + + + +def wasm_memorytype_vec_new_empty(arg0): + _wasm_memorytype_vec_new_empty = libiwasm.wasm_memorytype_vec_new_empty + _wasm_memorytype_vec_new_empty.restype = None + _wasm_memorytype_vec_new_empty.argtypes = [POINTER(wasm_memorytype_vec_t)] + return _wasm_memorytype_vec_new_empty(arg0) + +def wasm_memorytype_vec_new_uninitialized(arg0,arg1): + _wasm_memorytype_vec_new_uninitialized = libiwasm.wasm_memorytype_vec_new_uninitialized + _wasm_memorytype_vec_new_uninitialized.restype = None + _wasm_memorytype_vec_new_uninitialized.argtypes = [POINTER(wasm_memorytype_vec_t),c_size_t] + return _wasm_memorytype_vec_new_uninitialized(arg0,arg1) + +def wasm_memorytype_vec_new(arg0,arg1,arg2): + _wasm_memorytype_vec_new = libiwasm.wasm_memorytype_vec_new + _wasm_memorytype_vec_new.restype = None + _wasm_memorytype_vec_new.argtypes = [POINTER(wasm_memorytype_vec_t),c_size_t,POINTER(POINTER(wasm_memorytype_t))] + return _wasm_memorytype_vec_new(arg0,arg1,arg2) + +def wasm_memorytype_vec_copy(arg0,arg1): + _wasm_memorytype_vec_copy = libiwasm.wasm_memorytype_vec_copy + _wasm_memorytype_vec_copy.restype = None + _wasm_memorytype_vec_copy.argtypes = [POINTER(wasm_memorytype_vec_t),POINTER(wasm_memorytype_vec_t)] + return _wasm_memorytype_vec_copy(arg0,arg1) + +def wasm_memorytype_vec_delete(arg0): + _wasm_memorytype_vec_delete = libiwasm.wasm_memorytype_vec_delete + _wasm_memorytype_vec_delete.restype = None + _wasm_memorytype_vec_delete.argtypes = [POINTER(wasm_memorytype_vec_t)] + return _wasm_memorytype_vec_delete(arg0) + +def wasm_memorytype_copy(arg0): + _wasm_memorytype_copy = libiwasm.wasm_memorytype_copy + _wasm_memorytype_copy.restype = POINTER(wasm_memorytype_t) + _wasm_memorytype_copy.argtypes = [POINTER(wasm_memorytype_t)] + return _wasm_memorytype_copy(arg0) + +def wasm_memorytype_new(arg0): + _wasm_memorytype_new = libiwasm.wasm_memorytype_new + _wasm_memorytype_new.restype = POINTER(wasm_memorytype_t) + _wasm_memorytype_new.argtypes = [POINTER(wasm_limits_t)] + return _wasm_memorytype_new(arg0) + +def wasm_memorytype_limits(arg0): + _wasm_memorytype_limits = libiwasm.wasm_memorytype_limits + _wasm_memorytype_limits.restype = POINTER(wasm_limits_t) + _wasm_memorytype_limits.argtypes = [POINTER(wasm_memorytype_t)] + return _wasm_memorytype_limits(arg0) + +class wasm_externtype_t(Structure): + pass + +def wasm_externtype_delete(arg0): + _wasm_externtype_delete = libiwasm.wasm_externtype_delete + _wasm_externtype_delete.restype = None + _wasm_externtype_delete.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_delete(arg0) + +class wasm_externtype_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_externtype_t))), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_externtype_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(dereference(self.data[i])) + ret += " " + return ret + + + +def wasm_externtype_vec_new_empty(arg0): + _wasm_externtype_vec_new_empty = libiwasm.wasm_externtype_vec_new_empty + _wasm_externtype_vec_new_empty.restype = None + _wasm_externtype_vec_new_empty.argtypes = [POINTER(wasm_externtype_vec_t)] + return _wasm_externtype_vec_new_empty(arg0) + +def wasm_externtype_vec_new_uninitialized(arg0,arg1): + _wasm_externtype_vec_new_uninitialized = libiwasm.wasm_externtype_vec_new_uninitialized + _wasm_externtype_vec_new_uninitialized.restype = None + _wasm_externtype_vec_new_uninitialized.argtypes = [POINTER(wasm_externtype_vec_t),c_size_t] + return _wasm_externtype_vec_new_uninitialized(arg0,arg1) + +def wasm_externtype_vec_new(arg0,arg1,arg2): + _wasm_externtype_vec_new = libiwasm.wasm_externtype_vec_new + _wasm_externtype_vec_new.restype = None + _wasm_externtype_vec_new.argtypes = [POINTER(wasm_externtype_vec_t),c_size_t,POINTER(POINTER(wasm_externtype_t))] + return _wasm_externtype_vec_new(arg0,arg1,arg2) + +def wasm_externtype_vec_copy(arg0,arg1): + _wasm_externtype_vec_copy = libiwasm.wasm_externtype_vec_copy + _wasm_externtype_vec_copy.restype = None + _wasm_externtype_vec_copy.argtypes = [POINTER(wasm_externtype_vec_t),POINTER(wasm_externtype_vec_t)] + return _wasm_externtype_vec_copy(arg0,arg1) + +def wasm_externtype_vec_delete(arg0): + _wasm_externtype_vec_delete = libiwasm.wasm_externtype_vec_delete + _wasm_externtype_vec_delete.restype = None + _wasm_externtype_vec_delete.argtypes = [POINTER(wasm_externtype_vec_t)] + return _wasm_externtype_vec_delete(arg0) + +def wasm_externtype_copy(arg0): + _wasm_externtype_copy = libiwasm.wasm_externtype_copy + _wasm_externtype_copy.restype = POINTER(wasm_externtype_t) + _wasm_externtype_copy.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_copy(arg0) + +wasm_externkind_t = c_uint8 + +WASM_EXTERN_FUNC = 0 +WASM_EXTERN_GLOBAL = 1 +WASM_EXTERN_TABLE = 2 +WASM_EXTERN_MEMORY = 3 + +def wasm_externtype_kind(arg0): + _wasm_externtype_kind = libiwasm.wasm_externtype_kind + _wasm_externtype_kind.restype = wasm_externkind_t + _wasm_externtype_kind.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_kind(arg0) + +def wasm_functype_as_externtype(arg0): + _wasm_functype_as_externtype = libiwasm.wasm_functype_as_externtype + _wasm_functype_as_externtype.restype = POINTER(wasm_externtype_t) + _wasm_functype_as_externtype.argtypes = [POINTER(wasm_functype_t)] + return _wasm_functype_as_externtype(arg0) + +def wasm_globaltype_as_externtype(arg0): + _wasm_globaltype_as_externtype = libiwasm.wasm_globaltype_as_externtype + _wasm_globaltype_as_externtype.restype = POINTER(wasm_externtype_t) + _wasm_globaltype_as_externtype.argtypes = [POINTER(wasm_globaltype_t)] + return _wasm_globaltype_as_externtype(arg0) + +def wasm_tabletype_as_externtype(arg0): + _wasm_tabletype_as_externtype = libiwasm.wasm_tabletype_as_externtype + _wasm_tabletype_as_externtype.restype = POINTER(wasm_externtype_t) + _wasm_tabletype_as_externtype.argtypes = [POINTER(wasm_tabletype_t)] + return _wasm_tabletype_as_externtype(arg0) + +def wasm_memorytype_as_externtype(arg0): + _wasm_memorytype_as_externtype = libiwasm.wasm_memorytype_as_externtype + _wasm_memorytype_as_externtype.restype = POINTER(wasm_externtype_t) + _wasm_memorytype_as_externtype.argtypes = [POINTER(wasm_memorytype_t)] + return _wasm_memorytype_as_externtype(arg0) + +def wasm_externtype_as_functype(arg0): + _wasm_externtype_as_functype = libiwasm.wasm_externtype_as_functype + _wasm_externtype_as_functype.restype = POINTER(wasm_functype_t) + _wasm_externtype_as_functype.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_as_functype(arg0) + +def wasm_externtype_as_globaltype(arg0): + _wasm_externtype_as_globaltype = libiwasm.wasm_externtype_as_globaltype + _wasm_externtype_as_globaltype.restype = POINTER(wasm_globaltype_t) + _wasm_externtype_as_globaltype.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_as_globaltype(arg0) + +def wasm_externtype_as_tabletype(arg0): + _wasm_externtype_as_tabletype = libiwasm.wasm_externtype_as_tabletype + _wasm_externtype_as_tabletype.restype = POINTER(wasm_tabletype_t) + _wasm_externtype_as_tabletype.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_as_tabletype(arg0) + +def wasm_externtype_as_memorytype(arg0): + _wasm_externtype_as_memorytype = libiwasm.wasm_externtype_as_memorytype + _wasm_externtype_as_memorytype.restype = POINTER(wasm_memorytype_t) + _wasm_externtype_as_memorytype.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_as_memorytype(arg0) + +def wasm_functype_as_externtype_const(arg0): + _wasm_functype_as_externtype_const = libiwasm.wasm_functype_as_externtype_const + _wasm_functype_as_externtype_const.restype = POINTER(wasm_externtype_t) + _wasm_functype_as_externtype_const.argtypes = [POINTER(wasm_functype_t)] + return _wasm_functype_as_externtype_const(arg0) + +def wasm_globaltype_as_externtype_const(arg0): + _wasm_globaltype_as_externtype_const = libiwasm.wasm_globaltype_as_externtype_const + _wasm_globaltype_as_externtype_const.restype = POINTER(wasm_externtype_t) + _wasm_globaltype_as_externtype_const.argtypes = [POINTER(wasm_globaltype_t)] + return _wasm_globaltype_as_externtype_const(arg0) + +def wasm_tabletype_as_externtype_const(arg0): + _wasm_tabletype_as_externtype_const = libiwasm.wasm_tabletype_as_externtype_const + _wasm_tabletype_as_externtype_const.restype = POINTER(wasm_externtype_t) + _wasm_tabletype_as_externtype_const.argtypes = [POINTER(wasm_tabletype_t)] + return _wasm_tabletype_as_externtype_const(arg0) + +def wasm_memorytype_as_externtype_const(arg0): + _wasm_memorytype_as_externtype_const = libiwasm.wasm_memorytype_as_externtype_const + _wasm_memorytype_as_externtype_const.restype = POINTER(wasm_externtype_t) + _wasm_memorytype_as_externtype_const.argtypes = [POINTER(wasm_memorytype_t)] + return _wasm_memorytype_as_externtype_const(arg0) + +def wasm_externtype_as_functype_const(arg0): + _wasm_externtype_as_functype_const = libiwasm.wasm_externtype_as_functype_const + _wasm_externtype_as_functype_const.restype = POINTER(wasm_functype_t) + _wasm_externtype_as_functype_const.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_as_functype_const(arg0) + +def wasm_externtype_as_globaltype_const(arg0): + _wasm_externtype_as_globaltype_const = libiwasm.wasm_externtype_as_globaltype_const + _wasm_externtype_as_globaltype_const.restype = POINTER(wasm_globaltype_t) + _wasm_externtype_as_globaltype_const.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_as_globaltype_const(arg0) + +def wasm_externtype_as_tabletype_const(arg0): + _wasm_externtype_as_tabletype_const = libiwasm.wasm_externtype_as_tabletype_const + _wasm_externtype_as_tabletype_const.restype = POINTER(wasm_tabletype_t) + _wasm_externtype_as_tabletype_const.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_as_tabletype_const(arg0) + +def wasm_externtype_as_memorytype_const(arg0): + _wasm_externtype_as_memorytype_const = libiwasm.wasm_externtype_as_memorytype_const + _wasm_externtype_as_memorytype_const.restype = POINTER(wasm_memorytype_t) + _wasm_externtype_as_memorytype_const.argtypes = [POINTER(wasm_externtype_t)] + return _wasm_externtype_as_memorytype_const(arg0) + +class wasm_importtype_t(Structure): + pass + +def wasm_importtype_delete(arg0): + _wasm_importtype_delete = libiwasm.wasm_importtype_delete + _wasm_importtype_delete.restype = None + _wasm_importtype_delete.argtypes = [POINTER(wasm_importtype_t)] + return _wasm_importtype_delete(arg0) + +class wasm_importtype_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_importtype_t))), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_importtype_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(dereference(self.data[i])) + ret += " " + return ret + + + +def wasm_importtype_vec_new_empty(arg0): + _wasm_importtype_vec_new_empty = libiwasm.wasm_importtype_vec_new_empty + _wasm_importtype_vec_new_empty.restype = None + _wasm_importtype_vec_new_empty.argtypes = [POINTER(wasm_importtype_vec_t)] + return _wasm_importtype_vec_new_empty(arg0) + +def wasm_importtype_vec_new_uninitialized(arg0,arg1): + _wasm_importtype_vec_new_uninitialized = libiwasm.wasm_importtype_vec_new_uninitialized + _wasm_importtype_vec_new_uninitialized.restype = None + _wasm_importtype_vec_new_uninitialized.argtypes = [POINTER(wasm_importtype_vec_t),c_size_t] + return _wasm_importtype_vec_new_uninitialized(arg0,arg1) + +def wasm_importtype_vec_new(arg0,arg1,arg2): + _wasm_importtype_vec_new = libiwasm.wasm_importtype_vec_new + _wasm_importtype_vec_new.restype = None + _wasm_importtype_vec_new.argtypes = [POINTER(wasm_importtype_vec_t),c_size_t,POINTER(POINTER(wasm_importtype_t))] + return _wasm_importtype_vec_new(arg0,arg1,arg2) + +def wasm_importtype_vec_copy(arg0,arg1): + _wasm_importtype_vec_copy = libiwasm.wasm_importtype_vec_copy + _wasm_importtype_vec_copy.restype = None + _wasm_importtype_vec_copy.argtypes = [POINTER(wasm_importtype_vec_t),POINTER(wasm_importtype_vec_t)] + return _wasm_importtype_vec_copy(arg0,arg1) + +def wasm_importtype_vec_delete(arg0): + _wasm_importtype_vec_delete = libiwasm.wasm_importtype_vec_delete + _wasm_importtype_vec_delete.restype = None + _wasm_importtype_vec_delete.argtypes = [POINTER(wasm_importtype_vec_t)] + return _wasm_importtype_vec_delete(arg0) + +def wasm_importtype_copy(arg0): + _wasm_importtype_copy = libiwasm.wasm_importtype_copy + _wasm_importtype_copy.restype = POINTER(wasm_importtype_t) + _wasm_importtype_copy.argtypes = [POINTER(wasm_importtype_t)] + return _wasm_importtype_copy(arg0) + +def wasm_importtype_new(arg0,arg1,arg2): + _wasm_importtype_new = libiwasm.wasm_importtype_new + _wasm_importtype_new.restype = POINTER(wasm_importtype_t) + _wasm_importtype_new.argtypes = [POINTER(wasm_name_t),POINTER(wasm_name_t),POINTER(wasm_externtype_t)] + return _wasm_importtype_new(arg0,arg1,arg2) + +def wasm_importtype_module(arg0): + _wasm_importtype_module = libiwasm.wasm_importtype_module + _wasm_importtype_module.restype = POINTER(wasm_name_t) + _wasm_importtype_module.argtypes = [POINTER(wasm_importtype_t)] + return _wasm_importtype_module(arg0) + +def wasm_importtype_name(arg0): + _wasm_importtype_name = libiwasm.wasm_importtype_name + _wasm_importtype_name.restype = POINTER(wasm_name_t) + _wasm_importtype_name.argtypes = [POINTER(wasm_importtype_t)] + return _wasm_importtype_name(arg0) + +def wasm_importtype_type(arg0): + _wasm_importtype_type = libiwasm.wasm_importtype_type + _wasm_importtype_type.restype = POINTER(wasm_externtype_t) + _wasm_importtype_type.argtypes = [POINTER(wasm_importtype_t)] + return _wasm_importtype_type(arg0) + +class wasm_exporttype_t(Structure): + pass + +def wasm_exporttype_delete(arg0): + _wasm_exporttype_delete = libiwasm.wasm_exporttype_delete + _wasm_exporttype_delete.restype = None + _wasm_exporttype_delete.argtypes = [POINTER(wasm_exporttype_t)] + return _wasm_exporttype_delete(arg0) + +class wasm_exporttype_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_exporttype_t))), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_exporttype_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(dereference(self.data[i])) + ret += " " + return ret + + + +def wasm_exporttype_vec_new_empty(arg0): + _wasm_exporttype_vec_new_empty = libiwasm.wasm_exporttype_vec_new_empty + _wasm_exporttype_vec_new_empty.restype = None + _wasm_exporttype_vec_new_empty.argtypes = [POINTER(wasm_exporttype_vec_t)] + return _wasm_exporttype_vec_new_empty(arg0) + +def wasm_exporttype_vec_new_uninitialized(arg0,arg1): + _wasm_exporttype_vec_new_uninitialized = libiwasm.wasm_exporttype_vec_new_uninitialized + _wasm_exporttype_vec_new_uninitialized.restype = None + _wasm_exporttype_vec_new_uninitialized.argtypes = [POINTER(wasm_exporttype_vec_t),c_size_t] + return _wasm_exporttype_vec_new_uninitialized(arg0,arg1) + +def wasm_exporttype_vec_new(arg0,arg1,arg2): + _wasm_exporttype_vec_new = libiwasm.wasm_exporttype_vec_new + _wasm_exporttype_vec_new.restype = None + _wasm_exporttype_vec_new.argtypes = [POINTER(wasm_exporttype_vec_t),c_size_t,POINTER(POINTER(wasm_exporttype_t))] + return _wasm_exporttype_vec_new(arg0,arg1,arg2) + +def wasm_exporttype_vec_copy(arg0,arg1): + _wasm_exporttype_vec_copy = libiwasm.wasm_exporttype_vec_copy + _wasm_exporttype_vec_copy.restype = None + _wasm_exporttype_vec_copy.argtypes = [POINTER(wasm_exporttype_vec_t),POINTER(wasm_exporttype_vec_t)] + return _wasm_exporttype_vec_copy(arg0,arg1) + +def wasm_exporttype_vec_delete(arg0): + _wasm_exporttype_vec_delete = libiwasm.wasm_exporttype_vec_delete + _wasm_exporttype_vec_delete.restype = None + _wasm_exporttype_vec_delete.argtypes = [POINTER(wasm_exporttype_vec_t)] + return _wasm_exporttype_vec_delete(arg0) + +def wasm_exporttype_copy(arg0): + _wasm_exporttype_copy = libiwasm.wasm_exporttype_copy + _wasm_exporttype_copy.restype = POINTER(wasm_exporttype_t) + _wasm_exporttype_copy.argtypes = [POINTER(wasm_exporttype_t)] + return _wasm_exporttype_copy(arg0) + +def wasm_exporttype_new(arg0,arg1): + _wasm_exporttype_new = libiwasm.wasm_exporttype_new + _wasm_exporttype_new.restype = POINTER(wasm_exporttype_t) + _wasm_exporttype_new.argtypes = [POINTER(wasm_name_t),POINTER(wasm_externtype_t)] + return _wasm_exporttype_new(arg0,arg1) + +def wasm_exporttype_name(arg0): + _wasm_exporttype_name = libiwasm.wasm_exporttype_name + _wasm_exporttype_name.restype = POINTER(wasm_name_t) + _wasm_exporttype_name.argtypes = [POINTER(wasm_exporttype_t)] + return _wasm_exporttype_name(arg0) + +def wasm_exporttype_type(arg0): + _wasm_exporttype_type = libiwasm.wasm_exporttype_type + _wasm_exporttype_type.restype = POINTER(wasm_externtype_t) + _wasm_exporttype_type.argtypes = [POINTER(wasm_exporttype_t)] + return _wasm_exporttype_type(arg0) + +def wasm_val_delete(arg0): + _wasm_val_delete = libiwasm.wasm_val_delete + _wasm_val_delete.restype = None + _wasm_val_delete.argtypes = [POINTER(wasm_val_t)] + return _wasm_val_delete(arg0) + +def wasm_val_copy(arg0,arg1): + _wasm_val_copy = libiwasm.wasm_val_copy + _wasm_val_copy.restype = None + _wasm_val_copy.argtypes = [POINTER(wasm_val_t),POINTER(wasm_val_t)] + return _wasm_val_copy(arg0,arg1) + +class wasm_val_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(wasm_val_t)), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_val_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(self.data[i]) + ret += " " + return ret + + + +def wasm_val_vec_new_empty(arg0): + _wasm_val_vec_new_empty = libiwasm.wasm_val_vec_new_empty + _wasm_val_vec_new_empty.restype = None + _wasm_val_vec_new_empty.argtypes = [POINTER(wasm_val_vec_t)] + return _wasm_val_vec_new_empty(arg0) + +def wasm_val_vec_new_uninitialized(arg0,arg1): + _wasm_val_vec_new_uninitialized = libiwasm.wasm_val_vec_new_uninitialized + _wasm_val_vec_new_uninitialized.restype = None + _wasm_val_vec_new_uninitialized.argtypes = [POINTER(wasm_val_vec_t),c_size_t] + return _wasm_val_vec_new_uninitialized(arg0,arg1) + +def wasm_val_vec_new(arg0,arg1,arg2): + _wasm_val_vec_new = libiwasm.wasm_val_vec_new + _wasm_val_vec_new.restype = None + _wasm_val_vec_new.argtypes = [POINTER(wasm_val_vec_t),c_size_t,POINTER(wasm_val_t)] + return _wasm_val_vec_new(arg0,arg1,arg2) + +def wasm_val_vec_copy(arg0,arg1): + _wasm_val_vec_copy = libiwasm.wasm_val_vec_copy + _wasm_val_vec_copy.restype = None + _wasm_val_vec_copy.argtypes = [POINTER(wasm_val_vec_t),POINTER(wasm_val_vec_t)] + return _wasm_val_vec_copy(arg0,arg1) + +def wasm_val_vec_delete(arg0): + _wasm_val_vec_delete = libiwasm.wasm_val_vec_delete + _wasm_val_vec_delete.restype = None + _wasm_val_vec_delete.argtypes = [POINTER(wasm_val_vec_t)] + return _wasm_val_vec_delete(arg0) + +def wasm_ref_delete(arg0): + _wasm_ref_delete = libiwasm.wasm_ref_delete + _wasm_ref_delete.restype = None + _wasm_ref_delete.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_delete(arg0) + +def wasm_ref_copy(arg0): + _wasm_ref_copy = libiwasm.wasm_ref_copy + _wasm_ref_copy.restype = POINTER(wasm_ref_t) + _wasm_ref_copy.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_copy(arg0) + +def wasm_ref_same(arg0,arg1): + _wasm_ref_same = libiwasm.wasm_ref_same + _wasm_ref_same.restype = c_bool + _wasm_ref_same.argtypes = [POINTER(wasm_ref_t),POINTER(wasm_ref_t)] + return _wasm_ref_same(arg0,arg1) + +def wasm_ref_get_host_info(arg0): + _wasm_ref_get_host_info = libiwasm.wasm_ref_get_host_info + _wasm_ref_get_host_info.restype = c_void_p + _wasm_ref_get_host_info.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_get_host_info(arg0) + +def wasm_ref_set_host_info(arg0,arg1): + _wasm_ref_set_host_info = libiwasm.wasm_ref_set_host_info + _wasm_ref_set_host_info.restype = None + _wasm_ref_set_host_info.argtypes = [POINTER(wasm_ref_t),c_void_p] + return _wasm_ref_set_host_info(arg0,arg1) + +def wasm_ref_set_host_info_with_finalizer(arg0,arg1,arg2): + _wasm_ref_set_host_info_with_finalizer = libiwasm.wasm_ref_set_host_info_with_finalizer + _wasm_ref_set_host_info_with_finalizer.restype = None + _wasm_ref_set_host_info_with_finalizer.argtypes = [POINTER(wasm_ref_t),c_void_p,CFUNCTYPE(None,c_void_p)] + return _wasm_ref_set_host_info_with_finalizer(arg0,arg1,arg2) + +class wasm_frame_t(Structure): + pass + +def wasm_frame_delete(arg0): + _wasm_frame_delete = libiwasm.wasm_frame_delete + _wasm_frame_delete.restype = None + _wasm_frame_delete.argtypes = [POINTER(wasm_frame_t)] + return _wasm_frame_delete(arg0) + +class wasm_frame_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_frame_t))), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_frame_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(dereference(self.data[i])) + ret += " " + return ret + + + +def wasm_frame_vec_new_empty(arg0): + _wasm_frame_vec_new_empty = libiwasm.wasm_frame_vec_new_empty + _wasm_frame_vec_new_empty.restype = None + _wasm_frame_vec_new_empty.argtypes = [POINTER(wasm_frame_vec_t)] + return _wasm_frame_vec_new_empty(arg0) + +def wasm_frame_vec_new_uninitialized(arg0,arg1): + _wasm_frame_vec_new_uninitialized = libiwasm.wasm_frame_vec_new_uninitialized + _wasm_frame_vec_new_uninitialized.restype = None + _wasm_frame_vec_new_uninitialized.argtypes = [POINTER(wasm_frame_vec_t),c_size_t] + return _wasm_frame_vec_new_uninitialized(arg0,arg1) + +def wasm_frame_vec_new(arg0,arg1,arg2): + _wasm_frame_vec_new = libiwasm.wasm_frame_vec_new + _wasm_frame_vec_new.restype = None + _wasm_frame_vec_new.argtypes = [POINTER(wasm_frame_vec_t),c_size_t,POINTER(POINTER(wasm_frame_t))] + return _wasm_frame_vec_new(arg0,arg1,arg2) + +def wasm_frame_vec_copy(arg0,arg1): + _wasm_frame_vec_copy = libiwasm.wasm_frame_vec_copy + _wasm_frame_vec_copy.restype = None + _wasm_frame_vec_copy.argtypes = [POINTER(wasm_frame_vec_t),POINTER(wasm_frame_vec_t)] + return _wasm_frame_vec_copy(arg0,arg1) + +def wasm_frame_vec_delete(arg0): + _wasm_frame_vec_delete = libiwasm.wasm_frame_vec_delete + _wasm_frame_vec_delete.restype = None + _wasm_frame_vec_delete.argtypes = [POINTER(wasm_frame_vec_t)] + return _wasm_frame_vec_delete(arg0) + +def wasm_frame_copy(arg0): + _wasm_frame_copy = libiwasm.wasm_frame_copy + _wasm_frame_copy.restype = POINTER(wasm_frame_t) + _wasm_frame_copy.argtypes = [POINTER(wasm_frame_t)] + return _wasm_frame_copy(arg0) + +def wasm_frame_instance(arg0): + _wasm_frame_instance = libiwasm.wasm_frame_instance + _wasm_frame_instance.restype = POINTER(wasm_instance_t) + _wasm_frame_instance.argtypes = [POINTER(wasm_frame_t)] + return _wasm_frame_instance(arg0) + +def wasm_frame_func_index(arg0): + _wasm_frame_func_index = libiwasm.wasm_frame_func_index + _wasm_frame_func_index.restype = c_uint32 + _wasm_frame_func_index.argtypes = [POINTER(wasm_frame_t)] + return _wasm_frame_func_index(arg0) + +def wasm_frame_func_offset(arg0): + _wasm_frame_func_offset = libiwasm.wasm_frame_func_offset + _wasm_frame_func_offset.restype = c_size_t + _wasm_frame_func_offset.argtypes = [POINTER(wasm_frame_t)] + return _wasm_frame_func_offset(arg0) + +def wasm_frame_module_offset(arg0): + _wasm_frame_module_offset = libiwasm.wasm_frame_module_offset + _wasm_frame_module_offset.restype = c_size_t + _wasm_frame_module_offset.argtypes = [POINTER(wasm_frame_t)] + return _wasm_frame_module_offset(arg0) + +wasm_message_t = wasm_name_t + +class wasm_trap_t(Structure): + pass + +def wasm_trap_delete(arg0): + _wasm_trap_delete = libiwasm.wasm_trap_delete + _wasm_trap_delete.restype = None + _wasm_trap_delete.argtypes = [POINTER(wasm_trap_t)] + return _wasm_trap_delete(arg0) + +def wasm_trap_copy(arg0): + _wasm_trap_copy = libiwasm.wasm_trap_copy + _wasm_trap_copy.restype = POINTER(wasm_trap_t) + _wasm_trap_copy.argtypes = [POINTER(wasm_trap_t)] + return _wasm_trap_copy(arg0) + +def wasm_trap_same(arg0,arg1): + _wasm_trap_same = libiwasm.wasm_trap_same + _wasm_trap_same.restype = c_bool + _wasm_trap_same.argtypes = [POINTER(wasm_trap_t),POINTER(wasm_trap_t)] + return _wasm_trap_same(arg0,arg1) + +def wasm_trap_get_host_info(arg0): + _wasm_trap_get_host_info = libiwasm.wasm_trap_get_host_info + _wasm_trap_get_host_info.restype = c_void_p + _wasm_trap_get_host_info.argtypes = [POINTER(wasm_trap_t)] + return _wasm_trap_get_host_info(arg0) + +def wasm_trap_set_host_info(arg0,arg1): + _wasm_trap_set_host_info = libiwasm.wasm_trap_set_host_info + _wasm_trap_set_host_info.restype = None + _wasm_trap_set_host_info.argtypes = [POINTER(wasm_trap_t),c_void_p] + return _wasm_trap_set_host_info(arg0,arg1) + +def wasm_trap_set_host_info_with_finalizer(arg0,arg1,arg2): + _wasm_trap_set_host_info_with_finalizer = libiwasm.wasm_trap_set_host_info_with_finalizer + _wasm_trap_set_host_info_with_finalizer.restype = None + _wasm_trap_set_host_info_with_finalizer.argtypes = [POINTER(wasm_trap_t),c_void_p,CFUNCTYPE(None,c_void_p)] + return _wasm_trap_set_host_info_with_finalizer(arg0,arg1,arg2) + +def wasm_trap_as_ref(arg0): + _wasm_trap_as_ref = libiwasm.wasm_trap_as_ref + _wasm_trap_as_ref.restype = POINTER(wasm_ref_t) + _wasm_trap_as_ref.argtypes = [POINTER(wasm_trap_t)] + return _wasm_trap_as_ref(arg0) + +def wasm_ref_as_trap(arg0): + _wasm_ref_as_trap = libiwasm.wasm_ref_as_trap + _wasm_ref_as_trap.restype = POINTER(wasm_trap_t) + _wasm_ref_as_trap.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_trap(arg0) + +def wasm_trap_as_ref_const(arg0): + _wasm_trap_as_ref_const = libiwasm.wasm_trap_as_ref_const + _wasm_trap_as_ref_const.restype = POINTER(wasm_ref_t) + _wasm_trap_as_ref_const.argtypes = [POINTER(wasm_trap_t)] + return _wasm_trap_as_ref_const(arg0) + +def wasm_ref_as_trap_const(arg0): + _wasm_ref_as_trap_const = libiwasm.wasm_ref_as_trap_const + _wasm_ref_as_trap_const.restype = POINTER(wasm_trap_t) + _wasm_ref_as_trap_const.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_trap_const(arg0) + +def wasm_trap_new(arg0,arg1): + _wasm_trap_new = libiwasm.wasm_trap_new + _wasm_trap_new.restype = POINTER(wasm_trap_t) + _wasm_trap_new.argtypes = [POINTER(wasm_store_t),POINTER(wasm_message_t)] + return _wasm_trap_new(arg0,arg1) + +def wasm_trap_message(arg0,arg1): + _wasm_trap_message = libiwasm.wasm_trap_message + _wasm_trap_message.restype = None + _wasm_trap_message.argtypes = [POINTER(wasm_trap_t),POINTER(wasm_message_t)] + return _wasm_trap_message(arg0,arg1) + +def wasm_trap_origin(arg0): + _wasm_trap_origin = libiwasm.wasm_trap_origin + _wasm_trap_origin.restype = POINTER(wasm_frame_t) + _wasm_trap_origin.argtypes = [POINTER(wasm_trap_t)] + return _wasm_trap_origin(arg0) + +def wasm_trap_trace(arg0,arg1): + _wasm_trap_trace = libiwasm.wasm_trap_trace + _wasm_trap_trace.restype = None + _wasm_trap_trace.argtypes = [POINTER(wasm_trap_t),POINTER(wasm_frame_vec_t)] + return _wasm_trap_trace(arg0,arg1) + +class wasm_foreign_t(Structure): + pass + +def wasm_foreign_delete(arg0): + _wasm_foreign_delete = libiwasm.wasm_foreign_delete + _wasm_foreign_delete.restype = None + _wasm_foreign_delete.argtypes = [POINTER(wasm_foreign_t)] + return _wasm_foreign_delete(arg0) + +def wasm_foreign_copy(arg0): + _wasm_foreign_copy = libiwasm.wasm_foreign_copy + _wasm_foreign_copy.restype = POINTER(wasm_foreign_t) + _wasm_foreign_copy.argtypes = [POINTER(wasm_foreign_t)] + return _wasm_foreign_copy(arg0) + +def wasm_foreign_same(arg0,arg1): + _wasm_foreign_same = libiwasm.wasm_foreign_same + _wasm_foreign_same.restype = c_bool + _wasm_foreign_same.argtypes = [POINTER(wasm_foreign_t),POINTER(wasm_foreign_t)] + return _wasm_foreign_same(arg0,arg1) + +def wasm_foreign_get_host_info(arg0): + _wasm_foreign_get_host_info = libiwasm.wasm_foreign_get_host_info + _wasm_foreign_get_host_info.restype = c_void_p + _wasm_foreign_get_host_info.argtypes = [POINTER(wasm_foreign_t)] + return _wasm_foreign_get_host_info(arg0) + +def wasm_foreign_set_host_info(arg0,arg1): + _wasm_foreign_set_host_info = libiwasm.wasm_foreign_set_host_info + _wasm_foreign_set_host_info.restype = None + _wasm_foreign_set_host_info.argtypes = [POINTER(wasm_foreign_t),c_void_p] + return _wasm_foreign_set_host_info(arg0,arg1) + +def wasm_foreign_set_host_info_with_finalizer(arg0,arg1,arg2): + _wasm_foreign_set_host_info_with_finalizer = libiwasm.wasm_foreign_set_host_info_with_finalizer + _wasm_foreign_set_host_info_with_finalizer.restype = None + _wasm_foreign_set_host_info_with_finalizer.argtypes = [POINTER(wasm_foreign_t),c_void_p,CFUNCTYPE(None,c_void_p)] + return _wasm_foreign_set_host_info_with_finalizer(arg0,arg1,arg2) + +def wasm_foreign_as_ref(arg0): + _wasm_foreign_as_ref = libiwasm.wasm_foreign_as_ref + _wasm_foreign_as_ref.restype = POINTER(wasm_ref_t) + _wasm_foreign_as_ref.argtypes = [POINTER(wasm_foreign_t)] + return _wasm_foreign_as_ref(arg0) + +def wasm_ref_as_foreign(arg0): + _wasm_ref_as_foreign = libiwasm.wasm_ref_as_foreign + _wasm_ref_as_foreign.restype = POINTER(wasm_foreign_t) + _wasm_ref_as_foreign.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_foreign(arg0) + +def wasm_foreign_as_ref_const(arg0): + _wasm_foreign_as_ref_const = libiwasm.wasm_foreign_as_ref_const + _wasm_foreign_as_ref_const.restype = POINTER(wasm_ref_t) + _wasm_foreign_as_ref_const.argtypes = [POINTER(wasm_foreign_t)] + return _wasm_foreign_as_ref_const(arg0) + +def wasm_ref_as_foreign_const(arg0): + _wasm_ref_as_foreign_const = libiwasm.wasm_ref_as_foreign_const + _wasm_ref_as_foreign_const.restype = POINTER(wasm_foreign_t) + _wasm_ref_as_foreign_const.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_foreign_const(arg0) + +def wasm_foreign_new(arg0): + _wasm_foreign_new = libiwasm.wasm_foreign_new + _wasm_foreign_new.restype = POINTER(wasm_foreign_t) + _wasm_foreign_new.argtypes = [POINTER(wasm_store_t)] + return _wasm_foreign_new(arg0) + +class WASMModuleCommon(Structure): + pass + +class WASMModuleCommon(Structure): + pass + +wasm_module_t = POINTER(WASMModuleCommon) + +def wasm_module_new(arg0,arg1): + _wasm_module_new = libiwasm.wasm_module_new + _wasm_module_new.restype = POINTER(wasm_module_t) + _wasm_module_new.argtypes = [POINTER(wasm_store_t),POINTER(wasm_byte_vec_t)] + return _wasm_module_new(arg0,arg1) + +def wasm_module_delete(arg0): + _wasm_module_delete = libiwasm.wasm_module_delete + _wasm_module_delete.restype = None + _wasm_module_delete.argtypes = [POINTER(wasm_module_t)] + return _wasm_module_delete(arg0) + +def wasm_module_validate(arg0,arg1): + _wasm_module_validate = libiwasm.wasm_module_validate + _wasm_module_validate.restype = c_bool + _wasm_module_validate.argtypes = [POINTER(wasm_store_t),POINTER(wasm_byte_vec_t)] + return _wasm_module_validate(arg0,arg1) + +def wasm_module_imports(arg0,arg1): + _wasm_module_imports = libiwasm.wasm_module_imports + _wasm_module_imports.restype = None + _wasm_module_imports.argtypes = [POINTER(wasm_module_t),POINTER(wasm_importtype_vec_t)] + return _wasm_module_imports(arg0,arg1) + +def wasm_module_exports(arg0,arg1): + _wasm_module_exports = libiwasm.wasm_module_exports + _wasm_module_exports.restype = None + _wasm_module_exports.argtypes = [POINTER(wasm_module_t),POINTER(wasm_exporttype_vec_t)] + return _wasm_module_exports(arg0,arg1) + +def wasm_module_serialize(arg0,arg1): + _wasm_module_serialize = libiwasm.wasm_module_serialize + _wasm_module_serialize.restype = None + _wasm_module_serialize.argtypes = [POINTER(wasm_module_t),POINTER(wasm_byte_vec_t)] + return _wasm_module_serialize(arg0,arg1) + +def wasm_module_deserialize(arg0,arg1): + _wasm_module_deserialize = libiwasm.wasm_module_deserialize + _wasm_module_deserialize.restype = POINTER(wasm_module_t) + _wasm_module_deserialize.argtypes = [POINTER(wasm_store_t),POINTER(wasm_byte_vec_t)] + return _wasm_module_deserialize(arg0,arg1) + +class wasm_func_t(Structure): + pass + +def wasm_func_delete(arg0): + _wasm_func_delete = libiwasm.wasm_func_delete + _wasm_func_delete.restype = None + _wasm_func_delete.argtypes = [POINTER(wasm_func_t)] + return _wasm_func_delete(arg0) + +def wasm_func_copy(arg0): + _wasm_func_copy = libiwasm.wasm_func_copy + _wasm_func_copy.restype = POINTER(wasm_func_t) + _wasm_func_copy.argtypes = [POINTER(wasm_func_t)] + return _wasm_func_copy(arg0) + +def wasm_func_same(arg0,arg1): + _wasm_func_same = libiwasm.wasm_func_same + _wasm_func_same.restype = c_bool + _wasm_func_same.argtypes = [POINTER(wasm_func_t),POINTER(wasm_func_t)] + return _wasm_func_same(arg0,arg1) + +def wasm_func_get_host_info(arg0): + _wasm_func_get_host_info = libiwasm.wasm_func_get_host_info + _wasm_func_get_host_info.restype = c_void_p + _wasm_func_get_host_info.argtypes = [POINTER(wasm_func_t)] + return _wasm_func_get_host_info(arg0) + +def wasm_func_set_host_info(arg0,arg1): + _wasm_func_set_host_info = libiwasm.wasm_func_set_host_info + _wasm_func_set_host_info.restype = None + _wasm_func_set_host_info.argtypes = [POINTER(wasm_func_t),c_void_p] + return _wasm_func_set_host_info(arg0,arg1) + +def wasm_func_set_host_info_with_finalizer(arg0,arg1,arg2): + _wasm_func_set_host_info_with_finalizer = libiwasm.wasm_func_set_host_info_with_finalizer + _wasm_func_set_host_info_with_finalizer.restype = None + _wasm_func_set_host_info_with_finalizer.argtypes = [POINTER(wasm_func_t),c_void_p,CFUNCTYPE(None,c_void_p)] + return _wasm_func_set_host_info_with_finalizer(arg0,arg1,arg2) + +def wasm_func_as_ref(arg0): + _wasm_func_as_ref = libiwasm.wasm_func_as_ref + _wasm_func_as_ref.restype = POINTER(wasm_ref_t) + _wasm_func_as_ref.argtypes = [POINTER(wasm_func_t)] + return _wasm_func_as_ref(arg0) + +def wasm_ref_as_func(arg0): + _wasm_ref_as_func = libiwasm.wasm_ref_as_func + _wasm_ref_as_func.restype = POINTER(wasm_func_t) + _wasm_ref_as_func.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_func(arg0) + +def wasm_func_as_ref_const(arg0): + _wasm_func_as_ref_const = libiwasm.wasm_func_as_ref_const + _wasm_func_as_ref_const.restype = POINTER(wasm_ref_t) + _wasm_func_as_ref_const.argtypes = [POINTER(wasm_func_t)] + return _wasm_func_as_ref_const(arg0) + +def wasm_ref_as_func_const(arg0): + _wasm_ref_as_func_const = libiwasm.wasm_ref_as_func_const + _wasm_ref_as_func_const.restype = POINTER(wasm_func_t) + _wasm_ref_as_func_const.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_func_const(arg0) + +wasm_func_callback_t = CFUNCTYPE(c_void_p,POINTER(wasm_val_vec_t),POINTER(wasm_val_vec_t)) + +wasm_func_callback_with_env_t = CFUNCTYPE(c_void_p,c_void_p,POINTER(wasm_val_vec_t),POINTER(wasm_val_vec_t)) + +def wasm_func_new(arg0,arg1,arg2): + _wasm_func_new = libiwasm.wasm_func_new + _wasm_func_new.restype = POINTER(wasm_func_t) + _wasm_func_new.argtypes = [POINTER(wasm_store_t),POINTER(wasm_functype_t),wasm_func_callback_t] + return _wasm_func_new(arg0,arg1,arg2) + +def wasm_func_new_with_env(arg0,arg1,arg2,arg3,arg4): + _wasm_func_new_with_env = libiwasm.wasm_func_new_with_env + _wasm_func_new_with_env.restype = POINTER(wasm_func_t) + _wasm_func_new_with_env.argtypes = [POINTER(wasm_store_t),POINTER(wasm_functype_t),wasm_func_callback_with_env_t,c_void_p,CFUNCTYPE(None,c_void_p)] + return _wasm_func_new_with_env(arg0,arg1,arg2,arg3,arg4) + +def wasm_func_type(arg0): + _wasm_func_type = libiwasm.wasm_func_type + _wasm_func_type.restype = POINTER(wasm_functype_t) + _wasm_func_type.argtypes = [POINTER(wasm_func_t)] + return _wasm_func_type(arg0) + +def wasm_func_param_arity(arg0): + _wasm_func_param_arity = libiwasm.wasm_func_param_arity + _wasm_func_param_arity.restype = c_size_t + _wasm_func_param_arity.argtypes = [POINTER(wasm_func_t)] + return _wasm_func_param_arity(arg0) + +def wasm_func_result_arity(arg0): + _wasm_func_result_arity = libiwasm.wasm_func_result_arity + _wasm_func_result_arity.restype = c_size_t + _wasm_func_result_arity.argtypes = [POINTER(wasm_func_t)] + return _wasm_func_result_arity(arg0) + +def wasm_func_call(arg0,arg1,arg2): + _wasm_func_call = libiwasm.wasm_func_call + _wasm_func_call.restype = POINTER(wasm_trap_t) + _wasm_func_call.argtypes = [POINTER(wasm_func_t),POINTER(wasm_val_vec_t),POINTER(wasm_val_vec_t)] + return _wasm_func_call(arg0,arg1,arg2) + +class wasm_global_t(Structure): + pass + +def wasm_global_delete(arg0): + _wasm_global_delete = libiwasm.wasm_global_delete + _wasm_global_delete.restype = None + _wasm_global_delete.argtypes = [POINTER(wasm_global_t)] + return _wasm_global_delete(arg0) + +def wasm_global_copy(arg0): + _wasm_global_copy = libiwasm.wasm_global_copy + _wasm_global_copy.restype = POINTER(wasm_global_t) + _wasm_global_copy.argtypes = [POINTER(wasm_global_t)] + return _wasm_global_copy(arg0) + +def wasm_global_same(arg0,arg1): + _wasm_global_same = libiwasm.wasm_global_same + _wasm_global_same.restype = c_bool + _wasm_global_same.argtypes = [POINTER(wasm_global_t),POINTER(wasm_global_t)] + return _wasm_global_same(arg0,arg1) + +def wasm_global_get_host_info(arg0): + _wasm_global_get_host_info = libiwasm.wasm_global_get_host_info + _wasm_global_get_host_info.restype = c_void_p + _wasm_global_get_host_info.argtypes = [POINTER(wasm_global_t)] + return _wasm_global_get_host_info(arg0) + +def wasm_global_set_host_info(arg0,arg1): + _wasm_global_set_host_info = libiwasm.wasm_global_set_host_info + _wasm_global_set_host_info.restype = None + _wasm_global_set_host_info.argtypes = [POINTER(wasm_global_t),c_void_p] + return _wasm_global_set_host_info(arg0,arg1) + +def wasm_global_set_host_info_with_finalizer(arg0,arg1,arg2): + _wasm_global_set_host_info_with_finalizer = libiwasm.wasm_global_set_host_info_with_finalizer + _wasm_global_set_host_info_with_finalizer.restype = None + _wasm_global_set_host_info_with_finalizer.argtypes = [POINTER(wasm_global_t),c_void_p,CFUNCTYPE(None,c_void_p)] + return _wasm_global_set_host_info_with_finalizer(arg0,arg1,arg2) + +def wasm_global_as_ref(arg0): + _wasm_global_as_ref = libiwasm.wasm_global_as_ref + _wasm_global_as_ref.restype = POINTER(wasm_ref_t) + _wasm_global_as_ref.argtypes = [POINTER(wasm_global_t)] + return _wasm_global_as_ref(arg0) + +def wasm_ref_as_global(arg0): + _wasm_ref_as_global = libiwasm.wasm_ref_as_global + _wasm_ref_as_global.restype = POINTER(wasm_global_t) + _wasm_ref_as_global.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_global(arg0) + +def wasm_global_as_ref_const(arg0): + _wasm_global_as_ref_const = libiwasm.wasm_global_as_ref_const + _wasm_global_as_ref_const.restype = POINTER(wasm_ref_t) + _wasm_global_as_ref_const.argtypes = [POINTER(wasm_global_t)] + return _wasm_global_as_ref_const(arg0) + +def wasm_ref_as_global_const(arg0): + _wasm_ref_as_global_const = libiwasm.wasm_ref_as_global_const + _wasm_ref_as_global_const.restype = POINTER(wasm_global_t) + _wasm_ref_as_global_const.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_global_const(arg0) + +def wasm_global_new(arg0,arg1,arg2): + _wasm_global_new = libiwasm.wasm_global_new + _wasm_global_new.restype = POINTER(wasm_global_t) + _wasm_global_new.argtypes = [POINTER(wasm_store_t),POINTER(wasm_globaltype_t),POINTER(wasm_val_t)] + return _wasm_global_new(arg0,arg1,arg2) + +def wasm_global_type(arg0): + _wasm_global_type = libiwasm.wasm_global_type + _wasm_global_type.restype = POINTER(wasm_globaltype_t) + _wasm_global_type.argtypes = [POINTER(wasm_global_t)] + return _wasm_global_type(arg0) + +def wasm_global_get(arg0,arg1): + _wasm_global_get = libiwasm.wasm_global_get + _wasm_global_get.restype = None + _wasm_global_get.argtypes = [POINTER(wasm_global_t),POINTER(wasm_val_t)] + return _wasm_global_get(arg0,arg1) + +def wasm_global_set(arg0,arg1): + _wasm_global_set = libiwasm.wasm_global_set + _wasm_global_set.restype = None + _wasm_global_set.argtypes = [POINTER(wasm_global_t),POINTER(wasm_val_t)] + return _wasm_global_set(arg0,arg1) + +class wasm_table_t(Structure): + pass + +def wasm_table_delete(arg0): + _wasm_table_delete = libiwasm.wasm_table_delete + _wasm_table_delete.restype = None + _wasm_table_delete.argtypes = [POINTER(wasm_table_t)] + return _wasm_table_delete(arg0) + +def wasm_table_copy(arg0): + _wasm_table_copy = libiwasm.wasm_table_copy + _wasm_table_copy.restype = POINTER(wasm_table_t) + _wasm_table_copy.argtypes = [POINTER(wasm_table_t)] + return _wasm_table_copy(arg0) + +def wasm_table_same(arg0,arg1): + _wasm_table_same = libiwasm.wasm_table_same + _wasm_table_same.restype = c_bool + _wasm_table_same.argtypes = [POINTER(wasm_table_t),POINTER(wasm_table_t)] + return _wasm_table_same(arg0,arg1) + +def wasm_table_get_host_info(arg0): + _wasm_table_get_host_info = libiwasm.wasm_table_get_host_info + _wasm_table_get_host_info.restype = c_void_p + _wasm_table_get_host_info.argtypes = [POINTER(wasm_table_t)] + return _wasm_table_get_host_info(arg0) + +def wasm_table_set_host_info(arg0,arg1): + _wasm_table_set_host_info = libiwasm.wasm_table_set_host_info + _wasm_table_set_host_info.restype = None + _wasm_table_set_host_info.argtypes = [POINTER(wasm_table_t),c_void_p] + return _wasm_table_set_host_info(arg0,arg1) + +def wasm_table_set_host_info_with_finalizer(arg0,arg1,arg2): + _wasm_table_set_host_info_with_finalizer = libiwasm.wasm_table_set_host_info_with_finalizer + _wasm_table_set_host_info_with_finalizer.restype = None + _wasm_table_set_host_info_with_finalizer.argtypes = [POINTER(wasm_table_t),c_void_p,CFUNCTYPE(None,c_void_p)] + return _wasm_table_set_host_info_with_finalizer(arg0,arg1,arg2) + +def wasm_table_as_ref(arg0): + _wasm_table_as_ref = libiwasm.wasm_table_as_ref + _wasm_table_as_ref.restype = POINTER(wasm_ref_t) + _wasm_table_as_ref.argtypes = [POINTER(wasm_table_t)] + return _wasm_table_as_ref(arg0) + +def wasm_ref_as_table(arg0): + _wasm_ref_as_table = libiwasm.wasm_ref_as_table + _wasm_ref_as_table.restype = POINTER(wasm_table_t) + _wasm_ref_as_table.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_table(arg0) + +def wasm_table_as_ref_const(arg0): + _wasm_table_as_ref_const = libiwasm.wasm_table_as_ref_const + _wasm_table_as_ref_const.restype = POINTER(wasm_ref_t) + _wasm_table_as_ref_const.argtypes = [POINTER(wasm_table_t)] + return _wasm_table_as_ref_const(arg0) + +def wasm_ref_as_table_const(arg0): + _wasm_ref_as_table_const = libiwasm.wasm_ref_as_table_const + _wasm_ref_as_table_const.restype = POINTER(wasm_table_t) + _wasm_ref_as_table_const.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_table_const(arg0) + +wasm_table_size_t = c_uint32 + +def wasm_table_new(arg0,arg1,arg2): + _wasm_table_new = libiwasm.wasm_table_new + _wasm_table_new.restype = POINTER(wasm_table_t) + _wasm_table_new.argtypes = [POINTER(wasm_store_t),POINTER(wasm_tabletype_t),POINTER(wasm_ref_t)] + return _wasm_table_new(arg0,arg1,arg2) + +def wasm_table_type(arg0): + _wasm_table_type = libiwasm.wasm_table_type + _wasm_table_type.restype = POINTER(wasm_tabletype_t) + _wasm_table_type.argtypes = [POINTER(wasm_table_t)] + return _wasm_table_type(arg0) + +def wasm_table_get(arg0,arg1): + _wasm_table_get = libiwasm.wasm_table_get + _wasm_table_get.restype = POINTER(wasm_ref_t) + _wasm_table_get.argtypes = [POINTER(wasm_table_t),wasm_table_size_t] + return _wasm_table_get(arg0,arg1) + +def wasm_table_set(arg0,arg1,arg2): + _wasm_table_set = libiwasm.wasm_table_set + _wasm_table_set.restype = c_bool + _wasm_table_set.argtypes = [POINTER(wasm_table_t),wasm_table_size_t,POINTER(wasm_ref_t)] + return _wasm_table_set(arg0,arg1,arg2) + +def wasm_table_size(arg0): + _wasm_table_size = libiwasm.wasm_table_size + _wasm_table_size.restype = wasm_table_size_t + _wasm_table_size.argtypes = [POINTER(wasm_table_t)] + return _wasm_table_size(arg0) + +def wasm_table_grow(arg0,arg1,arg2): + _wasm_table_grow = libiwasm.wasm_table_grow + _wasm_table_grow.restype = c_bool + _wasm_table_grow.argtypes = [POINTER(wasm_table_t),wasm_table_size_t,POINTER(wasm_ref_t)] + return _wasm_table_grow(arg0,arg1,arg2) + +class wasm_memory_t(Structure): + pass + +def wasm_memory_delete(arg0): + _wasm_memory_delete = libiwasm.wasm_memory_delete + _wasm_memory_delete.restype = None + _wasm_memory_delete.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_delete(arg0) + +def wasm_memory_copy(arg0): + _wasm_memory_copy = libiwasm.wasm_memory_copy + _wasm_memory_copy.restype = POINTER(wasm_memory_t) + _wasm_memory_copy.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_copy(arg0) + +def wasm_memory_same(arg0,arg1): + _wasm_memory_same = libiwasm.wasm_memory_same + _wasm_memory_same.restype = c_bool + _wasm_memory_same.argtypes = [POINTER(wasm_memory_t),POINTER(wasm_memory_t)] + return _wasm_memory_same(arg0,arg1) + +def wasm_memory_get_host_info(arg0): + _wasm_memory_get_host_info = libiwasm.wasm_memory_get_host_info + _wasm_memory_get_host_info.restype = c_void_p + _wasm_memory_get_host_info.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_get_host_info(arg0) + +def wasm_memory_set_host_info(arg0,arg1): + _wasm_memory_set_host_info = libiwasm.wasm_memory_set_host_info + _wasm_memory_set_host_info.restype = None + _wasm_memory_set_host_info.argtypes = [POINTER(wasm_memory_t),c_void_p] + return _wasm_memory_set_host_info(arg0,arg1) + +def wasm_memory_set_host_info_with_finalizer(arg0,arg1,arg2): + _wasm_memory_set_host_info_with_finalizer = libiwasm.wasm_memory_set_host_info_with_finalizer + _wasm_memory_set_host_info_with_finalizer.restype = None + _wasm_memory_set_host_info_with_finalizer.argtypes = [POINTER(wasm_memory_t),c_void_p,CFUNCTYPE(None,c_void_p)] + return _wasm_memory_set_host_info_with_finalizer(arg0,arg1,arg2) + +def wasm_memory_as_ref(arg0): + _wasm_memory_as_ref = libiwasm.wasm_memory_as_ref + _wasm_memory_as_ref.restype = POINTER(wasm_ref_t) + _wasm_memory_as_ref.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_as_ref(arg0) + +def wasm_ref_as_memory(arg0): + _wasm_ref_as_memory = libiwasm.wasm_ref_as_memory + _wasm_ref_as_memory.restype = POINTER(wasm_memory_t) + _wasm_ref_as_memory.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_memory(arg0) + +def wasm_memory_as_ref_const(arg0): + _wasm_memory_as_ref_const = libiwasm.wasm_memory_as_ref_const + _wasm_memory_as_ref_const.restype = POINTER(wasm_ref_t) + _wasm_memory_as_ref_const.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_as_ref_const(arg0) + +def wasm_ref_as_memory_const(arg0): + _wasm_ref_as_memory_const = libiwasm.wasm_ref_as_memory_const + _wasm_ref_as_memory_const.restype = POINTER(wasm_memory_t) + _wasm_ref_as_memory_const.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_memory_const(arg0) + +wasm_memory_pages_t = c_uint32 + +def wasm_memory_new(arg0,arg1): + _wasm_memory_new = libiwasm.wasm_memory_new + _wasm_memory_new.restype = POINTER(wasm_memory_t) + _wasm_memory_new.argtypes = [POINTER(wasm_store_t),POINTER(wasm_memorytype_t)] + return _wasm_memory_new(arg0,arg1) + +def wasm_memory_type(arg0): + _wasm_memory_type = libiwasm.wasm_memory_type + _wasm_memory_type.restype = POINTER(wasm_memorytype_t) + _wasm_memory_type.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_type(arg0) + +def wasm_memory_data(arg0): + _wasm_memory_data = libiwasm.wasm_memory_data + _wasm_memory_data.restype = POINTER(c_ubyte) + _wasm_memory_data.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_data(arg0) + +def wasm_memory_data_size(arg0): + _wasm_memory_data_size = libiwasm.wasm_memory_data_size + _wasm_memory_data_size.restype = c_size_t + _wasm_memory_data_size.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_data_size(arg0) + +def wasm_memory_size(arg0): + _wasm_memory_size = libiwasm.wasm_memory_size + _wasm_memory_size.restype = wasm_memory_pages_t + _wasm_memory_size.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_size(arg0) + +def wasm_memory_grow(arg0,arg1): + _wasm_memory_grow = libiwasm.wasm_memory_grow + _wasm_memory_grow.restype = c_bool + _wasm_memory_grow.argtypes = [POINTER(wasm_memory_t),wasm_memory_pages_t] + return _wasm_memory_grow(arg0,arg1) + +class wasm_extern_t(Structure): + pass + +def wasm_extern_delete(arg0): + _wasm_extern_delete = libiwasm.wasm_extern_delete + _wasm_extern_delete.restype = None + _wasm_extern_delete.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_delete(arg0) + +def wasm_extern_copy(arg0): + _wasm_extern_copy = libiwasm.wasm_extern_copy + _wasm_extern_copy.restype = POINTER(wasm_extern_t) + _wasm_extern_copy.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_copy(arg0) + +def wasm_extern_same(arg0,arg1): + _wasm_extern_same = libiwasm.wasm_extern_same + _wasm_extern_same.restype = c_bool + _wasm_extern_same.argtypes = [POINTER(wasm_extern_t),POINTER(wasm_extern_t)] + return _wasm_extern_same(arg0,arg1) + +def wasm_extern_get_host_info(arg0): + _wasm_extern_get_host_info = libiwasm.wasm_extern_get_host_info + _wasm_extern_get_host_info.restype = c_void_p + _wasm_extern_get_host_info.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_get_host_info(arg0) + +def wasm_extern_set_host_info(arg0,arg1): + _wasm_extern_set_host_info = libiwasm.wasm_extern_set_host_info + _wasm_extern_set_host_info.restype = None + _wasm_extern_set_host_info.argtypes = [POINTER(wasm_extern_t),c_void_p] + return _wasm_extern_set_host_info(arg0,arg1) + +def wasm_extern_set_host_info_with_finalizer(arg0,arg1,arg2): + _wasm_extern_set_host_info_with_finalizer = libiwasm.wasm_extern_set_host_info_with_finalizer + _wasm_extern_set_host_info_with_finalizer.restype = None + _wasm_extern_set_host_info_with_finalizer.argtypes = [POINTER(wasm_extern_t),c_void_p,CFUNCTYPE(None,c_void_p)] + return _wasm_extern_set_host_info_with_finalizer(arg0,arg1,arg2) + +def wasm_extern_as_ref(arg0): + _wasm_extern_as_ref = libiwasm.wasm_extern_as_ref + _wasm_extern_as_ref.restype = POINTER(wasm_ref_t) + _wasm_extern_as_ref.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_as_ref(arg0) + +def wasm_ref_as_extern(arg0): + _wasm_ref_as_extern = libiwasm.wasm_ref_as_extern + _wasm_ref_as_extern.restype = POINTER(wasm_extern_t) + _wasm_ref_as_extern.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_extern(arg0) + +def wasm_extern_as_ref_const(arg0): + _wasm_extern_as_ref_const = libiwasm.wasm_extern_as_ref_const + _wasm_extern_as_ref_const.restype = POINTER(wasm_ref_t) + _wasm_extern_as_ref_const.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_as_ref_const(arg0) + +def wasm_ref_as_extern_const(arg0): + _wasm_ref_as_extern_const = libiwasm.wasm_ref_as_extern_const + _wasm_ref_as_extern_const.restype = POINTER(wasm_extern_t) + _wasm_ref_as_extern_const.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_extern_const(arg0) + +class wasm_extern_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_extern_t))), + ("num_elems", c_size_t), + ("size_of_elem", c_size_t), + ("lock", c_void_p), + ] + + def __eq__(self, other): + if not isinstance(other, wasm_extern_vec_t): + return False + return self.size == other.size and self.num_elems == other.num_elems and self.size_of_elem == other.size_of_elem + + def __repr__(self): + ret = "" + for i in range(self.num_elems): + ret += str(dereference(self.data[i])) + ret += " " + return ret + + + +def wasm_extern_vec_new_empty(arg0): + _wasm_extern_vec_new_empty = libiwasm.wasm_extern_vec_new_empty + _wasm_extern_vec_new_empty.restype = None + _wasm_extern_vec_new_empty.argtypes = [POINTER(wasm_extern_vec_t)] + return _wasm_extern_vec_new_empty(arg0) + +def wasm_extern_vec_new_uninitialized(arg0,arg1): + _wasm_extern_vec_new_uninitialized = libiwasm.wasm_extern_vec_new_uninitialized + _wasm_extern_vec_new_uninitialized.restype = None + _wasm_extern_vec_new_uninitialized.argtypes = [POINTER(wasm_extern_vec_t),c_size_t] + return _wasm_extern_vec_new_uninitialized(arg0,arg1) + +def wasm_extern_vec_new(arg0,arg1,arg2): + _wasm_extern_vec_new = libiwasm.wasm_extern_vec_new + _wasm_extern_vec_new.restype = None + _wasm_extern_vec_new.argtypes = [POINTER(wasm_extern_vec_t),c_size_t,POINTER(POINTER(wasm_extern_t))] + return _wasm_extern_vec_new(arg0,arg1,arg2) + +def wasm_extern_vec_copy(arg0,arg1): + _wasm_extern_vec_copy = libiwasm.wasm_extern_vec_copy + _wasm_extern_vec_copy.restype = None + _wasm_extern_vec_copy.argtypes = [POINTER(wasm_extern_vec_t),POINTER(wasm_extern_vec_t)] + return _wasm_extern_vec_copy(arg0,arg1) + +def wasm_extern_vec_delete(arg0): + _wasm_extern_vec_delete = libiwasm.wasm_extern_vec_delete + _wasm_extern_vec_delete.restype = None + _wasm_extern_vec_delete.argtypes = [POINTER(wasm_extern_vec_t)] + return _wasm_extern_vec_delete(arg0) + +def wasm_extern_kind(arg0): + _wasm_extern_kind = libiwasm.wasm_extern_kind + _wasm_extern_kind.restype = wasm_externkind_t + _wasm_extern_kind.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_kind(arg0) + +def wasm_extern_type(arg0): + _wasm_extern_type = libiwasm.wasm_extern_type + _wasm_extern_type.restype = POINTER(wasm_externtype_t) + _wasm_extern_type.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_type(arg0) + +def wasm_func_as_extern(arg0): + _wasm_func_as_extern = libiwasm.wasm_func_as_extern + _wasm_func_as_extern.restype = POINTER(wasm_extern_t) + _wasm_func_as_extern.argtypes = [POINTER(wasm_func_t)] + return _wasm_func_as_extern(arg0) + +def wasm_global_as_extern(arg0): + _wasm_global_as_extern = libiwasm.wasm_global_as_extern + _wasm_global_as_extern.restype = POINTER(wasm_extern_t) + _wasm_global_as_extern.argtypes = [POINTER(wasm_global_t)] + return _wasm_global_as_extern(arg0) + +def wasm_table_as_extern(arg0): + _wasm_table_as_extern = libiwasm.wasm_table_as_extern + _wasm_table_as_extern.restype = POINTER(wasm_extern_t) + _wasm_table_as_extern.argtypes = [POINTER(wasm_table_t)] + return _wasm_table_as_extern(arg0) + +def wasm_memory_as_extern(arg0): + _wasm_memory_as_extern = libiwasm.wasm_memory_as_extern + _wasm_memory_as_extern.restype = POINTER(wasm_extern_t) + _wasm_memory_as_extern.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_as_extern(arg0) + +def wasm_extern_as_func(arg0): + _wasm_extern_as_func = libiwasm.wasm_extern_as_func + _wasm_extern_as_func.restype = POINTER(wasm_func_t) + _wasm_extern_as_func.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_as_func(arg0) + +def wasm_extern_as_global(arg0): + _wasm_extern_as_global = libiwasm.wasm_extern_as_global + _wasm_extern_as_global.restype = POINTER(wasm_global_t) + _wasm_extern_as_global.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_as_global(arg0) + +def wasm_extern_as_table(arg0): + _wasm_extern_as_table = libiwasm.wasm_extern_as_table + _wasm_extern_as_table.restype = POINTER(wasm_table_t) + _wasm_extern_as_table.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_as_table(arg0) + +def wasm_extern_as_memory(arg0): + _wasm_extern_as_memory = libiwasm.wasm_extern_as_memory + _wasm_extern_as_memory.restype = POINTER(wasm_memory_t) + _wasm_extern_as_memory.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_as_memory(arg0) + +def wasm_func_as_extern_const(arg0): + _wasm_func_as_extern_const = libiwasm.wasm_func_as_extern_const + _wasm_func_as_extern_const.restype = POINTER(wasm_extern_t) + _wasm_func_as_extern_const.argtypes = [POINTER(wasm_func_t)] + return _wasm_func_as_extern_const(arg0) + +def wasm_global_as_extern_const(arg0): + _wasm_global_as_extern_const = libiwasm.wasm_global_as_extern_const + _wasm_global_as_extern_const.restype = POINTER(wasm_extern_t) + _wasm_global_as_extern_const.argtypes = [POINTER(wasm_global_t)] + return _wasm_global_as_extern_const(arg0) + +def wasm_table_as_extern_const(arg0): + _wasm_table_as_extern_const = libiwasm.wasm_table_as_extern_const + _wasm_table_as_extern_const.restype = POINTER(wasm_extern_t) + _wasm_table_as_extern_const.argtypes = [POINTER(wasm_table_t)] + return _wasm_table_as_extern_const(arg0) + +def wasm_memory_as_extern_const(arg0): + _wasm_memory_as_extern_const = libiwasm.wasm_memory_as_extern_const + _wasm_memory_as_extern_const.restype = POINTER(wasm_extern_t) + _wasm_memory_as_extern_const.argtypes = [POINTER(wasm_memory_t)] + return _wasm_memory_as_extern_const(arg0) + +def wasm_extern_as_func_const(arg0): + _wasm_extern_as_func_const = libiwasm.wasm_extern_as_func_const + _wasm_extern_as_func_const.restype = POINTER(wasm_func_t) + _wasm_extern_as_func_const.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_as_func_const(arg0) + +def wasm_extern_as_global_const(arg0): + _wasm_extern_as_global_const = libiwasm.wasm_extern_as_global_const + _wasm_extern_as_global_const.restype = POINTER(wasm_global_t) + _wasm_extern_as_global_const.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_as_global_const(arg0) + +def wasm_extern_as_table_const(arg0): + _wasm_extern_as_table_const = libiwasm.wasm_extern_as_table_const + _wasm_extern_as_table_const.restype = POINTER(wasm_table_t) + _wasm_extern_as_table_const.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_as_table_const(arg0) + +def wasm_extern_as_memory_const(arg0): + _wasm_extern_as_memory_const = libiwasm.wasm_extern_as_memory_const + _wasm_extern_as_memory_const.restype = POINTER(wasm_memory_t) + _wasm_extern_as_memory_const.argtypes = [POINTER(wasm_extern_t)] + return _wasm_extern_as_memory_const(arg0) + +class wasm_instance_t(Structure): + pass + +def wasm_instance_delete(arg0): + _wasm_instance_delete = libiwasm.wasm_instance_delete + _wasm_instance_delete.restype = None + _wasm_instance_delete.argtypes = [POINTER(wasm_instance_t)] + return _wasm_instance_delete(arg0) + +def wasm_instance_copy(arg0): + _wasm_instance_copy = libiwasm.wasm_instance_copy + _wasm_instance_copy.restype = POINTER(wasm_instance_t) + _wasm_instance_copy.argtypes = [POINTER(wasm_instance_t)] + return _wasm_instance_copy(arg0) + +def wasm_instance_same(arg0,arg1): + _wasm_instance_same = libiwasm.wasm_instance_same + _wasm_instance_same.restype = c_bool + _wasm_instance_same.argtypes = [POINTER(wasm_instance_t),POINTER(wasm_instance_t)] + return _wasm_instance_same(arg0,arg1) + +def wasm_instance_get_host_info(arg0): + _wasm_instance_get_host_info = libiwasm.wasm_instance_get_host_info + _wasm_instance_get_host_info.restype = c_void_p + _wasm_instance_get_host_info.argtypes = [POINTER(wasm_instance_t)] + return _wasm_instance_get_host_info(arg0) + +def wasm_instance_set_host_info(arg0,arg1): + _wasm_instance_set_host_info = libiwasm.wasm_instance_set_host_info + _wasm_instance_set_host_info.restype = None + _wasm_instance_set_host_info.argtypes = [POINTER(wasm_instance_t),c_void_p] + return _wasm_instance_set_host_info(arg0,arg1) + +def wasm_instance_set_host_info_with_finalizer(arg0,arg1,arg2): + _wasm_instance_set_host_info_with_finalizer = libiwasm.wasm_instance_set_host_info_with_finalizer + _wasm_instance_set_host_info_with_finalizer.restype = None + _wasm_instance_set_host_info_with_finalizer.argtypes = [POINTER(wasm_instance_t),c_void_p,CFUNCTYPE(None,c_void_p)] + return _wasm_instance_set_host_info_with_finalizer(arg0,arg1,arg2) + +def wasm_instance_as_ref(arg0): + _wasm_instance_as_ref = libiwasm.wasm_instance_as_ref + _wasm_instance_as_ref.restype = POINTER(wasm_ref_t) + _wasm_instance_as_ref.argtypes = [POINTER(wasm_instance_t)] + return _wasm_instance_as_ref(arg0) + +def wasm_ref_as_instance(arg0): + _wasm_ref_as_instance = libiwasm.wasm_ref_as_instance + _wasm_ref_as_instance.restype = POINTER(wasm_instance_t) + _wasm_ref_as_instance.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_instance(arg0) + +def wasm_instance_as_ref_const(arg0): + _wasm_instance_as_ref_const = libiwasm.wasm_instance_as_ref_const + _wasm_instance_as_ref_const.restype = POINTER(wasm_ref_t) + _wasm_instance_as_ref_const.argtypes = [POINTER(wasm_instance_t)] + return _wasm_instance_as_ref_const(arg0) + +def wasm_ref_as_instance_const(arg0): + _wasm_ref_as_instance_const = libiwasm.wasm_ref_as_instance_const + _wasm_ref_as_instance_const.restype = POINTER(wasm_instance_t) + _wasm_ref_as_instance_const.argtypes = [POINTER(wasm_ref_t)] + return _wasm_ref_as_instance_const(arg0) + +def wasm_instance_new(arg0,arg1,arg2,arg3): + _wasm_instance_new = libiwasm.wasm_instance_new + _wasm_instance_new.restype = POINTER(wasm_instance_t) + _wasm_instance_new.argtypes = [POINTER(wasm_store_t),POINTER(wasm_module_t),POINTER(wasm_extern_vec_t),POINTER(POINTER(wasm_trap_t))] + return _wasm_instance_new(arg0,arg1,arg2,arg3) + +def wasm_instance_new_with_args(arg0,arg1,arg2,arg3,arg4,arg5): + _wasm_instance_new_with_args = libiwasm.wasm_instance_new_with_args + _wasm_instance_new_with_args.restype = POINTER(wasm_instance_t) + _wasm_instance_new_with_args.argtypes = [POINTER(wasm_store_t),POINTER(wasm_module_t),POINTER(wasm_extern_vec_t),POINTER(POINTER(wasm_trap_t)),c_uint32,c_uint32] + return _wasm_instance_new_with_args(arg0,arg1,arg2,arg3,arg4,arg5) + +def wasm_instance_exports(arg0,arg1): + _wasm_instance_exports = libiwasm.wasm_instance_exports + _wasm_instance_exports.restype = None + _wasm_instance_exports.argtypes = [POINTER(wasm_instance_t),POINTER(wasm_extern_vec_t)] + return _wasm_instance_exports(arg0,arg1) diff --git a/language-bindings/python/wamr/ffi.py b/language-bindings/python/wamr/ffi.py new file mode 100644 index 000000000..a29b607c1 --- /dev/null +++ b/language-bindings/python/wamr/ffi.py @@ -0,0 +1,642 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python3 +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# pylint: disable=missing-class-docstring +# pylint: disable=missing-function-docstring +# pylint: disable=missing-module-docstring + +import ctypes as c +import os +from pathlib import Path +import sys + +# +# Prologue. Dependencies of binding +# + +# how to open the library file of WAMR + +if sys.platform == "linux": + BUILDING_DIR = "product-mini/platforms/linux/build" + LIBRARY_NAME = "libiwasm.so" +elif sys.platform == "win32": + BUILDING_DIR = "product-mini/platforms/windows/build" + LIBRARY_NAME = "iwasm.dll" +elif sys.platform == "darwin": + BUILDING_DIR = "product-mini/platforms/darwin/build" + LIBRARY_NAME = "libiwasm.dylib" +else: + raise RuntimeError(f"unsupported platform `{sys.platform}`") + +# FIXME: should load libiwasm.so from current system library path +current_file = Path(__file__) +if current_file.is_symlink(): + current_file = Path(os.readlink(current_file)) +current_dir = current_file.parent.resolve() +root_dir = current_dir.parent.parent.parent.parent.resolve() +wamr_dir = root_dir.joinpath("wasm-micro-runtime").resolve() +if not wamr_dir.exists(): + raise RuntimeError(f"not found the repo of wasm-micro-runtime under {root_dir}") + +libpath = wamr_dir.joinpath(BUILDING_DIR).joinpath(LIBRARY_NAME).resolve() +if not libpath.exists(): + raise RuntimeError(f"not found precompiled wamr library at {libpath}") + +print(f"loading WAMR library from {libpath} ...") +libiwasm = c.cdll.LoadLibrary(libpath) + + +class wasm_ref_t(c.Structure): + # pylint: disable=invalid-name + pass + + +class wasm_val_union(c.Union): + # pylint: disable=invalid-name + _fields_ = [ + ("i32", c.c_int32), + ("i64", c.c_int64), + ("f32", c.c_float), + ("f64", c.c_double), + ("ref", c.POINTER(wasm_ref_t)), + ] + + +class wasm_val_t(c.Structure): + # pylint: disable=invalid-name + _fields_ = [ + ("kind", c.c_uint8), + ("of", wasm_val_union), + ] + + +def dereference(p): + # pylint: disable=protected-access + if not isinstance(p, c._Pointer): + raise RuntimeError("not a pointer") + return p.contents + + +# HELPERs +def create_null_pointer(struct_type): + return c.POINTER(struct_type)() + + +def is_null_pointer(c_pointer): + # pylint: disable=protected-access + if isinstance(c_pointer, c._Pointer): + return False if c_pointer else True + else: + raise RuntimeError("not a pointer") + + +def wasm_vec_to_list(vec): + """ + Converts a vector or a POINTER(vector) to a list + vector of type pointers -> list of type pointers + """ + known_vec_type = [ + wasm_byte_vec_t, + wasm_valtype_vec_t, + wasm_functype_vec_t, + wasm_globaltype_vec_t, + wasm_tabletype_vec_t, + wasm_memorytype_vec_t, + wasm_externtype_vec_t, + wasm_importtype_vec_t, + wasm_exporttype_vec_t, + wasm_val_vec_t, + wasm_frame_vec_t, + wasm_extern_vec_t, + ] + known_vec_pointer_type = [POINTER(type) for type in known_vec_type] + + if any([isinstance(vec, type) for type in known_vec_pointer_type]): + vec = dereference(vec) + return [vec.data[i] for i in range(vec.num_elems)] + elif any([isinstance(vec, type) for type in known_vec_type]): + return [vec.data[i] for i in range(vec.num_elems)] + else: + raise RuntimeError("not a known vector type") + + +def list_to_carray(elem_type, *args): + """ + Converts a python list into a C array + """ + data = (elem_type * len(args))(*args) + return data + + +def load_module_file(wasm_content): + binary = wasm_byte_vec_t() + wasm_byte_vec_new_uninitialized(binary, len(wasm_content)) + # has to use malloced memory. + c.memmove(binary.data, wasm_content, len(wasm_content)) + binary.num_elems = len(wasm_content) + return binary + + +# +# Enhancment of binding +# + +from .binding import * + +# Built-in functions for Structure + + +wasm_finalizer = CFUNCTYPE(None, c_void_p) + + +def __repr_wasm_limits_t(self): + return f"{self.min:#x} {self.max:#x}" + + +# overwrite +wasm_limits_t.__repr__ = __repr_wasm_limits_t + + +def __compare_wasm_valtype_t(self, other): + if not isinstance(other, wasm_valtype_t): + return False + + return wasm_valtype_kind(byref(self)) == wasm_valtype_kind(byref(other)) + + +def __repr_wasm_valtype_t(self): + val_kind = wasm_valtype_kind(byref(self)) + if WASM_I32 == val_kind: + return "i32" + elif WASM_I64 == val_kind: + return "i64" + elif WASM_F32 == val_kind: + return "f32" + elif WASM_F64 == val_kind: + return "f64" + elif WASM_FUNCREF == val_kind: + return "funcref" + else: + return "anyref" + + +wasm_valtype_t.__eq__ = __compare_wasm_valtype_t +wasm_valtype_t.__repr__ = __repr_wasm_valtype_t + + +def __compare_wasm_byte_vec_t(self, other): + if not isinstance(other, wasm_byte_vec_t): + return False + + if self.num_elems != other.num_elems: + return False + + self_data = bytes(self.data[: self.num_elems]) + other_data = bytes(other.data[: other.num_elems]) + return self_data.decode() == other_data.decode() + + +def __repr_wasm_byte_vec_t(self): + data = bytes(self.data[: self.num_elems]) + return data.decode() if self.size else "" + + +wasm_byte_vec_t.__eq__ = __compare_wasm_byte_vec_t +wasm_byte_vec_t.__repr__ = __repr_wasm_byte_vec_t + + +def __compare_wasm_functype_t(self, other): + if not isinstance(other, wasm_functype_t): + return False + + params1 = dereference(wasm_functype_params(byref(self))) + params2 = dereference(wasm_functype_params(byref(other))) + results1 = dereference(wasm_functype_results(byref(self))) + results2 = dereference(wasm_functype_results(byref(other))) + return params1 == params2 and results1 == results2 + + +def __repr_wasm_functype_t(self): + params = dereference(wasm_functype_params(byref(self))) + results = dereference(wasm_functype_results(byref(self))) + params = f" (params {params})" if params.size else "" + results = f" (results {results})" if results.size else "" + return f"(func{params}{results})" + + +wasm_functype_t.__eq__ = __compare_wasm_functype_t +wasm_functype_t.__repr__ = __repr_wasm_functype_t + + +def __compare_wasm_globaltype_t(self, other): + if not isinstance(other, wasm_globaltype_t): + return False + + content1 = dereference(wasm_globaltype_content(byref(self))) + content2 = dereference(wasm_globaltype_content(byref(other))) + mutability1 = wasm_globaltype_mutability(byref(self)) + mutability2 = wasm_globaltype_mutability(byref(other)) + return content1 == content2 and mutability1 == mutability2 + + +def __repr_wasm_globaltype_t(self): + mutability = f"{wasm_globaltype_mutability(byref(self))}" + content = f"{dereference(wasm_globaltype_content(byref(self)))}" + return f"(global{' mut ' if mutability else ' '}{content})" + + +wasm_globaltype_t.__eq__ = __compare_wasm_globaltype_t +wasm_globaltype_t.__repr__ = __repr_wasm_globaltype_t + + +def __compare_wasm_tabletype_t(self, other): + if not isinstance(other, wasm_tabletype_t): + return False + + element1 = dereference(wasm_tabletype_element(byref(self))) + element2 = dereference(wasm_tabletype_element(byref(other))) + limits1 = dereference(wasm_tabletype_limits(byref(self))) + limits2 = dereference(wasm_tabletype_limits(byref(other))) + return element1 == element2 and limits1 == limits2 + + +def __repr_wasm_tabletype_t(self): + element = dereference(wasm_tabletype_element(byref(self))) + limit = dereference(wasm_tabletype_limits(byref(self))) + return f"(table {limit} {element})" + + +wasm_tabletype_t.__eq__ = __compare_wasm_tabletype_t +wasm_tabletype_t.__repr__ = __repr_wasm_tabletype_t + + +def __compare_wasm_memorytype_t(self, other): + if not isinstance(other, wasm_memorytype_t): + return False + + limits1 = dereference(wasm_memorytype_limits(byref(self))) + limits2 = dereference(wasm_memorytype_limits(byref(other))) + return limits1 == limits2 + + +def __repr_wasm_memorytype_t(self): + limit = dereference(wasm_memorytype_limits(byref(self))) + return f"(memory {limit})" + + +wasm_memorytype_t.__eq__ = __compare_wasm_memorytype_t +wasm_memorytype_t.__repr__ = __repr_wasm_memorytype_t + + +def __compare_wasm_externtype_t(self, other): + if not isinstance(other, wasm_externtype_t): + return False + + if wasm_externtype_kind(byref(self)) != wasm_externtype_kind(byref(other)): + return False + + extern_kind = wasm_externtype_kind(byref(self)) + if WASM_EXTERN_FUNC == extern_kind: + return dereference(wasm_externtype_as_functype(self)) == dereference( + wasm_externtype_as_functype(other) + ) + elif WASM_EXTERN_GLOBAL == extern_kind: + return dereference(wasm_externtype_as_globaltype(self)) == dereference( + wasm_externtype_as_globaltype(other) + ) + elif WASM_EXTERN_MEMORY == extern_kind: + return dereference(wasm_externtype_as_memorytype(self)) == dereference( + wasm_externtype_as_memorytype(other) + ) + elif WASM_EXTERN_TABLE == extern_kind: + return dereference(wasm_externtype_as_tabletype(self)) == dereference( + wasm_externtype_as_tabletype(other) + ) + else: + raise RuntimeError("not a valid wasm_externtype_t") + + +def __repr_wasm_externtype_t(self): + extern_kind = wasm_externtype_kind(byref(self)) + if WASM_EXTERN_FUNC == extern_kind: + return str(dereference(wasm_externtype_as_functype(byref(self)))) + elif WASM_EXTERN_GLOBAL == extern_kind: + return str(dereference(wasm_externtype_as_globaltype(byref(self)))) + elif WASM_EXTERN_MEMORY == extern_kind: + return str(dereference(wasm_externtype_as_memorytype(byref(self)))) + elif WASM_EXTERN_TABLE == extern_kind: + return str(dereference(wasm_externtype_as_tabletype(byref(self)))) + else: + raise RuntimeError("not a valid wasm_externtype_t") + + +wasm_externtype_t.__eq__ = __compare_wasm_externtype_t +wasm_externtype_t.__repr__ = __repr_wasm_externtype_t + + +def __compare_wasm_importtype_t(self, other): + if not isinstance(other, wasm_importtype_t): + return False + + if dereference(wasm_importtype_module(self)) != dereference( + wasm_importtype_module(other) + ): + return False + + if dereference(wasm_importtype_name(self)) != dereference( + wasm_importtype_name(other) + ): + return False + + self_type = dereference(wasm_importtype_type(byref(self))) + other_type = dereference(wasm_importtype_type(byref(other))) + return self_type == other_type + + +def __repr_wasm_importtype_t(self): + module = wasm_importtype_module(byref(self)) + name = wasm_importtype_name(byref(self)) + extern_type = wasm_importtype_type(byref(self)) + return f'(import "{dereference(module)}" "{dereference(name)}" {dereference(extern_type)})' + + +wasm_importtype_t.__eq__ = __compare_wasm_importtype_t +wasm_importtype_t.__repr__ = __repr_wasm_importtype_t + + +def __compare_wasm_exporttype_t(self, other): + if not isinstance(other, wasm_exporttype_t): + return False + + self_name = dereference(wasm_exporttype_name(byref(self))) + other_name = dereference(wasm_exporttype_name(byref(other))) + if self_name != other_name: + return False + + self_type = dereference(wasm_exporttype_type(byref(self))) + other_type = dereference(wasm_exporttype_type(byref(other))) + return self_type == other_type + + +def __repr_wasm_exporttype_t(self): + name = wasm_exporttype_name(byref(self)) + extern_type = wasm_exporttype_type(byref(self)) + return f'(export "{dereference(name)}" {dereference(extern_type)})' + + +wasm_exporttype_t.__eq__ = __compare_wasm_exporttype_t +wasm_exporttype_t.__repr__ = __repr_wasm_exporttype_t + + +def __compare_wasm_val_t(self, other): + if not isinstance(other, wasm_val_t): + return False + + if self.kind != other.kind: + return False + + if WASM_I32 == self.kind: + return self.of.i32 == other.of.i32 + elif WASM_I64 == self.kind: + return self.of.i64 == other.of.i64 + elif WASM_F32 == self.kind: + return self.of.f32 == other.of.f32 + elif WASM_F64 == self.kind: + return self.of.f64 == other.of.f63 + elif WASM_ANYREF == self.kind: + raise RuntimeError("FIXME") + else: + raise RuntimeError("not a valid val kind") + + +def __repr_wasm_val_t(self): + if WASM_I32 == self.kind: + return f"i32 {self.of.i32}" + elif WASM_I64 == self.kind: + return f"i64 {self.of.i64}" + elif WASM_F32 == self.kind: + return f"f32 {self.of.f32}" + elif WASM_F64 == self.kind: + return f"f64 {self.of.f64}" + elif WASM_ANYREF == self.kind: + return f"anyref {self.of.ref}" + else: + raise RuntimeError("not a valid val kind") + + +wasm_val_t.__repr__ = __repr_wasm_val_t +wasm_val_t.__eq__ = __compare_wasm_val_t + + +def __repr_wasm_trap_t(self): + message = wasm_message_t() + wasm_trap_message(self, message) + return f'(trap "{str(message)}")' + + +wasm_trap_t.__repr__ = __repr_wasm_trap_t + + +def __repr_wasm_frame_t(self): + instance = wasm_frame_instance(self) + module_offset = wasm_frame_module_offset(self) + func_index = wasm_frame_func_index(self) + func_offset = wasm_frame_func_offset(self) + return f"> module:{module_offset:#x} => func#{func_index:#x}.{func_offset:#x}" + + +wasm_frame_t.__repr__ = __repr_wasm_frame_t + + +def __repr_wasm_module_t(self): + imports = wasm_importtype_vec_t() + wasm_module_imports(self, imports) + + exports = wasm_exporttype_vec_t() + wasm_module_exports(self, exports) + + ret = "(module" + ret += str(imports).replace("(import", "\n (import") + ret += str(exports).replace("(export", "\n (export") + ret += "\n)" + return ret + + +wasm_module_t.__repr__ = __repr_wasm_module_t + + +def __repr_wasm_instance_t(self): + exports = wasm_extern_vec_t() + wasm_instance_exports(self, exports) + + ret = "(instance" + ret += str(exports).replace("(export", "\n (export") + ret += "\n)" + return ret + + +wasm_instance_t.__repr__ = __repr_wasm_instance_t + + +def __repr_wasm_func_t(self): + ft = wasm_func_type(self) + return f"{str(dereference(ft))[:-1]} ... )" + + +wasm_func_t.__repr__ = __repr_wasm_func_t + + +def __repr_wasm_global_t(self): + gt = wasm_global_type(self) + return f"{str(dereference(gt))[:-1]} ... )" + + +wasm_global_t.__repr__ = __repr_wasm_global_t + + +def __repr_wasm_table_t(self): + tt = wasm_table_type(self) + return f"{str(dereference(tt))[:-1]} ... )" + + +wasm_table_t.__repr__ = __repr_wasm_table_t + + +def __repr_wasm_memory_t(self): + mt = wasm_memory_type(self) + return f"{str(dereference(mt))[:-1]} ... )" + + +wasm_memory_t.__repr__ = __repr_wasm_memory_t + + +def __repr_wasm_extern_t(self): + ext_type = wasm_extern_type(self) + ext_kind = wasm_extern_kind(self) + + ret = "(export " + if WASM_EXTERN_FUNC == ext_kind: + ft = wasm_externtype_as_functype(ext_type) + ret += str(dereference(ft)) + elif WASM_EXTERN_GLOBAL == ext_kind: + gt = wasm_externtype_as_globaltype(ext_type) + ret += str(dereference(gt)) + elif WASM_EXTERN_MEMORY == ext_kind: + mt = wasm_externtype_as_memorytype(ext_type) + ret += str(dereference(mt)) + elif WASM_EXTERN_TABLE == ext_kind: + tt = wasm_externtype_as_tabletype(ext_type) + ret += str(dereference(tt)) + else: + raise RuntimeError("not a valid extern kind") + ret += ")" + return ret + + +wasm_extern_t.__repr__ = __repr_wasm_extern_t + + +# Function Types construction short-hands +def wasm_name_new_from_string(s): + name = wasm_name_t() + data = ((c.c_ubyte) * len(s)).from_buffer_copy(s.encode()) + wasm_byte_vec_new(byref(name), len(s), data) + return name + + +def __wasm_functype_new(param_list, result_list): + def __list_to_wasm_valtype_vec(l): + vec = wasm_valtype_vec_t() + + if not l: + wasm_valtype_vec_new_empty(byref(vec)) + else: + data_type = POINTER(wasm_valtype_t) * len(l) + data = data_type() + for i in range(len(l)): + data[i] = l[i] + wasm_valtype_vec_new(byref(vec), len(l), data) + + return vec + + params = __list_to_wasm_valtype_vec(param_list) + results = __list_to_wasm_valtype_vec(result_list) + return wasm_functype_new(byref(params), byref(results)) + + +def wasm_functype_new_0_0(): + return __wasm_functype_new([], []) + + +def wasm_functype_new_1_0(p1): + return __wasm_functype_new([p1], []) + + +def wasm_functype_new_2_0(p1, p2): + return __wasm_functype_new([p1, p2], []) + + +def wasm_functype_new_3_0(p1, p2, p3): + return __wasm_functype_new([p1, p2, p3], []) + + +def wasm_functype_new_0_1(r1): + return __wasm_functype_new([], [r1]) + + +def wasm_functype_new_1_1(p1, r1): + return __wasm_functype_new([p1], [r1]) + + +def wasm_functype_new_2_1(p1, p2, r1): + return __wasm_functype_new([p1, p2], [r1]) + + +def wasm_functype_new_3_1(p1, p2, p3, r1): + return __wasm_functype_new([p1, p2, p3], [r1]) + + +def wasm_limits_new(min, max): + limit = wasm_limits_t() + limit.min = min + limit.max = max + return c.pointer(limit) + + +def wasm_i32_val(i): + v = wasm_val_t() + v.kind = WASM_I32 + v.of.i32 = i + return v + + +def wasm_i64_val(i): + v = wasm_val_t() + v.kind = WASM_I64 + v.of.i64 = i + return v + + +def wasm_f32_val(z): + v = wasm_val_t() + v.kind = WASM_F32 + v.of.f32 = z + return v + + +def wasm_f64_val(z): + v = wasm_val_t() + v.kind = WASM_F64 + v.of.f64 = z + return v + + +def wasm_func_cb_decl(func): + return wasm_func_callback_t(func) + + +def wasm_func_with_env_cb_decl(func): + return wasm_func_callback_with_env_t(func) diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index 3f5683a0a..92f89a93b 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -160,6 +160,12 @@ else CFLAGS += -DWASM_ENABLE_BULK_MEMORY=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_PERF_PROFILING),y) +CFLAGS += -DWASM_ENABLE_PERF_PROFILING=1 +else +CFLAGS += -DWASM_ENABLE_PERF_PROFILING=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_MEMORY_PROFILING),y) CFLAGS += -DWASM_ENABLE_MEMORY_PROFILING=1 else @@ -174,10 +180,27 @@ endif ifeq ($(CONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN),y) CFLAGS += -DWASM_ENABLE_LIBC_BUILTIN=1 +CSRCS += libc_builtin_wrapper.c +VPATH += $(IWASM_ROOT)/libraries/libc-builtin else CFLAGS += -DWASM_ENABLE_LIBC_BUILTIN=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_LIBC_WASI),y) +CFLAGS += -DWASM_ENABLE_LIBC_WASI=1 +CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src +CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/include +CSRCS += posix_socket.c +CSRCS += libc_wasi_wrapper.c +VPATH += $(IWASM_ROOT)/libraries/libc-wasi +CSRCS += posix.c +CSRCS += random.c +CSRCS += str.c +VPATH += $(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src +else +CFLAGS += -DWASM_ENABLE_LIBC_WASI=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_MULTI_MODULE),y) CFLAGS += -DWASM_ENABLE_MULTI_MODULE=1 else @@ -253,7 +276,6 @@ CSRCS += nuttx_platform.c \ bh_vector.c \ bh_read_file.c \ runtime_timer.c \ - libc_builtin_wrapper.c \ wasm_application.c \ wasm_runtime_common.c \ wasm_native.c \ @@ -272,7 +294,6 @@ 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 diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index c78ef399e..6942df8c0 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -98,7 +98,7 @@ app_instance_func(wasm_module_inst_t module_inst, const char *func_name) static char ** split_string(char *str, int *count) { - char **res = NULL; + char **res = NULL, **res1; char *p; int idx = 0; @@ -106,16 +106,18 @@ split_string(char *str, int *count) do { p = strtok(str, " "); str = NULL; - res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1)); + res1 = res; + res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1)); if (res == NULL) { + free(res1); return NULL; } res[idx++] = p; } while (p); /** - * since the function name, - * res[0] might be contains a '\' to indicate a space + * Due to the function name, + * res[0] might contain a '\' to indicate a space * func\name -> func name */ p = strchr(res[0], '\\'); diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 9baecc1a4..0276c1dc7 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -84,7 +84,7 @@ app_instance_func(wasm_module_inst_t module_inst, const char *func_name) static char ** split_string(char *str, int *count) { - char **res = NULL; + char **res = NULL, **res1; char *p, *next_token; int idx = 0; @@ -92,16 +92,18 @@ split_string(char *str, int *count) do { p = strtok_s(str, " ", &next_token); str = NULL; - res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1)); + res1 = res; + res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1)); if (res == NULL) { + free(res1); return NULL; } res[idx++] = p; } while (p); /** - * since the function name, - * res[0] might be contains a '\' to indicate a space + * Due to the function name, + * res[0] might contain a '\' to indicate a space * func\name -> func name */ p = strchr(res[0], '\\'); diff --git a/tests/wamr-test-suites/spec-test-script/LICENSE b/tests/wamr-test-suites/spec-test-script/LICENSE deleted file mode 100644 index 49b2aa2cf..000000000 --- a/tests/wamr-test-suites/spec-test-script/LICENSE +++ /dev/null @@ -1,387 +0,0 @@ -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/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index 920b0d0f3..9053a720c 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -57,26 +57,25 @@ 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 + self.process = None env = os.environ env['TERM'] = 'dumb' env['INPUTRC'] = '/dev/null' env['PERL_RL'] = 'false' if no_pty: - self.p = Popen(args, bufsize=0, + self.process = 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 + self.stdin = self.process.stdin + self.stdout = self.process.stdout else: - # provide tty to get 'interactive' readline to work + # Use tty to setup an interactive environment master, slave = pty.openpty() # Set terminal size large so that readline will not send @@ -84,7 +83,7 @@ class Runner(): buf = array.array('h', [100, 200, 0, 0]) fcntl.ioctl(master, termios.TIOCSWINSZ, buf, True) - self.p = Popen(args, bufsize=0, + self.process = Popen(args, bufsize=0, stdin=slave, stdout=slave, stderr=STDOUT, preexec_fn=os.setsid, env=env) @@ -95,55 +94,55 @@ class Runner(): 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: + wait_until = time.time() + timeout + while time.time() < wait_until: [outs,_,_] = select([self.stdout], [], [], 1) if self.stdout in outs: - new_data = self.stdout.read(1) - if not new_data: + read_byte = self.stdout.read(1) + if not read_byte: # 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) + read_byte = read_byte.decode('utf-8') if IS_PY_3 else read_byte + + debug(read_byte) if self.no_pty: - self.buf += new_data.replace("\n", "\r\n") + self.buf += read_byte.replace('\n', '\r\n') else: - self.buf += new_data - self.buf = self.buf.replace("\r\r", "\r") + self.buf += read_byte + self.buf = self.buf.replace('\r\r', '\r') + + # filter the prompts for prompt in prompts: - regexp = re.compile(prompt) - match = regexp.search(self.buf) + pattern = re.compile(prompt) + match = pattern.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 + str_to_write = str + '\n' + str_to_write = bytes( + str_to_write, 'utf-8') if IS_PY_3 else str_to_write - self.stdin.write(_to_bytes(str + "\n")) + self.stdin.write(str_to_write) def cleanup(self): - if self.p: + if self.process: try: self.writeline("__exit__") time.sleep(.020) - os.killpg(self.p.pid, signal.SIGTERM) + self.process.kill() except OSError: pass except IOError: pass - self.p = None + self.process = None self.stdin.close() if self.stdin != self.stdout: self.stdout.close() diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index df32251b3..d38157fbb 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -35,11 +35,16 @@ add_definitions(-DWASM_ENABLE_REF_TYPES=1) add_definitions(-DWASM_ENABLE_CUSTOM_NAME_SECTION=1) add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1) add_definitions(-DWASM_ENABLE_PERF_PROFILING=1) +add_definitions(-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1) if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1) add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1) endif() +if (DEFINED WAMR_BUILD_AOT_FUNC_PREFIX) + add_definitions(-DAOT_FUNC_PREFIX="${WAMR_BUILD_AOT_FUNC_PREFIX}") +endif () + # Set WAMR_BUILD_TARGET, currently values supported: # "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" if (NOT WAMR_BUILD_TARGET) diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 1587d2ae1..67e3edbbb 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -10,7 +10,7 @@ #include "aot_export.h" /* clang-format off */ -static int +static void print_help() { printf("Usage: wamrc [options] -o output_file wasm_file\n"); @@ -58,14 +58,66 @@ print_help() 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(" --disable-llvm-lto Disable the LLVM link time optimization\n"); + printf(" --emit-custom-sections=
\n"); + printf(" Emit the specified custom sections to AoT file, using comma to separate\n"); + printf(" multiple names, e.g.\n"); + printf(" --emit-custom-sections=section1,section2,sectionN\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"); printf(" wamrc --target=i386 --format=object -o test.o test.wasm\n"); - return 1; } /* clang-format on */ +#define PRINT_HELP_AND_EXIT() \ + do { \ + print_help(); \ + goto fail0; \ + } while (0) + +/** + * Split a 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, const char *delimer) +{ + char **res = NULL, **res1; + char *p; + int idx = 0; + + /* split string and append tokens to 'res' */ + do { + p = strtok(str, delimer); + str = NULL; + res1 = res; + res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1)); + if (res == NULL) { + free(res1); + return NULL; + } + res[idx++] = p; + } while (p); + + /** + * Due to the section name, + * res[0] might contain 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; +} + int main(int argc, char *argv[]) { @@ -97,39 +149,39 @@ main(int argc, char *argv[]) if (!strcmp(argv[0], "-o")) { argc--, argv++; if (argc < 2) - return print_help(); + PRINT_HELP_AND_EXIT(); out_file_name = argv[0]; } else if (!strncmp(argv[0], "--target=", 9)) { if (argv[0][9] == '\0') - return print_help(); + PRINT_HELP_AND_EXIT(); option.target_arch = argv[0] + 9; } else if (!strncmp(argv[0], "--target-abi=", 13)) { if (argv[0][13] == '\0') - return print_help(); + PRINT_HELP_AND_EXIT(); option.target_abi = argv[0] + 13; } else if (!strncmp(argv[0], "--cpu=", 6)) { if (argv[0][6] == '\0') - return print_help(); + PRINT_HELP_AND_EXIT(); option.target_cpu = argv[0] + 6; } else if (!strncmp(argv[0], "--cpu-features=", 15)) { if (argv[0][15] == '\0') - return print_help(); + PRINT_HELP_AND_EXIT(); option.cpu_features = argv[0] + 15; } else if (!strncmp(argv[0], "--opt-level=", 12)) { if (argv[0][12] == '\0') - return print_help(); + PRINT_HELP_AND_EXIT(); option.opt_level = (uint32)atoi(argv[0] + 12); if (option.opt_level > 3) option.opt_level = 3; } else if (!strncmp(argv[0], "--size-level=", 13)) { if (argv[0][13] == '\0') - return print_help(); + PRINT_HELP_AND_EXIT(); option.size_level = (uint32)atoi(argv[0] + 13); if (option.size_level > 3) option.size_level = 3; @@ -143,7 +195,7 @@ main(int argc, char *argv[]) } else if (!strncmp(argv[0], "--format=", 9)) { if (argv[0][9] == '\0') - return print_help(); + PRINT_HELP_AND_EXIT(); if (!strcmp(argv[0] + 9, "aot")) option.output_format = AOT_FORMAT_FILE; else if (!strcmp(argv[0] + 9, "object")) @@ -154,13 +206,13 @@ main(int argc, char *argv[]) option.output_format = AOT_LLVMIR_OPT_FILE; else { printf("Invalid format %s.\n", argv[0] + 9); - return print_help(); + PRINT_HELP_AND_EXIT(); } } 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(); + PRINT_HELP_AND_EXIT(); } else if (!strcmp(argv[0], "--disable-bulk-memory")) { option.enable_bulk_memory = false; @@ -201,12 +253,27 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0], "--disable-llvm-lto")) { option.disable_llvm_lto = true; } + else if (!strncmp(argv[0], "--emit-custom-sections=", 23)) { + int len = 0; + if (option.custom_sections) { + free(option.custom_sections); + } + + option.custom_sections = split_string(argv[0] + 23, &len, ","); + if (!option.custom_sections) { + printf("Failed to process emit-custom-sections: alloc " + "memory failed\n"); + PRINT_HELP_AND_EXIT(); + } + + option.custom_sections_count = len; + } else - return print_help(); + PRINT_HELP_AND_EXIT(); } if (argc == 0 || !out_file_name) - return print_help(); + PRINT_HELP_AND_EXIT(); if (!size_level_set) { /** @@ -348,6 +415,12 @@ fail1: /* Destroy runtime environment */ wasm_runtime_destroy(); +fail0: + /* free option.custom_sections */ + if (option.custom_sections) { + free(option.custom_sections); + } + bh_print_time("wamrc return"); return exit_status; }