diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 5ddba8f3..7ccfa246 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -12,7 +12,7 @@ ENV TZ=Asian/Shanghai # hadolint ignore=DL3008 RUN apt-get update \ && apt-get install -y apt-transport-https apt-utils build-essential \ - ca-certificates curl g++-multilib git gnupg \ + ca-certificates ccache curl g++-multilib git gnupg \ libgcc-9-dev lib32gcc-9-dev lsb-release \ ninja-build ocaml ocamlbuild python2.7 \ software-properties-common tree tzdata \ @@ -20,6 +20,15 @@ RUN apt-get update \ && apt-get clean -y \ && rm -rf /var/lib/apt/lists/* +# +# binaryen +ARG BINARYEN_VER=111 +WORKDIR /opt +RUN wget -c --progress=dot:giga https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VER}/binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \ + && tar xf binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \ + && ln -sf /opt/binaryen-version_111 /opt/binaryen \ + && rm binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz + # # CMAKE (https://apt.kitware.com/) SHELL ["/bin/bash", "-o", "pipefail", "-c"] @@ -31,25 +40,26 @@ RUN wget --progress=dot:giga -O - https://apt.kitware.com/keys/kitware-archive-l && apt-get install -y kitware-archive-keyring --no-install-recommends \ && apt-get install -y cmake --no-install-recommends \ && apt-get clean -y \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* # # install emsdk WORKDIR /opt RUN git clone https://github.com/emscripten-core/emsdk.git +ARG EMSDK_VER=3.0.0 WORKDIR /opt/emsdk RUN git pull \ - && ./emsdk install 2.0.26 \ - && ./emsdk activate 2.0.26 \ + && ./emsdk install ${EMSDK_VER} \ + && ./emsdk activate ${EMSDK_VER} \ && echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc # # install wasi-sdk -ARG WASI_SDK_VER=16 +ARG WASI_SDK_VER=19 RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt \ && tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \ - && ln -fs /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \ + && ln -sf /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \ && rm /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz # @@ -57,29 +67,29 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases ARG WABT_VER=1.0.29 RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -P /opt \ && tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \ - && ln -fs /opt/wabt-${WABT_VER} /opt/wabt \ + && ln -sf /opt/wabt-${WABT_VER} /opt/wabt \ && rm /opt/wabt-${WABT_VER}-ubuntu.tar.gz # # install bazelisk ARG BAZELISK_VER=1.12.0 -RUN mkdir /opt/bazelisk \ +RUN mkdir /opt/bazelisk \ && wget -c --progress=dot:giga https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -P /opt/bazelisk \ && chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \ && ln -fs /opt/bazelisk/bazelisk-linux-amd64 /opt/bazelisk/bazel # # install clang+llvm +ARG LLVM_VER=14 +RUN apt-get purge -y clang-10 llvm-10 && apt autoremove -y WORKDIR /etc/apt/apt.conf.d RUN touch 99verfiy-peer.conf \ && echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf -WORKDIR /tmp +WORKDIR /tmp RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \ && chmod a+x ./llvm.sh \ - && /tmp/llvm.sh 12 all \ - && ln -sf /usr/bin/clang-format-12 /usr/bin/clang-format \ - && rm -rf /tmp/* + && ./llvm.sh ${LLVM_VER} all # # [Optional] @@ -96,17 +106,28 @@ RUN apt-get update \ # Install required python packages # hadolint ignore=DL3013 RUN python3 -m pip install --no-cache-dir --upgrade pip \ - && pip3 install --no-cache-dir --user black nose pycparser pylint + && pip3 install --no-cache-dir black nose pycparser pylint -# set path, PS and clean up -ENV PATH "/opt/bazelisk:/opt/clang-llvm/bin:${PATH}" -RUN echo "export PATH=/opt/bazelisk:/opt/clang-llvm/bin:${PATH}" >> /root/.bashrc \ - && printf "%s\n" "PS1='\n[ \u@wamr-dev-docker \W ]\n$ '" >> /root/.bashrc \ +# +# Install github-cli. It doens't work as a feature of devcontainer.json +RUN cd /tmp \ + && wget https://github.com/cli/cli/releases/download/v2.20.2/gh_2.20.2_linux_amd64.deb \ + && dpkg -i gh_2.20.2_linux_amd64.deb + +# +# Install NodeJS +RUN curl -fsSL https://deb.nodesource.com/setup_19.x | bash - +RUN apt-get install -y nodejs + +# set path +ENV PATH="/opt/bazelisk:/usr/lib/llvm-${LLVM_VER}/bin:${PATH}" +ENV CC=/usr/lib/llvm-${LLVM_VER}/bin/clang CXX=/usr/lib/llvm-${LLVM_VER}/bin/clang++ +RUN printf "%s\n" "PS1='\n[ \u@wamr-dev-docker \W ]\n$ '" >> /root/.bashrc \ && apt-get autoremove -y \ && apt-get clean -y \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /tmp/* # set workdir when container run -VOLUME /workspace -WORKDIR /workspace \ No newline at end of file +VOLUME /workspaces +WORKDIR /workspaces diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 976f5beb..24e1bdfd 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,5 @@ // Copyright (C) 2019 Intel Corporation. All rights reserved. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: // https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp { @@ -10,7 +9,12 @@ // Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 // Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon "args": { - "VARIANT": "ubuntu-20.04" + "BINARYEN_VER": "111", + "EMSDK_VER": "3.0.0", + "LLVM_VER": "15", + "VARIANT": "ubuntu-20.04", + "WASI_SDK_VER": "19", + "WABT_VER": "1.0.31" } }, "runArgs": [ @@ -27,12 +31,10 @@ // Add the IDs of extensions you want installed when the container is created. "extensions": [ "dtsvet.vscode-wasm", - "esbenp.prettier-vscode", + "llvm-vs-code-extensions.vscode-clangd", "ms-python.python", "ms-python.vscode-pylance", "ms-vscode.cmake-tools", - "ms-vscode.cpptools", - "twxs.cmake" ] } }, diff --git a/.github/workflows/build_iwasm_release.yml b/.github/workflows/build_iwasm_release.yml index 9a47c6c4..557a81fc 100644 --- a/.github/workflows/build_iwasm_release.yml +++ b/.github/workflows/build_iwasm_release.yml @@ -36,7 +36,7 @@ jobs: - name: generate iwasm binary release run: | cmake -S . -B build \ - -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 \ + -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 \ -DWAMR_BUILD_CUSTOM_NAME_SECTION=0 \ -DWAMR_BUILD_DEBUG_INTERP=0 \ -DWAMR_BUILD_DEBUG_AOT=0 \ diff --git a/.github/workflows/build_llvm_libraries.yml b/.github/workflows/build_llvm_libraries.yml index 6eaa2be7..7ef1dd63 100644 --- a/.github/workflows/build_llvm_libraries.yml +++ b/.github/workflows/build_llvm_libraries.yml @@ -5,23 +5,46 @@ name: Reusable workflow-build_llvm_libraries on: workflow_call: inputs: - runs-on: + os: required: true type: string + arch: + required: true + type: string + outputs: + cache_key: + description: "A cached key of LLVM libraries" + value: ${{ jobs.build_llvm_libraries.outputs.key}} jobs: build_llvm_libraries: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: ${{ fromJson(inputs.runs-on) }} + runs-on: ${{ inputs.os }} + outputs: + key: ${{ steps.create_lib_cache_key.outputs.key}} steps: - name: checkout uses: actions/checkout@v3 + - name: install dependencies + run: /usr/bin/env python3 -m pip install -r requirements.txt + working-directory: build-scripts + + - name: retrive the last commit ID + id: get_last_commit + run: echo "last_commit=$(GH_TOKEN=${{ secrets.GITHUB_TOKEN }} /usr/bin/env python3 ./build_llvm.py --llvm-ver)" >> $GITHUB_OUTPUT + working-directory: build-scripts + + # Bump the prefix number to evict all previous caches and + # enforce a clean build, in the unlikely case that some + # weird build error occur and llvm/build becomes a potential + # suspect. + - name: form the cache key of libraries + id: create_lib_cache_key + run: echo "key=0-llvm-libraries-${{ inputs.os }}-${{ inputs.arch }}-${{ steps.get_last_commit.outputs.last_commit }}" >> $GITHUB_OUTPUT + - name: Cache LLVM libraries - id: cache_llvm + id: retrieve_llvm_libs uses: actions/cache@v3 with: path: | @@ -30,10 +53,39 @@ jobs: ./core/deps/llvm/build/lib ./core/deps/llvm/build/libexec ./core/deps/llvm/build/share - key: ${{ matrix.os }}-build-llvm_libraries_ex + key: ${{ steps.create_lib_cache_key.outputs.key}} - - name: Build llvm - id: build_llvm - if: ${{ steps.cache_llvm.outputs.cache-hit != 'true' }} - run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly + - uses: actions/cache@v3 + with: + path: ~/.ccache + key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} + restore-keys: | + 0-ccache-${{ inputs.os }} + if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && inputs.os == 'ubuntu-20.04' + + - uses: actions/cache@v3 + with: + path: ~/.cache/ccache + key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} + restore-keys: | + 0-ccache-${{ inputs.os }} + if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && inputs.os == 'ubuntu-22.04' + + - run: sudo apt install -y ccache ninja-build + if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'ubuntu') + + - uses: actions/cache@v3 + with: + path: ~/Library/Caches/ccache + key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} + restore-keys: | + 0-ccache-${{ inputs.os }} + if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'macos') + + - run: brew install ccache ninja + if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'macos') + + - name: Build LLVM libraries + if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' + run: /usr/bin/env python3 ./build_llvm.py --arch ${{ inputs.arch }} working-directory: build-scripts diff --git a/.github/workflows/codeing_guildelines.yml b/.github/workflows/coding_guidelines.yml similarity index 97% rename from .github/workflows/codeing_guildelines.yml rename to .github/workflows/coding_guidelines.yml index bc66436c..259e84fe 100644 --- a/.github/workflows/codeing_guildelines.yml +++ b/.github/workflows/coding_guidelines.yml @@ -15,7 +15,7 @@ concurrency: cancel-in-progress: true jobs: - complinace_job: + compliance_job: runs-on: ubuntu-latest steps: - name: checkout diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index b8e2edd2..42871585 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -53,8 +53,7 @@ env: FAST_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" LLVM_LAZY_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1" LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0" - # LLVM - LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex" + MULTI_TIER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1" # For Spec Test DEFAULT_TEST_OPTIONS: "-s spec -b -P" MULTI_MODULES_TEST_OPTIONS: "-s spec -b -M -P" @@ -64,23 +63,37 @@ env: WASI_TEST_OPTIONS: "-s wasi_certification" jobs: - build_llvm_libraries: + build_llvm_libraries_on_ubuntu_2004: uses: ./.github/workflows/build_llvm_libraries.yml with: - runs-on: "['ubuntu-20.04', 'ubuntu-22.04']" + os: "ubuntu-20.04" + arch: "X86" + + build_llvm_libraries_on_ubuntu_2204: + uses: ./.github/workflows/build_llvm_libraries.yml + with: + os: "ubuntu-22.04" + arch: "X86" build_wamrc: - needs: [build_llvm_libraries] + needs: + [build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2204] runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-20.04, ubuntu-22.04] + include: + - os: ubuntu-20.04 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} + - os: ubuntu-22.04 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout uses: actions/checkout@v3 + # since jobs.id can't contain the dot character + # it is hard to use `format` to assemble the cache key - name: Get LLVM libraries - id: cache_llvm + id: retrieve_llvm_libs uses: actions/cache@v3 with: path: | @@ -89,10 +102,10 @@ jobs: ./core/deps/llvm/build/lib ./core/deps/llvm/build/libexec ./core/deps/llvm/build/share - key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + key: ${{ matrix.llvm_cache_key }} - name: Quit if cache miss - if: steps.cache_llvm.outputs.cache-hit != 'true' + if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: Build wamrc @@ -103,7 +116,8 @@ jobs: working-directory: wamr-compiler build_iwasm: - needs: [build_llvm_libraries] + needs: + [build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2204] runs-on: ${{ matrix.os }} strategy: matrix: @@ -115,6 +129,7 @@ jobs: $FAST_JIT_BUILD_OPTIONS, $LLVM_LAZY_JIT_BUILD_OPTIONS, $LLVM_EAGER_JIT_BUILD_OPTIONS, + $MULTI_TIER_JIT_BUILD_OPTIONS, ] make_options_feature: [ # Features @@ -147,6 +162,8 @@ jobs: make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" + - make_options_run_mode: $MULTI_TIER_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" @@ -163,6 +180,8 @@ jobs: make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1" - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1" + - make_options_run_mode: $MULTI_TIER_JIT_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" @@ -175,6 +194,8 @@ jobs: make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" + - make_options_run_mode: $MULTI_TIER_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" @@ -184,16 +205,28 @@ jobs: make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - # Fast-JIT mode doesn't support android(X86-32) + - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS + make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" + # Fast-JIT and Multi-Tier-JIT mode don't support android(X86-32) - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS platform: android + - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS + platform: android + # only test andorid on ubuntu latest + - os: ubuntu-20.04 + platform: android + include: + - os: ubuntu-20.04 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} + - os: ubuntu-22.04 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout uses: actions/checkout@v3 # only download llvm cache when needed - name: Get LLVM libraries - id: cache_llvm + id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') uses: actions/cache@v3 with: @@ -203,10 +236,10 @@ jobs: ./core/deps/llvm/build/lib ./core/deps/llvm/build/libexec ./core/deps/llvm/build/share - key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + key: ${{ matrix.llvm_cache_key }} - name: Quit if cache miss - if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.cache_llvm.outputs.cache-hit != 'true') + if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true') run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: Build iwasm @@ -217,7 +250,13 @@ jobs: working-directory: product-mini/platforms/${{ matrix.platform }} build_samples_wasm_c_api: - needs: [build_iwasm, build_llvm_libraries, build_wamrc] + needs: + [ + build_iwasm, + build_llvm_libraries_on_ubuntu_2004, + build_llvm_libraries_on_ubuntu_2204, + build_wamrc, + ] runs-on: ${{ matrix.os }} strategy: matrix: @@ -229,22 +268,28 @@ jobs: $FAST_JIT_BUILD_OPTIONS, $LLVM_LAZY_JIT_BUILD_OPTIONS, $LLVM_EAGER_JIT_BUILD_OPTIONS, + $MULTI_TIER_JIT_BUILD_OPTIONS, ] os: [ubuntu-20.04, ubuntu-22.04] wasi_sdk_release: [ - "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-linux.tar.gz", + "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz", ] wabt_release: [ - "https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz", + "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz", ] + include: + - os: ubuntu-20.04 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} + - os: ubuntu-22.04 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout uses: actions/checkout@v3 - name: Get LLVM libraries - id: cache_llvm + id: retrieve_llvm_libs if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) uses: actions/cache@v3 with: @@ -254,18 +299,18 @@ jobs: ./core/deps/llvm/build/lib ./core/deps/llvm/build/libexec ./core/deps/llvm/build/share - key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + key: ${{ matrix.llvm_cache_key }} - name: Quit if cache miss - if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true') + if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true') run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: download and install wabt run: | cd /opt sudo wget ${{ matrix.wabt_release }} - sudo tar -xzf wabt-1.0.24-*.tar.gz - sudo mv wabt-1.0.24 wabt + sudo tar -xzf wabt-1.0.31-*.tar.gz + sudo mv wabt-1.0.31 wabt - name: Build wamrc if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) @@ -277,19 +322,9 @@ jobs: - name: Build Sample [wasm-c-api] 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 + cmake -S . -B build ${{ matrix.make_options }} + cmake --build build --config Release --parallel 4 + ctest --test-dir build working-directory: samples/wasm-c-api build_samples_others: @@ -298,14 +333,13 @@ jobs: strategy: matrix: os: [ubuntu-20.04, ubuntu-22.04] - wasi_sdk_release: - [ - "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-linux.tar.gz", - ] - wabt_release: - [ - "https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz", - ] + include: + - os: ubuntu-20.04 + wasi_sdk_release: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz" + wabt_release: "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz" + - os: ubuntu-22.04 + wasi_sdk_release: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz" + wabt_release: "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz" steps: - name: checkout uses: actions/checkout@v3 @@ -314,15 +348,15 @@ jobs: run: | cd /opt sudo wget ${{ matrix.wasi_sdk_release }} - sudo tar -xzf wasi-sdk-16.0-*.tar.gz - sudo mv wasi-sdk-16.0 wasi-sdk + sudo tar -xzf wasi-sdk-*.tar.gz + sudo mv wasi-sdk-19.0 wasi-sdk - name: download and install wabt run: | cd /opt sudo wget ${{ matrix.wabt_release }} - sudo tar -xzf wabt-1.0.24-*.tar.gz - sudo mv wabt-1.0.24 wabt + sudo tar -xzf wabt-1.0.31-*.tar.gz + sudo mv wabt-1.0.31 wabt - name: build wasi-libc (needed for wasi-threads) run: | @@ -402,12 +436,19 @@ jobs: ./iwasm wasm-apps/no_pthread.wasm test: - needs: [build_iwasm, build_llvm_libraries, build_wamrc] + needs: [build_iwasm, build_llvm_libraries_on_ubuntu_2004, build_wamrc] runs-on: ubuntu-20.04 strategy: matrix: running_mode: - ["classic-interp", "fast-interp", "jit", "aot", "fast-jit"] + [ + "classic-interp", + "fast-interp", + "jit", + "aot", + "fast-jit", + "multi-tier-jit", + ] test_option: [ $DEFAULT_TEST_OPTIONS, @@ -416,6 +457,8 @@ jobs: $THREADS_TEST_OPTIONS, $WASI_TEST_OPTIONS, ] + llvm_cache_key: + ["${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}"] exclude: # uncompatiable modes and features # classic-interp and fast-interp don't support simd @@ -431,32 +474,39 @@ jobs: test_option: $WASI_TEST_OPTIONS - running_mode: "jit" test_option: $MULTI_MODULES_TEST_OPTIONS - # fast-jit is only tested on default mode, exclude other three + # fast-jit doesn't support multi module, simd, and threads - running_mode: "fast-jit" test_option: $MULTI_MODULES_TEST_OPTIONS - running_mode: "fast-jit" test_option: $SIMD_TEST_OPTIONS - running_mode: "fast-jit" test_option: $THREADS_TEST_OPTIONS + # multi-tier-jit doesn't support multi module, simd, and threads + - running_mode: "multi-tier-jit" + test_option: $MULTI_MODULES_TEST_OPTIONS + - running_mode: "multi-tier-jit" + test_option: $SIMD_TEST_OPTIONS + - running_mode: "multi-tier-jit" + test_option: $THREADS_TEST_OPTIONS steps: - name: checkout uses: actions/checkout@v3 - name: set env variable(if llvm are used) - if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' + if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit' run: echo "USE_LLVM=true" >> $GITHUB_ENV - name: set env variable(if x86_32 test needed) if: > (matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS' || matrix.test_option == '$WASI_TEST_OPTIONS') - && matrix.running_mode != 'fast-jit' && matrix.running_mode != 'jit' + && matrix.running_mode != 'fast-jit' && matrix.running_mode != 'jit' && matrix.running_mode != 'multi-tier-jit' run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV #only download llvm libraries in jit and aot mode - name: Get LLVM libraries if: env.USE_LLVM == 'true' - id: cache_llvm + id: retrieve_llvm_libs uses: actions/cache@v3 with: path: | @@ -465,10 +515,10 @@ jobs: ./core/deps/llvm/build/lib ./core/deps/llvm/build/libexec ./core/deps/llvm/build/share - key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }} + key: ${{ matrix.llvm_cache_key }} - name: Quit if cache miss - if: env.USE_LLVM == 'true' && steps.cache_llvm.outputs.cache-hit != 'true' + if: env.USE_LLVM == 'true' && steps.retrieve_llvm_libs.outputs.cache-hit != 'true' run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: run tests diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml index 31bd424b..816e65ce 100644 --- a/.github/workflows/compilation_on_macos.yml +++ b/.github/workflows/compilation_on_macos.yml @@ -51,26 +51,28 @@ env: 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" LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1" LLVM_EAGER_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: build_llvm_libraries: uses: ./.github/workflows/build_llvm_libraries.yml with: - runs-on: "['macos-latest']" + os: "macos-latest" + arch: "X86" build_wamrc: needs: [build_llvm_libraries] runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-latest] + include: + - os: macos-latest + llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }} steps: - name: checkout uses: actions/checkout@v3 - name: Get LLVM libraries - id: cache_llvm + id: retrieve_llvm_libs uses: actions/cache@v3 with: path: | @@ -79,10 +81,10 @@ jobs: ./core/deps/llvm/build/lib ./core/deps/llvm/build/libexec ./core/deps/llvm/build/share - key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + key: ${{ matrix.llvm_cache_key }} - name: Quit if cache miss - if: steps.cache_llvm.outputs.cache-hit != 'true' + if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: Build wamrc @@ -166,13 +168,16 @@ jobs: make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" + include: + - os: macos-latest + llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }} steps: - name: checkout uses: actions/checkout@v3 # only download llvm cache when needed - name: Get LLVM libraries - id: cache_llvm + id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') uses: actions/cache@v3 with: @@ -182,10 +187,10 @@ jobs: ./core/deps/llvm/build/lib ./core/deps/llvm/build/libexec ./core/deps/llvm/build/share - key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + key: ${{ matrix.llvm_cache_key }} - name: Quit if cache miss - if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.cache_llvm.outputs.cache-hit != 'true') + if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true') run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: Build iwasm @@ -210,8 +215,14 @@ jobs: #$AOT_BUILD_OPTIONS, ] os: [macos-latest] - wasi_sdk_release: ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-macos.tar.gz"] - wabt_release: ["https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz"] + wasi_sdk_release: + [ + "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz", + ] + wabt_release: + [ + "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-macos-12.tar.gz", + ] steps: - name: checkout uses: actions/checkout@v3 @@ -220,24 +231,14 @@ jobs: run: | cd /opt sudo wget ${{ matrix.wabt_release }} - sudo tar -xzf wabt-1.0.24-*.tar.gz - sudo mv wabt-1.0.24 wabt + sudo tar -xzf wabt-1.0.31-*.tar.gz + sudo mv wabt-1.0.31 wabt - name: Build Sample [wasm-c-api] 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 + cmake -S . -B build ${{ matrix.make_options }} + cmake --build build --config Release --parallel 4 + ctest --test-dir build working-directory: samples/wasm-c-api build_samples_others: @@ -246,8 +247,14 @@ jobs: strategy: matrix: os: [macos-latest] - wasi_sdk_release: ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-macos.tar.gz"] - wabt_release: ["https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz"] + wasi_sdk_release: + [ + "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz", + ] + wabt_release: + [ + "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-macos-12.tar.gz", + ] steps: - name: checkout uses: actions/checkout@v3 @@ -256,15 +263,15 @@ jobs: run: | cd /opt sudo wget ${{ matrix.wasi_sdk_release }} - sudo tar -xzf wasi-sdk-16.0-*.tar.gz - sudo mv wasi-sdk-16.0 wasi-sdk + sudo tar -xzf wasi-sdk-*.tar.gz + sudo mv wasi-sdk-19.0 wasi-sdk - name: download and install wabt run: | cd /opt sudo wget ${{ matrix.wabt_release }} - sudo tar -xzf wabt-1.0.24-*.tar.gz - sudo mv wabt-1.0.24 wabt + sudo tar -xzf wabt-1.0.31-*.tar.gz + sudo mv wabt-1.0.31 wabt - name: build wasi-libc (needed for wasi-threads) run: | diff --git a/.github/workflows/compilation_on_nuttx.yml b/.github/workflows/compilation_on_nuttx.yml index 7df9e87e..c587c041 100644 --- a/.github/workflows/compilation_on_nuttx.yml +++ b/.github/workflows/compilation_on_nuttx.yml @@ -65,9 +65,12 @@ jobs: "boards/risc-v/k210/maix-bit/configs/nsh", ] wamr_config_option: [ - "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n", "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n", + "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_WASI=y\\n", + "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n", "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\n", + "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_WASI=y\\n", + "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n", "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n", "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\n", "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n", @@ -112,7 +115,7 @@ jobs: - name: Enable WAMR for NuttX run: | - find nuttx/boards -name defconfig | xargs sed -i '$a\CONFIG_EOL_IS_LF=y\n${{ matrix.wamr_config_option }}' + find nuttx/boards -name defconfig | xargs sed -i '$a\CONFIG_EOL_IS_LF=y\nCONFIG_PSEUDOFS_SOFTLINKS=y\n${{ matrix.wamr_config_option }}' find nuttx/boards/sim -name defconfig | xargs sed -i '$a\CONFIG_LIBM=y\n' - name: Build diff --git a/.github/workflows/compilation_on_sgx.yml b/.github/workflows/compilation_on_sgx.yml index efcb294a..2988a6fe 100644 --- a/.github/workflows/compilation_on_sgx.yml +++ b/.github/workflows/compilation_on_sgx.yml @@ -51,13 +51,13 @@ env: 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" LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1" LLVM_EAGER_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: build_llvm_libraries: uses: ./.github/workflows/build_llvm_libraries.yml with: - runs-on: "['ubuntu-20.04']" + os: "ubuntu-20.04" + arch: "X86" build_iwasm: runs-on: ${{ matrix.os }} @@ -131,7 +131,9 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-20.04] + include: + - os: ubuntu-20.04 + llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }} steps: - name: install SGX SDK and necessary libraries run: | @@ -150,7 +152,7 @@ jobs: uses: actions/checkout@v3 - name: Get LLVM libraries - id: cache_llvm + id: retrieve_llvm_libs uses: actions/cache@v3 with: path: | @@ -159,10 +161,10 @@ jobs: ./core/deps/llvm/build/lib ./core/deps/llvm/build/libexec ./core/deps/llvm/build/share - key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + key: ${{ matrix.llvm_cache_key }} - name: Quit if cache miss - if: steps.cache_llvm.outputs.cache-hit != 'true' + if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: Build wamrc @@ -189,11 +191,11 @@ jobs: os: [ubuntu-20.04] wasi_sdk_release: [ - "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz", + "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz", ] wabt_release: [ - "https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz", + "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz", ] steps: - name: checkout @@ -203,8 +205,8 @@ jobs: run: | cd /opt sudo wget ${{ matrix.wabt_release }} - sudo tar -xzf wabt-1.0.24-*.tar.gz - sudo mv wabt-1.0.24 wabt + sudo tar -xzf wabt-1.0.31-*.tar.gz + sudo mv wabt-1.0.31 wabt - name: install SGX SDK and necessary libraries run: | @@ -221,19 +223,9 @@ jobs: - name: Build Sample [wasm-c-api] 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 + cmake -S . -B build ${{ matrix.make_options }} + cmake --build build --config Release --parallel 4 + ctest --test-dir build working-directory: samples/wasm-c-api build_samples_others: @@ -244,11 +236,11 @@ jobs: os: [ubuntu-20.04] wasi_sdk_release: [ - "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-linux.tar.gz", + "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz", ] wabt_release: [ - "https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz", + "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz", ] steps: - name: checkout @@ -258,15 +250,15 @@ jobs: run: | cd /opt sudo wget ${{ matrix.wasi_sdk_release }} - sudo tar -xzf wasi-sdk-16.0-*.tar.gz - sudo mv wasi-sdk-16.0 wasi-sdk + sudo tar -xzf wasi-sdk-*.tar.gz + sudo mv wasi-sdk-19.0 wasi-sdk - name: download and install wabt run: | cd /opt sudo wget ${{ matrix.wabt_release }} - sudo tar -xzf wabt-1.0.24-*.tar.gz - sudo mv wabt-1.0.24 wabt + sudo tar -xzf wabt-1.0.31-*.tar.gz + sudo mv wabt-1.0.31 wabt - name: build wasi-libc (needed for wasi-threads) run: | @@ -358,6 +350,7 @@ jobs: matrix: running_mode: ["classic-interp", "fast-interp", "aot"] test_option: ["-x -p -s spec -b -P", "-x -p -s spec -S -b -P"] + llvm_cache_key: ["${{ needs.build_llvm_libraries.outputs.cache_key }}"] # classic-interp and fast-interp don't support simd exclude: - running_mode: "classic-interp" @@ -371,7 +364,7 @@ jobs: - name: Get LLVM libraries if: matrix.running_mode == 'aot' - id: cache_llvm + id: retrieve_llvm_libs uses: actions/cache@v3 with: path: | @@ -380,10 +373,10 @@ jobs: ./core/deps/llvm/build/lib ./core/deps/llvm/build/libexec ./core/deps/llvm/build/share - key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }} + key: ${{ matrix.llvm_cache_key }} - name: Quit if cache miss - if: matrix.running_mode == 'aot' && steps.cache_llvm.outputs.cache-hit != 'true' + if: matrix.running_mode == 'aot' && steps.retrieve_llvm_libs.outputs.cache-hit != 'true' run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: install SGX SDK and necessary libraries diff --git a/.github/workflows/release_process.yml b/.github/workflows/release_process.yml index 824a0823..88f595dd 100644 --- a/.github/workflows/release_process.yml +++ b/.github/workflows/release_process.yml @@ -123,7 +123,7 @@ jobs: runner: ubuntu-20.04 upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver}} - wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz + wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz release_wamr_sdk_on_ubuntu_2204: needs: [create_tag, create_release] @@ -133,7 +133,7 @@ jobs: runner: ubuntu-22.04 upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver}} - wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz + wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz release_wamr_sdk_on_macos: needs: [create_tag, create_release] @@ -143,7 +143,7 @@ jobs: runner: macos-latest upload_url: ${{ needs.create_release.outputs.upload_url }} ver_num: ${{ needs.create_tag.outputs.new_ver}} - wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz + wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz # # vscode extension cross-platform diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 03f99f73..bf39c140 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -16,7 +16,8 @@ jobs: build_llvm_libraries: uses: ./.github/workflows/build_llvm_libraries.yml with: - runs-on: "['ubuntu-22.04']" + os: "ubuntu-22.04" + arch: "ARM RISCV AArch64" spec_test_on_qemu: runs-on: ${{ matrix.os }} @@ -37,6 +38,7 @@ jobs: "-t aot", "-t aot -X" ] + llvm_cache_key: [ "${{ needs.build_llvm_libraries.outputs.cache_key }}" ] steps: - name: Install Utilities run: | @@ -72,7 +74,7 @@ jobs: path: apps/interpreters/wamr/wamr - name: Get LLVM libraries - id: cache_llvm + id: retrieve_llvm_libs uses: actions/cache@v3 with: path: | @@ -81,10 +83,10 @@ jobs: ./core/deps/llvm/build/lib ./core/deps/llvm/build/libexec ./core/deps/llvm/build/share - key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} + key: ${{ matrix.llvm_cache_key }} - name: Quit if cache miss - if: steps.cache_llvm.outputs.cache-hit != 'true' + if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' run: echo "::error::can not get prebuilt llvm libraries" && exit 1 - name: Copy LLVM diff --git a/.gitignore b/.gitignore index a7abd7c1..8b4dce9b 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ samples/socket-api/wasm-src/inc/pthread.h **/__pycache__ tests/benchmarks/coremark/coremark* + +samples/workload/include/** +!samples/workload/include/.gitkeep diff --git a/build-scripts/build_llvm.py b/build-scripts/build_llvm.py index bc0daf1f..1531895c 100755 --- a/build-scripts/build_llvm.py +++ b/build-scripts/build_llvm.py @@ -7,6 +7,7 @@ import argparse import os import pathlib +import requests import shlex import shutil import subprocess @@ -21,28 +22,43 @@ def clone_llvm(dst_dir, llvm_repo, llvm_branch): llvm_dir = dst_dir.joinpath("llvm").resolve() if not llvm_dir.exists(): - print(f"Clone llvm to {llvm_dir} ...") GIT_CLONE_CMD = f"git clone --depth 1 --branch {llvm_branch} {llvm_repo} llvm" subprocess.check_output(shlex.split(GIT_CLONE_CMD), cwd=dst_dir) - else: - print(f"There is an LLVM local repo in {llvm_dir}, clean and keep using it") return llvm_dir -def build_llvm(llvm_dir, platform, backends, projects): +def query_llvm_version(llvm_info): + github_token = os.environ['GH_TOKEN'] + owner_project = llvm_info['repo'].replace("https://github.com/", "").replace(".git", "") + url = f"https://api.github.com/repos/{owner_project}/commits/{llvm_info['branch']}" + headers = { + 'Authorization': f"Bearer {github_token}" + } + + try: + response = requests.request("GET", url, headers=headers, data={}) + response.raise_for_status() + except requests.exceptions.HTTPError as error: + print (error) # for debugging purpose + return None + + response = response.json() + return response['sha'] + + +def build_llvm(llvm_dir, platform, backends, projects, use_clang=False): LLVM_COMPILE_OPTIONS = [ '-DCMAKE_BUILD_TYPE:STRING="Release"', "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "-DLLVM_APPEND_VC_REV:BOOL=ON", - "-DLLVM_BUILD_BENCHMARKS:BOOL=OFF", - "-DLLVM_BUILD_DOCS:BOOL=OFF", "-DLLVM_BUILD_EXAMPLES:BOOL=OFF", "-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF", "-DLLVM_BUILD_TESTS:BOOL=OFF", - "-DLLVM_CCACHE_BUILD:BOOL=OFF", + "-DLLVM_CCACHE_BUILD:BOOL=ON", "-DLLVM_ENABLE_BINDINGS:BOOL=OFF", "-DLLVM_ENABLE_IDE:BOOL=OFF", + "-DLLVM_ENABLE_LIBEDIT=OFF", "-DLLVM_ENABLE_TERMINFO:BOOL=OFF", "-DLLVM_ENABLE_ZLIB:BOOL=OFF", "-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF", @@ -54,6 +70,18 @@ def build_llvm(llvm_dir, platform, backends, projects): "-DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON", ] + # use clang/clang++/lld. but macos doesn't support lld + if not sys.platform.startswith("darwin") and use_clang: + if shutil.which("clang") and shutil.which("clang++") and shutil.which("lld"): + os.environ["CC"] = "clang" + os.environ["CXX"] = "clang++" + LLVM_COMPILE_OPTIONS.append('-DLLVM_USE_LINKER:STRING="lld"') + print("Use the clang toolchain") + else: + print("Can not find clang, clang++ and lld, keep using the gcc toolchain") + else: + print("Use the gcc toolchain") + LLVM_EXTRA_COMPILE_OPTIONS = { "arc": [ '-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="ARC"', @@ -99,8 +127,10 @@ def build_llvm(llvm_dir, platform, backends, projects): lib_llvm_core_library = build_dir.joinpath("lib/libLLVMCore.a").resolve() if lib_llvm_core_library.exists(): - print(f"Please remove {build_dir} manually and try again") - return build_dir + print( + f"It has already been fully compiled. If want to a re-build, please remove {build_dir} manually and try again" + ) + return None compile_options = " ".join( LLVM_COMPILE_OPTIONS @@ -119,10 +149,11 @@ def build_llvm(llvm_dir, platform, backends, projects): CONFIG_CMD += " -G'Unix Makefiles'" else: CONFIG_CMD += " -A x64" - print(f"{CONFIG_CMD}") + else: + CONFIG_CMD += " -G'Ninja'" subprocess.check_call(shlex.split(CONFIG_CMD), cwd=build_dir) - BUILD_CMD = f"cmake --build . --target package --parallel {os.cpu_count()}" + ( + BUILD_CMD = "cmake --build . --target package" + ( " --config Release" if "windows" == platform else "" ) subprocess.check_call(shlex.split(BUILD_CMD), cwd=build_dir) @@ -133,23 +164,25 @@ def build_llvm(llvm_dir, platform, backends, projects): def repackage_llvm(llvm_dir): build_dir = llvm_dir.joinpath("./build").resolve() - packs = [f for f in build_dir.glob("LLVM-13*.tar.gz")] + packs = [f for f in build_dir.glob("LLVM-*.tar.gz")] if len(packs) > 1: - raise Exception("Find more than one LLVM-13*.tar.gz") + raise Exception("Find more than one LLVM-*.tar.gz") if not packs: return llvm_package = packs[0].name - # mv build/LLVM-13.0.0*.gz . + # mv build/LLVM-*.gz . shutil.move(str(build_dir.joinpath(llvm_package).resolve()), str(llvm_dir)) # rm -r build shutil.rmtree(str(build_dir)) # mkdir build build_dir.mkdir() - # tar xf ./LLVM-13.0.0-*.tar.gz --strip-components=1 --directory=build + # tar xf ./LLVM-*.tar.gz --strip-components=1 --directory=build CMD = f"tar xf {llvm_dir.joinpath(llvm_package).resolve()} --strip-components=1 --directory={build_dir}" subprocess.check_call(shlex.split(CMD), cwd=llvm_dir) + # rm ./LLVM-1*.gz + os.remove(llvm_dir.joinpath(llvm_package).resolve()) def main(): @@ -184,8 +217,17 @@ def main(): choices=["clang", "lldb"], help="identify extra LLVM projects, separate by space, like '--project clang lldb'", ) + parser.add_argument( + "--llvm-ver", + action="store_true", + help="return the version info of generated llvm libraries", + ) + parser.add_argument( + "--use-clang", + action="store_true", + help="use clang instead of gcc", + ) options = parser.parse_args() - print(f"options={options}") # if the "platform" is not identified in the command line option, # detect it @@ -199,12 +241,10 @@ def main(): else: platform = options.platform - print(f"========== Build LLVM for {platform} ==========\n") - llvm_repo_and_branch = { "arc": { "repo": "https://github.com/llvm/llvm-project.git", - "branch": "release/13.x", + "branch": "release/15.x", }, "xtensa": { "repo": "https://github.com/espressif/llvm-project.git", @@ -212,7 +252,7 @@ def main(): }, "default": { "repo": "https://github.com/llvm/llvm-project.git", - "branch": "release/13.x", + "branch": "release/15.x", }, } @@ -225,19 +265,22 @@ def main(): deps_dir = current_dir.joinpath("../core/deps").resolve() try: - print(f"==================== CLONE LLVM ====================") llvm_info = llvm_repo_and_branch.get(platform, llvm_repo_and_branch["default"]) + + if options.llvm_ver: + commit_hash = query_llvm_version(llvm_info) + print(commit_hash) + return commit_hash is not None + llvm_dir = clone_llvm(deps_dir, llvm_info["repo"], llvm_info["branch"]) + if ( + build_llvm( + llvm_dir, platform, options.arch, options.project, options.use_clang + ) + is not None + ): + repackage_llvm(llvm_dir) - print() - print(f"==================== BUILD LLVM ====================") - build_llvm(llvm_dir, platform, options.arch, options.project) - - print() - print(f"==================== PACKAGE LLVM ====================") - repackage_llvm(llvm_dir) - - print() return True except subprocess.CalledProcessError: return False diff --git a/build-scripts/requirements.txt b/build-scripts/requirements.txt new file mode 100644 index 00000000..bf0d9d41 --- /dev/null +++ b/build-scripts/requirements.txt @@ -0,0 +1 @@ +requests==2.28.2 \ No newline at end of file diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index 4130894d..5464ae19 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -19,6 +19,11 @@ endif () if (NOT DEFINED DEPS_DIR) set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps) endif () +if (NOT DEFINED SHARED_PLATFORM_CONFIG) + # CMake file for platform configuration. The PLATFORM_SHARED_SOURCE varable + # should point to a list of platform-specfic source files to compile. + set (SHARED_PLATFORM_CONFIG ${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) +endif () if (DEFINED EXTRA_SDK_INCLUDE_PATH) message(STATUS, "EXTRA_SDK_INCLUDE_PATH = ${EXTRA_SDK_INCLUDE_PATH} ") @@ -96,9 +101,13 @@ if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1) endif () if (WAMR_BUILD_WASI_NN EQUAL 1) - execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh - RESULT_VARIABLE TENSORFLOW_RESULT - ) + if (NOT EXISTS "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") + execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh + RESULT_VARIABLE TENSORFLOW_RESULT + ) + else () + message("Tensorflow is already downloaded.") + endif() set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include) include_directories (${TENSORFLOW_SOURCE_DIR}) @@ -169,7 +178,7 @@ LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) enable_language (ASM) -include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) +include (${SHARED_PLATFORM_CONFIG}) include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) include (${IWASM_DIR}/common/iwasm_common.cmake) include (${SHARED_DIR}/utils/shared_utils.cmake) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 5fa5438b..0c94ef7c 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -30,6 +30,8 @@ bh_static_assert(offsetof(WASMExecEnv, aux_stack_boundary) bh_static_assert(offsetof(WASMExecEnv, aux_stack_bottom) == 7 * sizeof(uintptr_t)); bh_static_assert(offsetof(WASMExecEnv, native_symbol) == 8 * sizeof(uintptr_t)); +bh_static_assert(offsetof(WASMExecEnv, native_stack_top_min) + == 9 * sizeof(uintptr_t)); bh_static_assert(offsetof(AOTModuleInstance, memories) == 1 * sizeof(uint64)); bh_static_assert(offsetof(AOTModuleInstance, func_ptrs) == 5 * sizeof(uint64)); @@ -1083,6 +1085,17 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size, } #endif +#if WASM_ENABLE_WASI_NN != 0 + if (!is_sub_inst) { + if (!(((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx = + wasi_nn_initialize())) { + set_error_buf(error_buf, error_buf_size, + "wasi nn initialization failed"); + goto fail; + } + } +#endif + /* Initialize the thread related data */ if (stack_size == 0) stack_size = DEFAULT_WASM_STACK_SIZE; @@ -1194,6 +1207,15 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) wasm_runtime_free( ((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports); +#if WASM_ENABLE_WASI_NN != 0 + if (!is_sub_inst) { + WASINNContext *wasi_nn_ctx = + ((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx; + if (wasi_nn_ctx) + wasi_nn_destroy(wasi_nn_ctx); + } +#endif + wasm_runtime_free(module_inst); } @@ -1237,6 +1259,7 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, /* Check native stack overflow firstly to ensure we have enough native stack to run the following codes before actually calling the aot function in invokeNative function. */ + RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst); if ((uint8 *)&module_inst < exec_env->native_stack_boundary + page_size * (guard_page_count + 1)) { aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); @@ -1836,6 +1859,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx, exec_env->native_stack_boundary must have been set, we don't set it again */ + RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst); if ((uint8 *)&module_inst < exec_env->native_stack_boundary) { aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); goto fail; diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index a6371729..de12bdaa 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -11,6 +11,10 @@ #include "../interpreter/wasm_runtime.h" #include "../compilation/aot.h" +#if WASM_ENABLE_WASI_NN != 0 +#include "../libraries/wasi-nn/src/wasi_nn_private.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -75,6 +79,9 @@ typedef struct AOTFunctionInstance { typedef struct AOTModuleInstanceExtra { CApiFuncImport *c_api_func_imports; +#if WASM_ENABLE_WASI_NN != 0 + WASINNContext *wasi_nn_ctx; +#endif } AOTModuleInstanceExtra; #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) diff --git a/core/iwasm/common/arch/invokeNative_ia32.s b/core/iwasm/common/arch/invokeNative_ia32.s index 0056a53e..de1c1a5e 100644 --- a/core/iwasm/common/arch/invokeNative_ia32.s +++ b/core/iwasm/common/arch/invokeNative_ia32.s @@ -16,9 +16,14 @@ _invokeNative: push %ebp movl %esp, %ebp movl 16(%ebp), %ecx /* ecx = argc */ - movl 12(%ebp), %edx /* edx = argv */ + leal 2(%ecx), %edx /* edx = ecx + 2 (count return address and saved ebp) */ + andl $3, %edx /* edx = edx % 4 */ + jz stack_aligned /* if edx == 0, stack is already 16 bytes aligned */ + leal -16(%esp, %edx, 4), %esp /* esp = esp - 16 + edx * 4 */ +stack_aligned: test %ecx, %ecx jz skip_push_args /* if ecx == 0, skip pushing arguments */ + movl 12(%ebp), %edx /* edx = argv */ leal -4(%edx,%ecx,4), %edx /* edx = edx + ecx * 4 - 4 */ subl %esp, %edx /* edx = edx - esp */ 1: diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 10398b26..d3c8ea1e 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -276,7 +276,7 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete) WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete) #ifndef NDEBUG -#if WAMR_BUILD_MEMORY_PROFILING != 0 +#if WASM_ENABLE_MEMORY_PROFILING != 0 #define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM() #else #define WASM_C_DUMP_PROC_MEM() (void)0 @@ -398,7 +398,7 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts) } /* global engine instance */ -static wasm_engine_t *singleton_engine = NULL; +static wasm_engine_t *singleton_engine; #ifdef os_thread_local_attribute /* categorize wasm_store_t as threads*/ static os_thread_local_attribute unsigned thread_local_stores_num = 0; @@ -1458,6 +1458,30 @@ wasm_importtype_type(const wasm_importtype_t *import_type) return import_type->extern_type; } +bool +wasm_importtype_is_linked(const wasm_importtype_t *import_type) +{ + if (!import_type) + return false; + + const wasm_name_t *module_name = wasm_importtype_module(import_type); + const wasm_name_t *field_name = wasm_importtype_name(import_type); + + switch (wasm_externtype_kind(wasm_importtype_type(import_type))) { + case WASM_EXTERN_FUNC: + return wasm_runtime_is_import_func_linked(module_name->data, + field_name->data); + case WASM_EXTERN_GLOBAL: + return wasm_runtime_is_import_global_linked(module_name->data, + field_name->data); + case WASM_EXTERN_MEMORY: + case WASM_EXTERN_TABLE: + default: + break; + } + return false; +} + own wasm_exporttype_t * wasm_exporttype_new(own wasm_byte_vec_t *name, own wasm_externtype_t *extern_type) @@ -2537,12 +2561,12 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out) bh_assert(extern_type); - wasm_name_new_from_string(&module_name, module_name_rt); + wasm_name_new_from_string_nt(&module_name, module_name_rt); if (strlen(module_name_rt) && !module_name.data) { goto failed; } - wasm_name_new_from_string(&name, field_name_rt); + wasm_name_new_from_string_nt(&name, field_name_rt); if (strlen(field_name_rt) && !name.data) { goto failed; } @@ -2622,7 +2646,7 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out) } /* byte* -> wasm_byte_vec_t */ - wasm_name_new_from_string(&name, export->name); + wasm_name_new_from_string_nt(&name, export->name); if (strlen(export->name) && !name.data) { goto failed; } @@ -3008,6 +3032,20 @@ failed: return NULL; } +static wasm_func_t * +wasm_func_new_empty(wasm_store_t *store) +{ + wasm_func_t *func = NULL; + + if (!(func = malloc_internal(sizeof(wasm_func_t)))) + goto failed; + + func->store = store; + func->kind = WASM_EXTERN_FUNC; + + RETURN_OBJ(func, wasm_func_delete) +} + void wasm_func_delete(wasm_func_t *func) { @@ -3211,7 +3249,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params, wasm_name_t message = { 0 }; wasm_trap_t *trap; - wasm_name_new_from_string(&message, "failed to call unlinked function"); + wasm_name_new_from_string_nt(&message, + "failed to call unlinked function"); trap = wasm_trap_new(func->store, &message); wasm_byte_vec_delete(&message); @@ -3371,6 +3410,25 @@ failed: return NULL; } +static wasm_global_t * +wasm_global_new_empty(wasm_store_t *store) +{ + wasm_global_t *global = NULL; + + global = malloc_internal(sizeof(wasm_global_t)); + if (!global) + goto failed; + + global->store = store; + global->kind = WASM_EXTERN_GLOBAL; + + return global; +failed: + LOG_DEBUG("%s failed", __FUNCTION__); + wasm_global_delete(global); + return NULL; +} + /* almost same with wasm_global_new */ wasm_global_t * wasm_global_copy(const wasm_global_t *src) @@ -4205,7 +4263,8 @@ wasm_memory_data_size(const wasm_memory_t *memory) (WASMModuleInstance *)module_inst_comm; WASMMemoryInstance *memory_inst = module_inst->memories[memory->memory_idx_rt]; - return memory_inst->cur_page_count * memory_inst->num_bytes_per_page; + return (size_t)memory_inst->cur_page_count + * memory_inst->num_bytes_per_page; } #endif @@ -4215,7 +4274,8 @@ wasm_memory_data_size(const wasm_memory_t *memory) AOTMemoryInstance *memory_inst = ((AOTMemoryInstance **) module_inst->memories)[memory->memory_idx_rt]; - return memory_inst->cur_page_count * memory_inst->num_bytes_per_page; + return (size_t)memory_inst->cur_page_count + * memory_inst->num_bytes_per_page; } #endif @@ -4286,6 +4346,11 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp, imported_func_interp = module_interp->import_functions + func_idx_rt; bh_assert(imported_func_interp); + bh_assert(imported_func_interp->kind == IMPORT_KIND_FUNC); + + /* it is a placeholder and let's skip it*/ + if (!import->type) + return true; /* type comparison */ if (!wasm_functype_same_internal( @@ -4300,6 +4365,8 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp, imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb; else imported_func_interp->u.function.func_ptr_linked = import->u.cb; + bh_assert(imported_func_interp->u.function.func_ptr_linked); + import->func_idx_rt = func_idx_rt; (void)inst; @@ -4318,12 +4385,19 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt, imported_global_interp = module_interp->import_globals + global_idx_rt; bh_assert(imported_global_interp); + bh_assert(imported_global_interp->kind == IMPORT_KIND_GLOBAL); + /* it is a placeholder and let's skip it*/ + if (!import->type) + return true; + + /* type comparison */ if (!cmp_val_kind_with_val_type(wasm_valtype_kind(import->type->val_type), imported_global_interp->u.global.type)) return false; /* set init value */ + bh_assert(import->init); switch (wasm_valtype_kind(import->type->val_type)) { case WASM_I32: imported_global_interp->u.global.global_data_linked.i32 = @@ -4350,58 +4424,6 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt, return true; } -static bool -interp_link(const wasm_instance_t *inst, const WASMModule *module_interp, - wasm_extern_t *imports[]) -{ - uint32 i = 0; - uint32 import_func_i = 0; - uint32 import_global_i = 0; - - bh_assert(inst && module_interp && imports); - - for (i = 0; i < module_interp->import_count; ++i) { - wasm_extern_t *import = imports[i]; - WASMImport *import_rt = module_interp->imports + i; - - switch (import_rt->kind) { - case IMPORT_KIND_FUNC: - { - if (!interp_link_func(inst, module_interp, import_func_i, - wasm_extern_as_func(import))) { - LOG_WARNING("link #%d function failed", import_func_i); - goto failed; - } - import_func_i++; - break; - } - case IMPORT_KIND_GLOBAL: - { - if (!interp_link_global(module_interp, import_global_i, - wasm_extern_as_global(import))) { - LOG_WARNING("link #%d global failed", import_global_i); - goto failed; - } - import_global_i++; - break; - } - case IMPORT_KIND_MEMORY: - case IMPORT_KIND_TABLE: - default: - ASSERT_NOT_IMPLEMENTED(); - LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__, - import_rt->kind); - goto failed; - } - } - - return true; - -failed: - LOG_DEBUG("%s failed", __FUNCTION__); - return false; -} - static bool interp_process_export(wasm_store_t *store, const WASMModuleInstance *inst_interp, @@ -4501,6 +4523,10 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot, import_aot_func = module_aot->import_funcs + import_func_idx_rt; bh_assert(import_aot_func); + /* it is a placeholder and let's skip it*/ + if (!import->type) + return true; + /* type comparison */ if (!wasm_functype_same_internal(import->type, import_aot_func->func_type)) return false; @@ -4513,6 +4539,8 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot, import_aot_func->func_ptr_linked = import->u.cb_env.cb; else import_aot_func->func_ptr_linked = import->u.cb; + bh_assert(import_aot_func->func_ptr_linked); + import->func_idx_rt = import_func_idx_rt; return true; @@ -4530,6 +4558,10 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt, import_aot_global = module_aot->import_globals + global_idx_rt; bh_assert(import_aot_global); + /* it is a placeholder and let's skip it*/ + if (!import->type) + return true; + val_type = wasm_globaltype_content(import->type); bh_assert(val_type); @@ -4537,6 +4569,7 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt, import_aot_global->type)) return false; + bh_assert(import->init); switch (wasm_valtype_kind(val_type)) { case WASM_I32: import_aot_global->global_data_linked.i32 = import->init->of.i32; @@ -4557,62 +4590,6 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt, import->global_idx_rt = global_idx_rt; import_aot_global->is_linked = true; return true; - -failed: - LOG_DEBUG("%s failed", __FUNCTION__); - return false; -} - -static bool -aot_link(const wasm_instance_t *inst, const AOTModule *module_aot, - wasm_extern_t *imports[]) -{ - uint32 i = 0; - uint32 import_func_i = 0; - uint32 import_global_i = 0; - wasm_extern_t *import = NULL; - wasm_func_t *func = NULL; - wasm_global_t *global = NULL; - - bh_assert(inst && module_aot && imports); - - while (import_func_i < module_aot->import_func_count - || import_global_i < module_aot->import_global_count) { - import = imports[i++]; - - bh_assert(import); - - switch (wasm_extern_kind(import)) { - case WASM_EXTERN_FUNC: - bh_assert(import_func_i < module_aot->import_func_count); - func = wasm_extern_as_func((wasm_extern_t *)import); - if (!aot_link_func(inst, module_aot, import_func_i, func)) { - LOG_WARNING("link #%d function failed", import_func_i); - goto failed; - } - import_func_i++; - - break; - case WASM_EXTERN_GLOBAL: - bh_assert(import_global_i < module_aot->import_global_count); - global = wasm_extern_as_global((wasm_extern_t *)import); - if (!aot_link_global(module_aot, import_global_i, global)) { - LOG_WARNING("link #%d global failed", import_global_i); - goto failed; - } - import_global_i++; - - break; - case WASM_EXTERN_MEMORY: - case WASM_EXTERN_TABLE: - default: - ASSERT_NOT_IMPLEMENTED(); - goto failed; - } - } - - return true; - failed: LOG_DEBUG("%s failed", __FUNCTION__); return false; @@ -4693,7 +4670,7 @@ aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot, goto failed; } - wasm_name_new_from_string(external->name, export->name); + wasm_name_new_from_string_nt(external->name, export->name); if (strlen(export->name) && !external->name->data) { goto failed; } @@ -4711,6 +4688,95 @@ failed: } #endif /* WASM_ENABLE_AOT */ +static bool +do_link(const wasm_instance_t *inst, const wasm_module_t *module, + const wasm_extern_vec_t *imports) +{ + uint32 i, import_func_i, import_global_i; + + bh_assert(inst && module); + + /* we have run a module_type check before. */ + + for (i = 0, import_func_i = 0, import_global_i = 0; i < imports->num_elems; + i++) { + wasm_extern_t *import = imports->data[i]; + + if (!import) { + LOG_ERROR("imports[%d] is NULL and it is fatal\n", i); + goto failed; + } + + switch (wasm_extern_kind(import)) { + case WASM_EXTERN_FUNC: + { + bool ret = false; +#if WASM_ENABLE_INTERP != 0 + if ((*module)->module_type == Wasm_Module_Bytecode) { + ret = interp_link_func(inst, MODULE_INTERP(module), + import_func_i, + wasm_extern_as_func(import)); + } +#endif +#if WASM_ENABLE_AOT != 0 + if ((*module)->module_type == Wasm_Module_AoT) { + ret = aot_link_func(inst, MODULE_AOT(module), import_func_i, + wasm_extern_as_func(import)); + } +#endif + if (!ret) { + LOG_WARNING("link function #%d failed", import_func_i); + goto failed; + } + + import_func_i++; + break; + } + case WASM_EXTERN_GLOBAL: + { + bool ret = false; +#if WASM_ENABLE_INTERP != 0 + if ((*module)->module_type == Wasm_Module_Bytecode) { + ret = interp_link_global(MODULE_INTERP(module), + import_global_i, + wasm_extern_as_global(import)); + } +#endif +#if WASM_ENABLE_AOT != 0 + if ((*module)->module_type == Wasm_Module_AoT) { + ret = aot_link_global(MODULE_AOT(module), import_global_i, + wasm_extern_as_global(import)); + } +#endif + if (!ret) { + LOG_WARNING("link global #%d failed", import_global_i); + goto failed; + } + + import_global_i++; + break; + } + case WASM_EXTERN_MEMORY: + case WASM_EXTERN_TABLE: + { + LOG_WARNING("doesn't support import memories and tables for " + "now, ignore them"); + break; + } + default: + { + UNREACHABLE(); + break; + } + } + } + + return true; +failed: + LOG_DEBUG("%s failed", __FUNCTION__); + return false; +} + wasm_instance_t * wasm_instance_new(wasm_store_t *store, const wasm_module_t *module, const wasm_extern_vec_t *imports, own wasm_trap_t **trap) @@ -4719,57 +4785,6 @@ wasm_instance_new(wasm_store_t *store, const wasm_module_t *module, KILOBYTE(32), KILOBYTE(32)); } -static bool -compare_imports(const wasm_module_t *module, const wasm_extern_vec_t *imports) -{ - unsigned import_func_count = 0; - unsigned import_global_count = 0; - unsigned import_memory_count = 0; - unsigned import_table_count = 0; - unsigned i = 0; - - for (i = 0; imports && i < imports->num_elems; i++) { - wasm_extern_t *import = imports->data[i]; - switch (wasm_extern_kind(import)) { - case WASM_EXTERN_FUNC: - import_func_count++; - break; - case WASM_EXTERN_GLOBAL: - import_global_count++; - break; - case WASM_EXTERN_MEMORY: - import_memory_count++; - break; - case WASM_EXTERN_TABLE: - import_table_count++; - break; - default: - UNREACHABLE(); - return false; - } - } - -#if WASM_ENABLE_INTERP != 0 - if ((*module)->module_type == Wasm_Module_Bytecode) - return import_func_count == MODULE_INTERP(module)->import_function_count - && import_global_count - == MODULE_INTERP(module)->import_global_count - && import_memory_count - == MODULE_INTERP(module)->import_memory_count - && import_table_count - == MODULE_INTERP(module)->import_table_count; -#endif -#if WASM_ENABLE_AOT != 0 - if ((*module)->module_type == Wasm_Module_AoT) - return import_func_count == MODULE_AOT(module)->import_func_count - && import_global_count == MODULE_AOT(module)->import_global_count - && import_memory_count == MODULE_AOT(module)->import_memory_count - && import_table_count == MODULE_AOT(module)->import_table_count; -#endif - - return false; -} - wasm_instance_t * wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, const wasm_extern_vec_t *imports, @@ -4779,7 +4794,6 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, char sub_error_buf[128] = { 0 }; char error_buf[256] = { 0 }; wasm_instance_t *instance = NULL; - WASMModuleInstance *inst_rt; CApiFuncImport *func_import = NULL, **p_func_imports = NULL; uint32 i = 0, import_func_count = 0; uint64 total_size; @@ -4790,11 +4804,9 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, if (!module) return NULL; - if (!compare_imports(module, imports)) { - snprintf(sub_error_buf, sizeof(sub_error_buf), - "Failed to match imports"); - goto failed; - } + /* + * will do the check at the end of wasm_runtime_instantiate + */ WASM_C_DUMP_PROC_MEM(); @@ -4805,43 +4817,17 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, goto failed; } - /* link module and imports */ - if (imports && imports->num_elems) { - bool link = false; -#if WASM_ENABLE_INTERP != 0 - if ((*module)->module_type == Wasm_Module_Bytecode) { - if (!interp_link(instance, MODULE_INTERP(module), - (wasm_extern_t **)imports->data)) { - snprintf(sub_error_buf, sizeof(sub_error_buf), - "Failed to validate imports"); - goto failed; - } - link = true; - } -#endif - -#if WASM_ENABLE_AOT != 0 - if ((*module)->module_type == Wasm_Module_AoT) { - if (!aot_link(instance, MODULE_AOT(module), - (wasm_extern_t **)imports->data)) { - snprintf(sub_error_buf, sizeof(sub_error_buf), - "Failed to validate imports"); - goto failed; - } - link = true; - } -#endif - - /* - * a wrong combination of module filetype and compilation flags - * also leads to below branch - */ - if (!link) { + /* executes the instantiate-time linking if provided */ + if (imports) { + if (!do_link(instance, module, imports)) { snprintf(sub_error_buf, sizeof(sub_error_buf), - "Failed to verify import count"); + "Failed to validate imports"); goto failed; } } + /* + * will do the linking result check at the end of wasm_runtime_instantiate + */ instance->inst_comm_rt = wasm_runtime_instantiate( *module, stack_size, heap_size, sub_error_buf, sizeof(sub_error_buf)); @@ -4856,18 +4842,22 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, } /* create the c-api func import list */ - inst_rt = (WASMModuleInstance *)instance->inst_comm_rt; #if WASM_ENABLE_INTERP != 0 if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) { - p_func_imports = &inst_rt->e->c_api_func_imports; - import_func_count = inst_rt->module->import_function_count; + WASMModuleInstanceExtra *e = + ((WASMModuleInstance *)instance->inst_comm_rt)->e; + p_func_imports = &(e->c_api_func_imports); + import_func_count = MODULE_INTERP(module)->import_function_count; } #endif #if WASM_ENABLE_AOT != 0 if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) { - p_func_imports = - &((AOTModuleInstanceExtra *)inst_rt->e)->c_api_func_imports; - import_func_count = ((AOTModule *)inst_rt->module)->import_func_count; + AOTModuleInstanceExtra *e = + (AOTModuleInstanceExtra *)((AOTModuleInstance *) + instance->inst_comm_rt) + ->e; + p_func_imports = &(e->c_api_func_imports); + import_func_count = MODULE_AOT(module)->import_func_count; } #endif bh_assert(p_func_imports); @@ -4880,16 +4870,21 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, goto failed; } - /* fill in c-api func import list */ + /* fill in module_inst->e->c_api_func_imports */ for (i = 0; imports && i < imports->num_elems; i++) { - wasm_func_t *func_host; - wasm_extern_t *in; + wasm_func_t *func_host = NULL; + wasm_extern_t *in = imports->data[i]; + bh_assert(in); - in = imports->data[i]; if (wasm_extern_kind(in) != WASM_EXTERN_FUNC) continue; func_host = wasm_extern_as_func(in); + /* it is a placeholder and let's skip it*/ + if (!func_host->type) { + func_import++; + continue; + } func_import->with_env_arg = func_host->with_env; if (func_host->with_env) { @@ -4900,6 +4895,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, func_import->func_ptr_linked = func_host->u.cb; func_import->env_arg = NULL; } + bh_assert(func_import->func_ptr_linked); func_import++; } @@ -4907,6 +4903,8 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, /* fill with inst */ for (i = 0; imports && imports->data && i < imports->num_elems; ++i) { wasm_extern_t *import = imports->data[i]; + bh_assert(import); + switch (import->kind) { case WASM_EXTERN_FUNC: wasm_extern_as_func(import)->inst_comm_rt = @@ -5002,7 +5000,7 @@ failed: sub_error_buf); if (trap != NULL) { wasm_message_t message = { 0 }; - wasm_name_new_from_string(&message, error_buf); + wasm_name_new_from_string_nt(&message, error_buf); *trap = wasm_trap_new(store, &message); wasm_byte_vec_delete(&message); } @@ -5202,3 +5200,16 @@ BASIC_FOUR_LIST(WASM_EXTERN_AS_OTHER_CONST) BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN_CONST) #undef WASM_OTHER_AS_EXTERN_CONST + +wasm_extern_t * +wasm_extern_new_empty(wasm_store_t *store, wasm_externkind_t extern_kind) +{ + if (extern_kind == WASM_EXTERN_FUNC) + return wasm_func_as_extern(wasm_func_new_empty(store)); + + if (extern_kind == WASM_EXTERN_GLOBAL) + return wasm_global_as_extern(wasm_global_new_empty(store)); + + LOG_ERROR("Don't support linking table and memory for now"); + return NULL; +} diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c index 7939c759..9bd74d7d 100644 --- a/core/iwasm/common/wasm_exec_env.c +++ b/core/iwasm/common/wasm_exec_env.c @@ -211,6 +211,7 @@ wasm_exec_env_set_thread_info(WASMExecEnv *exec_env) exec_env->handle = os_self_thread(); exec_env->native_stack_boundary = stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL; + exec_env->native_stack_top_min = (void *)UINTPTR_MAX; } #if WASM_ENABLE_THREAD_MGR != 0 diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h index 72f973e7..29b28a15 100644 --- a/core/iwasm/common/wasm_exec_env.h +++ b/core/iwasm/common/wasm_exec_env.h @@ -84,6 +84,12 @@ typedef struct WASMExecEnv { void **native_symbol; #endif + /* + * The lowest stack pointer value observed. + * Assumption: native stack grows to the lower address. + */ + uint8 *native_stack_top_min; + #if WASM_ENABLE_FAST_JIT != 0 /** * Cache for @@ -165,6 +171,17 @@ typedef struct WASMExecEnv { } wasm_stack; } WASMExecEnv; +#if WASM_ENABLE_MEMORY_PROFILING != 0 +#define RECORD_STACK_USAGE(e, p) \ + do { \ + if ((e)->native_stack_top_min > (p)) { \ + (e)->native_stack_top_min = (p); \ + } \ + } while (0) +#else +#define RECORD_STACK_USAGE(e, p) (void)0 +#endif + WASMExecEnv * wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst, uint32 stack_size); diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index e80d4e78..1acaed6e 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -250,6 +250,10 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols, return NULL; } +/** + * allow func_type and all outputs, like p_signature, p_attachment and + * p_call_conv_raw to be NULL + */ void * wasm_native_resolve_symbol(const char *module_name, const char *field_name, const WASMType *func_type, const char **p_signature, @@ -275,10 +279,13 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name, node = node_next; } + if (!p_signature || !p_attachment || !p_call_conv_raw) + return func_ptr; + if (func_ptr) { if (signature && signature[0] != '\0') { /* signature is not empty, check its format */ - if (!check_symbol_signature(func_type, signature)) { + if (!func_type || !check_symbol_signature(func_type, signature)) { #if WASM_ENABLE_WAMR_COMPILER == 0 /* Output warning except running aot compiler */ LOG_WARNING("failed to check signature '%s' and resolve " diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index aed92edf..c820de7b 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -7,6 +7,7 @@ #include "bh_common.h" #include "bh_assert.h" #include "bh_log.h" +#include "wasm_native.h" #include "wasm_runtime_common.h" #include "wasm_memory.h" #if WASM_ENABLE_INTERP != 0 @@ -128,6 +129,12 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst, static JitCompOptions jit_options = { 0 }; #endif +#if WASM_ENABLE_JIT != 0 +static LLVMJITOptions llvm_jit_options = { 3, 3 }; +#endif + +static RunningMode runtime_running_mode = Mode_Default; + #ifdef OS_ENABLE_HW_BOUND_CHECK /* The exec_env of thread local storage, set before calling function and used in signal handler, as we cannot get it from the argument @@ -514,6 +521,20 @@ wasm_runtime_destroy() wasm_runtime_memory_destroy(); } +RunningMode +wasm_runtime_get_default_running_mode(void) +{ + return runtime_running_mode; +} + +#if WASM_ENABLE_JIT != 0 +LLVMJITOptions +wasm_runtime_get_llvm_jit_options(void) +{ + return llvm_jit_options; +} +#endif + bool wasm_runtime_full_init(RuntimeInitArgs *init_args) { @@ -521,10 +542,20 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args) &init_args->mem_alloc_option)) return false; + if (!wasm_runtime_set_default_running_mode(init_args->running_mode)) { + wasm_runtime_memory_destroy(); + return false; + } + #if WASM_ENABLE_FAST_JIT != 0 jit_options.code_cache_size = init_args->fast_jit_code_cache_size; #endif +#if WASM_ENABLE_JIT != 0 + llvm_jit_options.size_level = init_args->llvm_jit_size_level; + llvm_jit_options.opt_level = init_args->llvm_jit_opt_level; +#endif + if (!wasm_runtime_env_init()) { wasm_runtime_memory_destroy(); return false; @@ -554,6 +585,47 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args) return true; } +bool +wasm_runtime_is_running_mode_supported(RunningMode running_mode) +{ + if (running_mode == Mode_Default) { + return true; + } + else if (running_mode == Mode_Interp) { +#if WASM_ENABLE_INTERP != 0 + return true; +#endif + } + else if (running_mode == Mode_Fast_JIT) { +#if WASM_ENABLE_FAST_JIT != 0 + return true; +#endif + } + else if (running_mode == Mode_LLVM_JIT) { +#if WASM_ENABLE_JIT != 0 + return true; +#endif + } + else if (running_mode == Mode_Multi_Tier_JIT) { +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + return true; +#endif + } + + return false; +} + +bool +wasm_runtime_set_default_running_mode(RunningMode running_mode) +{ + if (wasm_runtime_is_running_mode_supported(running_mode)) { + runtime_running_mode = running_mode; + return true; + } + return false; +} + PackageType get_package_type(const uint8 *buf, uint32 size) { @@ -1171,6 +1243,41 @@ wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst, #endif } +bool +wasm_runtime_set_running_mode(wasm_module_inst_t module_inst, + RunningMode running_mode) +{ +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return true; +#endif + +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + WASMModuleInstance *module_inst_interp = + (WASMModuleInstance *)module_inst; + + return wasm_set_running_mode(module_inst_interp, running_mode); + } +#endif + + return false; +} + +RunningMode +wasm_runtime_get_running_mode(wasm_module_inst_t module_inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + WASMModuleInstance *module_inst_interp = + (WASMModuleInstance *)module_inst; + return module_inst_interp->e->running_mode; + } +#endif + + return Mode_Default; +} + void wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst) { @@ -1399,6 +1506,22 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env) else os_printf("Total aux stack used: no enough info to profile\n"); + /* + * Report the native stack usage estimation. + * + * Unlike the aux stack above, we report the amount unused + * because we don't know the stack "bottom". + * + * Note that this is just about what the runtime itself observed. + * It doesn't cover host func implementations, signal handlers, etc. + */ + if (exec_env->native_stack_top_min != (void *)UINTPTR_MAX) + os_printf("Native stack left: %zd\n", + exec_env->native_stack_top_min + - exec_env->native_stack_boundary); + else + os_printf("Native stack left: no enough info to profile\n"); + os_printf("Total app heap used: %u\n", app_heap_peak_size); } #endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \ @@ -2195,6 +2318,12 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) if (exec_env) { wasm_cluster_spread_exception(exec_env, exception ? false : true); } +#if WASM_ENABLE_SHARED_MEMORY + if (exception) { + notify_stale_threads_on_exception( + (WASMModuleInstanceCommon *)module_inst); + } +#endif #else (void)exec_env; #endif @@ -2219,9 +2348,7 @@ static const char *exception_msgs[] = { "wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */ "out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */ "wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */ -#if WASM_ENABLE_FAST_JIT != 0 "failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */ -#endif "", /* EXCE_ALREADY_THROWN */ }; /* clang-format on */ @@ -5205,3 +5332,24 @@ wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch) *minor = WAMR_VERSION_MINOR; *patch = WAMR_VERSION_PATCH; } + +bool +wasm_runtime_is_import_func_linked(const char *module_name, + const char *func_name) +{ + return wasm_native_resolve_symbol(module_name, func_name, NULL, NULL, NULL, + NULL); +} + +bool +wasm_runtime_is_import_global_linked(const char *module_name, + const char *global_name) +{ +#if WASM_ENABLE_LIBC_BUILTIN != 0 + WASMGlobalImport global = { 0 }; + return wasm_native_lookup_libc_builtin_global(module_name, global_name, + &global); +#else + return false; +#endif +} diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 3e7f3725..e01f91ab 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -25,6 +25,9 @@ extern "C" { #endif +/* Internal use for setting default running mode */ +#define Mode_Default 0 + #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 #define PUT_I64_TO_ADDR(addr, value) \ @@ -413,6 +416,13 @@ typedef struct wasm_frame_t { const char *func_name_wp; } WASMCApiFrame; +#ifdef WASM_ENABLE_JIT +typedef struct LLVMJITOptions { + uint32 opt_level; + uint32 size_level; +} LLVMJITOptions; +#endif + #ifdef OS_ENABLE_HW_BOUND_CHECK /* Signal info passing to interp/aot signal handler */ typedef struct WASMSignalInfo { @@ -437,10 +447,28 @@ wasm_runtime_get_exec_env_tls(void); WASM_RUNTIME_API_EXTERN bool wasm_runtime_init(void); +/* Internal API */ +RunningMode +wasm_runtime_get_default_running_mode(void); + +#if WASM_ENABLE_JIT != 0 +/* Internal API */ +LLVMJITOptions +wasm_runtime_get_llvm_jit_options(void); +#endif + /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN bool wasm_runtime_full_init(RuntimeInitArgs *init_args); +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_is_running_mode_supported(RunningMode running_mode); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_set_default_running_mode(RunningMode running_mode); + /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN void wasm_runtime_destroy(void); @@ -484,6 +512,15 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size, uint32 heap_size, char *error_buf, uint32 error_buf_size); +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_set_running_mode(wasm_module_inst_t module_inst, + RunningMode running_mode); + +/* See wasm_export.h for description */ +WASM_RUNTIME_API_EXTERN RunningMode +wasm_runtime_get_running_mode(wasm_module_inst_t module_inst); + /* See wasm_export.h for description */ WASM_RUNTIME_API_EXTERN void wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst); @@ -956,6 +993,14 @@ void wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list); #endif +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_is_import_func_linked(const char *module_name, + const char *func_name); + +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_is_import_global_linked(const char *module_name, + const char *global_name); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index b2b63de5..3a9c1f59 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -30,6 +30,11 @@ typedef struct AtomicWaitNode { korp_cond wait_cond; } AtomicWaitNode; +typedef struct AtomicWaitAddressArgs { + uint32 index; + void **addr; +} AtomicWaitAddressArgs; + /* Atomic wait map */ static HashMap *wait_map; @@ -87,6 +92,61 @@ search_module(WASMModuleCommon *module) return NULL; } +static void +wait_map_address_count_callback(void *key, void *value, + void *p_total_elem_count) +{ + *(uint32 *)p_total_elem_count = *(uint32 *)p_total_elem_count + 1; +} + +static void +create_list_of_waiter_addresses(void *key, void *value, void *user_data) +{ + AtomicWaitAddressArgs *data = (AtomicWaitAddressArgs *)user_data; + data->addr[data->index++] = key; +} + +void +notify_stale_threads_on_exception(WASMModuleInstanceCommon *module_inst) +{ + AtomicWaitAddressArgs args = { 0 }; + uint32 i = 0, total_elem_count = 0; + uint64 total_elem_count_size = 0; + + os_mutex_lock(&shared_memory_list_lock); + + /* count number of addresses in wait_map */ + bh_hash_map_traverse(wait_map, wait_map_address_count_callback, + (void *)&total_elem_count); + + if (!total_elem_count) { + os_mutex_unlock(&shared_memory_list_lock); + return; + } + + /* allocate memory */ + total_elem_count_size = (uint64)sizeof(void *) * total_elem_count; + if (total_elem_count_size >= UINT32_MAX + || !(args.addr = wasm_runtime_malloc((uint32)total_elem_count_size))) { + LOG_ERROR( + "failed to allocate memory for list of atomic wait addresses"); + os_mutex_unlock(&shared_memory_list_lock); + return; + } + + /* set values in list of addresses */ + bh_hash_map_traverse(wait_map, create_list_of_waiter_addresses, &args); + os_mutex_unlock(&shared_memory_list_lock); + + /* notify */ + for (i = 0; i < args.index; i++) { + wasm_runtime_atomic_notify(module_inst, args.addr[i], UINT32_MAX); + } + + /* free memory allocated to args data */ + wasm_runtime_free(args.addr); +} + WASMSharedMemNode * wasm_module_get_shared_memory(WASMModuleCommon *module) { @@ -120,6 +180,7 @@ shared_memory_dec_reference(WASMModuleCommon *module) bh_list_remove(shared_memory_list, node); os_mutex_unlock(&shared_memory_list_lock); + os_mutex_destroy(&node->shared_mem_lock); os_mutex_destroy(&node->lock); wasm_runtime_free(node); } @@ -148,7 +209,14 @@ shared_memory_set_memory_inst(WASMModuleCommon *module, node->module = module; node->memory_inst = memory; node->ref_count = 1; + + if (os_mutex_init(&node->shared_mem_lock) != 0) { + wasm_runtime_free(node); + return NULL; + } + if (os_mutex_init(&node->lock) != 0) { + os_mutex_destroy(&node->shared_mem_lock); wasm_runtime_free(node); return NULL; } @@ -322,6 +390,10 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, bh_assert(module->module_type == Wasm_Module_Bytecode || module->module_type == Wasm_Module_AoT); + if (wasm_get_exception(module_inst)) { + return -1; + } + /* Currently we have only one memory instance */ if (!module_inst->memories[0]->is_shared) { wasm_runtime_set_exception(module, "expected shared memory"); diff --git a/core/iwasm/common/wasm_shared_memory.h b/core/iwasm/common/wasm_shared_memory.h index bc6f8945..98683f32 100644 --- a/core/iwasm/common/wasm_shared_memory.h +++ b/core/iwasm/common/wasm_shared_memory.h @@ -26,6 +26,8 @@ typedef struct WASMSharedMemNode { WASMModuleCommon *module; /* The memory information */ WASMMemoryInstanceCommon *memory_inst; + /* Lock used for atomic operations */ + korp_mutex shared_mem_lock; /* reference count */ uint32 ref_count; @@ -37,6 +39,9 @@ wasm_shared_memory_init(); void wasm_shared_memory_destroy(); +void +notify_stale_threads_on_exception(WASMModuleInstanceCommon *module); + WASMSharedMemNode * wasm_module_get_shared_memory(WASMModuleCommon *module); diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h index d5e45f28..e6031ab8 100644 --- a/core/iwasm/compilation/aot_compiler.h +++ b/core/iwasm/compilation/aot_compiler.h @@ -259,6 +259,7 @@ check_type_compatible(uint8 src_type, uint8 dst_type) #define I32_SIX LLVM_CONST(i32_six) #define I32_SEVEN LLVM_CONST(i32_seven) #define I32_EIGHT LLVM_CONST(i32_eight) +#define I32_NINE LLVM_CONST(i32_nine) #define I32_NEG_ONE LLVM_CONST(i32_neg_one) #define I64_NEG_ONE LLVM_CONST(i64_neg_one) #define I32_MIN LLVM_CONST(i32_min) diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index d6a5a4ab..4ac62a9e 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -366,6 +366,87 @@ fail: #endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \ || (WASM_ENABLE_PERF_PROFILING != 0) */ +static bool +record_stack_usage(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 callee_cell_num) +{ + LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder); + LLVMBasicBlockRef block_update; + LLVMBasicBlockRef block_after_update; + LLVMValueRef callee_local_size, new_sp, cmp; + LLVMValueRef native_stack_top_min; + LLVMTypeRef ptrdiff_type; + if (comp_ctx->pointer_size == sizeof(uint64_t)) { + ptrdiff_type = I64_TYPE; + } + else { + ptrdiff_type = I32_TYPE; + } + + /* + * new_sp = last_alloca - callee_local_size; + * if (*native_stack_top_min_addr > new_sp) { + * *native_stack_top_min_addr = new_sp; + * } + */ + + if (!(callee_local_size = LLVMConstInt( + ptrdiff_type, -(int64_t)callee_cell_num * 4, true))) { + aot_set_last_error("llvm build const failed."); + return false; + } + if (!(new_sp = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, + func_ctx->last_alloca, + &callee_local_size, 1, "new_sp"))) { + aot_set_last_error("llvm build gep failed"); + return false; + } + if (!(native_stack_top_min = LLVMBuildLoad2( + comp_ctx->builder, OPQ_PTR_TYPE, + func_ctx->native_stack_top_min_addr, "native_stack_top_min"))) { + aot_set_last_error("llvm build load failed"); + return false; + } + if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT, new_sp, + native_stack_top_min, "cmp"))) { + aot_set_last_error("llvm build icmp failed."); + return false; + } + + if (!(block_update = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "block_update"))) { + aot_set_last_error("llvm add basic block failed."); + return false; + } + if (!(block_after_update = LLVMAppendBasicBlockInContext( + comp_ctx->context, func_ctx->func, "block_after_update"))) { + aot_set_last_error("llvm add basic block failed."); + return false; + } + LLVMMoveBasicBlockAfter(block_update, block_curr); + LLVMMoveBasicBlockAfter(block_after_update, block_update); + + if (!LLVMBuildCondBr(comp_ctx->builder, cmp, block_update, + block_after_update)) { + aot_set_last_error("llvm build cond br failed."); + return false; + } + + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_update); + if (!LLVMBuildStore(comp_ctx->builder, new_sp, + func_ctx->native_stack_top_min_addr)) { + aot_set_last_error("llvm build store failed"); + return false; + } + if (!LLVMBuildBr(comp_ctx->builder, block_after_update)) { + aot_set_last_error("llvm build br failed."); + return false; + } + + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_after_update); + return true; +} + static bool check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 callee_cell_num) @@ -409,6 +490,19 @@ check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return true; } +static bool +check_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 callee_cell_num) +{ + if (comp_ctx->enable_stack_estimation + && !record_stack_usage(comp_ctx, func_ctx, callee_cell_num)) + return false; + if (comp_ctx->enable_stack_bound_check + && !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num)) + return false; + return true; +} + /** * Check whether the app address and its buffer are inside the linear memory, * if no, throw exception @@ -852,8 +946,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, callee_cell_num = aot_func->param_cell_num + aot_func->local_cell_num + 1; - if (comp_ctx->enable_stack_bound_check - && !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num)) + if (!check_stack(comp_ctx, func_ctx, callee_cell_num)) goto fail; #if LLVM_VERSION_MAJOR >= 14 @@ -1467,12 +1560,11 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Translate call non-import block */ LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import); - if (comp_ctx->enable_stack_bound_check - && !check_stack_boundary(comp_ctx, func_ctx, - param_cell_num + ext_cell_num - + 1 - /* Reserve some local variables */ - + 16)) + if (!check_stack(comp_ctx, func_ctx, + param_cell_num + ext_cell_num + + 1 + /* Reserve some local variables */ + + 16)) goto fail; /* Load function pointer */ diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 889ab259..27550560 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -286,6 +286,21 @@ create_native_stack_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) return true; } +static bool +create_native_stack_top_min(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef offset = I32_NINE; + + if (!(func_ctx->native_stack_top_min_addr = LLVMBuildInBoundsGEP2( + comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1, + "native_stack_top_min_addr"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + + return true; +} + static bool create_aux_stack_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { @@ -434,7 +449,8 @@ create_local_variables(AOTCompData *comp_data, AOTCompContext *comp_ctx, } } - if (comp_ctx->enable_stack_bound_check) { + if (comp_ctx->enable_stack_bound_check + || comp_ctx->enable_stack_estimation) { if (aot_func_type->param_count + func->local_count > 0) { func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count + func->local_count - 1]; @@ -963,6 +979,10 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, && !create_native_stack_bound(comp_ctx, func_ctx)) { goto fail; } + if (comp_ctx->enable_stack_estimation + && !create_native_stack_top_min(comp_ctx, func_ctx)) { + goto fail; + } /* Get auxiliary stack info */ if (wasm_func->has_op_set_global_aux_stack @@ -1622,6 +1642,9 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) if (option->disable_llvm_lto) comp_ctx->disable_llvm_lto = true; + if (option->enable_stack_estimation) + comp_ctx->enable_stack_estimation = true; + comp_ctx->opt_level = option->opt_level; comp_ctx->size_level = option->size_level; diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 219f36e7..b982e808 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -163,6 +163,7 @@ typedef struct AOTFuncContext { LLVMValueRef aot_inst; LLVMValueRef argv_buf; LLVMValueRef native_stack_bound; + LLVMValueRef native_stack_top_min_addr; LLVMValueRef aux_stack_bound; LLVMValueRef aux_stack_bottom; LLVMValueRef native_symbol; @@ -313,6 +314,9 @@ typedef struct AOTCompContext { /* Native stack bounday Check */ bool enable_stack_bound_check; + /* Native stack usage estimation */ + bool enable_stack_estimation; + /* 128-bit SIMD */ bool enable_simd; @@ -403,6 +407,7 @@ typedef struct AOTCompOption { bool enable_aux_stack_frame; bool disable_llvm_intrinsics; bool disable_llvm_lto; + bool enable_stack_estimation; uint32 opt_level; uint32 size_level; uint32 output_format; diff --git a/core/iwasm/fast-jit/fe/jit_emit_memory.c b/core/iwasm/fast-jit/fe/jit_emit_memory.c index 568766da..b71d98ba 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_memory.c +++ b/core/iwasm/fast-jit/fe/jit_emit_memory.c @@ -135,7 +135,8 @@ check_and_seek(JitCompContext *cc, JitReg addr, uint32 offset, uint32 bytes) #ifndef OS_ENABLE_HW_BOUND_CHECK /* ---------- check ---------- */ /* 1. shortcut if the memory size is 0 */ - if (0 == cc->cur_wasm_module->memories[mem_idx].init_page_count) { + if (cc->cur_wasm_module->memories != NULL + && 0 == cc->cur_wasm_module->memories[mem_idx].init_page_count) { JitReg module_inst, cur_page_count; uint32 cur_page_count_offset = (uint32)offsetof(WASMModuleInstance, global_table_data.bytes) @@ -176,6 +177,18 @@ fail: return 0; } +#define CHECK_ALIGNMENT(maddr, memory_data, offset1) \ + do { \ + GEN_INSN(ADD, maddr, memory_data, offset1); \ + JitReg align_mask = NEW_CONST(I64, ((uint64)1 << align) - 1); \ + JitReg AND_res = jit_cc_new_reg_I64(cc); \ + GEN_INSN(AND, AND_res, maddr, align_mask); \ + GEN_INSN(CMP, cc->cmp_reg, AND_res, NEW_CONST(I64, 0)); \ + if (!jit_emit_exception(cc, EXCE_UNALIGNED_ATOMIC, JIT_OP_BNE, \ + cc->cmp_reg, NULL)) \ + goto fail; \ + } while (0) + bool jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset, uint32 bytes, bool sign, bool atomic) @@ -779,6 +792,51 @@ bool jit_compile_op_atomic_wait(JitCompContext *cc, uint8 op_type, uint32 align, uint32 offset, uint32 bytes) { + bh_assert(op_type == VALUE_TYPE_I32 || op_type == VALUE_TYPE_I64); + + // Pop atomic.wait arguments + JitReg timeout, expect, expect_64, addr; + POP_I64(timeout); + if (op_type == VALUE_TYPE_I32) { + POP_I32(expect); + expect_64 = jit_cc_new_reg_I64(cc); + GEN_INSN(I32TOI64, expect_64, expect); + } + else { + POP_I64(expect_64); + } + POP_I32(addr); + + // Get referenced address and store it in `maddr` + JitReg memory_data = get_memory_data_reg(cc->jit_frame, 0); + JitReg offset1 = check_and_seek(cc, addr, offset, bytes); + if (!offset1) + goto fail; + JitReg maddr = jit_cc_new_reg_I64(cc); + CHECK_ALIGNMENT(maddr, memory_data, offset1); + + // Prepare `wasm_runtime_atomic_wait` arguments + JitReg res = jit_cc_new_reg_I32(cc); + JitReg args[5] = { 0 }; + args[0] = get_module_inst_reg(cc->jit_frame); + args[1] = maddr; + args[2] = expect_64; + args[3] = timeout; + args[4] = NEW_CONST(I32, false); + + if (!jit_emit_callnative(cc, wasm_runtime_atomic_wait, res, args, + sizeof(args) / sizeof(args[0]))) + goto fail; + + // Handle return code + GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, -1)); + if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ, cc->cmp_reg, + NULL)) + goto fail; + + PUSH_I32(res); + return true; +fail: return false; } @@ -786,6 +844,39 @@ bool jit_compiler_op_atomic_notify(JitCompContext *cc, uint32 align, uint32 offset, uint32 bytes) { + // Pop atomic.notify arguments + JitReg notify_count, addr; + POP_I32(notify_count); + POP_I32(addr); + + // Get referenced address and store it in `maddr` + JitReg memory_data = get_memory_data_reg(cc->jit_frame, 0); + JitReg offset1 = check_and_seek(cc, addr, offset, bytes); + if (!offset1) + goto fail; + JitReg maddr = jit_cc_new_reg_I64(cc); + CHECK_ALIGNMENT(maddr, memory_data, offset1); + + // Prepare `wasm_runtime_atomic_notify` arguments + JitReg res = jit_cc_new_reg_I32(cc); + JitReg args[3] = { 0 }; + args[0] = get_module_inst_reg(cc->jit_frame); + args[1] = maddr; + args[2] = notify_count; + + if (!jit_emit_callnative(cc, wasm_runtime_atomic_notify, res, args, + sizeof(args) / sizeof(args[0]))) + goto fail; + + // Handle return code + GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0)); + if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg, + NULL)) + goto fail; + + PUSH_I32(res); + return true; +fail: return false; } #endif diff --git a/core/iwasm/fast-jit/jit_codecache.c b/core/iwasm/fast-jit/jit_codecache.c index 66c2d033..73a034f3 100644 --- a/core/iwasm/fast-jit/jit_codecache.c +++ b/core/iwasm/fast-jit/jit_codecache.c @@ -56,9 +56,31 @@ jit_code_cache_free(void *ptr) bool jit_pass_register_jitted_code(JitCompContext *cc) { - uint32 jit_func_idx = - cc->cur_wasm_func_idx - cc->cur_wasm_module->import_function_count; - cc->cur_wasm_module->fast_jit_func_ptrs[jit_func_idx] = - cc->cur_wasm_func->fast_jit_jitted_code = cc->jitted_addr_begin; + WASMModuleInstance *instance; + WASMModule *module = cc->cur_wasm_module; + WASMFunction *func = cc->cur_wasm_func; + uint32 jit_func_idx = cc->cur_wasm_func_idx - module->import_function_count; + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + os_mutex_lock(&module->instance_list_lock); +#endif + + module->fast_jit_func_ptrs[jit_func_idx] = func->fast_jit_jitted_code = + cc->jitted_addr_begin; + +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + instance = module->instance_list; + while (instance) { + if (instance->e->running_mode == Mode_Fast_JIT) + instance->fast_jit_func_ptrs[jit_func_idx] = cc->jitted_addr_begin; + instance = instance->e->next; + } + + os_mutex_unlock(&module->instance_list_lock); +#else + (void)instance; +#endif return true; } diff --git a/core/iwasm/fast-jit/jit_compiler.c b/core/iwasm/fast-jit/jit_compiler.c index 67dcb7b5..958d0e98 100644 --- a/core/iwasm/fast-jit/jit_compiler.c +++ b/core/iwasm/fast-jit/jit_compiler.c @@ -157,8 +157,16 @@ jit_compiler_compile(WASMModule *module, uint32 func_idx) /* Apply compiler passes */ if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) { last_error = jit_get_last_error(cc); + +#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 + char *function_name = cc->cur_wasm_func->field_name; + os_printf("fast jit compilation failed: %s (function_name=%s)\n", + last_error ? last_error : "unknown error", function_name); +#else os_printf("fast jit compilation failed: %s\n", last_error ? last_error : "unknown error"); +#endif + goto fail; } @@ -246,6 +254,8 @@ jit_compiler_set_call_to_fast_jit(WASMModule *module, uint32 func_idx) func_ptr = jit_codegen_compile_call_to_fast_jit(module, func_idx); if (func_ptr) { + uint32 i = func_idx - module->import_function_count; + module->functions[i]->call_to_fast_jit_from_llvm_jit = func_ptr; jit_compiler_set_llvm_jit_func_ptr(module, func_idx, func_ptr); } @@ -259,12 +269,14 @@ jit_compiler_set_llvm_jit_func_ptr(WASMModule *module, uint32 func_idx, WASMModuleInstance *instance; uint32 i = func_idx - module->import_function_count; - module->functions[i]->llvm_jit_func_ptr = module->func_ptrs[i] = func_ptr; - os_mutex_lock(&module->instance_list_lock); + + module->func_ptrs[i] = func_ptr; + instance = module->instance_list; while (instance) { - instance->func_ptrs[func_idx] = func_ptr; + if (instance->e->running_mode == Mode_Multi_Tier_JIT) + instance->func_ptrs[func_idx] = func_ptr; instance = instance->e->next; } os_mutex_unlock(&module->instance_list_lock); diff --git a/core/iwasm/include/aot_export.h b/core/iwasm/include/aot_export.h index f8df168e..792a4baa 100644 --- a/core/iwasm/include/aot_export.h +++ b/core/iwasm/include/aot_export.h @@ -55,6 +55,7 @@ typedef struct AOTCompOption { bool enable_aux_stack_frame; bool disable_llvm_intrinsics; bool disable_llvm_lto; + bool enable_stack_estimation; uint32_t opt_level; uint32_t size_level; uint32_t output_format; diff --git a/core/iwasm/include/wasm_c_api.h b/core/iwasm/include/wasm_c_api.h index 85fcd186..324a43bd 100644 --- a/core/iwasm/include/wasm_c_api.h +++ b/core/iwasm/include/wasm_c_api.h @@ -354,6 +354,7 @@ WASM_API_EXTERN own wasm_importtype_t* wasm_importtype_new( WASM_API_EXTERN const wasm_name_t* wasm_importtype_module(const wasm_importtype_t*); WASM_API_EXTERN const wasm_name_t* wasm_importtype_name(const wasm_importtype_t*); WASM_API_EXTERN const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t*); +WASM_API_EXTERN bool wasm_importtype_is_linked(const wasm_importtype_t*); // Export Types @@ -797,6 +798,9 @@ static inline void* wasm_val_ptr(const wasm_val_t* val) { #define KILOBYTE(n) ((n) * 1024) +// Create placeholders filled in `wasm_externvec_t* imports` for `wasm_instance_new()` +WASM_API_EXTERN wasm_extern_t *wasm_extern_new_empty(wasm_store_t *, wasm_externkind_t); + /////////////////////////////////////////////////////////////////////////////// #undef own diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 2d5e8515..3bb5f873 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -131,6 +131,14 @@ typedef struct mem_alloc_info_t { uint32_t highmark_size; } mem_alloc_info_t; +/* Running mode of runtime and module instance*/ +typedef enum RunningMode { + Mode_Interp = 1, + Mode_Fast_JIT, + Mode_LLVM_JIT, + Mode_Multi_Tier_JIT, +} RunningMode; + /* WASM runtime initialize arguments */ typedef struct RuntimeInitArgs { mem_alloc_type_t mem_alloc_type; @@ -152,6 +160,13 @@ typedef struct RuntimeInitArgs { /* Fast JIT code cache size */ uint32_t fast_jit_code_cache_size; + + /* Default running mode of the runtime */ + RunningMode running_mode; + + /* LLVM JIT opt and size level */ + uint32_t llvm_jit_opt_level; + uint32_t llvm_jit_size_level; } RuntimeInitArgs; #ifndef WASM_VALKIND_T_DEFINED @@ -195,9 +210,9 @@ WASM_RUNTIME_API_EXTERN bool wasm_runtime_init(void); /** - * Initialize the WASM runtime environment, and also initialize - * the memory allocator and register native symbols, which are specified - * with init arguments + * Initialize the WASM runtime environment, WASM running mode, + * and also initialize the memory allocator and register native symbols, + * which are specified with init arguments * * @param init_args specifies the init arguments * @@ -206,6 +221,28 @@ wasm_runtime_init(void); WASM_RUNTIME_API_EXTERN bool wasm_runtime_full_init(RuntimeInitArgs *init_args); +/** + * Query whether a certain running mode is supported for the runtime + * + * @param running_mode the running mode to query + * + * @return true if this running mode is supported, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_is_running_mode_supported(RunningMode running_mode); + +/** + * Set the default running mode for the runtime. It is inherited + * to set the running mode of a module instance when it is instantiated, + * and can be changed by calling wasm_runtime_set_running_mode + * + * @param running_mode the running mode to set + * + * @return true if success, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_set_default_running_mode(RunningMode running_mode); + /** * Destroy the WASM runtime environment. */ @@ -450,6 +487,34 @@ wasm_runtime_instantiate(const wasm_module_t module, uint32_t stack_size, uint32_t heap_size, char *error_buf, uint32_t error_buf_size); +/** + * Set the running mode of a WASM module instance, override the + * default running mode of the runtime. Note that it only makes sense when + * the input is a wasm bytecode file: for the AOT file, runtime always runs + * it with AOT engine, and this function always returns true. + * + * @param module_inst the WASM module instance to set running mode + * @param running_mode the running mode to set + * + * @return true if success, false otherwise + */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_set_running_mode(wasm_module_inst_t module_inst, + RunningMode running_mode); + +/** + * Get the running mode of a WASM module instance, if no running mode + * is explicitly set the default running mode of runtime will + * be used and returned. Note that it only makes sense when the input is a + * wasm bytecode file: for the AOT file, this function always returns 0. + * + * @param module_inst the WASM module instance to query for running mode + * + * @return the running mode this module instance currently use + */ +WASM_RUNTIME_API_EXTERN RunningMode +wasm_runtime_get_running_mode(wasm_module_inst_t module_inst); + /** * Deinstantiate a WASM module instance, destroy the resources. * @@ -1259,6 +1324,22 @@ wasm_runtime_get_custom_section(wasm_module_t const module_comm, */ WASM_RUNTIME_API_EXTERN void wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch); + +/** + * Check whether an import func `(import (func ...))` is linked or not + * with runtime registered natvie functions + */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_is_import_func_linked(const char *module_name, + const char *func_name); + +/** + * Check whether an import global `(import (global ...))` is linked or not + * with runtime registered natvie globals + */ +WASM_RUNTIME_API_EXTERN bool +wasm_runtime_is_import_global_linked(const char *module_name, + const char *global_name); /* clang-format on */ #ifdef __cplusplus diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 7efa6d5f..e6d02c3f 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -278,9 +278,14 @@ struct WASMFunction { #endif #if WASM_ENABLE_FAST_JIT != 0 + /* The compiled fast jit jitted code block of this function */ void *fast_jit_jitted_code; #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + /* The compiled llvm jit func ptr of this function */ void *llvm_jit_func_ptr; + /* Code block to call fast jit jitted code of this function + from the llvm jit jitted code */ + void *call_to_fast_jit_from_llvm_jit; #endif #endif }; @@ -505,15 +510,14 @@ struct WASMModule { uint64 load_size; #endif -#if WASM_ENABLE_DEBUG_INTERP != 0 \ - || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ && WASM_ENABLE_LAZY_JIT != 0) /** * List of instances referred to this module. When source debugging * feature is enabled, the debugger may modify the code section of * the module, so we need to report a warning if user create several - * instances based on the same module. Sub instances created by - * lib-pthread or spawn API won't be added into the list. + * instances based on the same module. * * Also add the instance to the list for Fast JIT to LLVM JIT * tier-up, since we need to lazily update the LLVM func pointers @@ -533,7 +537,22 @@ struct WASMModule { #endif #if WASM_ENABLE_FAST_JIT != 0 - /* func pointers of Fast JITed (un-imported) functions */ + /** + * func pointers of Fast JITed (un-imported) functions + * for non Multi-Tier JIT mode: + * (1) when lazy jit is disabled, each pointer is set to the compiled + * fast jit jitted code + * (2) when lazy jit is enabled, each pointer is firstly inited as + * jit_global->compile_fast_jit_and_then_call, and then set to the + * compiled fast jit jitted code when it is called (the stub will + * compile the jit function and then update itself) + * for Multi-Tier JIT mode: + * each pointer is firstly inited as compile_fast_jit_and_then_call, + * and then set to the compiled fast jit jitted code when it is called, + * and when the llvm jit func ptr of the same function is compiled, it + * will be set to call_to_llvm_jit_from_fast_jit of this function type + * (tier-up from fast-jit to llvm-jit) + */ void **fast_jit_func_ptrs; /* locks for Fast JIT lazy compilation */ korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM]; @@ -543,7 +562,16 @@ struct WASMModule { #if WASM_ENABLE_JIT != 0 struct AOTCompData *comp_data; struct AOTCompContext *comp_ctx; - /* func pointers of LLVM JITed (un-imported) functions */ + /** + * func pointers of LLVM JITed (un-imported) functions + * for non Multi-Tier JIT mode: + * each pointer is set to the lookuped llvm jit func ptr, note that it + * is a stub and will trigger the actual compilation when it is called + * for Multi-Tier JIT mode: + * each pointer is inited as call_to_fast_jit code block, when the llvm + * jit func ptr is actually compiled, it is set to the compiled llvm jit + * func ptr + */ void **func_ptrs; /* whether the func pointers are compiled */ bool *func_ptrs_compiled; @@ -568,6 +596,12 @@ struct WASMModule { korp_tid llvm_jit_init_thread; /* whether the llvm jit is initialized */ bool llvm_jit_inited; + /* Whether to enable llvm jit compilation: + it is set to true only when there is a module instance starts to + run with running mode Mode_LLVM_JIT or Mode_Multi_Tier_JIT, + since no need to enable llvm jit compilation for Mode_Interp and + Mode_Fast_JIT, so as to improve performance for them */ + bool enable_llvm_jit_compilation; #endif }; diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 3e16b380..d8985713 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -696,28 +696,28 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint32)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint32)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ else { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = LOAD_I32(maddr); \ STORE_U32(maddr, readv op sval); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ PUSH_I32(readv); \ break; \ @@ -736,39 +736,39 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min, CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint64)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint64)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint64)LOAD_U32(maddr); \ STORE_U32(maddr, (uint32)(readv op sval)); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ else { \ uint64 op_result; \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint64)LOAD_I64(maddr); \ op_result = readv op sval; \ STORE_I64(maddr, op_result); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ PUSH_I64(readv); \ break; \ @@ -1151,6 +1151,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 cache_index, type_index, param_cell_num, cell_num; uint8 value_type; +#if WASM_ENABLE_SHARED_MEMORY != 0 + WASMSharedMemNode *node = + wasm_module_get_shared_memory((WASMModuleCommon *)module->module); +#endif + #if WASM_ENABLE_DEBUG_INTERP != 0 uint8 *frame_ip_orig = NULL; WASMDebugInstance *debug_instance = wasm_exec_env_get_instance(exec_env); @@ -3458,23 +3463,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint32)(*(uint8 *)maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint32)LOAD_U16(maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = LOAD_I32(maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } PUSH_I32(readv); @@ -3493,30 +3498,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)(*(uint8 *)maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)LOAD_U16(maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)LOAD_U32(maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = LOAD_I64(maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } PUSH_I64(readv); @@ -3535,23 +3540,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); STORE_U32(maddr, frame_sp[1]); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } break; } @@ -3569,31 +3574,31 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I64_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); STORE_U32(maddr, (uint32)sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); PUT_I64_TO_ADDR((uint32 *)maddr, GET_I64_FROM_ADDR(frame_sp + 1)); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } break; } @@ -3613,32 +3618,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint8)expect; - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint32)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint16)expect; - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint32)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = LOAD_I32(maddr); if (readv == expect) STORE_U32(maddr, sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } PUSH_I32(readv); break; @@ -3659,44 +3664,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint8)expect; - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint16)expect; - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); expect = (uint32)expect; - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)LOAD_U32(maddr); if (readv == expect) STORE_U32(maddr, (uint32)(sval)); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)LOAD_I64(maddr); if (readv == expect) { STORE_I64(maddr, sval); } - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } PUSH_I64(readv); break; @@ -4150,6 +4155,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, } argc = function->param_cell_num; + RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame); #if !(defined(OS_ENABLE_HW_BOUND_CHECK) \ && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0) if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) { @@ -4194,58 +4200,51 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, } } else { -#if WASM_ENABLE_LAZY_JIT != 0 + RunningMode running_mode = + wasm_runtime_get_running_mode((wasm_module_inst_t)module_inst); - /* Fast JIT to LLVM JIT tier-up is enabled */ -#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 - /* Fast JIT and LLVM JIT are both enabled, call llvm jit function - if it is compiled, else call fast jit function */ - uint32 func_idx = (uint32)(function - module_inst->e->functions); - if (module_inst->module->func_ptrs_compiled - [func_idx - module_inst->module->import_function_count]) { + if (running_mode == Mode_Interp) { + wasm_interp_call_func_bytecode(module_inst, exec_env, function, + frame); + } +#if WASM_ENABLE_FAST_JIT != 0 + else if (running_mode == Mode_Fast_JIT) { + fast_jit_call_func_bytecode(module_inst, exec_env, function, frame); + } +#endif +#if WASM_ENABLE_JIT != 0 + else if (running_mode == Mode_LLVM_JIT) { llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc, argv); /* For llvm jit, the results have been stored in argv, no need to copy them from stack frame again */ copy_argv_from_frame = false; } - else { - fast_jit_call_func_bytecode(module_inst, exec_env, function, frame); +#endif +#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \ + && WASM_ENABLE_JIT != 0 + else if (running_mode == Mode_Multi_Tier_JIT) { + /* Tier-up from Fast JIT to LLVM JIT, call llvm jit function + if it is compiled, else call fast jit function */ + uint32 func_idx = (uint32)(function - module_inst->e->functions); + if (module_inst->module->func_ptrs_compiled + [func_idx - module_inst->module->import_function_count]) { + llvm_jit_call_func_bytecode(module_inst, exec_env, function, + argc, argv); + /* For llvm jit, the results have been stored in argv, + no need to copy them from stack frame again */ + copy_argv_from_frame = false; + } + else { + fast_jit_call_func_bytecode(module_inst, exec_env, function, + frame); + } } -#elif WASM_ENABLE_JIT != 0 - /* Only LLVM JIT is enabled */ - llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc, - argv); - /* For llvm jit, the results have been stored in argv, - no need to copy them from stack frame again */ - copy_argv_from_frame = false; -#elif WASM_ENABLE_FAST_JIT != 0 - /* Only Fast JIT is enabled */ - fast_jit_call_func_bytecode(module_inst, exec_env, function, frame); -#else - /* Both Fast JIT and LLVM JIT are disabled */ - wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame); #endif - -#else /* else of WASM_ENABLE_LAZY_JIT != 0 */ - - /* Fast JIT to LLVM JIT tier-up is enabled */ -#if WASM_ENABLE_JIT != 0 - /* LLVM JIT is enabled */ - llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc, - argv); - /* For llvm jit, the results have been stored in argv, - no need to copy them from stack frame again */ - copy_argv_from_frame = false; -#elif WASM_ENABLE_FAST_JIT != 0 - /* Fast JIT is enabled */ - fast_jit_call_func_bytecode(module_inst, exec_env, function, frame); -#else - /* Both Fast JIT and LLVM JIT are disabled */ - wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame); -#endif - -#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */ + else { + /* There should always be a supported running mode selected */ + bh_assert(0); + } (void)wasm_interp_call_func_bytecode; #if WASM_ENABLE_FAST_JIT != 0 diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 0ea920f2..be924646 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -469,28 +469,28 @@ LOAD_PTR(void *addr) CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(1); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint32)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(2); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint32)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ else { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(4); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = LOAD_I32(maddr); \ STORE_U32(maddr, readv op sval); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ PUSH_I32(readv); \ break; \ @@ -509,39 +509,39 @@ LOAD_PTR(void *addr) CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(1); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint64)(*(uint8 *)maddr); \ *(uint8 *)maddr = (uint8)(readv op sval); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(2); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint64)LOAD_U16(maddr); \ STORE_U16(maddr, (uint16)(readv op sval)); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(4); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint64)LOAD_U32(maddr); \ STORE_U32(maddr, (uint32)(readv op sval)); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ else { \ uint64 op_result; \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ CHECK_ATOMIC_MEMORY_ACCESS(8); \ \ - os_mutex_lock(&module->e->mem_lock); \ + os_mutex_lock(&node->shared_mem_lock); \ readv = (uint64)LOAD_I64(maddr); \ op_result = readv op sval; \ STORE_I64(maddr, op_result); \ - os_mutex_unlock(&module->e->mem_lock); \ + os_mutex_unlock(&node->shared_mem_lock); \ } \ PUSH_I64(readv); \ break; \ @@ -1183,6 +1183,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 local_idx, local_offset, global_idx; uint8 opcode, local_type, *global_addr; +#if WASM_ENABLE_SHARED_MEMORY != 0 + WASMSharedMemNode *node = + wasm_module_get_shared_memory((WASMModuleCommon *)module->module); +#endif + #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op DEFINE_GOTO_TABLE(const void *, handle_table); @@ -3296,23 +3301,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint32)(*(uint8 *)maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint32)LOAD_U16(maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = LOAD_I32(maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } PUSH_I32(readv); @@ -3331,30 +3336,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)(*(uint8 *)maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)LOAD_U16(maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)LOAD_U32(maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = LOAD_I64(maddr); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } PUSH_I64(readv); @@ -3372,23 +3377,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I32_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); STORE_U32(maddr, sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } break; } @@ -3406,30 +3411,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (opcode == WASM_OP_ATOMIC_I64_STORE8) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_ATOMIC_MEMORY_ACCESS(1); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); *(uint8 *)maddr = (uint8)sval; - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I64_STORE16) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); STORE_U16(maddr, (uint16)sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); STORE_U32(maddr, (uint32)sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); STORE_I64(maddr, sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } break; } @@ -3449,32 +3454,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(1); expect = (uint8)expect; - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint32)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); expect = (uint16)expect; - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint32)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = LOAD_I32(maddr); if (readv == expect) STORE_U32(maddr, sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } PUSH_I32(readv); break; @@ -3495,44 +3500,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, CHECK_ATOMIC_MEMORY_ACCESS(1); expect = (uint8)expect; - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)(*(uint8 *)maddr); if (readv == expect) *(uint8 *)maddr = (uint8)(sval); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_ATOMIC_MEMORY_ACCESS(2); expect = (uint16)expect; - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)LOAD_U16(maddr); if (readv == expect) STORE_U16(maddr, (uint16)(sval)); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_ATOMIC_MEMORY_ACCESS(4); expect = (uint32)expect; - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)LOAD_U32(maddr); if (readv == expect) STORE_U32(maddr, (uint32)(sval)); - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } else { CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_ATOMIC_MEMORY_ACCESS(8); - os_mutex_lock(&module->e->mem_lock); + os_mutex_lock(&node->shared_mem_lock); readv = (uint64)LOAD_I64(maddr); if (readv == expect) { STORE_I64(maddr, sval); } - os_mutex_unlock(&module->e->mem_lock); + os_mutex_unlock(&node->shared_mem_lock); } PUSH_I64(readv); break; @@ -3901,6 +3906,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, } argc = function->param_cell_num; + RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame); #if !(defined(OS_ENABLE_HW_BOUND_CHECK) \ && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0) if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) { diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 753f837d..37615276 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -1399,6 +1399,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, WASMModule *sub_module = NULL; WASMGlobal *linked_global = NULL; #endif + bool ret = false; CHECK_BUF(p, p_end, 2); declare_type = read_uint8(p); @@ -1411,15 +1412,16 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, } #if WASM_ENABLE_LIBC_BUILTIN != 0 - global->is_linked = wasm_native_lookup_libc_builtin_global( - sub_module_name, global_name, global); - if (global->is_linked) { + ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name, + global); + if (ret) { if (global->type != declare_type || global->is_mutable != declare_mutable) { set_error_buf(error_buf, error_buf_size, "incompatible import type"); return false; } + global->is_linked = true; } #endif #if WASM_ENABLE_MULTI_MODULE != 0 @@ -1449,6 +1451,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end, global->is_mutable = (declare_mutable == 1); (void)parent_module; + (void)ret; return true; fail: return false; @@ -2989,6 +2992,7 @@ static bool init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, uint32 error_buf_size) { + LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options(); AOTCompOption option = { 0 }; char *aot_last_error; uint64 size; @@ -3027,8 +3031,11 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, } option.is_jit_mode = true; - option.opt_level = 3; - option.size_level = 3; + + llvm_jit_options = wasm_runtime_get_llvm_jit_options(); + option.opt_level = llvm_jit_options.opt_level; + option.size_level = llvm_jit_options.size_level; + #if WASM_ENABLE_BULK_MEMORY != 0 option.enable_bulk_memory = true; #endif @@ -3048,6 +3055,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, #if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0) option.enable_aux_stack_frame = true; #endif +#if WASM_ENABLE_MEMORY_PROFILING != 0 + option.enable_stack_estimation = true; +#endif module->comp_ctx = aot_create_comp_context(module->comp_data, &option); if (!module->comp_ctx) { @@ -3109,6 +3119,8 @@ init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf, module->func_ptrs[i] = (void *)func_addr; #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + module->functions[i]->llvm_jit_func_ptr = (void *)func_addr; + if (module->orcjit_stop_compiling) return false; #endif @@ -3199,9 +3211,9 @@ orcjit_thread_callback(void *arg) /* Wait until init_llvm_jit_functions_stage2 finishes */ os_mutex_lock(&module->tierup_wait_lock); - while (!module->llvm_jit_inited) { + while (!(module->llvm_jit_inited && module->enable_llvm_jit_compilation)) { os_cond_reltimedwait(&module->tierup_wait_cond, - &module->tierup_wait_lock, 10); + &module->tierup_wait_lock, 10000); if (module->orcjit_stop_compiling) { /* init_llvm_jit_functions_stage2 failed */ os_mutex_unlock(&module->tierup_wait_lock); @@ -3852,8 +3864,8 @@ create_module(char *error_buf, uint32 error_buf_size) bh_assert(ret == BH_LIST_SUCCESS); #endif -#if WASM_ENABLE_DEBUG_INTERP != 0 \ - || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ && WASM_ENABLE_LAZY_JIT != 0) if (os_mutex_init(&module->instance_list_lock) != 0) { set_error_buf(error_buf, error_buf_size, @@ -4148,10 +4160,8 @@ check_wasi_abi_compatibility(const WASMModule *module, /* should have one at least */ if (module->import_wasi_api && !start && !initialize) { - set_error_buf( - error_buf, error_buf_size, - "a module with WASI apis must be either a command or a reactor"); - return false; + LOG_WARNING("warning: a module with WASI apis should be either " + "a command or a reactor"); } /* @@ -4256,7 +4266,8 @@ wasm_loader_unload(WASMModule *module) if (!module) return; -#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 module->orcjit_stop_compiling = true; if (module->llvm_jit_init_thread) os_thread_join(module->llvm_jit_init_thread, NULL); @@ -4277,7 +4288,8 @@ wasm_loader_unload(WASMModule *module) aot_destroy_comp_data(module->comp_data); #endif -#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 if (module->tierup_wait_lock_inited) { os_mutex_destroy(&module->tierup_wait_lock); os_cond_destroy(&module->tierup_wait_cond); @@ -4312,9 +4324,9 @@ wasm_loader_unload(WASMModule *module) module->functions[i]->fast_jit_jitted_code); } #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 - if (module->functions[i]->llvm_jit_func_ptr) { + if (module->functions[i]->call_to_fast_jit_from_llvm_jit) { jit_code_cache_free( - module->functions[i]->llvm_jit_func_ptr); + module->functions[i]->call_to_fast_jit_from_llvm_jit); } #endif #endif @@ -4406,8 +4418,8 @@ wasm_loader_unload(WASMModule *module) } #endif -#if WASM_ENABLE_DEBUG_INTERP != 0 \ - || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ && WASM_ENABLE_LAZY_JIT != 0) os_mutex_destroy(&module->instance_list_lock); #endif diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index b1243a06..92be851f 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -1835,6 +1835,7 @@ static bool init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, uint32 error_buf_size) { + LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options(); AOTCompOption option = { 0 }; char *aot_last_error; uint64 size; @@ -1873,8 +1874,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, } option.is_jit_mode = true; - option.opt_level = 3; - option.size_level = 3; + option.opt_level = llvm_jit_options.opt_level; + option.size_level = llvm_jit_options.size_level; + #if WASM_ENABLE_BULK_MEMORY != 0 option.enable_bulk_memory = true; #endif @@ -1894,6 +1896,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, #if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0) option.enable_aux_stack_frame = true; #endif +#if WASM_ENABLE_MEMORY_PROFILING != 0 + option.enable_stack_estimation = true; +#endif module->comp_ctx = aot_create_comp_context(module->comp_data, &option); if (!module->comp_ctx) { @@ -1957,6 +1962,8 @@ init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf, module->func_ptrs[i] = (void *)func_addr; #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + module->functions[i]->llvm_jit_func_ptr = (void *)func_addr; + if (module->orcjit_stop_compiling) return false; #endif @@ -2047,9 +2054,9 @@ orcjit_thread_callback(void *arg) /* Wait until init_llvm_jit_functions_stage2 finishes */ os_mutex_lock(&module->tierup_wait_lock); - while (!module->llvm_jit_inited) { + while (!(module->llvm_jit_inited && module->enable_llvm_jit_compilation)) { os_cond_reltimedwait(&module->tierup_wait_cond, - &module->tierup_wait_lock, 10); + &module->tierup_wait_lock, 10000); if (module->orcjit_stop_compiling) { /* init_llvm_jit_functions_stage2 failed */ os_mutex_unlock(&module->tierup_wait_lock); @@ -2718,7 +2725,8 @@ create_module(char *error_buf, uint32 error_buf_size) bh_assert(ret == BH_LIST_SUCCESS); #endif -#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 if (os_mutex_init(&module->instance_list_lock) != 0) { set_error_buf(error_buf, error_buf_size, "init instance list lock failed"); @@ -2939,7 +2947,8 @@ wasm_loader_unload(WASMModule *module) if (!module) return; -#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 module->orcjit_stop_compiling = true; if (module->llvm_jit_init_thread) os_thread_join(module->llvm_jit_init_thread, NULL); @@ -2960,7 +2969,8 @@ wasm_loader_unload(WASMModule *module) aot_destroy_comp_data(module->comp_data); #endif -#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 if (module->tierup_wait_lock_inited) { os_mutex_destroy(&module->tierup_wait_lock); os_cond_destroy(&module->tierup_wait_cond); @@ -2995,9 +3005,9 @@ wasm_loader_unload(WASMModule *module) module->functions[i]->fast_jit_jitted_code); } #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 - if (module->functions[i]->llvm_jit_func_ptr) { + if (module->functions[i]->call_to_fast_jit_from_llvm_jit) { jit_code_cache_free( - module->functions[i]->llvm_jit_func_ptr); + module->functions[i]->call_to_fast_jit_from_llvm_jit); } #endif #endif @@ -3056,7 +3066,8 @@ wasm_loader_unload(WASMModule *module) } #endif -#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 os_mutex_destroy(&module->instance_list_lock); #endif diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index c33ad8d0..f365f9cc 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -737,13 +737,12 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, function++; } + bh_assert((uint32)(function - functions) == function_count); #if WASM_ENABLE_FAST_JIT != 0 module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs; #endif - bh_assert((uint32)(function - functions) == function_count); - (void)module_inst; return functions; } @@ -1288,9 +1287,8 @@ init_func_ptrs(WASMModuleInstance *module_inst, WASMModule *module, *func_ptrs = import_func->func_ptr_linked; } - /* Set defined function pointers */ - bh_memcpy_s(func_ptrs, sizeof(void *) * module->function_count, - module->func_ptrs, sizeof(void *) * module->function_count); + /* The defined function pointers will be set in + wasm_runtime_set_running_mode, no need to set them here */ return true; } #endif /* end of WASM_ENABLE_JIT != 0 */ @@ -1336,6 +1334,173 @@ init_func_type_indexes(WASMModuleInstance *module_inst, char *error_buf, } #endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */ +static bool +set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode, + bool first_time_set) +{ + WASMModule *module = module_inst->module; + + if (running_mode == Mode_Default) { +#if WASM_ENABLE_FAST_JIT == 0 && WASM_ENABLE_JIT == 0 + running_mode = Mode_Interp; +#elif WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT == 0 + running_mode = Mode_Fast_JIT; +#elif WASM_ENABLE_FAST_JIT == 0 && WASM_ENABLE_JIT != 0 + running_mode = Mode_LLVM_JIT; +#else /* WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 */ +#if WASM_ENABLE_LAZY_JIT == 0 + running_mode = Mode_LLVM_JIT; +#else + running_mode = Mode_Multi_Tier_JIT; +#endif +#endif + } + + if (!wasm_runtime_is_running_mode_supported(running_mode)) + return false; + +#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0) /* No possible multi-tier JIT */ + module_inst->e->running_mode = running_mode; + + if (running_mode == Mode_Interp) { + /* Do nothing for Mode_Interp */ + } + else if (running_mode == Mode_Fast_JIT) { + /* Do nothing for Mode_Fast_JIT since + module_inst->fast_jit_func_ptrs is same as + module->fast_jit_func_ptrs */ + } +#if WASM_ENABLE_JIT != 0 + else if (running_mode == Mode_LLVM_JIT) { + /* Set defined function pointers */ + bh_memcpy_s(module_inst->func_ptrs + module->import_function_count, + sizeof(void *) * module->function_count, module->func_ptrs, + sizeof(void *) * module->function_count); + } +#endif + else { + bh_assert(0); + } +#else /* Possible multi-tier JIT */ + os_mutex_lock(&module->instance_list_lock); + + module_inst->e->running_mode = running_mode; + + if (running_mode == Mode_Interp) { + /* Do nothing for Mode_Interp */ + } +#if WASM_ENABLE_FAST_JIT != 0 + else if (running_mode == Mode_Fast_JIT) { + JitGlobals *jit_globals = jit_compiler_get_jit_globals(); + uint32 i; + + /* Allocate memory for fast_jit_func_ptrs if needed */ + if (!module_inst->fast_jit_func_ptrs + || module_inst->fast_jit_func_ptrs == module->fast_jit_func_ptrs) { + uint64 total_size = (uint64)sizeof(void *) * module->function_count; + if (!(module_inst->fast_jit_func_ptrs = + runtime_malloc(total_size, NULL, 0))) { + os_mutex_unlock(&module->instance_list_lock); + return false; + } + } + + for (i = 0; i < module->function_count; i++) { + if (module->functions[i]->fast_jit_jitted_code) { + /* current fast jit function has been compiled */ + module_inst->fast_jit_func_ptrs[i] = + module->functions[i]->fast_jit_jitted_code; + } + else { + module_inst->fast_jit_func_ptrs[i] = + jit_globals->compile_fast_jit_and_then_call; + } + } + } +#endif +#if WASM_ENABLE_JIT != 0 + else if (running_mode == Mode_LLVM_JIT) { + void **llvm_jit_func_ptrs; + uint32 i; + + /* Notify backend threads to start llvm jit compilation */ + module->enable_llvm_jit_compilation = true; + + /* Wait until llvm jit finishes initialization */ + os_mutex_lock(&module->tierup_wait_lock); + while (!module->llvm_jit_inited) { + os_cond_reltimedwait(&module->tierup_wait_cond, + &module->tierup_wait_lock, 10); + if (module->orcjit_stop_compiling) { + /* init_llvm_jit_functions_stage2 failed */ + os_mutex_unlock(&module->tierup_wait_lock); + os_mutex_unlock(&module->instance_list_lock); + return false; + } + } + os_mutex_unlock(&module->tierup_wait_lock); + + llvm_jit_func_ptrs = + module_inst->func_ptrs + module->import_function_count; + for (i = 0; i < module->function_count; i++) { + llvm_jit_func_ptrs[i] = module->functions[i]->llvm_jit_func_ptr; + } + } +#endif + else if (running_mode == Mode_Multi_Tier_JIT) { + /* Notify backend threads to start llvm jit compilation */ + module->enable_llvm_jit_compilation = true; + + /* Free fast_jit_func_ptrs if it is allocated before */ + if (module_inst->fast_jit_func_ptrs + && module_inst->fast_jit_func_ptrs != module->fast_jit_func_ptrs) { + wasm_runtime_free(module_inst->fast_jit_func_ptrs); + } + module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs; + + /* Copy all llvm jit func ptrs from the module */ + bh_memcpy_s(module_inst->func_ptrs + module->import_function_count, + sizeof(void *) * module->function_count, module->func_ptrs, + sizeof(void *) * module->function_count); + } + else { + bh_assert(0); + } + + /* Add module instance into module's instance list if not added */ + if (first_time_set) { + bool found = false; + WASMModuleInstance *node = module->instance_list; + + while (node) { + if (node == module_inst) { + found = true; + break; + } + node = node->e->next; + } + + if (!found) { + module_inst->e->next = module->instance_list; + module->instance_list = module_inst; + } + } + + os_mutex_unlock(&module->instance_list_lock); +#endif /* end of !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0) */ + + (void)module; + return true; +} + +bool +wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode) +{ + return set_running_mode(module_inst, running_mode, false); +} + /** * Instantiate module */ @@ -1422,15 +1587,6 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size, module_inst->e = (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset); -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (os_mutex_init(&module_inst->e->mem_lock) != 0) { - set_error_buf(error_buf, error_buf_size, - "create shared memory lock failed"); - goto fail; - } - module_inst->e->mem_lock_inited = true; -#endif - #if WASM_ENABLE_MULTI_MODULE != 0 module_inst->e->sub_module_inst_list = &module_inst->e->sub_module_inst_list_head; @@ -1803,33 +1959,39 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size, } #endif -#if WASM_ENABLE_DEBUG_INTERP != 0 \ - || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ - && WASM_ENABLE_LAZY_JIT != 0) +#if WASM_ENABLE_WASI_NN != 0 + if (!is_sub_inst) { + if (!(module_inst->e->wasi_nn_ctx = wasi_nn_initialize())) { + set_error_buf(error_buf, error_buf_size, + "wasi nn initialization failed"); + goto fail; + } + } +#endif + +#if WASM_ENABLE_DEBUG_INTERP != 0 if (!is_sub_inst) { /* Add module instance into module's instance list */ os_mutex_lock(&module->instance_list_lock); -#if WASM_ENABLE_DEBUG_INTERP != 0 if (module->instance_list) { LOG_WARNING( "warning: multiple instances referencing to the same module " "may cause unexpected behaviour during debugging"); } -#endif -#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ - && WASM_ENABLE_LAZY_JIT != 0 - /* Copy llvm func ptrs again in case that they were updated - after the module instance was created */ - bh_memcpy_s(module_inst->func_ptrs + module->import_function_count, - sizeof(void *) * module->function_count, module->func_ptrs, - sizeof(void *) * module->function_count); -#endif module_inst->e->next = module->instance_list; module->instance_list = module_inst; os_mutex_unlock(&module->instance_list_lock); } #endif + /* Set running mode before executing wasm functions */ + if (!set_running_mode(module_inst, wasm_runtime_get_default_running_mode(), + true)) { + set_error_buf(error_buf, error_buf_size, + "set instance running mode failed"); + goto fail; + } + if (module->start_function != (uint32)-1) { /* TODO: fix start function can be import function issue */ if (module->start_function >= module->import_function_count) @@ -1895,11 +2057,48 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) if (!module_inst) return; +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0) + /* Remove instance from module's instance list before freeing + func_ptrs and fast_jit_func_ptrs of the instance, to avoid + accessing the freed memory in the jit backend compilation + threads */ + if (!is_sub_inst) { + WASMModule *module = module_inst->module; + WASMModuleInstance *instance_prev = NULL, *instance; + os_mutex_lock(&module->instance_list_lock); + + instance = module->instance_list; + while (instance) { + if (instance == module_inst) { + if (!instance_prev) + module->instance_list = instance->e->next; + else + instance_prev->e->next = instance->e->next; + break; + } + instance_prev = instance; + instance = instance->e->next; + } + + os_mutex_unlock(&module->instance_list_lock); + } +#endif + #if WASM_ENABLE_JIT != 0 if (module_inst->func_ptrs) wasm_runtime_free(module_inst->func_ptrs); #endif +#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + if (module_inst->fast_jit_func_ptrs + && module_inst->fast_jit_func_ptrs + != module_inst->module->fast_jit_func_ptrs) + wasm_runtime_free(module_inst->fast_jit_func_ptrs); +#endif + #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 if (module_inst->func_type_indexes) wasm_runtime_free(module_inst->func_type_indexes); @@ -1951,39 +2150,17 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) } #endif -#if WASM_ENABLE_DEBUG_INTERP != 0 \ - || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ - && WASM_ENABLE_LAZY_JIT != 0) - if (!is_sub_inst) { - WASMModule *module = module_inst->module; - WASMModuleInstance *instance_prev = NULL, *instance; - os_mutex_lock(&module->instance_list_lock); - - instance = module->instance_list; - while (instance) { - if (instance == module_inst) { - if (!instance_prev) - module->instance_list = instance->e->next; - else - instance_prev->e->next = instance->e->next; - break; - } - instance_prev = instance; - instance = instance->e->next; - } - - os_mutex_unlock(&module->instance_list_lock); - } -#endif - -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (module_inst->e->mem_lock_inited) - os_mutex_destroy(&module_inst->e->mem_lock); -#endif - if (module_inst->e->c_api_func_imports) wasm_runtime_free(module_inst->e->c_api_func_imports); +#if WASM_ENABLE_WASI_NN != 0 + if (!is_sub_inst) { + WASINNContext *wasi_nn_ctx = module_inst->e->wasi_nn_ctx; + if (wasi_nn_ctx) + wasi_nn_destroy(wasi_nn_ctx); + } +#endif + wasm_runtime_free(module_inst); } @@ -2056,6 +2233,7 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst, /* Check native stack overflow firstly to ensure we have enough native stack to run the following codes before actually calling the aot function in invokeNative function. */ + RECORD_STACK_USAGE(exec_env, (uint8 *)&exec_env_tls); if ((uint8 *)&exec_env_tls < exec_env->native_stack_boundary + page_size * (guard_page_count + 1)) { wasm_set_exception(module_inst, "native stack overflow"); diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 5bf09bb8..bf231ad6 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -11,6 +11,10 @@ #include "../common/wasm_runtime_common.h" #include "../common/wasm_exec_env.h" +#if WASM_ENABLE_WASI_NN != 0 +#include "../libraries/wasi-nn/src/wasi_nn_private.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -59,9 +63,7 @@ typedef enum WASMExceptionID { EXCE_AUX_STACK_UNDERFLOW, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, EXCE_OPERAND_STACK_OVERFLOW, -#if WASM_ENABLE_FAST_JIT != 0 EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC, -#endif EXCE_ALREADY_THROWN, EXCE_NUM, } WASMExceptionID; @@ -219,12 +221,7 @@ typedef struct WASMModuleInstanceExtra { WASMFunctionInstance *retain_function; CApiFuncImport *c_api_func_imports; - -#if WASM_ENABLE_SHARED_MEMORY != 0 - /* lock for shared memory atomic operations */ - korp_mutex mem_lock; - bool mem_lock_inited; -#endif + RunningMode running_mode; #if WASM_ENABLE_MULTI_MODULE != 0 bh_list sub_module_inst_list_head; @@ -237,11 +234,15 @@ typedef struct WASMModuleInstanceExtra { uint32 max_aux_stack_used; #endif -#if WASM_ENABLE_DEBUG_INTERP != 0 \ - || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ +#if WASM_ENABLE_DEBUG_INTERP != 0 \ + || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ && WASM_ENABLE_LAZY_JIT != 0) WASMModuleInstance *next; #endif + +#if WASM_ENABLE_WASI_NN != 0 + WASINNContext *wasi_nn_ctx; +#endif } WASMModuleInstanceExtra; struct AOTFuncPerfProfInfo; @@ -298,7 +299,11 @@ struct WASMModuleInstance { not available in AOTModuleInstance */ DefPointer(void **, import_func_ptrs); /* Array of function pointers to fast jit functions, - not available in AOTModuleInstance */ + not available in AOTModuleInstance: + Only when the multi-tier JIT macros are all enabled and the running + mode of current module instance is set to Mode_Fast_JIT, runtime + will allocate new memory for it, otherwise it always points to the + module->fast_jit_func_ptrs */ DefPointer(void **, fast_jit_func_ptrs); /* The custom data that can be set/get by wasm_{get|set}_custom_data */ DefPointer(void *, custom_data); @@ -402,6 +407,10 @@ wasm_dump_perf_profiling(const WASMModuleInstance *module_inst); void wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst); +bool +wasm_set_running_mode(WASMModuleInstance *module_inst, + RunningMode running_mode); + WASMFunctionInstance * wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name, const char *signature); diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index d4d9023e..efce5b4e 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -565,6 +565,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, #if WASM_ENABLE_LIBC_WASI != 0 WASIContext *wasi_ctx; #endif + CApiFuncImport **new_c_api_func_imports = NULL; bh_assert(module); bh_assert(module_inst); @@ -597,6 +598,46 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx); #endif + /* workaround about passing instantiate-linking information */ + { + CApiFuncImport *c_api_func_imports; + uint32 import_func_count = 0; + uint32 size_in_bytes = 0; + +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + new_c_api_func_imports = &( + ((WASMModuleInstance *)new_module_inst)->e->c_api_func_imports); + c_api_func_imports = + ((WASMModuleInstance *)module_inst)->e->c_api_func_imports; + import_func_count = ((WASMModule *)module)->import_function_count; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + AOTModuleInstanceExtra *e = + (AOTModuleInstanceExtra *)((AOTModuleInstance *)new_module_inst) + ->e; + new_c_api_func_imports = &(e->c_api_func_imports); + + e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e; + c_api_func_imports = e->c_api_func_imports; + + import_func_count = ((AOTModule *)module)->import_func_count; + } +#endif + + if (import_func_count != 0 && c_api_func_imports) { + size_in_bytes = sizeof(CApiFuncImport *) * import_func_count; + *new_c_api_func_imports = wasm_runtime_malloc(size_in_bytes); + if (!(*new_c_api_func_imports)) + goto fail; + + bh_memcpy_s(*new_c_api_func_imports, size_in_bytes, + c_api_func_imports, size_in_bytes); + } + } + if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode)))) goto fail; diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index a6a448b5..815fa5aa 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -63,6 +63,12 @@ typedef struct WASIContext { wasi_ctx_t wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst); +static inline size_t +min(size_t a, size_t b) +{ + return a > b ? b : a; +} + static inline struct fd_table * wasi_ctx_get_curfds(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) { @@ -951,6 +957,97 @@ wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, return wasmtime_ssp_path_remove_directory(curfds, fd, path, path_len); } +#if WASM_ENABLE_THREAD_MGR != 0 +static __wasi_timestamp_t +get_timeout_for_poll_oneoff(const wasi_subscription_t *in, + uint32 nsubscriptions) +{ + __wasi_timestamp_t timeout = (__wasi_timestamp_t)-1; + uint32 i = 0; + + for (i = 0; i < nsubscriptions; ++i) { + const __wasi_subscription_t *s = &in[i]; + if (s->u.type == __WASI_EVENTTYPE_CLOCK + && (s->u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) == 0) { + timeout = min(timeout, s->u.u.clock.timeout); + } + } + return timeout; +} + +static void +update_clock_subscription_data(wasi_subscription_t *in, uint32 nsubscriptions, + const wasi_timestamp_t new_timeout) +{ + uint32 i = 0; + for (i = 0; i < nsubscriptions; ++i) { + __wasi_subscription_t *s = &in[i]; + if (s->u.type == __WASI_EVENTTYPE_CLOCK) { + s->u.u.clock.timeout = new_timeout; + } + } +} + +static wasi_errno_t +execute_interruptible_poll_oneoff(wasm_module_inst_t module_inst, +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + const __wasi_subscription_t *in, + __wasi_event_t *out, size_t nsubscriptions, + size_t *nevents) +{ + if (nsubscriptions == 0) { + *nevents = 0; + return __WASI_ESUCCESS; + } + + wasi_errno_t err; + __wasi_timestamp_t elapsed = 0; + + const __wasi_timestamp_t timeout = get_timeout_for_poll_oneoff( + in, nsubscriptions), + time_quant = 1e9; + const uint64 size_to_copy = + nsubscriptions * (uint64)sizeof(wasi_subscription_t); + __wasi_subscription_t *in_copy = NULL; + + if (size_to_copy >= UINT32_MAX + || !(in_copy = (__wasi_subscription_t *)wasm_runtime_malloc( + (uint32)size_to_copy))) { + return __WASI_ENOMEM; + } + + bh_memcpy_s(in_copy, size_to_copy, in, size_to_copy); + + while (timeout == (__wasi_timestamp_t)-1 || elapsed <= timeout) { + elapsed += time_quant; + + /* update timeout for clock subscription events */ + update_clock_subscription_data(in_copy, nsubscriptions, + min(time_quant, timeout - elapsed)); + err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions, + nevents); + if (err) { + wasm_runtime_free(in_copy); + return err; + } + + if (wasm_runtime_get_exception(module_inst) || *nevents > 0) { + wasm_runtime_free(in_copy); + + if (*nevents) { + return __WASI_ESUCCESS; + } + return EINTR; + } + } + + wasm_runtime_free(in_copy); + return __WASI_ESUCCESS; +} +#endif + static wasi_errno_t wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app) @@ -958,7 +1055,7 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - size_t nevents; + size_t nevents = 0; wasi_errno_t err; if (!wasi_ctx) @@ -969,7 +1066,12 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, || !validate_native_addr(nevents_app, sizeof(uint32))) return (wasi_errno_t)-1; +#if WASM_ENABLE_THREAD_MGR == 0 err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents); +#else + err = execute_interruptible_poll_oneoff(module_inst, curfds, in, out, + nsubscriptions, &nevents); +#endif if (err) return err; @@ -1861,12 +1963,6 @@ allocate_iovec_app_buffer(wasm_module_inst_t module_inst, return __WASI_ESUCCESS; } -static inline size_t -min(size_t a, size_t b) -{ - return a > b ? b : a; -} - static wasi_errno_t copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin, uint32 buf_size, iovec_app_t *data, uint32 data_len, diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h new file mode 100644 index 00000000..70000ae0 --- /dev/null +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#if !defined(__GNUC_PREREQ) && (defined(__GNUC__) || defined(__GNUG__)) \ + && !defined(__clang__) && defined(__GNUC_MINOR__) +/* Depending on the platform the macro is defined in sys/features.h or + features.h Given the macro is simple, we re-implement it here instead of + dealing with two different paths. + */ +#define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h deleted file mode 100644 index 233f3733..00000000 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h +++ /dev/null @@ -1,42 +0,0 @@ -// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM -// Exceptions. See -// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license -// information. -// -// Significant parts of this file are derived from cloudabi-utils. See -// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE -// for license information. -// -// The upstream file contains the following copyright notice: -// -// Copyright (c) 2015 Nuxi, https://nuxi.nl/ - -#ifndef COMMON_LIMITS_H -#define COMMON_LIMITS_H - -#define NUMERIC_MIN(t) \ - _Generic((t)0, char \ - : CHAR_MIN, signed char \ - : SCHAR_MIN, unsigned char : 0, short \ - : SHRT_MIN, unsigned short : 0, int \ - : INT_MIN, unsigned int : 0, long \ - : LONG_MIN, unsigned long : 0, long long \ - : LLONG_MIN, unsigned long long : 0, default \ - : (void)0) - -#define NUMERIC_MAX(t) \ - _Generic((t)0, char \ - : CHAR_MAX, signed char \ - : SCHAR_MAX, unsigned char \ - : UCHAR_MAX, short \ - : SHRT_MAX, unsigned short \ - : USHRT_MAX, int \ - : INT_MAX, unsigned int \ - : UINT_MAX, long \ - : LONG_MAX, unsigned long \ - : ULONG_MAX, long long \ - : LLONG_MAX, unsigned long long \ - : ULLONG_MAX, default \ - : (void)0) - -#endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index d8c57459..36fe1be6 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -15,7 +15,6 @@ #include "bh_platform.h" #include "wasmtime_ssp.h" #include "locking.h" -#include "numeric_limits.h" #include "posix.h" #include "random.h" #include "refcount.h" @@ -2257,8 +2256,7 @@ convert_timestamp(__wasi_timestamp_t in, struct timespec *out) in /= 1000000000; // Clamp to the maximum in case it would overflow our system's time_t. - out->tv_sec = - (time_t)in < NUMERIC_MAX(time_t) ? (time_t)in : NUMERIC_MAX(time_t); + out->tv_sec = (time_t)in < BH_TIME_T_MAX ? (time_t)in : BH_TIME_T_MAX; } // Converts the provided timestamps and flags to a set of arguments for @@ -3226,6 +3224,7 @@ wasi_ssp_sock_get_reuse_port( #else errno = ENOTSUP; ret = BHT_ERROR; + optval = 0; #endif /* defined(SO_REUSEPORT) */ fd_object_release(fo); diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h index ac348ebb..03b4b87a 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h @@ -16,6 +16,7 @@ #include "bh_platform.h" #include "locking.h" +#include "gnuc.h" #define PRODUCES(...) LOCKS_SHARED(__VA_ARGS__) NO_LOCK_ANALYSIS #define CONSUMES(...) UNLOCKS(__VA_ARGS__) NO_LOCK_ANALYSIS @@ -95,6 +96,42 @@ refcount_release(struct refcount *r) return old == 1; } +#elif defined(__GNUC_PREREQ) + +#if __GNUC_PREREQ(4, 7) + +struct refcount { + unsigned int count; +}; + +/* Initialize the reference counter. */ +static inline void +refcount_init(struct refcount *r, unsigned int count) +{ + __atomic_store_n(&r->count, count, __ATOMIC_SEQ_CST); +} + +/* Increment the reference counter. */ +static inline void +refcount_acquire(struct refcount *r) +{ + __atomic_fetch_add(&r->count, 1, __ATOMIC_ACQUIRE); +} + +/* Decrement the reference counter, returning whether the reference + dropped to zero. */ +static inline bool +refcount_release(struct refcount *r) +{ + int old = (int)__atomic_fetch_sub(&r->count, 1, __ATOMIC_RELEASE); + bh_assert(old != 0 && "Reference count becoming negative"); + return old == 1; +} + +#else /* else of __GNUC_PREREQ (4.7) */ +#error "Reference counter isn't implemented" +#endif /* end of __GNUC_PREREQ (4.7) */ + #else /* else of CONFIG_HAS_STD_ATOMIC */ #error "Reference counter isn't implemented" #endif /* end of CONFIG_HAS_STD_ATOMIC */ diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h index 68b0faf3..d5babd02 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h @@ -14,6 +14,7 @@ #ifndef SSP_CONFIG_H #define SSP_CONFIG_H +#include "gnuc.h" #include #if defined(__FreeBSD__) || defined(__APPLE__) \ @@ -107,10 +108,31 @@ #endif #if !defined(BH_PLATFORM_LINUX_SGX) +/* Clang's __GNUC_PREREQ macro has a different meaning than GCC one, +so we have to handle this case specially */ +#if defined(__clang__) +/* Clang provides stdatomic.h since 3.6.0 +See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html */ +#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6) #define CONFIG_HAS_STD_ATOMIC 1 #else #define CONFIG_HAS_STD_ATOMIC 0 #endif +#elif defined(__GNUC_PREREQ) +/* Even though older versions of GCC support C11, atomics were +not implemented until 4.9. See +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58016 */ +#if __GNUC_PREREQ(4, 9) +#define CONFIG_HAS_STD_ATOMIC 1 +#else /* else of __GNUC_PREREQ(4, 9) */ +#define CONFIG_HAS_STD_ATOMIC 0 +#endif /* end of __GNUC_PREREQ(4, 9) */ +#else /* else of defined(__GNUC_PREREQ) */ +#define CONFIG_HAS_STD_ATOMIC 1 +#endif /* end of defined(__GNUC_PREREQ) */ +#else /* else of !defined(BH_PLATFORM_LINUX_SGX) */ +#define CONFIG_HAS_STD_ATOMIC 0 +#endif /* end of !defined(BH_PLATFORM_LINUX_SGX) */ #if !defined(__NuttX__) #define CONFIG_HAS_D_INO 1 diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index 8ec310d9..d3c66cae 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -76,6 +76,58 @@ traverse_list(bh_list *l, list_visitor visitor, void *user_data) } } +/* Assumes cluster->lock is locked */ +static bool +safe_traverse_exec_env_list(WASMCluster *cluster, list_visitor visitor, + void *user_data) +{ + Vector proc_nodes; + void *node; + bool ret = true; + + if (!bh_vector_init(&proc_nodes, cluster->exec_env_list.len, sizeof(void *), + false)) { + ret = false; + goto final; + } + + node = bh_list_first_elem(&cluster->exec_env_list); + + while (node) { + bool already_processed = false; + void *proc_node; + for (size_t i = 0; i < bh_vector_size(&proc_nodes); i++) { + if (!bh_vector_get(&proc_nodes, i, &proc_node)) { + ret = false; + goto final; + } + if (proc_node == node) { + already_processed = true; + break; + } + } + if (already_processed) { + node = bh_list_elem_next(node); + continue; + } + + os_mutex_unlock(&cluster->lock); + visitor(node, user_data); + os_mutex_lock(&cluster->lock); + if (!bh_vector_append(&proc_nodes, &node)) { + ret = false; + goto final; + } + + node = bh_list_first_elem(&cluster->exec_env_list); + } + +final: + bh_vector_destroy(&proc_nodes); + + return ret; +} + /* The caller must lock cluster->lock */ static bool allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size) @@ -344,7 +396,6 @@ wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env) os_mutex_unlock(&cluster->debug_inst->wait_lock); } #endif - if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0) ret = false; @@ -478,7 +529,7 @@ fail4: /* free the allocated aux stack space */ free_aux_stack(exec_env, aux_stack_start); fail3: - wasm_exec_env_destroy(new_exec_env); + wasm_exec_env_destroy_internal(new_exec_env); fail2: wasm_runtime_deinstantiate_internal(new_module_inst, true); fail1: @@ -616,7 +667,7 @@ fail3: if (alloc_aux_stack) free_aux_stack(exec_env, aux_stack_start); fail2: - wasm_exec_env_destroy(new_exec_env); + wasm_exec_env_destroy_internal(new_exec_env); fail1: os_mutex_unlock(&cluster->lock); @@ -786,16 +837,22 @@ wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val) korp_tid handle; os_mutex_lock(&cluster_list_lock); + os_mutex_lock(&exec_env->cluster->lock); + if (!clusters_have_exec_env(exec_env) || exec_env->thread_is_detached) { /* Invalid thread, thread has exited or thread has been detached */ if (ret_val) *ret_val = NULL; + os_mutex_unlock(&exec_env->cluster->lock); os_mutex_unlock(&cluster_list_lock); return 0; } exec_env->wait_count++; handle = exec_env->handle; + + os_mutex_unlock(&exec_env->cluster->lock); os_mutex_unlock(&cluster_list_lock); + return os_thread_join(handle, ret_val); } @@ -878,15 +935,22 @@ int32 wasm_cluster_cancel_thread(WASMExecEnv *exec_env) { os_mutex_lock(&cluster_list_lock); + os_mutex_lock(&exec_env->cluster->lock); + + if (!exec_env->cluster) { + goto final; + } if (!clusters_have_exec_env(exec_env)) { /* Invalid thread or the thread has exited */ - os_mutex_unlock(&cluster_list_lock); - return 0; + goto final; } - os_mutex_unlock(&cluster_list_lock); set_thread_cancel_flags(exec_env); +final: + os_mutex_unlock(&exec_env->cluster->lock); + os_mutex_unlock(&cluster_list_lock); + return 0; } @@ -908,11 +972,9 @@ wasm_cluster_terminate_all(WASMCluster *cluster) { os_mutex_lock(&cluster->lock); cluster->processing = true; - os_mutex_unlock(&cluster->lock); - traverse_list(&cluster->exec_env_list, terminate_thread_visitor, NULL); + safe_traverse_exec_env_list(cluster, terminate_thread_visitor, NULL); - os_mutex_lock(&cluster->lock); cluster->processing = false; os_mutex_unlock(&cluster->lock); } @@ -923,12 +985,10 @@ wasm_cluster_terminate_all_except_self(WASMCluster *cluster, { os_mutex_lock(&cluster->lock); cluster->processing = true; - os_mutex_unlock(&cluster->lock); - traverse_list(&cluster->exec_env_list, terminate_thread_visitor, - (void *)exec_env); + safe_traverse_exec_env_list(cluster, terminate_thread_visitor, + (void *)exec_env); - os_mutex_lock(&cluster->lock); cluster->processing = false; os_mutex_unlock(&cluster->lock); } @@ -950,11 +1010,9 @@ wams_cluster_wait_for_all(WASMCluster *cluster) { os_mutex_lock(&cluster->lock); cluster->processing = true; - os_mutex_unlock(&cluster->lock); - traverse_list(&cluster->exec_env_list, wait_for_thread_visitor, NULL); + safe_traverse_exec_env_list(cluster, wait_for_thread_visitor, NULL); - os_mutex_lock(&cluster->lock); cluster->processing = false; os_mutex_unlock(&cluster->lock); } @@ -965,12 +1023,10 @@ wasm_cluster_wait_for_all_except_self(WASMCluster *cluster, { os_mutex_lock(&cluster->lock); cluster->processing = true; - os_mutex_unlock(&cluster->lock); - traverse_list(&cluster->exec_env_list, wait_for_thread_visitor, - (void *)exec_env); + safe_traverse_exec_env_list(cluster, wait_for_thread_visitor, + (void *)exec_env); - os_mutex_lock(&cluster->lock); cluster->processing = false; os_mutex_unlock(&cluster->lock); } diff --git a/core/iwasm/libraries/wasi-nn/.dockerignore b/core/iwasm/libraries/wasi-nn/.dockerignore deleted file mode 100644 index 0e2be498..00000000 --- a/core/iwasm/libraries/wasi-nn/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -**/Dockerfile diff --git a/core/iwasm/libraries/wasi-nn/README.md b/core/iwasm/libraries/wasi-nn/README.md index 22ef13db..efd8fbfc 100644 --- a/core/iwasm/libraries/wasi-nn/README.md +++ b/core/iwasm/libraries/wasi-nn/README.md @@ -17,27 +17,76 @@ By only including this file in your WASM application you will bind WASI-NN into To run the tests we assume that the current directory is the root of the repository. -1. Build the docker image, +### Build the runtime + +Build the runtime base image, ``` -docker build -t wasi-nn -f core/iwasm/libraries/wasi-nn/test/Dockerfile . +docker build -t wasi-nn-base -f core/iwasm/libraries/wasi-nn/test/Dockerfile.base . ``` -2. Run the container +Build the runtime image for your execution target type. + +`EXECUTION_TYPE` can be: +* `cpu` +* `nvidia-gpu` ``` -docker run wasi-nn +EXECUTION_TYPE=cpu +docker build -t wasi-nn-${EXECUTION_TYPE} -f core/iwasm/libraries/wasi-nn/test/Dockerfile.${EXECUTION_TYPE} . ``` + +### Build wasm app + +``` +docker build -t wasi-nn-compile -f core/iwasm/libraries/wasi-nn/test/Dockerfile.compile . +``` + +``` +docker run -v $PWD/core/iwasm/libraries/wasi-nn:/wasi-nn wasi-nn-compile +``` + + +### Run wasm app + If all the tests have run properly you will the the following message in the terminal, ``` Tests: passed! ``` +* CPU + +``` +docker run \ + -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-cpu \ + --dir=/assets \ + --env="TARGET=cpu" \ + /assets/test_tensorflow.wasm +``` + +* (NVIDIA) GPU + +``` +docker run \ + --runtime=nvidia \ + -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-nvidia-gpu \ + --dir=/assets \ + --env="TARGET=gpu" \ + /assets/test_tensorflow.wasm +``` + +Requirements: +* [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker). + ## What is missing -* Only 1 model at a time is supported. +Supported: + +* Only 1 WASM app at a time. +* Only 1 model at a time. * `graph` and `graph-execution-context` are ignored. -* Only `tensorflow` (lite) is supported. -* Only `cpu` is supported. +* Graph encoding: `tensorflowlite`. +* Execution target: `cpu` and `gpu`. +* Tensor type: `fp32`. diff --git a/core/iwasm/libraries/wasi-nn/logger.h b/core/iwasm/libraries/wasi-nn/logger.h deleted file mode 100644 index 25588eb6..00000000 --- a/core/iwasm/libraries/wasi-nn/logger.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef WASI_NN_LOGGER_H -#define WASI_NN_LOGGER_H - -#include -#include - -#define __FILENAME__ \ - (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) - -/* Disable a level by removing the define */ -#define ENABLE_ERR_LOG -#define ENABLE_WARN_LOG -#define ENABLE_DBG_LOG -#define ENABLE_INFO_LOG - -// Definition of the levels -#ifdef ENABLE_ERR_LOG -#define NN_ERR_PRINTF(fmt, ...) \ - printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \ - printf("\n"); \ - fflush(stdout) -#else -#define NN_ERR_PRINTF(fmt, ...) -#endif -#ifdef ENABLE_WARN_LOG -#define NN_WARN_PRINTF(fmt, ...) \ - printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \ - printf("\n"); \ - fflush(stdout) -#else -#define NN_WARN_PRINTF(fmt, ...) -#endif -#ifdef ENABLE_DBG_LOG -#define NN_DBG_PRINTF(fmt, ...) \ - printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \ - printf("\n"); \ - fflush(stdout) -#else -#define NN_DBG_PRINTF(fmt, ...) -#endif -#ifdef ENABLE_INFO_LOG -#define NN_INFO_PRINTF(fmt, ...) \ - printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \ - printf("\n"); \ - fflush(stdout) -#else -#define NN_INFO_PRINTF(fmt, ...) -#endif - -#endif diff --git a/core/iwasm/libraries/wasi-nn/src/utils/logger.h b/core/iwasm/libraries/wasi-nn/src/utils/logger.h new file mode 100644 index 00000000..55128213 --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/src/utils/logger.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef WASI_NN_LOGGER_H +#define WASI_NN_LOGGER_H + +#include +#include + +#define __FILENAME__ \ + (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) + +/* Disable a level by removing the define */ +#define ENABLE_ERR_LOG +#define ENABLE_WARN_LOG +#define ENABLE_DBG_LOG +#define ENABLE_INFO_LOG + +// Definition of the levels +#ifdef ENABLE_ERR_LOG +#define NN_ERR_PRINTF(fmt, ...) \ + do { \ + printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \ + printf("\n"); \ + fflush(stdout); \ + } while (0) +#else +#define NN_ERR_PRINTF(fmt, ...) +#endif +#ifdef ENABLE_WARN_LOG +#define NN_WARN_PRINTF(fmt, ...) \ + do { \ + printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \ + printf("\n"); \ + fflush(stdout); \ + } while (0) +#else +#define NN_WARN_PRINTF(fmt, ...) +#endif +#ifdef ENABLE_DBG_LOG +#define NN_DBG_PRINTF(fmt, ...) \ + do { \ + printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \ + printf("\n"); \ + fflush(stdout); \ + } while (0) +#else +#define NN_DBG_PRINTF(fmt, ...) +#endif +#ifdef ENABLE_INFO_LOG +#define NN_INFO_PRINTF(fmt, ...) \ + do { \ + printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \ + printf("\n"); \ + fflush(stdout); \ + } while (0) +#else +#define NN_INFO_PRINTF(fmt, ...) +#endif + +#endif diff --git a/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c new file mode 100644 index 00000000..fe04b657 --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasi_nn_app_native.h" + +static error +graph_builder_app_native(wasm_module_inst_t instance, + graph_builder_wasm *builder_wasm, + graph_builder *builder) +{ + if (!wasm_runtime_validate_app_addr(instance, builder_wasm->buf_offset, + builder_wasm->size * sizeof(uint8_t))) { + NN_ERR_PRINTF("builder_wasm->buf_offset is invalid"); + return invalid_argument; + } + + builder->buf = (uint8_t *)wasm_runtime_addr_app_to_native( + instance, builder_wasm->buf_offset); + builder->size = builder_wasm->size; + return success; +} + +error +graph_builder_array_app_native(wasm_module_inst_t instance, + graph_builder_array_wasm *builder_array_wasm, + graph_builder_array *builder_array) +{ + if (!wasm_runtime_validate_native_addr(instance, builder_array_wasm, + sizeof(graph_builder_array_wasm))) { + NN_ERR_PRINTF("builder_array_wasm is invalid"); + return invalid_argument; + } + + NN_DBG_PRINTF("Graph builder array contains %d elements", + builder_array_wasm->size); + + if (!wasm_runtime_validate_app_addr( + instance, builder_array_wasm->buf_offset, + builder_array_wasm->size * sizeof(graph_builder_wasm))) { + NN_ERR_PRINTF("builder_array_wasm->buf_offset is invalid"); + return invalid_argument; + } + + graph_builder_wasm *builder_wasm = + (graph_builder_wasm *)wasm_runtime_addr_app_to_native( + instance, builder_array_wasm->buf_offset); + + graph_builder *builder = (graph_builder *)wasm_runtime_malloc( + builder_array_wasm->size * sizeof(graph_builder)); + if (builder == NULL) + return missing_memory; + + for (uint32_t i = 0; i < builder_array_wasm->size; ++i) { + error res; + if (success + != (res = graph_builder_app_native(instance, &builder_wasm[i], + &builder[i]))) { + wasm_runtime_free(builder); + return res; + } + + NN_DBG_PRINTF("Graph builder %d contains %d elements", i, + builder->size); + } + + builder_array->buf = builder; + builder_array->size = builder_array_wasm->size; + return success; +} + +static error +tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements, + tensor_wasm *input_tensor_wasm, tensor_data *data) +{ + if (!wasm_runtime_validate_app_addr( + instance, input_tensor_wasm->data_offset, total_elements)) { + NN_ERR_PRINTF("input_tensor_wasm->data_offset is invalid"); + return invalid_argument; + } + *data = (tensor_data)wasm_runtime_addr_app_to_native( + instance, input_tensor_wasm->data_offset); + return success; +} + +static error +tensor_dimensions_app_native(wasm_module_inst_t instance, + tensor_wasm *input_tensor_wasm, + tensor_dimensions **dimensions) +{ + if (!wasm_runtime_validate_app_addr(instance, + input_tensor_wasm->dimensions_offset, + sizeof(tensor_dimensions_wasm))) { + NN_ERR_PRINTF("input_tensor_wasm->dimensions_offset is invalid"); + return invalid_argument; + } + + tensor_dimensions_wasm *dimensions_wasm = + (tensor_dimensions_wasm *)wasm_runtime_addr_app_to_native( + instance, input_tensor_wasm->dimensions_offset); + + if (!wasm_runtime_validate_app_addr(instance, dimensions_wasm->buf_offset, + sizeof(tensor_dimensions))) { + NN_ERR_PRINTF("dimensions_wasm->buf_offset is invalid"); + return invalid_argument; + } + + *dimensions = + (tensor_dimensions *)wasm_runtime_malloc(sizeof(tensor_dimensions)); + if (dimensions == NULL) + return missing_memory; + + (*dimensions)->size = dimensions_wasm->size; + (*dimensions)->buf = (uint32_t *)wasm_runtime_addr_app_to_native( + instance, dimensions_wasm->buf_offset); + + NN_DBG_PRINTF("Number of dimensions: %d", (*dimensions)->size); + return success; +} + +error +tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm, + tensor *input_tensor) +{ + NN_DBG_PRINTF("Converting tensor_wasm to tensor"); + if (!wasm_runtime_validate_native_addr(instance, input_tensor_wasm, + sizeof(tensor_wasm))) { + NN_ERR_PRINTF("input_tensor_wasm is invalid"); + return invalid_argument; + } + + error res; + + tensor_dimensions *dimensions = NULL; + if (success + != (res = tensor_dimensions_app_native(instance, input_tensor_wasm, + &dimensions))) { + NN_ERR_PRINTF("error when parsing dimensions"); + return res; + } + + uint32_t total_elements = 1; + for (uint32_t i = 0; i < dimensions->size; ++i) { + total_elements *= dimensions->buf[i]; + NN_DBG_PRINTF("Dimension %d: %d", i, dimensions->buf[i]); + } + NN_DBG_PRINTF("Tensor type: %d", input_tensor_wasm->type); + NN_DBG_PRINTF("Total number of elements: %d", total_elements); + + tensor_data data = NULL; + if (success + != (res = tensor_data_app_native(instance, total_elements, + input_tensor_wasm, &data))) { + wasm_runtime_free(dimensions); + return res; + } + + input_tensor->type = input_tensor_wasm->type; + input_tensor->dimensions = dimensions; + input_tensor->data = data; + return success; +} diff --git a/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h new file mode 100644 index 00000000..15154bd3 --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef WASI_NN_APP_NATIVE +#define WASI_NN_APP_NATIVE + +#include +#include +#include +#include +#include + +#include "wasi_nn.h" +#include "logger.h" + +#include "bh_platform.h" +#include "wasm_export.h" + +typedef struct { + uint32_t buf_offset; + uint32_t size; +} graph_builder_wasm; + +typedef struct { + uint32_t buf_offset; + uint32_t size; +} graph_builder_array_wasm; + +typedef struct { + uint32_t buf_offset; + uint32_t size; +} tensor_dimensions_wasm; + +typedef struct { + uint32_t dimensions_offset; + tensor_type type; + uint32_t data_offset; +} tensor_wasm; + +error +graph_builder_array_app_native(wasm_module_inst_t instance, + graph_builder_array_wasm *builder, + graph_builder_array *builder_native); + +error +tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor, + tensor *input_tensor_native); + +#endif diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn.c b/core/iwasm/libraries/wasi-nn/src/wasi_nn.c new file mode 100644 index 00000000..0176bbed --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn.c @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include +#include + +#include "wasi_nn.h" +#include "wasi_nn_app_native.h" +#include "logger.h" +#include "wasi_nn_tensorflowlite.hpp" + +#include "bh_platform.h" +#include "wasm_export.h" +#include "wasm_runtime.h" +#include "aot_runtime.h" + +/* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */ + +typedef error (*LOAD)(graph_builder_array *, graph_encoding, execution_target, + graph *); +typedef error (*INIT_EXECUTION_CONTEXT)(graph, graph_execution_context *); +typedef error (*SET_INPUT)(graph_execution_context, uint32_t, tensor *); +typedef error (*COMPUTE)(graph_execution_context); +typedef error (*GET_OUTPUT)(graph_execution_context, uint32_t, tensor_data, + uint32_t *); + +typedef struct { + LOAD load; + INIT_EXECUTION_CONTEXT init_execution_context; + SET_INPUT set_input; + COMPUTE compute; + GET_OUTPUT get_output; +} api_function; + +/* Global variables */ + +static api_function lookup[] = { + { NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL }, + { tensorflowlite_load, tensorflowlite_init_execution_context, + tensorflowlite_set_input, tensorflowlite_compute, + tensorflowlite_get_output } +}; + +/* Utils */ + +static bool +is_encoding_implemented(graph_encoding encoding) +{ + return lookup[encoding].load && lookup[encoding].init_execution_context + && lookup[encoding].set_input && lookup[encoding].compute + && lookup[encoding].get_output; +} + +static error +is_model_initialized(WASINNContext *wasi_nn_ctx) +{ + if (!wasi_nn_ctx->is_initialized) { + NN_ERR_PRINTF("Model not initialized."); + return runtime_error; + } + return success; +} + +WASINNContext * +wasm_runtime_get_wasi_nn_ctx(wasm_module_inst_t instance) +{ + WASINNContext *wasi_nn_ctx = NULL; +#if WASM_ENABLE_INTERP != 0 + if (instance->module_type == Wasm_Module_Bytecode) { + NN_DBG_PRINTF("Getting ctx from WASM"); + WASMModuleInstance *module_inst = (WASMModuleInstance *)instance; + wasi_nn_ctx = ((WASMModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (instance->module_type == Wasm_Module_AoT) { + NN_DBG_PRINTF("Getting ctx from AOT"); + AOTModuleInstance *module_inst = (AOTModuleInstance *)instance; + wasi_nn_ctx = ((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx; + } +#endif + bh_assert(wasi_nn_ctx != NULL); + NN_DBG_PRINTF("Returning ctx"); + return wasi_nn_ctx; +} + +/* WASI-NN implementation */ + +error +wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder, + graph_encoding encoding, execution_target target, graph *g) +{ + NN_DBG_PRINTF("Running wasi_nn_load [encoding=%d, target=%d]...", encoding, + target); + + if (!is_encoding_implemented(encoding)) { + NN_ERR_PRINTF("Encoding not supported."); + return invalid_encoding; + } + + wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env); + bh_assert(instance); + + error res; + graph_builder_array builder_native = { 0 }; + if (success + != (res = graph_builder_array_app_native(instance, builder, + &builder_native))) + return res; + + if (!wasm_runtime_validate_native_addr(instance, g, sizeof(graph))) { + NN_ERR_PRINTF("graph is invalid"); + res = invalid_argument; + goto fail; + } + + res = lookup[encoding].load(&builder_native, encoding, target, g); + + NN_DBG_PRINTF("wasi_nn_load finished with status %d [graph=%d]", res, *g); + + WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); + + wasi_nn_ctx->current_encoding = encoding; + wasi_nn_ctx->is_initialized = true; + +fail: + // XXX: Free intermediate structure pointers + if (builder_native.buf) + wasm_runtime_free(builder_native.buf); + + return res; +} + +error +wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g, + graph_execution_context *ctx) +{ + NN_DBG_PRINTF("Running wasi_nn_init_execution_context [graph=%d]...", g); + + wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env); + bh_assert(instance); + WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); + + error res; + if (success != (res = is_model_initialized(wasi_nn_ctx))) + return res; + + if (!wasm_runtime_validate_native_addr(instance, ctx, + sizeof(graph_execution_context))) { + NN_ERR_PRINTF("ctx is invalid"); + return invalid_argument; + } + + res = lookup[wasi_nn_ctx->current_encoding].init_execution_context(g, ctx); + *ctx = g; + NN_DBG_PRINTF( + "wasi_nn_init_execution_context finished with status %d [ctx=%d]", res, + *ctx); + return res; +} + +error +wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx, + uint32_t index, tensor_wasm *input_tensor) +{ + NN_DBG_PRINTF("Running wasi_nn_set_input [ctx=%d, index=%d]...", ctx, + index); + + wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env); + bh_assert(instance); + WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); + + error res; + if (success != (res = is_model_initialized(wasi_nn_ctx))) + return res; + + tensor input_tensor_native = { 0 }; + if (success + != (res = tensor_app_native(instance, input_tensor, + &input_tensor_native))) + return res; + + res = lookup[wasi_nn_ctx->current_encoding].set_input(ctx, index, + &input_tensor_native); + + // XXX: Free intermediate structure pointers + if (input_tensor_native.dimensions) + wasm_runtime_free(input_tensor_native.dimensions); + + NN_DBG_PRINTF("wasi_nn_set_input finished with status %d", res); + return res; +} + +error +wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx) +{ + NN_DBG_PRINTF("Running wasi_nn_compute [ctx=%d]...", ctx); + + wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env); + bh_assert(instance); + WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); + + error res; + if (success != (res = is_model_initialized(wasi_nn_ctx))) + return res; + + res = lookup[wasi_nn_ctx->current_encoding].compute(ctx); + NN_DBG_PRINTF("wasi_nn_compute finished with status %d", res); + return res; +} + +error +wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx, + uint32_t index, tensor_data output_tensor, + uint32_t *output_tensor_size) +{ + NN_DBG_PRINTF("Running wasi_nn_get_output [ctx=%d, index=%d]...", ctx, + index); + + wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env); + bh_assert(instance); + WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance); + + error res; + if (success != (res = is_model_initialized(wasi_nn_ctx))) + return res; + + if (!wasm_runtime_validate_native_addr(instance, output_tensor_size, + sizeof(uint32_t))) { + NN_ERR_PRINTF("output_tensor_size is invalid"); + return invalid_argument; + } + + res = lookup[wasi_nn_ctx->current_encoding].get_output( + ctx, index, output_tensor, output_tensor_size); + NN_DBG_PRINTF("wasi_nn_get_output finished with status %d [data_size=%d]", + res, *output_tensor_size); + return res; +} + +/* Non-exposed public functions */ + +WASINNContext * +wasi_nn_initialize() +{ + NN_DBG_PRINTF("Initializing wasi-nn"); + WASINNContext *wasi_nn_ctx = + (WASINNContext *)wasm_runtime_malloc(sizeof(WASINNContext)); + if (wasi_nn_ctx == NULL) { + NN_ERR_PRINTF("Error when allocating memory for WASI-NN context"); + return NULL; + } + wasi_nn_ctx->is_initialized = true; + wasi_nn_ctx->current_encoding = 3; + return wasi_nn_ctx; +} + +void +wasi_nn_destroy(WASINNContext *wasi_nn_ctx) +{ + if (wasi_nn_ctx == NULL) { + NN_ERR_PRINTF( + "Error when deallocating memory. WASI-NN context is NULL"); + return; + } + NN_DBG_PRINTF("Freeing wasi-nn"); + NN_DBG_PRINTF("-> is_initialized: %d", wasi_nn_ctx->is_initialized); + NN_DBG_PRINTF("-> current_encoding: %d", wasi_nn_ctx->current_encoding); + tensorflowlite_destroy(); + wasm_runtime_free(wasi_nn_ctx); +} + +/* Register WASI-NN in WAMR */ + +/* clang-format off */ +#define REG_NATIVE_FUNC(func_name, signature) \ + { #func_name, wasi_nn_##func_name, signature, NULL } +/* clang-format on */ + +static NativeSymbol native_symbols_wasi_nn[] = { + REG_NATIVE_FUNC(load, "(*ii*)i"), + REG_NATIVE_FUNC(init_execution_context, "(i*)i"), + REG_NATIVE_FUNC(set_input, "(ii*)i"), + REG_NATIVE_FUNC(compute, "(i)i"), + REG_NATIVE_FUNC(get_output, "(ii**)i"), +}; + +uint32_t +get_wasi_nn_export_apis(NativeSymbol **p_libc_wasi_apis) +{ + *p_libc_wasi_apis = native_symbols_wasi_nn; + return sizeof(native_symbols_wasi_nn) / sizeof(NativeSymbol); +} diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h b/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h new file mode 100644 index 00000000..9571081b --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef WASI_NN_PRIVATE_H +#define WASI_NN_PRIVATE_H + +#include "wasi_nn_types.h" + +typedef struct { + bool is_initialized; + graph_encoding current_encoding; +} WASINNContext; + +/** + * @brief Initialize wasi-nn + * + */ +WASINNContext * +wasi_nn_initialize(); +/** + * @brief Destroy wasi-nn on app exists + * + */ + +void +wasi_nn_destroy(WASINNContext *wasi_nn_ctx); + +#endif diff --git a/core/iwasm/libraries/wasi-nn/wasi_nn_tensorflow.cpp b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp similarity index 64% rename from core/iwasm/libraries/wasi-nn/wasi_nn_tensorflow.cpp rename to core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp index 597b04dc..d40e2399 100644 --- a/core/iwasm/libraries/wasi-nn/wasi_nn_tensorflow.cpp +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp @@ -3,8 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wasi_nn_tensorflow.hpp" -#include "wasi_nn_common.h" +#include "wasi_nn.h" +#include "wasi_nn_tensorflowlite.hpp" +#include "logger.h" + #include "bh_common.h" #include "bh_platform.h" #include "platform_common.h" @@ -14,6 +16,7 @@ #include #include #include +#include /* Global variables */ @@ -25,30 +28,30 @@ static char *model_pointer = NULL; /* WASI-NN (tensorflow) implementation */ error -tensorflow_load(graph_builder_array builder, graph_encoding encoding, - execution_target target, graph *graph) +tensorflowlite_load(graph_builder_array *builder, graph_encoding encoding, + execution_target target, graph *g) { if (model_pointer != NULL) { wasm_runtime_free(model_pointer); model_pointer = NULL; } - if (builder.size != 1) { + if (builder->size != 1) { NN_ERR_PRINTF("Unexpected builder format."); return invalid_argument; } - if (encoding != tensorflow) { - NN_ERR_PRINTF("Encoding is not tensorflow."); + if (encoding != tensorflowlite) { + NN_ERR_PRINTF("Encoding is not tensorflowlite."); return invalid_argument; } - if (target != cpu) { - NN_ERR_PRINTF("Only CPU target is supported."); + if (target != cpu && target != gpu) { + NN_ERR_PRINTF("Only CPU and GPU target is supported."); return invalid_argument; } - uint32_t size = builder.buf[0].size; + uint32_t size = builder->buf[0].size; model_pointer = (char *)wasm_runtime_malloc(size); if (model_pointer == NULL) { @@ -56,7 +59,7 @@ tensorflow_load(graph_builder_array builder, graph_encoding encoding, return missing_memory; } - bh_memcpy_s(model_pointer, size, builder.buf[0].buf, size); + bh_memcpy_s(model_pointer, size, builder->buf[0].buf, size); model = tflite::FlatBufferModel::BuildFromBuffer(model_pointer, size, NULL); if (model == NULL) { @@ -77,11 +80,34 @@ tensorflow_load(graph_builder_array builder, graph_encoding encoding, return missing_memory; } + bool use_default = false; + switch (target) { + case gpu: + { + // https://www.tensorflow.org/lite/performance/gpu + auto options = TfLiteGpuDelegateOptionsV2Default(); + options.inference_preference = + TFLITE_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED; + options.inference_priority1 = + TFLITE_GPU_INFERENCE_PRIORITY_MIN_LATENCY; + auto *delegate = TfLiteGpuDelegateV2Create(&options); + if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) { + NN_ERR_PRINTF("Error when enabling GPU delegate."); + use_default = true; + } + break; + } + default: + use_default = true; + } + if (use_default) + NN_WARN_PRINTF("Default encoding is CPU."); + return success; } error -tensorflow_init_execution_context(graph graph) +tensorflowlite_init_execution_context(graph g, graph_execution_context *ctx) { if (interpreter == NULL) { NN_ERR_PRINTF("Non-initialized interpreter."); @@ -92,8 +118,8 @@ tensorflow_init_execution_context(graph graph) } error -tensorflow_set_input(graph_execution_context ctx, uint32_t index, - tensor *input_tensor) +tensorflowlite_set_input(graph_execution_context ctx, uint32_t index, + tensor *input_tensor) { if (interpreter == NULL) { NN_ERR_PRINTF("Non-initialized interpreter."); @@ -113,11 +139,11 @@ tensorflow_set_input(graph_execution_context ctx, uint32_t index, } uint32_t model_tensor_size = 1; - for (int i = 0; i < (int)tensor->dims->size; ++i) + for (int i = 0; i < tensor->dims->size; ++i) model_tensor_size *= (uint32_t)tensor->dims->data[i]; uint32_t input_tensor_size = 1; - for (int i = 0; i < input_tensor->dimensions->size; i++) + for (uint32_t i = 0; i < input_tensor->dimensions->size; i++) input_tensor_size *= (uint32_t)input_tensor->dimensions->buf[i]; if (model_tensor_size != input_tensor_size) { @@ -136,7 +162,7 @@ tensorflow_set_input(graph_execution_context ctx, uint32_t index, } error -tensorflow_compute(graph_execution_context ctx) +tensorflowlite_compute(graph_execution_context ctx) { if (interpreter == NULL) { NN_ERR_PRINTF("Non-initialized interpreter."); @@ -147,8 +173,9 @@ tensorflow_compute(graph_execution_context ctx) } error -tensorflow_get_output(graph_execution_context context, uint32_t index, - tensor_data output_tensor, uint32_t *output_tensor_size) +tensorflowlite_get_output(graph_execution_context ctx, uint32_t index, + tensor_data output_tensor, + uint32_t *output_tensor_size) { if (interpreter == NULL) { NN_ERR_PRINTF("Non-initialized interpreter."); @@ -178,7 +205,7 @@ tensorflow_get_output(graph_execution_context context, uint32_t index, } float *tensor_f = interpreter->typed_output_tensor(index); - for (int i = 0; i < model_tensor_size; ++i) + for (uint32_t i = 0; i < model_tensor_size; ++i) NN_DBG_PRINTF("output: %f", tensor_f[i]); *output_tensor_size = model_tensor_size; @@ -186,3 +213,22 @@ tensorflow_get_output(graph_execution_context context, uint32_t index, model_tensor_size * sizeof(float)); return success; } + +void +tensorflowlite_destroy() +{ + /* + TensorFlow Lite memory is man + + Related issues: + * https://github.com/tensorflow/tensorflow/issues/15880 + */ + NN_DBG_PRINTF("Freeing memory."); + model.reset(nullptr); + model = NULL; + interpreter.reset(nullptr); + interpreter = NULL; + wasm_runtime_free(model_pointer); + model_pointer = NULL; + NN_DBG_PRINTF("Memory free'd."); +} diff --git a/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp new file mode 100644 index 00000000..32b29662 --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef WASI_NN_TENSORFLOWLITE_HPP +#define WASI_NN_TENSORFLOWLITE_HPP + +#include "wasi_nn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +error +tensorflowlite_load(graph_builder_array *builder, graph_encoding encoding, + execution_target target, graph *g); + +error +tensorflowlite_init_execution_context(graph g, graph_execution_context *ctx); + +error +tensorflowlite_set_input(graph_execution_context ctx, uint32_t index, + tensor *input_tensor); + +error +tensorflowlite_compute(graph_execution_context ctx); + +error +tensorflowlite_get_output(graph_execution_context ctx, uint32_t index, + tensor_data output_tensor, + uint32_t *output_tensor_size); + +void +tensorflowlite_destroy(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt b/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt index 7951dec4..eff716bd 100644 --- a/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt +++ b/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt @@ -7,10 +7,10 @@ project (iwasm) set (CMAKE_VERBOSE_MAKEFILE OFF) # Reset default linker flags -set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") -set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") set (CMAKE_C_STANDARD 99) set (CMAKE_CXX_STANDARD 14) +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") if (NOT DEFINED WAMR_BUILD_PLATFORM) set (WAMR_BUILD_PLATFORM "linux") diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile b/core/iwasm/libraries/wasi-nn/test/Dockerfile deleted file mode 100644 index a69b101b..00000000 --- a/core/iwasm/libraries/wasi-nn/test/Dockerfile +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -FROM ubuntu:22.04 - -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install -y \ - cmake build-essential git wget python3.10 python3-pip - -RUN wget -q https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-14/wasi-sdk-14.0-linux.tar.gz && \ - tar xf wasi-sdk-*-linux.tar.gz -C /opt && rm -f wasi-sdk-*-linux.tar.gz && \ - mv /opt/wasi-sdk-14.0 /opt/wasi-sdk - -WORKDIR /home/wamr - -COPY core core -COPY build-scripts build-scripts -COPY product-mini product-mini - -RUN pip3 install -r core/iwasm/libraries/wasi-nn/test/requirements.txt - -WORKDIR /home/wamr/core/iwasm/libraries/wasi-nn/test/build - -RUN cmake -DWAMR_BUILD_WASI_NN=1 .. -RUN make -j $(grep -c ^processor /proc/cpuinfo) - -WORKDIR /home/wamr/core/iwasm/libraries/wasi-nn/test - -RUN ./build.sh - -ENTRYPOINT [ "./build/iwasm", "--dir=.", "test_tensorflow.wasm" ] diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.base b/core/iwasm/libraries/wasi-nn/test/Dockerfile.base new file mode 100644 index 00000000..769c5389 --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.base @@ -0,0 +1,22 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +FROM ubuntu:20.04 AS base + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y \ + cmake build-essential git + +WORKDIR /home/wamr + +COPY . . + +WORKDIR /home/wamr/core/iwasm/libraries/wasi-nn/test/build + +RUN cmake \ + -DWAMR_BUILD_WASI_NN=1 \ + -DTFLITE_ENABLE_GPU=ON \ + .. + +RUN make -j $(grep -c ^processor /proc/cpuinfo) diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.compile b/core/iwasm/libraries/wasi-nn/test/Dockerfile.compile new file mode 100644 index 00000000..51a59707 --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.compile @@ -0,0 +1,23 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +FROM ubuntu:20.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y \ + cmake build-essential git wget python3.10 python3-pip + +ARG WASI_SDK_VER=19 +RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt \ + && tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \ + && ln -fs /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \ + && rm /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz + +WORKDIR /wasi-nn/test + +COPY core/iwasm/libraries/wasi-nn/test/requirements.txt . + +RUN pip3 install -r requirements.txt && rm requirements.txt + +ENTRYPOINT [ "bash", "./build.sh" ] diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu b/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu new file mode 100644 index 00000000..cec918cb --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu @@ -0,0 +1,8 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +FROM ubuntu:20.04 + +COPY --from=wasi-nn-base /home/wamr/core/iwasm/libraries/wasi-nn/test/build/iwasm /run/iwasm + +ENTRYPOINT [ "/run/iwasm" ] diff --git a/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu b/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu new file mode 100644 index 00000000..3d876efb --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu @@ -0,0 +1,20 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +FROM nvidia/cuda:11.3.0-runtime-ubuntu20.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ocl-icd-libopencl1 \ + ocl-icd-opencl-dev \ + clinfo && \ + rm -rf /var/lib/apt/lists/* + +RUN mkdir -p /etc/OpenCL/vendors && \ + echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd + +ENV NVIDIA_VISIBLE_DEVICES=all +ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility + +COPY --from=wasi-nn-base /home/wamr/core/iwasm/libraries/wasi-nn/test/build/iwasm /run/iwasm + +ENTRYPOINT [ "/run/iwasm" ] diff --git a/core/iwasm/libraries/wasi-nn/test/build.sh b/core/iwasm/libraries/wasi-nn/test/build.sh index 4dc8d015..dbf2f2d6 100755 --- a/core/iwasm/libraries/wasi-nn/test/build.sh +++ b/core/iwasm/libraries/wasi-nn/test/build.sh @@ -7,7 +7,7 @@ -Wl,--allow-undefined \ -Wl,--strip-all,--no-entry \ --sysroot=/opt/wasi-sdk/share/wasi-sysroot \ - -I/home/wamr/core/iwasm/libraries/wasi-nn \ + -I.. \ -o test_tensorflow.wasm test_tensorflow.c # TFLite models to use in the tests diff --git a/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c b/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c old mode 100755 new mode 100644 index 0e5e6a98..46883d23 --- a/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c +++ b/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c @@ -28,7 +28,7 @@ typedef struct { // WASI-NN wrappers error -wasm_load(char *model_name, graph *graph) +wasm_load(char *model_name, graph *g, execution_target target) { FILE *pFile = fopen(model_name, "r"); if (pFile == NULL) @@ -64,7 +64,7 @@ wasm_load(char *model_name, graph *graph) arr.buf[0].size = result; arr.buf[0].buf = buffer; - error res = load(&arr, tensorflow, cpu, graph); + error res = load(&arr, tensorflowlite, target, g); fclose(pFile); free(buffer); @@ -73,13 +73,13 @@ wasm_load(char *model_name, graph *graph) } error -wasm_init_execution_context(graph graph, graph_execution_context *ctx) +wasm_init_execution_context(graph g, graph_execution_context *ctx) { - return init_execution_context(graph, ctx); + return init_execution_context(g, ctx); } error -wasm_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim) +wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim) { tensor_dimensions dims; dims.size = INPUT_TENSOR_DIMS; @@ -115,11 +115,12 @@ wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor, // Inference float * -run_inference(float *input, uint32_t *input_size, uint32_t *output_size, - char *model_name, uint32_t num_output_tensors) +run_inference(execution_target target, float *input, uint32_t *input_size, + uint32_t *output_size, char *model_name, + uint32_t num_output_tensors) { graph graph; - if (wasm_load(model_name, &graph) != success) { + if (wasm_load(model_name, &graph, target) != success) { fprintf(stderr, "Error when loading model."); exit(1); } @@ -130,7 +131,7 @@ run_inference(float *input, uint32_t *input_size, uint32_t *output_size, exit(1); } - if (wasm_input(ctx, input, input_size) != success) { + if (wasm_set_input(ctx, input, input_size) != success) { fprintf(stderr, "Error when setting input tensor."); exit(1); } @@ -151,7 +152,7 @@ run_inference(float *input, uint32_t *input_size, uint32_t *output_size, *output_size = MAX_OUTPUT_TENSOR_SIZE - *output_size; if (wasm_get_output(ctx, i, &out_tensor[offset], output_size) != success) { - fprintf(stderr, "Error when getting input ."); + fprintf(stderr, "Error when getting output ."); exit(1); } @@ -185,14 +186,14 @@ create_input(int *dims) // TESTS void -test_sum() +test_sum(execution_target target) { int dims[] = { 1, 5, 5, 1 }; input_info input = create_input(dims); uint32_t output_size = 0; - float *output = run_inference(input.input_tensor, input.dim, &output_size, - "models/sum.tflite", 1); + float *output = run_inference(target, input.input_tensor, input.dim, + &output_size, "/assets/models/sum.tflite", 1); assert(output_size == 1); assert(fabs(output[0] - 300.0) < EPSILON); @@ -203,14 +204,14 @@ test_sum() } void -test_max() +test_max(execution_target target) { int dims[] = { 1, 5, 5, 1 }; input_info input = create_input(dims); uint32_t output_size = 0; - float *output = run_inference(input.input_tensor, input.dim, &output_size, - "models/max.tflite", 1); + float *output = run_inference(target, input.input_tensor, input.dim, + &output_size, "/assets/models/max.tflite", 1); assert(output_size == 1); assert(fabs(output[0] - 24.0) < EPSILON); @@ -222,14 +223,15 @@ test_max() } void -test_average() +test_average(execution_target target) { int dims[] = { 1, 5, 5, 1 }; input_info input = create_input(dims); uint32_t output_size = 0; - float *output = run_inference(input.input_tensor, input.dim, &output_size, - "models/average.tflite", 1); + float *output = + run_inference(target, input.input_tensor, input.dim, &output_size, + "/assets/models/average.tflite", 1); assert(output_size == 1); assert(fabs(output[0] - 12.0) < EPSILON); @@ -241,14 +243,15 @@ test_average() } void -test_mult_dimensions() +test_mult_dimensions(execution_target target) { int dims[] = { 1, 3, 3, 1 }; input_info input = create_input(dims); uint32_t output_size = 0; - float *output = run_inference(input.input_tensor, input.dim, &output_size, - "models/mult_dim.tflite", 1); + float *output = + run_inference(target, input.input_tensor, input.dim, &output_size, + "/assets/models/mult_dim.tflite", 1); assert(output_size == 9); for (int i = 0; i < 9; i++) @@ -260,14 +263,15 @@ test_mult_dimensions() } void -test_mult_outputs() +test_mult_outputs(execution_target target) { int dims[] = { 1, 4, 4, 1 }; input_info input = create_input(dims); uint32_t output_size = 0; - float *output = run_inference(input.input_tensor, input.dim, &output_size, - "models/mult_out.tflite", 2); + float *output = + run_inference(target, input.input_tensor, input.dim, &output_size, + "/assets/models/mult_out.tflite", 2); assert(output_size == 8); // first tensor check @@ -285,16 +289,30 @@ test_mult_outputs() int main() { + char *env = getenv("TARGET"); + if (env == NULL) { + printf("Usage:\n--env=\"TARGET=[cpu|gpu]\"\n"); + return 1; + } + execution_target target; + if (strcmp(env, "cpu") == 0) + target = cpu; + else if (strcmp(env, "gpu") == 0) + target = gpu; + else { + printf("Wrong target!"); + return 1; + } printf("################### Testing sum...\n"); - test_sum(); + test_sum(target); printf("################### Testing max...\n"); - test_max(); + test_max(target); printf("################### Testing average...\n"); - test_average(); + test_average(target); printf("################### Testing multiple dimensions...\n"); - test_mult_dimensions(); + test_mult_dimensions(target); printf("################### Testing multiple outputs...\n"); - test_mult_outputs(); + test_mult_outputs(target); printf("Tests: passed!\n"); return 0; diff --git a/core/iwasm/libraries/wasi-nn/wasi_nn.cmake b/core/iwasm/libraries/wasi-nn/wasi_nn.cmake index 6d34b5ef..d6fca891 100644 --- a/core/iwasm/libraries/wasi-nn/wasi_nn.cmake +++ b/core/iwasm/libraries/wasi-nn/wasi_nn.cmake @@ -5,6 +5,15 @@ set (WASI_NN_DIR ${CMAKE_CURRENT_LIST_DIR}) add_definitions (-DWASM_ENABLE_WASI_NN=1) -set (LIBC_WASI_NN_SOURCE ${WASI_NN_DIR}/wasi_nn_native.c ${WASI_NN_DIR}/wasi_nn_tensorflow.cpp) +include_directories (${WASI_NN_DIR}) +include_directories (${WASI_NN_DIR}/src) +include_directories (${WASI_NN_DIR}/src/utils) + +set ( + LIBC_WASI_NN_SOURCE + ${WASI_NN_DIR}/src/wasi_nn.c + ${WASI_NN_DIR}/src/wasi_nn_tensorflowlite.cpp + ${WASI_NN_DIR}/src/utils/wasi_nn_app_native.c +) set (TENSORFLOW_LIB tensorflow-lite) diff --git a/core/iwasm/libraries/wasi-nn/wasi_nn.h b/core/iwasm/libraries/wasi-nn/wasi_nn.h index 115ac928..2bf0a192 100644 --- a/core/iwasm/libraries/wasi-nn/wasi_nn.h +++ b/core/iwasm/libraries/wasi-nn/wasi_nn.h @@ -3,63 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#ifndef WASI_NN_WASM_H -#define WASI_NN_WASM_H - -#include "wasi_nn_common.h" - /** * Following definition from: - * [Aug 10th, 2022] - * https://github.com/WebAssembly/wasi-nn/blob/e5e1a6c31f424c7cd63026cd270e9746775675a0/wasi-nn.wit.md + * [Oct 25th, 2022] + * https://github.com/WebAssembly/wasi-nn/blob/0f77c48ec195748990ff67928a4b3eef5f16c2de/wasi-nn.wit.md */ -/* The graph initialization data. */ +#ifndef WASI_NN_H +#define WASI_NN_H -// This consists of an array of buffers because implementing backends may encode -// their graph IR in parts (e.g., OpenVINO stores its IR and weights -// separately). -typedef struct { - uint8_t *buf; - uint32_t size; -} graph_builder; - -typedef struct { - graph_builder *buf; - uint32_t size; -} graph_builder_array; - -/* The dimensions of a tensor. */ - -// The array length matches the tensor rank and each element in the array -// describes the size of each dimension. -typedef struct { - uint32_t *buf; - uint32_t size; -} tensor_dimensions; - -/* The tensor data. */ - -// Initially conceived as a sparse representation, each empty cell would be -// filled with zeros and the array length must match the product of all of the -// dimensions and the number of bytes in the type (e.g., a 2x2 tensor with -// 4-byte f32 elements would have a data array of length 16). Naturally, this -// representation requires some knowledge of how to lay out data in -// memory--e.g., using row-major ordering--and could perhaps be improved. -typedef uint8_t *tensor_data; - -/* A tensor. */ - -typedef struct { - // Describe the size of the tensor (e.g., 2x2x2x2 -> [2, 2, 2, 2]). To - // represent a tensor containing a single value, use `[1]` for the tensor - // dimensions. - tensor_dimensions *dimensions; - // Describe the type of element in the tensor (e.g., f32). - tensor_type type; - // Contains the tensor data. - tensor_data data; -} tensor; +#include +#include "wasi_nn_types.h" /** * @brief Load an opaque sequence of bytes to use for inference. @@ -67,25 +21,31 @@ typedef struct { * @param builder Model builder. * @param encoding Model encoding. * @param target Execution target. - * @param graph Graph. + * @param g Graph. * @return error Execution status. */ error load(graph_builder_array *builder, graph_encoding encoding, - execution_target target, graph *graph) - __attribute__((export_module("wasi_nn"))) + execution_target target, graph *g) __attribute__((import_module("wasi_nn"))); +/** + * INFERENCE + * + */ + +// Bind a `graph` to the input and output tensors for an inference. +typedef uint32_t graph_execution_context; + /** * @brief Create an execution instance of a loaded graph. * - * @param graph Graph. + * @param g Graph. * @param ctx Execution context. * @return error Execution status. */ error -init_execution_context(graph graph, graph_execution_context *ctx) - __attribute__((export_module("wasi_nn"))) +init_execution_context(graph g, graph_execution_context *ctx) __attribute__((import_module("wasi_nn"))); /** @@ -98,7 +58,6 @@ init_execution_context(graph graph, graph_execution_context *ctx) */ error set_input(graph_execution_context ctx, uint32_t index, tensor *tensor) - __attribute__((export_module("wasi_nn"))) __attribute__((import_module("wasi_nn"))); /** @@ -108,8 +67,7 @@ set_input(graph_execution_context ctx, uint32_t index, tensor *tensor) * @return error Execution status. */ error -compute(graph_execution_context ctx) __attribute__((export_module("wasi_nn"))) -__attribute__((import_module("wasi_nn"))); +compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn"))); /** * @brief Extract the outputs after inference. @@ -126,7 +84,6 @@ __attribute__((import_module("wasi_nn"))); error get_output(graph_execution_context ctx, uint32_t index, tensor_data output_tensor, uint32_t *output_tensor_size) - __attribute__((export_module("wasi_nn"))) __attribute__((import_module("wasi_nn"))); #endif diff --git a/core/iwasm/libraries/wasi-nn/wasi_nn_common.h b/core/iwasm/libraries/wasi-nn/wasi_nn_common.h deleted file mode 100644 index 103185bd..00000000 --- a/core/iwasm/libraries/wasi-nn/wasi_nn_common.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef WASI_NN_COMMON_H -#define WASI_NN_COMMON_H - -#include - -// The type of the elements in a tensor. -typedef enum { fp16 = 0, fp32, up8, ip32 } tensor_type; - -// Describes the encoding of the graph. This allows the API to be implemented by -// various backends that encode (i.e., serialize) their graph IR with different -// formats. -typedef enum { openvino = 0, onnx, tensorflow, pytorch } graph_encoding; - -// Define where the graph should be executed. -typedef enum { cpu = 0, gpu, tpu } execution_target; - -// Error codes returned by functions in this API. -typedef enum { - // No error occurred. - success = 0, - // Caller module passed an invalid argument. - invalid_argument, - // Invalid encoding. - invalid_encoding, - // Caller module is missing a memory export. - missing_memory, - // Device or resource busy. - busy, - // Runtime Error. - runtime_error, -} error; - -// An execution graph for performing inference (i.e., a model). -typedef uint32_t graph; - -// Bind a `graph` to the input and output tensors for an inference. -typedef uint32_t graph_execution_context; - -#endif diff --git a/core/iwasm/libraries/wasi-nn/wasi_nn_native.c b/core/iwasm/libraries/wasi-nn/wasi_nn_native.c deleted file mode 100644 index 333dd475..00000000 --- a/core/iwasm/libraries/wasi-nn/wasi_nn_native.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include -#include -#include -#include -#include - -#include "wasi_nn_common.h" -#include "wasm_export.h" -#include "bh_platform.h" - -#include "wasi_nn.h" -#include "wasi_nn_tensorflow.hpp" -#include "logger.h" - -/* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */ - -typedef struct { - uint32_t buf_offset; - uint32_t size; -} graph_builder_wasm; - -typedef struct { - uint32_t buf_offset; - uint32_t size; -} graph_builder_array_wasm; - -typedef struct { - uint32_t dimensions_offset; - tensor_type type; - uint32_t data_offset; -} tensor_wasm; - -typedef struct { - uint32_t buf_offset; - uint32_t size; -} tensor_dimensions_wasm; - -/* Global variables */ - -static uint8_t _is_initialized; -static graph_encoding _encoding; - -/* Utils */ - -static error -check_initialized() -{ - if (!_is_initialized) { - NN_ERR_PRINTF("Model not initialized."); - return invalid_argument; - } - if (_encoding != tensorflow) { - NN_ERR_PRINTF("Model encoding is not tensorflow."); - return invalid_argument; - } - return success; -} - -/* WASI-NN implementation */ - -error -wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder, - graph_encoding encoding, execution_target target, graph *graph) -{ - NN_DBG_PRINTF("Running wasi_nn_load [encoding=%d, target=%d]...", encoding, - target); - - wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env); - bh_assert(instance); - - if (!wasm_runtime_validate_native_addr(instance, builder, - sizeof(graph_builder_array_wasm))) - return invalid_argument; - - if (!wasm_runtime_validate_app_addr(instance, builder->buf_offset, - builder->size * sizeof(uint32_t))) - return invalid_argument; - - NN_DBG_PRINTF("Graph builder array contains %d elements", builder->size); - - graph_builder_wasm *gb_wasm = - (graph_builder_wasm *)wasm_runtime_addr_app_to_native( - instance, builder->buf_offset); - - graph_builder *gb_native = (graph_builder *)wasm_runtime_malloc( - builder->size * sizeof(graph_builder)); - if (gb_native == NULL) - return missing_memory; - - for (int i = 0; i < builder->size; ++i) { - if (!wasm_runtime_validate_app_addr(instance, gb_wasm[i].buf_offset, - gb_wasm[i].size - * sizeof(uint8_t))) { - wasm_runtime_free(gb_native); - return invalid_argument; - } - - gb_native[i].buf = (uint8_t *)wasm_runtime_addr_app_to_native( - instance, gb_wasm[i].buf_offset); - gb_native[i].size = gb_wasm[i].size; - - NN_DBG_PRINTF("Graph builder %d contains %d elements", i, - gb_wasm[i].size); - } - - graph_builder_array gba_native = { .buf = gb_native, - .size = builder->size }; - - if (!wasm_runtime_validate_native_addr(instance, graph, sizeof(graph))) { - wasm_runtime_free(gb_native); - return invalid_argument; - } - - switch (encoding) { - case tensorflow: - break; - default: - NN_ERR_PRINTF("Only tensorflow is supported."); - wasm_runtime_free(gb_native); - return invalid_argument; - } - - _encoding = encoding; - _is_initialized = 1; - - error res = tensorflow_load(gba_native, _encoding, target, graph); - NN_DBG_PRINTF("wasi_nn_load finished with status %d [graph=%d]", res, - *graph); - - wasm_runtime_free(gb_native); - return res; -} - -error -wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph graph, - graph_execution_context *ctx) -{ - NN_DBG_PRINTF("Running wasi_nn_init_execution_context [graph=%d]...", - graph); - error res; - if (success != (res = check_initialized())) - return res; - res = tensorflow_init_execution_context(graph); - *ctx = graph; - NN_DBG_PRINTF( - "wasi_nn_init_execution_context finished with status %d [ctx=%d]", res, - *ctx); - return res; -} - -error -wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx, - uint32_t index, tensor_wasm *input_tensor) -{ - NN_DBG_PRINTF("Running wasi_nn_set_input [ctx=%d, index=%d]...", ctx, - index); - - error res; - if (success != (res = check_initialized())) - return res; - - wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env); - bh_assert(instance); - - if (!wasm_runtime_validate_native_addr(instance, input_tensor, - sizeof(tensor_wasm))) - return invalid_argument; - - if (!wasm_runtime_validate_app_addr( - instance, input_tensor->dimensions_offset, sizeof(uint32_t))) - return invalid_argument; - - tensor_dimensions_wasm *dimensions_w = - (tensor_dimensions_wasm *)wasm_runtime_addr_app_to_native( - instance, input_tensor->dimensions_offset); - - if (!wasm_runtime_validate_app_addr(instance, dimensions_w->buf_offset, - dimensions_w->size * sizeof(uint32_t))) - return invalid_argument; - - tensor_dimensions dimensions = { - .buf = (uint32_t *)wasm_runtime_addr_app_to_native( - instance, dimensions_w->buf_offset), - .size = dimensions_w->size - }; - - NN_DBG_PRINTF("Number of dimensions: %d", dimensions.size); - int total_elements = 1; - for (int i = 0; i < dimensions.size; ++i) { - NN_DBG_PRINTF("Dimension %d: %d", i, dimensions.buf[i]); - total_elements *= dimensions.buf[i]; - } - NN_DBG_PRINTF("Tensor type: %d", input_tensor->type); - - if (!wasm_runtime_validate_app_addr(instance, input_tensor->data_offset, - total_elements)) - return invalid_argument; - - tensor tensor = { .type = input_tensor->type, - .dimensions = &dimensions, - .data = (uint8_t *)wasm_runtime_addr_app_to_native( - instance, input_tensor->data_offset) }; - - res = tensorflow_set_input(ctx, index, &tensor); - NN_DBG_PRINTF("wasi_nn_set_input finished with status %d", res); - return res; -} - -error -wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx) -{ - NN_DBG_PRINTF("Running wasi_nn_compute [ctx=%d]...", ctx); - error res; - if (success != (res = check_initialized())) - return res; - - res = tensorflow_compute(ctx); - NN_DBG_PRINTF("wasi_nn_compute finished with status %d", res); - return res; -} - -error -wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx, - uint32_t index, tensor_data output_tensor, - uint32_t *output_tensor_size) -{ - NN_DBG_PRINTF("Running wasi_nn_get_output [ctx=%d, index=%d]...", ctx, - index); - error res; - if (success != (res = check_initialized())) - return res; - - res = tensorflow_get_output(ctx, index, output_tensor, output_tensor_size); - NN_DBG_PRINTF("wasi_nn_get_output finished with status %d [data_size=%d]", - res, *output_tensor_size); - return res; -} - -/* Register WASI-NN in WAMR */ - -/* clang-format off */ -#define REG_NATIVE_FUNC(func_name, signature) \ - { #func_name, wasi_nn_##func_name, signature, NULL } -/* clang-format on */ - -static NativeSymbol native_symbols_wasi_nn[] = { - REG_NATIVE_FUNC(load, "(*ii*)i"), - REG_NATIVE_FUNC(init_execution_context, "(i*)i"), - REG_NATIVE_FUNC(set_input, "(ii*)i"), - REG_NATIVE_FUNC(compute, "(i)i"), - REG_NATIVE_FUNC(get_output, "(ii**)i"), -}; - -uint32_t -get_wasi_nn_export_apis(NativeSymbol **p_libc_wasi_apis) -{ - *p_libc_wasi_apis = native_symbols_wasi_nn; - return sizeof(native_symbols_wasi_nn) / sizeof(NativeSymbol); -} diff --git a/core/iwasm/libraries/wasi-nn/wasi_nn_tensorflow.hpp b/core/iwasm/libraries/wasi-nn/wasi_nn_tensorflow.hpp deleted file mode 100644 index 46264c0b..00000000 --- a/core/iwasm/libraries/wasi-nn/wasi_nn_tensorflow.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef WASI_NN_TENSORFLOW_HPP -#define WASI_NN_TENSORFLOW_HPP - -#include - -#include "wasi_nn.h" -#include "logger.h" - -#ifdef __cplusplus -extern "C" { -#endif - -error -tensorflow_load(graph_builder_array builder, graph_encoding encoding, - execution_target target, graph *graph); - -error -tensorflow_init_execution_context(graph graph); - -error -tensorflow_set_input(graph_execution_context ctx, uint32_t index, - tensor *input_tensor); - -error -tensorflow_compute(graph_execution_context ctx); - -error -tensorflow_get_output(graph_execution_context context, uint32_t index, - tensor_data output_tensor, uint32_t *output_tensor_size); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/core/iwasm/libraries/wasi-nn/wasi_nn_types.h b/core/iwasm/libraries/wasi-nn/wasi_nn_types.h new file mode 100644 index 00000000..a2cebe49 --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/wasi_nn_types.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef WASI_NN_TYPES_H +#define WASI_NN_TYPES_H + +/** + * ERRORS + * + */ + +// Error codes returned by functions in this API. +typedef enum { + // No error occurred. + success = 0, + // Caller module passed an invalid argument. + invalid_argument, + // Invalid encoding. + invalid_encoding, + // Caller module is missing a memory export. + missing_memory, + // Device or resource busy. + busy, + // Runtime Error. + runtime_error, +} error; + +/** + * TENSOR + * + */ + +// The dimensions of a tensor. +// +// The array length matches the tensor rank and each element in the array +// describes the size of each dimension. +typedef struct { + uint32_t *buf; + uint32_t size; +} tensor_dimensions; + +// The type of the elements in a tensor. +typedef enum { fp16 = 0, fp32, up8, ip32 } tensor_type; + +// The tensor data. +// +// Initially conceived as a sparse representation, each empty cell would be +// filled with zeros and the array length must match the product of all of the +// dimensions and the number of bytes in the type (e.g., a 2x2 tensor with +// 4-byte f32 elements would have a data array of length 16). Naturally, this +// representation requires some knowledge of how to lay out data in +// memory--e.g., using row-major ordering--and could perhaps be improved. +typedef uint8_t *tensor_data; + +// A tensor. +typedef struct { + // Describe the size of the tensor (e.g., 2x2x2x2 -> [2, 2, 2, 2]). To + // represent a tensor containing a single value, use `[1]` for the tensor + // dimensions. + tensor_dimensions *dimensions; + // Describe the type of element in the tensor (e.g., f32). + tensor_type type; + // Contains the tensor data. + tensor_data data; +} tensor; + +/** + * GRAPH + * + */ + +// The graph initialization data. +// +// This consists of an array of buffers because implementing backends may encode +// their graph IR in parts (e.g., OpenVINO stores its IR and weights +// separately). +typedef struct { + uint8_t *buf; + uint32_t size; +} graph_builder; + +typedef struct { + graph_builder *buf; + uint32_t size; +} graph_builder_array; + +// An execution graph for performing inference (i.e., a model). +typedef uint32_t graph; + +// Describes the encoding of the graph. This allows the API to be implemented by +// various backends that encode (i.e., serialize) their graph IR with different +// formats. +typedef enum { + openvino = 0, + onnx, + tensorflow, + pytorch, + tensorflowlite +} graph_encoding; + +// Define where the graph should be executed. +typedef enum execution_target { cpu = 0, gpu, tpu } execution_target; + +#endif diff --git a/core/shared/platform/esp-idf/espidf_socket.c b/core/shared/platform/esp-idf/espidf_socket.c index 37e412b2..9f441b71 100644 --- a/core/shared/platform/esp-idf/espidf_socket.c +++ b/core/shared/platform/esp-idf/espidf_socket.c @@ -77,7 +77,7 @@ os_socket_bind(bh_socket_t socket, const char *host, int *port) } socklen = sizeof(addr); - if (getsockname(socket, (void *)&addr, &socklen) == -1) { + if (getsockname(socket, (struct sockaddr *)&addr, &socklen) == -1) { goto fail; } @@ -120,7 +120,7 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, unsigned int *addrlen) { struct sockaddr addr_tmp; - unsigned int len = sizeof(struct sockaddr); + socklen_t len = sizeof(struct sockaddr); *sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len); @@ -205,7 +205,7 @@ os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr) struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); - if (getpeername(socket, &addr, &addr_len) == -1) { + if (getpeername(socket, (struct sockaddr *)&addr, &addr_len) == -1) { return BHT_ERROR; } @@ -219,7 +219,7 @@ os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr) struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); - if (getsockname(socket, &addr, &addr_len) == -1) { + if (getsockname(socket, (struct sockaddr *)&addr, &addr_len) == -1) { return BHT_ERROR; } diff --git a/core/shared/platform/linux-sgx/sgx_ipfs.c b/core/shared/platform/linux-sgx/sgx_ipfs.c index 2b0a38ff..32268898 100644 --- a/core/shared/platform/linux-sgx/sgx_ipfs.c +++ b/core/shared/platform/linux-sgx/sgx_ipfs.c @@ -16,6 +16,11 @@ #define SGX_ERROR_FILE_LOWEST_ERROR_ID SGX_ERROR_FILE_BAD_STATUS #define SGX_ERROR_FILE_HIGHEST_ERROR_ID SGX_ERROR_FILE_CLOSE_FAILED +// Internal buffer filled with zeroes and used when extending the size of +// protected files. +#define ZEROES_PADDING_LENGTH 32 * 1024 +char zeroes_padding[ZEROES_PADDING_LENGTH] = { 0 }; + // The mapping between file descriptors and IPFS file pointers. static HashMap *ipfs_file_list; @@ -78,6 +83,27 @@ ipfs_file_destroy(void *sgx_file) sgx_fclose(sgx_file); } +// Writes a given number of zeroes in file at the current offset. +// The return value is zero if successful; otherwise non-zero. +static int +ipfs_write_zeroes(void *sgx_file, size_t len) +{ + int min_count; + + while (len > 0) { + min_count = len < ZEROES_PADDING_LENGTH ? len : ZEROES_PADDING_LENGTH; + + if (sgx_fwrite(zeroes_padding, 1, min_count, sgx_file) == 0) { + errno = convert_sgx_errno(sgx_ferror(sgx_file)); + return -1; + } + + len -= min_count; + } + + return 0; +} + int ipfs_init() { @@ -104,7 +130,7 @@ ipfs_posix_fallocate(int fd, off_t offset, size_t len) // The wrapper for fseek takes care of extending the file if sought beyond // the end - if (ipfs_lseek(fd, offset + len, SEEK_CUR) == -1) { + if (ipfs_lseek(fd, offset + len, SEEK_SET) == -1) { return errno; } @@ -354,7 +380,7 @@ ipfs_fflush(int fd) off_t ipfs_lseek(int fd, off_t offset, int nwhence) { - off_t new_offset; + off_t cursor_current_location; void *sgx_file = fd2file(fd); if (!sgx_file) { errno = EBADF; @@ -364,20 +390,20 @@ ipfs_lseek(int fd, off_t offset, int nwhence) // Optimization: if the offset is 0 and the whence is SEEK_CUR, // this is equivalent of a call to ftell. if (offset == 0 && nwhence == SEEK_CUR) { - int64_t ftell_result = (off_t)sgx_ftell(sgx_file); + cursor_current_location = (off_t)sgx_ftell(sgx_file); - if (ftell_result == -1) { + if (cursor_current_location == -1) { errno = convert_sgx_errno(sgx_ferror(sgx_file)); return -1; } - return ftell_result; + return cursor_current_location; } int fseek_result = sgx_fseek(sgx_file, offset, nwhence); if (fseek_result == 0) { - new_offset = (__wasi_filesize_t)sgx_ftell(sgx_file); + off_t new_offset = (off_t)sgx_ftell(sgx_file); if (new_offset == -1) { errno = convert_sgx_errno(sgx_ferror(sgx_file)); @@ -405,17 +431,39 @@ ipfs_lseek(int fd, off_t offset, int nwhence) // manually. // Assume the error is raised because the cursor is moved beyond the end - // of the file. Try to move the cursor at the end of the file. + // of the file. + + // If the whence is the current cursor location, retrieve it + if (nwhence == SEEK_CUR) { + cursor_current_location = (off_t)sgx_ftell(sgx_file); + } + + // Move the cursor at the end of the file if (sgx_fseek(sgx_file, 0, SEEK_END) == -1) { errno = convert_sgx_errno(sgx_ferror(sgx_file)); return -1; } + // Compute the number of zeroes to append. + int64_t number_of_zeroes; + switch (nwhence) { + case SEEK_SET: + number_of_zeroes = offset - sgx_ftell(sgx_file); + break; + case SEEK_END: + number_of_zeroes = offset; + break; + case SEEK_CUR: + number_of_zeroes = + cursor_current_location + offset - sgx_ftell(sgx_file); + break; + default: + errno = EINVAL; + return -1; + } + // Write the missing zeroes - char zero = 0; - int64_t number_of_zeroes = offset - sgx_ftell(sgx_file); - if (sgx_fwrite(&zero, 1, number_of_zeroes, sgx_file) == 0) { - errno = convert_sgx_errno(sgx_ferror(sgx_file)); + if (ipfs_write_zeroes(sgx_file, number_of_zeroes) != 0) { return -1; } @@ -468,9 +516,7 @@ ipfs_ftruncate(int fd, off_t len) // Increasing the size is equal to writing from the end of the file // with null bytes. - char null_byte = 0; - if (sgx_fwrite(&null_byte, 1, len - file_size, sgx_file) == 0) { - errno = convert_sgx_errno(sgx_ferror(sgx_file)); + if (ipfs_write_zeroes(sgx_file, len - file_size) != 0) { return -1; } diff --git a/doc/build_wasm_app.md b/doc/build_wasm_app.md index a10a1a4c..40f1b89d 100644 --- a/doc/build_wasm_app.md +++ b/doc/build_wasm_app.md @@ -3,12 +3,12 @@ Prepare WASM building environments ================================== -For C and C++, WASI-SDK version 12.0+ is the major tool supported by WAMR to build WASM applications. Also, we can use [Emscripten SDK (EMSDK)](https://github.com/emscripten-core/emsdk), but it is not recommended. And there are some other compilers such as the standard clang compiler, which might also work [here](./other_wasm_compilers.md). +For C and C++, WASI-SDK version 19.0+ is the major tool supported by WAMR to build WASM applications. Also, we can use [Emscripten SDK (EMSDK)](https://github.com/emscripten-core/emsdk), but it is not recommended. And there are some other compilers such as the standard clang compiler, which might also work [here](./other_wasm_compilers.md). To install WASI SDK, please download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. The official *wasi-sdk release* doesn't fully support *latest 128-bit SIMD spec* yet. WAMR provides a script in [build-wasi-sdk](../test-tools/build-wasi-sdk/) to generate -another wasi-sdk with *llvm-13* from source code and installs it at *../test-tools/wasi-sdk*. If you plan to build WASM applications with *latest 128-bit SIMD*, please use it instead of the official release. +another wasi-sdk with *llvm-15* from source code and installs it at *../test-tools/wasi-sdk*. If you plan to build WASM applications with *latest 128-bit SIMD*, please use it instead of the official release. And [sample workloads](../samples/workload) are using the self-compiled wasi-sdk. diff --git a/doc/port_wamr.md b/doc/port_wamr.md index 44ac50ec..7899ff31 100644 --- a/doc/port_wamr.md +++ b/doc/port_wamr.md @@ -10,9 +10,13 @@ This document describes how to port WAMR to a new platform "**new-os**" # Step 1: Implement platform API layer ------------------------- -Firstly create the folder **`core/shared/platform/new-os`** for platform API layer implementations. In the folder you just created, you must provide the following files: +Firstly create the folder for platform API layer implementations: +* for common platforms, create a folder in **`core/shared/platform/new-os`** in WAMR repository folder, so the implementation can be upstreamed +* for platforms that are internal and its implementation shouldn't be published, it's recommended to create a folder outside of the WAMR repository folder (e.g. have separate repository for platform API layer implementation) -- `platform_internal.h`: It can be used for any platform specific definitions such as macros, data types and internal APIs. +In the folder you just created, you must provide the following files: + +- `platform_internal.h`: It can be used for any platform-specific definitions such as macros, data types and internal APIs. - `shared_platform.cmake`: the cmake file will be included by the building script. It is recommended to add a definition for your platform: @@ -20,29 +24,29 @@ Firstly create the folder **`core/shared/platform/new-os`** for platform API lay add_definitions(-DBH_PLATFORM_YOUR_NAME) ``` -Then go to implement the APIs defined in following header files for the platform abstraction layer: +Then go to implement the APIs defined in the following header files for the platform abstraction layer: -- [`platform_api_vmcore.h`](../core/shared/platform/include/platform_api_vmcore.h): mandatory for building mini-product (vmcore only). Part of APIs are needed only for Ahead of Time compilation support. +- [`platform_api_vmcore.h`](../core/shared/platform/include/platform_api_vmcore.h): mandatory for building mini-product (vmcore only). Part of the APIs is needed only for Ahead of Time compilation support. - [`platform_api_extension.h`](../core/shared/platform/include/platform_api_extension.h): mandatory for app-mgr and app-framework. Given that the app-mgr and app-framework are not required for your target platform, you won't have to implement the API defined in the `platform_api_extension.h`. **common/posix:** -There is posix based implementation of the platform API located in the `platform/common/posix` folder. You can include it if your platform support posix API. refer to platform linux implementation. +There is posix based implementation of the platform API located in the `platform/common/posix` folder. You can include it if your platform supports posix API. refer to platform linux implementation. **common/math:** -Some platforms such as ZephyrOS don't provide math functions e.g. sqrt, fabs and isnan, then you should include source files under the folder `platform/common/math`. +Some platforms such as ZephyrOS don't provide math functions e.g. sqrt, fabs and isnan, then you should include source files under the folder `platform/common/math`. # Step 2: Create the mini product for the platform ------------------------- -You can build a mini WAMR product which is only the vmcore for you platform. Normally you need to implement the main function which loads a WASM file and run it with the WASM runtime. You don't have to do this step if there is no mini-product need for your platform porting. +You can build a mini WAMR product which is only the vmcore for your platform. Normally you need to implement the main function which loads a WASM file and run it with the WASM runtime. You don't have to do this step if there is no mini-product need for your platform porting. @@ -55,9 +59,14 @@ You should set cmake variable `WAMR_BUILD_PLATFORM` to your platform name while ``` mkdir build cd build -cmake .. -DWAMR_BUILD_PLATFORM=new-os +cmake .. -DWAMR_BUILD_PLATFORM=new-os ``` +For platform implementations that are outside of the WAMR repository (e.g. internal platforms), you also need to provide `SHARED_PLATFORM_CONFIG` path: + +``` +cmake .. -DWAMR_BUILD_PLATFORM=new-os -DSHARED_PLATFORM_CONFIG=/path/to/new-os/shared_platform.cmake +``` Refer to [build_wamr.md](./build_wamr.md) for the building configurations and parameters. diff --git a/language-bindings/python/MANIFEST.in b/language-bindings/python/MANIFEST.in new file mode 100644 index 00000000..9b0c0893 --- /dev/null +++ b/language-bindings/python/MANIFEST.in @@ -0,0 +1 @@ +include src/wamr/libs/* diff --git a/language-bindings/python/README.md b/language-bindings/python/README.md index 2698a059..9e504a9c 100644 --- a/language-bindings/python/README.md +++ b/language-bindings/python/README.md @@ -1,31 +1,34 @@ # wamr-python +The WAMR Python package contains a set of high-level bindings for WAMR API and WASM-C-API. + ## 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. +To Install from local source tree in _development mode_ run the following command, ```bash -$ python -m pip install -e /path/to/wamr-root/binding/python +python -m pip install -e . ``` +In this mode the package appears to be installed but still is editable from the source tree. + ## Usage -```python -import wamr.ffi as ffi +From the same package you can use two set of APIs. + +To use the WAMR API you can import the symbols as follows, + +```py +from wamr.wamrapi.wamr import Engine, Module, Instance, ExecEnv ``` -### Preparation +In the order hand, to use the WASM-C-API, -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. +```py +import wamr.wasmcapi.ffi as ffi +``` -The default compile options are good enough. +For more information: -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. +* [WAMR API](./wamr_api) +* [WASM-C-API](./wasm_c_api) diff --git a/language-bindings/python/setup.py b/language-bindings/python/setup.py index c7868187..bf0ba53e 100755 --- a/language-bindings/python/setup.py +++ b/language-bindings/python/setup.py @@ -8,7 +8,28 @@ # pylint: disable=missing-function-docstring # pylint: disable=missing-module-docstring -from setuptools import setup, find_packages +import pathlib +from setuptools import setup +from setuptools.command.develop import develop +from setuptools.command.install import install +from subprocess import check_call + + +def build_library(): + cur_path = pathlib.Path(__file__).parent + check_call(f"{cur_path}/utils/create_lib.sh".split()) + +class PreDevelopCommand(develop): + """Pre-installation for development mode.""" + def run(self): + build_library() + develop.run(self) + +class PreInstallCommand(install): + """Pre-installation for installation mode.""" + def run(self): + build_library() + install.run(self) with open("README.md") as f: @@ -24,7 +45,11 @@ setup( long_description=readme, author="The WAMR Project Developers", author_email="hello@bytecodealliance.org", - url="https://github.com/bytecodealliance/wamr-python", + url="https://github.com/bytecodealliance/wasm-micro-runtime", license=license, - packages=["wamr"], + include_package_data=True, + cmdclass={ + 'develop': PreDevelopCommand, + 'install': PreInstallCommand, + }, ) diff --git a/language-bindings/python/src/wamr/__init__.py b/language-bindings/python/src/wamr/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/language-bindings/python/src/wamr/libs/.placeholder b/language-bindings/python/src/wamr/libs/.placeholder new file mode 100644 index 00000000..e69de29b diff --git a/language-bindings/python/src/wamr/wamrapi/__init__.py b/language-bindings/python/src/wamr/wamrapi/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/language-bindings/python/src/wamr/wamrapi/iwasm.py b/language-bindings/python/src/wamr/wamrapi/iwasm.py new file mode 100644 index 00000000..df3ab81d --- /dev/null +++ b/language-bindings/python/src/wamr/wamrapi/iwasm.py @@ -0,0 +1,1779 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +r"""Wrapper for wasm_export.h + +Generated with: +ctypesgen ../../../../core/iwasm/include/wasm_export.h -l ../libs/libiwasm.so -o iwasm.py + +Do not modify this file. +""" + +__docformat__ = "restructuredtext" + +# Begin preamble for Python + +import ctypes +import sys +from ctypes import * # noqa: F401, F403 + +_int_types = (ctypes.c_int16, ctypes.c_int32) +if hasattr(ctypes, "c_int64"): + # Some builds of ctypes apparently do not have ctypes.c_int64 + # defined; it's a pretty good bet that these builds do not + # have 64-bit pointers. + _int_types += (ctypes.c_int64,) +for t in _int_types: + if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t): + c_ptrdiff_t = t +del t +del _int_types + + + +class UserString: + def __init__(self, seq): + if isinstance(seq, bytes): + self.data = seq + elif isinstance(seq, UserString): + self.data = seq.data[:] + else: + self.data = str(seq).encode() + + def __bytes__(self): + return self.data + + def __str__(self): + return self.data.decode() + + def __repr__(self): + return repr(self.data) + + def __int__(self): + return int(self.data.decode()) + + def __long__(self): + return int(self.data.decode()) + + def __float__(self): + return float(self.data.decode()) + + def __complex__(self): + return complex(self.data.decode()) + + def __hash__(self): + return hash(self.data) + + def __le__(self, string): + if isinstance(string, UserString): + return self.data <= string.data + else: + return self.data <= string + + def __lt__(self, string): + if isinstance(string, UserString): + return self.data < string.data + else: + return self.data < string + + def __ge__(self, string): + if isinstance(string, UserString): + return self.data >= string.data + else: + return self.data >= string + + def __gt__(self, string): + if isinstance(string, UserString): + return self.data > string.data + else: + return self.data > string + + def __eq__(self, string): + if isinstance(string, UserString): + return self.data == string.data + else: + return self.data == string + + def __ne__(self, string): + if isinstance(string, UserString): + return self.data != string.data + else: + return self.data != string + + def __contains__(self, char): + return char in self.data + + def __len__(self): + return len(self.data) + + def __getitem__(self, index): + return self.__class__(self.data[index]) + + def __getslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + return self.__class__(self.data[start:end]) + + def __add__(self, other): + if isinstance(other, UserString): + return self.__class__(self.data + other.data) + elif isinstance(other, bytes): + return self.__class__(self.data + other) + else: + return self.__class__(self.data + str(other).encode()) + + def __radd__(self, other): + if isinstance(other, bytes): + return self.__class__(other + self.data) + else: + return self.__class__(str(other).encode() + self.data) + + def __mul__(self, n): + return self.__class__(self.data * n) + + __rmul__ = __mul__ + + def __mod__(self, args): + return self.__class__(self.data % args) + + # the following methods are defined in alphabetical order: + def capitalize(self): + return self.__class__(self.data.capitalize()) + + def center(self, width, *args): + return self.__class__(self.data.center(width, *args)) + + def count(self, sub, start=0, end=sys.maxsize): + return self.data.count(sub, start, end) + + def decode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.decode(encoding, errors)) + else: + return self.__class__(self.data.decode(encoding)) + else: + return self.__class__(self.data.decode()) + + def encode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.encode(encoding, errors)) + else: + return self.__class__(self.data.encode(encoding)) + else: + return self.__class__(self.data.encode()) + + def endswith(self, suffix, start=0, end=sys.maxsize): + return self.data.endswith(suffix, start, end) + + def expandtabs(self, tabsize=8): + return self.__class__(self.data.expandtabs(tabsize)) + + def find(self, sub, start=0, end=sys.maxsize): + return self.data.find(sub, start, end) + + def index(self, sub, start=0, end=sys.maxsize): + return self.data.index(sub, start, end) + + def isalpha(self): + return self.data.isalpha() + + def isalnum(self): + return self.data.isalnum() + + def isdecimal(self): + return self.data.isdecimal() + + def isdigit(self): + return self.data.isdigit() + + def islower(self): + return self.data.islower() + + def isnumeric(self): + return self.data.isnumeric() + + def isspace(self): + return self.data.isspace() + + def istitle(self): + return self.data.istitle() + + def isupper(self): + return self.data.isupper() + + def join(self, seq): + return self.data.join(seq) + + def ljust(self, width, *args): + return self.__class__(self.data.ljust(width, *args)) + + def lower(self): + return self.__class__(self.data.lower()) + + def lstrip(self, chars=None): + return self.__class__(self.data.lstrip(chars)) + + def partition(self, sep): + return self.data.partition(sep) + + def replace(self, old, new, maxsplit=-1): + return self.__class__(self.data.replace(old, new, maxsplit)) + + def rfind(self, sub, start=0, end=sys.maxsize): + return self.data.rfind(sub, start, end) + + def rindex(self, sub, start=0, end=sys.maxsize): + return self.data.rindex(sub, start, end) + + def rjust(self, width, *args): + return self.__class__(self.data.rjust(width, *args)) + + def rpartition(self, sep): + return self.data.rpartition(sep) + + def rstrip(self, chars=None): + return self.__class__(self.data.rstrip(chars)) + + def split(self, sep=None, maxsplit=-1): + return self.data.split(sep, maxsplit) + + def rsplit(self, sep=None, maxsplit=-1): + return self.data.rsplit(sep, maxsplit) + + def splitlines(self, keepends=0): + return self.data.splitlines(keepends) + + def startswith(self, prefix, start=0, end=sys.maxsize): + return self.data.startswith(prefix, start, end) + + def strip(self, chars=None): + return self.__class__(self.data.strip(chars)) + + def swapcase(self): + return self.__class__(self.data.swapcase()) + + def title(self): + return self.__class__(self.data.title()) + + def translate(self, *args): + return self.__class__(self.data.translate(*args)) + + def upper(self): + return self.__class__(self.data.upper()) + + def zfill(self, width): + return self.__class__(self.data.zfill(width)) + + +class MutableString(UserString): + """mutable string objects + + Python strings are immutable objects. This has the advantage, that + strings may be used as dictionary keys. If this property isn't needed + and you insist on changing string values in place instead, you may cheat + and use MutableString. + + But the purpose of this class is an educational one: to prevent + people from inventing their own mutable string class derived + from UserString and than forget thereby to remove (override) the + __hash__ method inherited from UserString. This would lead to + errors that would be very hard to track down. + + A faster and better solution is to rewrite your program using lists.""" + + def __init__(self, string=""): + self.data = string + + def __hash__(self): + raise TypeError("unhashable type (it is mutable)") + + def __setitem__(self, index, sub): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + sub + self.data[index + 1 :] + + def __delitem__(self, index): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + self.data[index + 1 :] + + def __setslice__(self, start, end, sub): + start = max(start, 0) + end = max(end, 0) + if isinstance(sub, UserString): + self.data = self.data[:start] + sub.data + self.data[end:] + elif isinstance(sub, bytes): + self.data = self.data[:start] + sub + self.data[end:] + else: + self.data = self.data[:start] + str(sub).encode() + self.data[end:] + + def __delslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + self.data = self.data[:start] + self.data[end:] + + def immutable(self): + return UserString(self.data) + + def __iadd__(self, other): + if isinstance(other, UserString): + self.data += other.data + elif isinstance(other, bytes): + self.data += other + else: + self.data += str(other).encode() + return self + + def __imul__(self, n): + self.data *= n + return self + + +class String(MutableString, ctypes.Union): + + _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)] + + def __init__(self, obj=b""): + if isinstance(obj, (bytes, UserString)): + self.data = bytes(obj) + else: + self.raw = obj + + def __len__(self): + return self.data and len(self.data) or 0 + + def from_param(cls, obj): + # Convert None or 0 + if obj is None or obj == 0: + return cls(ctypes.POINTER(ctypes.c_char)()) + + # Convert from String + elif isinstance(obj, String): + return obj + + # Convert from bytes + elif isinstance(obj, bytes): + return cls(obj) + + # Convert from str + elif isinstance(obj, str): + return cls(obj.encode()) + + # Convert from c_char_p + elif isinstance(obj, ctypes.c_char_p): + return obj + + # Convert from POINTER(ctypes.c_char) + elif isinstance(obj, ctypes.POINTER(ctypes.c_char)): + return obj + + # Convert from raw pointer + elif isinstance(obj, int): + return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char))) + + # Convert from ctypes.c_char array + elif isinstance(obj, ctypes.c_char * len(obj)): + return obj + + # Convert from object + else: + return String.from_param(obj._as_parameter_) + + from_param = classmethod(from_param) + + +def ReturnString(obj, func=None, arguments=None): + return String.from_param(obj) + + +# As of ctypes 1.0, ctypes does not support custom error-checking +# functions on callbacks, nor does it support custom datatypes on +# callbacks, so we must ensure that all callbacks return +# primitive datatypes. +# +# Non-primitive return values wrapped with UNCHECKED won't be +# typechecked, and will be converted to ctypes.c_void_p. +def UNCHECKED(type): + if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P": + return type + else: + return ctypes.c_void_p + + +# ctypes doesn't have direct support for variadic functions, so we have to write +# our own wrapper class +class _variadic_function(object): + def __init__(self, func, restype, argtypes, errcheck): + self.func = func + self.func.restype = restype + self.argtypes = argtypes + if errcheck: + self.func.errcheck = errcheck + + def _as_parameter_(self): + # So we can pass this variadic function as a function pointer + return self.func + + def __call__(self, *args): + fixed_args = [] + i = 0 + for argtype in self.argtypes: + # Typecheck what we can + fixed_args.append(argtype.from_param(args[i])) + i += 1 + return self.func(*fixed_args + list(args[i:])) + + +def ord_if_char(value): + """ + Simple helper used for casts to simple builtin types: if the argument is a + string type, it will be converted to it's ordinal value. + + This function will raise an exception if the argument is string with more + than one characters. + """ + return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value + +# End preamble + +_libs = {} +_libdirs = [] + +# Begin loader + +""" +Load libraries - appropriately for all our supported platforms +""" +# ---------------------------------------------------------------------------- +# Copyright (c) 2008 David James +# Copyright (c) 2006-2008 Alex Holkner +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of pyglet nor the names of its +# contributors may be used to endorse or promote products +# derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# ---------------------------------------------------------------------------- + +import ctypes +import ctypes.util +import glob +import os.path +import platform +import re +import sys + + +def _environ_path(name): + """Split an environment variable into a path-like list elements""" + if name in os.environ: + return os.environ[name].split(":") + return [] + + +class LibraryLoader: + """ + A base class For loading of libraries ;-) + Subclasses load libraries for specific platforms. + """ + + # library names formatted specifically for platforms + name_formats = ["%s"] + + class Lookup: + """Looking up calling conventions for a platform""" + + mode = ctypes.DEFAULT_MODE + + def __init__(self, path): + super(LibraryLoader.Lookup, self).__init__() + self.access = dict(cdecl=ctypes.CDLL(path, self.mode)) + + def get(self, name, calling_convention="cdecl"): + """Return the given name according to the selected calling convention""" + if calling_convention not in self.access: + raise LookupError( + "Unknown calling convention '{}' for function '{}'".format( + calling_convention, name + ) + ) + return getattr(self.access[calling_convention], name) + + def has(self, name, calling_convention="cdecl"): + """Return True if this given calling convention finds the given 'name'""" + if calling_convention not in self.access: + return False + return hasattr(self.access[calling_convention], name) + + def __getattr__(self, name): + return getattr(self.access["cdecl"], name) + + def __init__(self): + self.other_dirs = [] + + def __call__(self, libname): + """Given the name of a library, load it.""" + paths = self.getpaths(libname) + + for path in paths: + # noinspection PyBroadException + try: + return self.Lookup(path) + except Exception: # pylint: disable=broad-except + pass + + raise ImportError("Could not load %s." % libname) + + def getpaths(self, libname): + """Return a list of paths where the library might be found.""" + if os.path.isabs(libname): + yield libname + else: + # search through a prioritized series of locations for the library + + # we first search any specific directories identified by user + for dir_i in self.other_dirs: + for fmt in self.name_formats: + # dir_i should be absolute already + yield os.path.join(dir_i, fmt % libname) + + # check if this code is even stored in a physical file + try: + this_file = __file__ + except NameError: + this_file = None + + # then we search the directory where the generated python interface is stored + if this_file is not None: + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname)) + + # now, use the ctypes tools to try to find the library + for fmt in self.name_formats: + path = ctypes.util.find_library(fmt % libname) + if path: + yield path + + # then we search all paths identified as platform-specific lib paths + for path in self.getplatformpaths(libname): + yield path + + # Finally, we'll try the users current working directory + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname)) + + def getplatformpaths(self, _libname): # pylint: disable=no-self-use + """Return all the library paths available in this platform""" + return [] + + +# Darwin (Mac OS X) + + +class DarwinLibraryLoader(LibraryLoader): + """Library loader for MacOS""" + + name_formats = [ + "lib%s.dylib", + "lib%s.so", + "lib%s.bundle", + "%s.dylib", + "%s.so", + "%s.bundle", + "%s", + ] + + class Lookup(LibraryLoader.Lookup): + """ + Looking up library files for this platform (Darwin aka MacOS) + """ + + # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead + # of the default RTLD_LOCAL. Without this, you end up with + # libraries not being loadable, resulting in "Symbol not found" + # errors + mode = ctypes.RTLD_GLOBAL + + def getplatformpaths(self, libname): + if os.path.pathsep in libname: + names = [libname] + else: + names = [fmt % libname for fmt in self.name_formats] + + for directory in self.getdirs(libname): + for name in names: + yield os.path.join(directory, name) + + @staticmethod + def getdirs(libname): + """Implements the dylib search as specified in Apple documentation: + + http://developer.apple.com/documentation/DeveloperTools/Conceptual/ + DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html + + Before commencing the standard search, the method first checks + the bundle's ``Frameworks`` directory if the application is running + within a bundle (OS X .app). + """ + + dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") + if not dyld_fallback_library_path: + dyld_fallback_library_path = [ + os.path.expanduser("~/lib"), + "/usr/local/lib", + "/usr/lib", + ] + + dirs = [] + + if "/" in libname: + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + else: + dirs.extend(_environ_path("LD_LIBRARY_PATH")) + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + dirs.extend(_environ_path("LD_RUN_PATH")) + + if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app": + dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")) + + dirs.extend(dyld_fallback_library_path) + + return dirs + + +# Posix + + +class PosixLibraryLoader(LibraryLoader): + """Library loader for POSIX-like systems (including Linux)""" + + _ld_so_cache = None + + _include = re.compile(r"^\s*include\s+(?P.*)") + + name_formats = ["lib%s.so", "%s.so", "%s"] + + class _Directories(dict): + """Deal with directories""" + + def __init__(self): + dict.__init__(self) + self.order = 0 + + def add(self, directory): + """Add a directory to our current set of directories""" + if len(directory) > 1: + directory = directory.rstrip(os.path.sep) + # only adds and updates order if exists and not already in set + if not os.path.exists(directory): + return + order = self.setdefault(directory, self.order) + if order == self.order: + self.order += 1 + + def extend(self, directories): + """Add a list of directories to our set""" + for a_dir in directories: + self.add(a_dir) + + def ordered(self): + """Sort the list of directories""" + return (i[0] for i in sorted(self.items(), key=lambda d: d[1])) + + def _get_ld_so_conf_dirs(self, conf, dirs): + """ + Recursive function to help parse all ld.so.conf files, including proper + handling of the `include` directive. + """ + + try: + with open(conf) as fileobj: + for dirname in fileobj: + dirname = dirname.strip() + if not dirname: + continue + + match = self._include.match(dirname) + if not match: + dirs.add(dirname) + else: + for dir2 in glob.glob(match.group("pattern")): + self._get_ld_so_conf_dirs(dir2, dirs) + except IOError: + pass + + def _create_ld_so_cache(self): + # Recreate search path followed by ld.so. This is going to be + # slow to build, and incorrect (ld.so uses ld.so.cache, which may + # not be up-to-date). Used only as fallback for distros without + # /sbin/ldconfig. + # + # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. + + directories = self._Directories() + for name in ( + "LD_LIBRARY_PATH", + "SHLIB_PATH", # HP-UX + "LIBPATH", # OS/2, AIX + "LIBRARY_PATH", # BE/OS + ): + if name in os.environ: + directories.extend(os.environ[name].split(os.pathsep)) + + self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories) + + bitage = platform.architecture()[0] + + unix_lib_dirs_list = [] + if bitage.startswith("64"): + # prefer 64 bit if that is our arch + unix_lib_dirs_list += ["/lib64", "/usr/lib64"] + + # must include standard libs, since those paths are also used by 64 bit + # installs + unix_lib_dirs_list += ["/lib", "/usr/lib"] + if sys.platform.startswith("linux"): + # Try and support multiarch work in Ubuntu + # https://wiki.ubuntu.com/MultiarchSpec + if bitage.startswith("32"): + # Assume Intel/AMD x86 compat + unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"] + elif bitage.startswith("64"): + # Assume Intel/AMD x86 compatible + unix_lib_dirs_list += [ + "/lib/x86_64-linux-gnu", + "/usr/lib/x86_64-linux-gnu", + ] + else: + # guess... + unix_lib_dirs_list += glob.glob("/lib/*linux-gnu") + directories.extend(unix_lib_dirs_list) + + cache = {} + lib_re = re.compile(r"lib(.*)\.s[ol]") + # ext_re = re.compile(r"\.s[ol]$") + for our_dir in directories.ordered(): + try: + for path in glob.glob("%s/*.s[ol]*" % our_dir): + file = os.path.basename(path) + + # Index by filename + cache_i = cache.setdefault(file, set()) + cache_i.add(path) + + # Index by library name + match = lib_re.match(file) + if match: + library = match.group(1) + cache_i = cache.setdefault(library, set()) + cache_i.add(path) + except OSError: + pass + + self._ld_so_cache = cache + + def getplatformpaths(self, libname): + if self._ld_so_cache is None: + self._create_ld_so_cache() + + result = self._ld_so_cache.get(libname, set()) + for i in result: + # we iterate through all found paths for library, since we may have + # actually found multiple architectures or other library types that + # may not load + yield i + + +# Windows + + +class WindowsLibraryLoader(LibraryLoader): + """Library loader for Microsoft Windows""" + + name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"] + + class Lookup(LibraryLoader.Lookup): + """Lookup class for Windows libraries...""" + + def __init__(self, path): + super(WindowsLibraryLoader.Lookup, self).__init__(path) + self.access["stdcall"] = ctypes.windll.LoadLibrary(path) + + +# Platform switching + +# If your value of sys.platform does not appear in this dict, please contact +# the Ctypesgen maintainers. + +loaderclass = { + "darwin": DarwinLibraryLoader, + "cygwin": WindowsLibraryLoader, + "win32": WindowsLibraryLoader, + "msys": WindowsLibraryLoader, +} + +load_library = loaderclass.get(sys.platform, PosixLibraryLoader)() + + +def add_library_search_dirs(other_dirs): + """ + Add libraries to search paths. + If library paths are relative, convert them to absolute with respect to this + file's directory + """ + for path in other_dirs: + if not os.path.isabs(path): + path = os.path.abspath(path) + load_library.other_dirs.append(path) + + +del loaderclass + +# End loader + +add_library_search_dirs([]) + +# Begin libraries +_libs["../libs/libiwasm.so"] = load_library("../libs/libiwasm.so") + +# 1 libraries +# End libraries + +# No modules + +__uint8_t = c_ubyte# /usr/include/x86_64-linux-gnu/bits/types.h: 38 + +__uint32_t = c_uint# /usr/include/x86_64-linux-gnu/bits/types.h: 42 + +uint8_t = __uint8_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 24 + +uint32_t = __uint32_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 26 + +uintptr_t = c_ulong# /usr/include/stdint.h: 90 + +# wasm-micro-runtime/core/iwasm/include/lib_export.h: 22 +class struct_NativeSymbol(Structure): + pass + +struct_NativeSymbol.__slots__ = [ + 'symbol', + 'func_ptr', + 'signature', + 'attachment', +] +struct_NativeSymbol._fields_ = [ + ('symbol', String), + ('func_ptr', POINTER(None)), + ('signature', String), + ('attachment', POINTER(None)), +] + +NativeSymbol = struct_NativeSymbol# wasm-micro-runtime/core/iwasm/include/lib_export.h: 22 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 62 +class struct_WASMModuleCommon(Structure): + pass + +wasm_module_t = POINTER(struct_WASMModuleCommon)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 63 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 67 +class struct_WASMModuleInstanceCommon(Structure): + pass + +wasm_module_inst_t = POINTER(struct_WASMModuleInstanceCommon)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 68 + +WASMFunctionInstanceCommon = None# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 71 + +wasm_function_inst_t = POINTER(WASMFunctionInstanceCommon)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 72 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 75 +class struct_wasm_section_t(Structure): + pass + +struct_wasm_section_t.__slots__ = [ + 'next', + 'section_type', + 'section_body', + 'section_body_size', +] +struct_wasm_section_t._fields_ = [ + ('next', POINTER(struct_wasm_section_t)), + ('section_type', c_int), + ('section_body', POINTER(uint8_t)), + ('section_body_size', uint32_t), +] + +wasm_section_t = struct_wasm_section_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 83 + +aot_section_t = struct_wasm_section_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 83 + +wasm_section_list_t = POINTER(struct_wasm_section_t)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 83 + +aot_section_list_t = POINTER(struct_wasm_section_t)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 83 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 86 +class struct_WASMExecEnv(Structure): + pass + +wasm_exec_env_t = POINTER(struct_WASMExecEnv)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 87 + +enum_anon_2 = c_int# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 94 + +Wasm_Module_Bytecode = 0# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 94 + +Wasm_Module_AoT = (Wasm_Module_Bytecode + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 94 + +Package_Type_Unknown = 0xFFFF# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 94 + +package_type_t = enum_anon_2# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 94 + +enum_anon_3 = c_int# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 108 + +Alloc_With_Pool = 0# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 108 + +Alloc_With_Allocator = (Alloc_With_Pool + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 108 + +Alloc_With_System_Allocator = (Alloc_With_Allocator + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 108 + +mem_alloc_type_t = enum_anon_3# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 108 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 112 +class struct_anon_4(Structure): + pass + +struct_anon_4.__slots__ = [ + 'heap_buf', + 'heap_size', +] +struct_anon_4._fields_ = [ + ('heap_buf', POINTER(None)), + ('heap_size', uint32_t), +] + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 116 +class struct_anon_5(Structure): + pass + +struct_anon_5.__slots__ = [ + 'malloc_func', + 'realloc_func', + 'free_func', + 'user_data', +] +struct_anon_5._fields_ = [ + ('malloc_func', POINTER(None)), + ('realloc_func', POINTER(None)), + ('free_func', POINTER(None)), + ('user_data', POINTER(None)), +] + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 124 +class union_MemAllocOption(Union): + pass + +union_MemAllocOption.__slots__ = [ + 'pool', + 'allocator', +] +union_MemAllocOption._fields_ = [ + ('pool', struct_anon_4), + ('allocator', struct_anon_5), +] + +MemAllocOption = union_MemAllocOption# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 124 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 132 +class struct_mem_alloc_info_t(Structure): + pass + +struct_mem_alloc_info_t.__slots__ = [ + 'total_size', + 'total_free_size', + 'highmark_size', +] +struct_mem_alloc_info_t._fields_ = [ + ('total_size', uint32_t), + ('total_free_size', uint32_t), + ('highmark_size', uint32_t), +] + +mem_alloc_info_t = struct_mem_alloc_info_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 132 + +enum_RunningMode = c_int# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140 + +Mode_Interp = 1# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140 + +Mode_Fast_JIT = (Mode_Interp + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140 + +Mode_LLVM_JIT = (Mode_Fast_JIT + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140 + +Mode_Multi_Tier_JIT = (Mode_LLVM_JIT + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140 + +RunningMode = enum_RunningMode# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 170 +class struct_RuntimeInitArgs(Structure): + pass + +struct_RuntimeInitArgs.__slots__ = [ + 'mem_alloc_type', + 'mem_alloc_option', + 'native_module_name', + 'native_symbols', + 'n_native_symbols', + 'max_thread_num', + 'ip_addr', + 'unused', + 'instance_port', + 'fast_jit_code_cache_size', + 'running_mode', + 'llvm_jit_opt_level', + 'llvm_jit_size_level', +] +struct_RuntimeInitArgs._fields_ = [ + ('mem_alloc_type', mem_alloc_type_t), + ('mem_alloc_option', MemAllocOption), + ('native_module_name', String), + ('native_symbols', POINTER(NativeSymbol)), + ('n_native_symbols', uint32_t), + ('max_thread_num', uint32_t), + ('ip_addr', c_char * int(128)), + ('unused', c_int), + ('instance_port', c_int), + ('fast_jit_code_cache_size', uint32_t), + ('running_mode', RunningMode), + ('llvm_jit_opt_level', uint32_t), + ('llvm_jit_size_level', uint32_t), +] + +RuntimeInitArgs = struct_RuntimeInitArgs# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 170 + +wasm_valkind_t = uint8_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 174 + +enum_wasm_valkind_enum = c_int# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175 + +WASM_I32 = 0# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175 + +WASM_I64 = (WASM_I32 + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175 + +WASM_F32 = (WASM_I64 + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175 + +WASM_F64 = (WASM_F32 + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175 + +WASM_ANYREF = 128# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175 + +WASM_FUNCREF = (WASM_ANYREF + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 190 +class union_anon_6(Union): + pass + +union_anon_6.__slots__ = [ + 'i32', + 'i64', + 'f32', + 'f64', + 'foreign', +] +union_anon_6._fields_ = [ + ('i32', c_int32), + ('i64', c_int64), + ('f32', c_float), + ('f64', c_double), + ('foreign', uintptr_t), +] + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 199 +class struct_wasm_val_t(Structure): + pass + +struct_wasm_val_t.__slots__ = [ + 'kind', + 'of', +] +struct_wasm_val_t._fields_ = [ + ('kind', wasm_valkind_t), + ('of', union_anon_6), +] + +wasm_val_t = struct_wasm_val_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 199 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 210 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_init", "cdecl"): + wasm_runtime_init = _libs["../libs/libiwasm.so"].get("wasm_runtime_init", "cdecl") + wasm_runtime_init.argtypes = [] + wasm_runtime_init.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 222 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_full_init", "cdecl"): + wasm_runtime_full_init = _libs["../libs/libiwasm.so"].get("wasm_runtime_full_init", "cdecl") + wasm_runtime_full_init.argtypes = [POINTER(RuntimeInitArgs)] + wasm_runtime_full_init.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 232 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_is_running_mode_supported", "cdecl"): + continue + wasm_runtime_is_running_mode_supported = _lib.get("wasm_runtime_is_running_mode_supported", "cdecl") + wasm_runtime_is_running_mode_supported.argtypes = [RunningMode] + wasm_runtime_is_running_mode_supported.restype = c_bool + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 244 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_set_default_running_mode", "cdecl"): + continue + wasm_runtime_set_default_running_mode = _lib.get("wasm_runtime_set_default_running_mode", "cdecl") + wasm_runtime_set_default_running_mode.argtypes = [RunningMode] + wasm_runtime_set_default_running_mode.restype = c_bool + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 250 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_destroy", "cdecl"): + wasm_runtime_destroy = _libs["../libs/libiwasm.so"].get("wasm_runtime_destroy", "cdecl") + wasm_runtime_destroy.argtypes = [] + wasm_runtime_destroy.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 259 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_malloc", "cdecl"): + wasm_runtime_malloc = _libs["../libs/libiwasm.so"].get("wasm_runtime_malloc", "cdecl") + wasm_runtime_malloc.argtypes = [c_uint] + wasm_runtime_malloc.restype = POINTER(c_ubyte) + wasm_runtime_malloc.errcheck = lambda v,*a : cast(v, c_void_p) + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 270 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_realloc", "cdecl"): + wasm_runtime_realloc = _libs["../libs/libiwasm.so"].get("wasm_runtime_realloc", "cdecl") + wasm_runtime_realloc.argtypes = [POINTER(None), c_uint] + wasm_runtime_realloc.restype = POINTER(c_ubyte) + wasm_runtime_realloc.errcheck = lambda v,*a : cast(v, c_void_p) + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 277 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_free", "cdecl"): + wasm_runtime_free = _libs["../libs/libiwasm.so"].get("wasm_runtime_free", "cdecl") + wasm_runtime_free.argtypes = [POINTER(None)] + wasm_runtime_free.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 283 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_mem_alloc_info", "cdecl"): + wasm_runtime_get_mem_alloc_info = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_mem_alloc_info", "cdecl") + wasm_runtime_get_mem_alloc_info.argtypes = [POINTER(mem_alloc_info_t)] + wasm_runtime_get_mem_alloc_info.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 294 +if _libs["../libs/libiwasm.so"].has("get_package_type", "cdecl"): + get_package_type = _libs["../libs/libiwasm.so"].get("get_package_type", "cdecl") + get_package_type.argtypes = [POINTER(uint8_t), uint32_t] + get_package_type.restype = package_type_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 305 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_is_xip_file", "cdecl"): + wasm_runtime_is_xip_file = _libs["../libs/libiwasm.so"].get("wasm_runtime_is_xip_file", "cdecl") + wasm_runtime_is_xip_file.argtypes = [POINTER(uint8_t), uint32_t] + wasm_runtime_is_xip_file.restype = c_bool + +module_reader = CFUNCTYPE(UNCHECKED(c_bool), String, POINTER(POINTER(uint8_t)), POINTER(uint32_t))# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 310 + +module_destroyer = CFUNCTYPE(UNCHECKED(None), POINTER(uint8_t), uint32_t)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 316 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 325 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_set_module_reader", "cdecl"): + continue + wasm_runtime_set_module_reader = _lib.get("wasm_runtime_set_module_reader", "cdecl") + wasm_runtime_set_module_reader.argtypes = [module_reader, module_destroyer] + wasm_runtime_set_module_reader.restype = None + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 339 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_register_module", "cdecl"): + continue + wasm_runtime_register_module = _lib.get("wasm_runtime_register_module", "cdecl") + wasm_runtime_register_module.argtypes = [String, wasm_module_t, String, uint32_t] + wasm_runtime_register_module.restype = c_bool + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 351 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_find_module_registered", "cdecl"): + continue + wasm_runtime_find_module_registered = _lib.get("wasm_runtime_find_module_registered", "cdecl") + wasm_runtime_find_module_registered.argtypes = [String] + wasm_runtime_find_module_registered.restype = wasm_module_t + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 375 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_load", "cdecl"): + wasm_runtime_load = _libs["../libs/libiwasm.so"].get("wasm_runtime_load", "cdecl") + wasm_runtime_load.argtypes = [POINTER(uint8_t), uint32_t, String, uint32_t] + wasm_runtime_load.restype = wasm_module_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 389 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_load_from_sections", "cdecl"): + wasm_runtime_load_from_sections = _libs["../libs/libiwasm.so"].get("wasm_runtime_load_from_sections", "cdecl") + wasm_runtime_load_from_sections.argtypes = [wasm_section_list_t, c_bool, String, uint32_t] + wasm_runtime_load_from_sections.restype = wasm_module_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 398 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_unload", "cdecl"): + wasm_runtime_unload = _libs["../libs/libiwasm.so"].get("wasm_runtime_unload", "cdecl") + wasm_runtime_unload.argtypes = [wasm_module_t] + wasm_runtime_unload.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 408 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_get_module_hash", "cdecl"): + continue + wasm_runtime_get_module_hash = _lib.get("wasm_runtime_get_module_hash", "cdecl") + wasm_runtime_get_module_hash.argtypes = [wasm_module_t] + if sizeof(c_int) == sizeof(c_void_p): + wasm_runtime_get_module_hash.restype = ReturnString + else: + wasm_runtime_get_module_hash.restype = String + wasm_runtime_get_module_hash.errcheck = ReturnString + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 438 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_wasi_args_ex", "cdecl"): + wasm_runtime_set_wasi_args_ex = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_wasi_args_ex", "cdecl") + wasm_runtime_set_wasi_args_ex.argtypes = [wasm_module_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), c_int, c_int, c_int, c_int] + wasm_runtime_set_wasi_args_ex.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 452 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_wasi_args", "cdecl"): + wasm_runtime_set_wasi_args = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_wasi_args", "cdecl") + wasm_runtime_set_wasi_args.argtypes = [wasm_module_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), c_int] + wasm_runtime_set_wasi_args.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 459 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_wasi_addr_pool", "cdecl"): + wasm_runtime_set_wasi_addr_pool = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_wasi_addr_pool", "cdecl") + wasm_runtime_set_wasi_addr_pool.argtypes = [wasm_module_t, POINTER(POINTER(c_char)), uint32_t] + wasm_runtime_set_wasi_addr_pool.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 463 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_wasi_ns_lookup_pool", "cdecl"): + wasm_runtime_set_wasi_ns_lookup_pool = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_wasi_ns_lookup_pool", "cdecl") + wasm_runtime_set_wasi_ns_lookup_pool.argtypes = [wasm_module_t, POINTER(POINTER(c_char)), uint32_t] + wasm_runtime_set_wasi_ns_lookup_pool.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 486 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_instantiate", "cdecl"): + wasm_runtime_instantiate = _libs["../libs/libiwasm.so"].get("wasm_runtime_instantiate", "cdecl") + wasm_runtime_instantiate.argtypes = [wasm_module_t, uint32_t, uint32_t, String, uint32_t] + wasm_runtime_instantiate.restype = wasm_module_inst_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 502 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_set_running_mode", "cdecl"): + continue + wasm_runtime_set_running_mode = _lib.get("wasm_runtime_set_running_mode", "cdecl") + wasm_runtime_set_running_mode.argtypes = [wasm_module_inst_t, RunningMode] + wasm_runtime_set_running_mode.restype = c_bool + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 516 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_get_running_mode", "cdecl"): + continue + wasm_runtime_get_running_mode = _lib.get("wasm_runtime_get_running_mode", "cdecl") + wasm_runtime_get_running_mode.argtypes = [wasm_module_inst_t] + wasm_runtime_get_running_mode.restype = RunningMode + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 524 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_deinstantiate", "cdecl"): + wasm_runtime_deinstantiate = _libs["../libs/libiwasm.so"].get("wasm_runtime_deinstantiate", "cdecl") + wasm_runtime_deinstantiate.argtypes = [wasm_module_inst_t] + wasm_runtime_deinstantiate.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 534 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_module", "cdecl"): + wasm_runtime_get_module = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_module", "cdecl") + wasm_runtime_get_module.argtypes = [wasm_module_inst_t] + wasm_runtime_get_module.restype = wasm_module_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 537 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_is_wasi_mode", "cdecl"): + wasm_runtime_is_wasi_mode = _libs["../libs/libiwasm.so"].get("wasm_runtime_is_wasi_mode", "cdecl") + wasm_runtime_is_wasi_mode.argtypes = [wasm_module_inst_t] + wasm_runtime_is_wasi_mode.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 540 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_lookup_wasi_start_function", "cdecl"): + wasm_runtime_lookup_wasi_start_function = _libs["../libs/libiwasm.so"].get("wasm_runtime_lookup_wasi_start_function", "cdecl") + wasm_runtime_lookup_wasi_start_function.argtypes = [wasm_module_inst_t] + wasm_runtime_lookup_wasi_start_function.restype = wasm_function_inst_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 552 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_wasi_exit_code", "cdecl"): + wasm_runtime_get_wasi_exit_code = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_wasi_exit_code", "cdecl") + wasm_runtime_get_wasi_exit_code.argtypes = [wasm_module_inst_t] + wasm_runtime_get_wasi_exit_code.restype = uint32_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 564 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_lookup_function", "cdecl"): + wasm_runtime_lookup_function = _libs["../libs/libiwasm.so"].get("wasm_runtime_lookup_function", "cdecl") + wasm_runtime_lookup_function.argtypes = [wasm_module_inst_t, String, String] + wasm_runtime_lookup_function.restype = wasm_function_inst_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 576 +if _libs["../libs/libiwasm.so"].has("wasm_func_get_param_count", "cdecl"): + wasm_func_get_param_count = _libs["../libs/libiwasm.so"].get("wasm_func_get_param_count", "cdecl") + wasm_func_get_param_count.argtypes = [wasm_function_inst_t, wasm_module_inst_t] + wasm_func_get_param_count.restype = uint32_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 588 +if _libs["../libs/libiwasm.so"].has("wasm_func_get_result_count", "cdecl"): + wasm_func_get_result_count = _libs["../libs/libiwasm.so"].get("wasm_func_get_result_count", "cdecl") + wasm_func_get_result_count.argtypes = [wasm_function_inst_t, wasm_module_inst_t] + wasm_func_get_result_count.restype = uint32_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 599 +if _libs["../libs/libiwasm.so"].has("wasm_func_get_param_types", "cdecl"): + wasm_func_get_param_types = _libs["../libs/libiwasm.so"].get("wasm_func_get_param_types", "cdecl") + wasm_func_get_param_types.argtypes = [wasm_function_inst_t, wasm_module_inst_t, POINTER(wasm_valkind_t)] + wasm_func_get_param_types.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 611 +if _libs["../libs/libiwasm.so"].has("wasm_func_get_result_types", "cdecl"): + wasm_func_get_result_types = _libs["../libs/libiwasm.so"].get("wasm_func_get_result_types", "cdecl") + wasm_func_get_result_types.argtypes = [wasm_function_inst_t, wasm_module_inst_t, POINTER(wasm_valkind_t)] + wasm_func_get_result_types.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 625 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_create_exec_env", "cdecl"): + wasm_runtime_create_exec_env = _libs["../libs/libiwasm.so"].get("wasm_runtime_create_exec_env", "cdecl") + wasm_runtime_create_exec_env.argtypes = [wasm_module_inst_t, uint32_t] + wasm_runtime_create_exec_env.restype = wasm_exec_env_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 634 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_destroy_exec_env", "cdecl"): + wasm_runtime_destroy_exec_env = _libs["../libs/libiwasm.so"].get("wasm_runtime_destroy_exec_env", "cdecl") + wasm_runtime_destroy_exec_env.argtypes = [wasm_exec_env_t] + wasm_runtime_destroy_exec_env.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 651 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_exec_env_singleton", "cdecl"): + wasm_runtime_get_exec_env_singleton = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_exec_env_singleton", "cdecl") + wasm_runtime_get_exec_env_singleton.argtypes = [wasm_module_inst_t] + wasm_runtime_get_exec_env_singleton.restype = wasm_exec_env_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 674 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_start_debug_instance_with_port", "cdecl"): + continue + wasm_runtime_start_debug_instance_with_port = _lib.get("wasm_runtime_start_debug_instance_with_port", "cdecl") + wasm_runtime_start_debug_instance_with_port.argtypes = [wasm_exec_env_t, c_int32] + wasm_runtime_start_debug_instance_with_port.restype = uint32_t + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 680 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_start_debug_instance", "cdecl"): + continue + wasm_runtime_start_debug_instance = _lib.get("wasm_runtime_start_debug_instance", "cdecl") + wasm_runtime_start_debug_instance.argtypes = [wasm_exec_env_t] + wasm_runtime_start_debug_instance.restype = uint32_t + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 695 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_init_thread_env", "cdecl"): + wasm_runtime_init_thread_env = _libs["../libs/libiwasm.so"].get("wasm_runtime_init_thread_env", "cdecl") + wasm_runtime_init_thread_env.argtypes = [] + wasm_runtime_init_thread_env.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 701 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_destroy_thread_env", "cdecl"): + wasm_runtime_destroy_thread_env = _libs["../libs/libiwasm.so"].get("wasm_runtime_destroy_thread_env", "cdecl") + wasm_runtime_destroy_thread_env.argtypes = [] + wasm_runtime_destroy_thread_env.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 707 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_thread_env_inited", "cdecl"): + wasm_runtime_thread_env_inited = _libs["../libs/libiwasm.so"].get("wasm_runtime_thread_env_inited", "cdecl") + wasm_runtime_thread_env_inited.argtypes = [] + wasm_runtime_thread_env_inited.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 717 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_module_inst", "cdecl"): + wasm_runtime_get_module_inst = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_module_inst", "cdecl") + wasm_runtime_get_module_inst.argtypes = [wasm_exec_env_t] + wasm_runtime_get_module_inst.restype = wasm_module_inst_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 731 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_module_inst", "cdecl"): + wasm_runtime_set_module_inst = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_module_inst", "cdecl") + wasm_runtime_set_module_inst.argtypes = [wasm_exec_env_t, wasm_module_inst_t] + wasm_runtime_set_module_inst.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 755 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_call_wasm", "cdecl"): + wasm_runtime_call_wasm = _libs["../libs/libiwasm.so"].get("wasm_runtime_call_wasm", "cdecl") + wasm_runtime_call_wasm.argtypes = [wasm_exec_env_t, wasm_function_inst_t, uint32_t, POINTER(uint32_t)] + wasm_runtime_call_wasm.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 776 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_call_wasm_a", "cdecl"): + wasm_runtime_call_wasm_a = _libs["../libs/libiwasm.so"].get("wasm_runtime_call_wasm_a", "cdecl") + wasm_runtime_call_wasm_a.argtypes = [wasm_exec_env_t, wasm_function_inst_t, uint32_t, POINTER(wasm_val_t), uint32_t, POINTER(wasm_val_t)] + wasm_runtime_call_wasm_a.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 798 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_call_wasm_v", "cdecl"): + _func = _libs["../libs/libiwasm.so"].get("wasm_runtime_call_wasm_v", "cdecl") + _restype = c_bool + _errcheck = None + _argtypes = [wasm_exec_env_t, wasm_function_inst_t, uint32_t, POINTER(wasm_val_t), uint32_t] + wasm_runtime_call_wasm_v = _variadic_function(_func,_restype,_argtypes,_errcheck) + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 818 +if _libs["../libs/libiwasm.so"].has("wasm_application_execute_main", "cdecl"): + wasm_application_execute_main = _libs["../libs/libiwasm.so"].get("wasm_application_execute_main", "cdecl") + wasm_application_execute_main.argtypes = [wasm_module_inst_t, c_int32, POINTER(POINTER(c_char))] + wasm_application_execute_main.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 837 +if _libs["../libs/libiwasm.so"].has("wasm_application_execute_func", "cdecl"): + wasm_application_execute_func = _libs["../libs/libiwasm.so"].get("wasm_application_execute_func", "cdecl") + wasm_application_execute_func.argtypes = [wasm_module_inst_t, String, c_int32, POINTER(POINTER(c_char))] + wasm_application_execute_func.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 846 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_exception", "cdecl"): + wasm_runtime_get_exception = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_exception", "cdecl") + wasm_runtime_get_exception.argtypes = [wasm_module_inst_t] + wasm_runtime_get_exception.restype = c_char_p + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 857 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_exception", "cdecl"): + wasm_runtime_set_exception = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_exception", "cdecl") + wasm_runtime_set_exception.argtypes = [wasm_module_inst_t, String] + wasm_runtime_set_exception.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 866 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_clear_exception", "cdecl"): + wasm_runtime_clear_exception = _libs["../libs/libiwasm.so"].get("wasm_runtime_clear_exception", "cdecl") + wasm_runtime_clear_exception.argtypes = [wasm_module_inst_t] + wasm_runtime_clear_exception.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 878 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_custom_data", "cdecl"): + wasm_runtime_set_custom_data = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_custom_data", "cdecl") + wasm_runtime_set_custom_data.argtypes = [wasm_module_inst_t, POINTER(None)] + wasm_runtime_set_custom_data.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 887 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_custom_data", "cdecl"): + wasm_runtime_get_custom_data = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_custom_data", "cdecl") + wasm_runtime_get_custom_data.argtypes = [wasm_module_inst_t] + wasm_runtime_get_custom_data.restype = POINTER(c_ubyte) + wasm_runtime_get_custom_data.errcheck = lambda v,*a : cast(v, c_void_p) + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 910 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_module_malloc", "cdecl"): + wasm_runtime_module_malloc = _libs["../libs/libiwasm.so"].get("wasm_runtime_module_malloc", "cdecl") + wasm_runtime_module_malloc.argtypes = [wasm_module_inst_t, uint32_t, POINTER(POINTER(None))] + wasm_runtime_module_malloc.restype = uint32_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 920 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_module_free", "cdecl"): + wasm_runtime_module_free = _libs["../libs/libiwasm.so"].get("wasm_runtime_module_free", "cdecl") + wasm_runtime_module_free.argtypes = [wasm_module_inst_t, uint32_t] + wasm_runtime_module_free.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 936 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_module_dup_data", "cdecl"): + wasm_runtime_module_dup_data = _libs["../libs/libiwasm.so"].get("wasm_runtime_module_dup_data", "cdecl") + wasm_runtime_module_dup_data.argtypes = [wasm_module_inst_t, String, uint32_t] + wasm_runtime_module_dup_data.restype = uint32_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 951 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_validate_app_addr", "cdecl"): + wasm_runtime_validate_app_addr = _libs["../libs/libiwasm.so"].get("wasm_runtime_validate_app_addr", "cdecl") + wasm_runtime_validate_app_addr.argtypes = [wasm_module_inst_t, uint32_t, uint32_t] + wasm_runtime_validate_app_addr.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 973 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_validate_app_str_addr", "cdecl"): + wasm_runtime_validate_app_str_addr = _libs["../libs/libiwasm.so"].get("wasm_runtime_validate_app_str_addr", "cdecl") + wasm_runtime_validate_app_str_addr.argtypes = [wasm_module_inst_t, uint32_t] + wasm_runtime_validate_app_str_addr.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 989 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_validate_native_addr", "cdecl"): + wasm_runtime_validate_native_addr = _libs["../libs/libiwasm.so"].get("wasm_runtime_validate_native_addr", "cdecl") + wasm_runtime_validate_native_addr.argtypes = [wasm_module_inst_t, POINTER(None), uint32_t] + wasm_runtime_validate_native_addr.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1004 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_addr_app_to_native", "cdecl"): + wasm_runtime_addr_app_to_native = _libs["../libs/libiwasm.so"].get("wasm_runtime_addr_app_to_native", "cdecl") + wasm_runtime_addr_app_to_native.argtypes = [wasm_module_inst_t, uint32_t] + wasm_runtime_addr_app_to_native.restype = POINTER(c_ubyte) + wasm_runtime_addr_app_to_native.errcheck = lambda v,*a : cast(v, c_void_p) + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1017 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_addr_native_to_app", "cdecl"): + wasm_runtime_addr_native_to_app = _libs["../libs/libiwasm.so"].get("wasm_runtime_addr_native_to_app", "cdecl") + wasm_runtime_addr_native_to_app.argtypes = [wasm_module_inst_t, POINTER(None)] + wasm_runtime_addr_native_to_app.restype = uint32_t + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1031 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_app_addr_range", "cdecl"): + wasm_runtime_get_app_addr_range = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_app_addr_range", "cdecl") + wasm_runtime_get_app_addr_range.argtypes = [wasm_module_inst_t, uint32_t, POINTER(uint32_t), POINTER(uint32_t)] + wasm_runtime_get_app_addr_range.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1050 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_native_addr_range", "cdecl"): + wasm_runtime_get_native_addr_range = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_native_addr_range", "cdecl") + wasm_runtime_get_native_addr_range.argtypes = [wasm_module_inst_t, POINTER(uint8_t), POINTER(POINTER(uint8_t)), POINTER(POINTER(uint8_t))] + wasm_runtime_get_native_addr_range.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1089 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_register_natives", "cdecl"): + wasm_runtime_register_natives = _libs["../libs/libiwasm.so"].get("wasm_runtime_register_natives", "cdecl") + wasm_runtime_register_natives.argtypes = [String, POINTER(NativeSymbol), uint32_t] + wasm_runtime_register_natives.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1104 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_register_natives_raw", "cdecl"): + wasm_runtime_register_natives_raw = _libs["../libs/libiwasm.so"].get("wasm_runtime_register_natives_raw", "cdecl") + wasm_runtime_register_natives_raw.argtypes = [String, POINTER(NativeSymbol), uint32_t] + wasm_runtime_register_natives_raw.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1123 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_unregister_natives", "cdecl"): + wasm_runtime_unregister_natives = _libs["../libs/libiwasm.so"].get("wasm_runtime_unregister_natives", "cdecl") + wasm_runtime_unregister_natives.argtypes = [String, POINTER(NativeSymbol)] + wasm_runtime_unregister_natives.restype = c_bool + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1133 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_function_attachment", "cdecl"): + wasm_runtime_get_function_attachment = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_function_attachment", "cdecl") + wasm_runtime_get_function_attachment.argtypes = [wasm_exec_env_t] + wasm_runtime_get_function_attachment.restype = POINTER(c_ubyte) + wasm_runtime_get_function_attachment.errcheck = lambda v,*a : cast(v, c_void_p) + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1143 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_user_data", "cdecl"): + wasm_runtime_set_user_data = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_user_data", "cdecl") + wasm_runtime_set_user_data.argtypes = [wasm_exec_env_t, POINTER(None)] + wasm_runtime_set_user_data.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1152 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_user_data", "cdecl"): + wasm_runtime_get_user_data = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_user_data", "cdecl") + wasm_runtime_get_user_data.argtypes = [wasm_exec_env_t] + wasm_runtime_get_user_data.restype = POINTER(c_ubyte) + wasm_runtime_get_user_data.errcheck = lambda v,*a : cast(v, c_void_p) + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1165 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_dump_mem_consumption", "cdecl"): + continue + wasm_runtime_dump_mem_consumption = _lib.get("wasm_runtime_dump_mem_consumption", "cdecl") + wasm_runtime_dump_mem_consumption.argtypes = [wasm_exec_env_t] + wasm_runtime_dump_mem_consumption.restype = None + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1173 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_dump_perf_profiling", "cdecl"): + continue + wasm_runtime_dump_perf_profiling = _lib.get("wasm_runtime_dump_perf_profiling", "cdecl") + wasm_runtime_dump_perf_profiling.argtypes = [wasm_module_inst_t] + wasm_runtime_dump_perf_profiling.restype = None + break + +wasm_thread_callback_t = CFUNCTYPE(UNCHECKED(POINTER(c_ubyte)), wasm_exec_env_t, POINTER(None))# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1176 + +wasm_thread_t = uintptr_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1178 + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1186 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_set_max_thread_num", "cdecl"): + continue + wasm_runtime_set_max_thread_num = _lib.get("wasm_runtime_set_max_thread_num", "cdecl") + wasm_runtime_set_max_thread_num.argtypes = [uint32_t] + wasm_runtime_set_max_thread_num.restype = None + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1197 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_spawn_exec_env", "cdecl"): + continue + wasm_runtime_spawn_exec_env = _lib.get("wasm_runtime_spawn_exec_env", "cdecl") + wasm_runtime_spawn_exec_env.argtypes = [wasm_exec_env_t] + wasm_runtime_spawn_exec_env.restype = wasm_exec_env_t + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1205 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_destroy_spawned_exec_env", "cdecl"): + continue + wasm_runtime_destroy_spawned_exec_env = _lib.get("wasm_runtime_destroy_spawned_exec_env", "cdecl") + wasm_runtime_destroy_spawned_exec_env.argtypes = [wasm_exec_env_t] + wasm_runtime_destroy_spawned_exec_env.restype = None + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1218 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_spawn_thread", "cdecl"): + continue + wasm_runtime_spawn_thread = _lib.get("wasm_runtime_spawn_thread", "cdecl") + wasm_runtime_spawn_thread.argtypes = [wasm_exec_env_t, POINTER(wasm_thread_t), wasm_thread_callback_t, POINTER(None)] + wasm_runtime_spawn_thread.restype = c_int32 + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1230 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_join_thread", "cdecl"): + continue + wasm_runtime_join_thread = _lib.get("wasm_runtime_join_thread", "cdecl") + wasm_runtime_join_thread.argtypes = [wasm_thread_t, POINTER(POINTER(None))] + wasm_runtime_join_thread.restype = c_int32 + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1244 +for _lib in _libs.values(): + if not _lib.has("wasm_externref_obj2ref", "cdecl"): + continue + wasm_externref_obj2ref = _lib.get("wasm_externref_obj2ref", "cdecl") + wasm_externref_obj2ref.argtypes = [wasm_module_inst_t, POINTER(None), POINTER(uint32_t)] + wasm_externref_obj2ref.restype = c_bool + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1257 +for _lib in _libs.values(): + if not _lib.has("wasm_externref_ref2obj", "cdecl"): + continue + wasm_externref_ref2obj = _lib.get("wasm_externref_ref2obj", "cdecl") + wasm_externref_ref2obj.argtypes = [uint32_t, POINTER(POINTER(None))] + wasm_externref_ref2obj.restype = c_bool + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1269 +for _lib in _libs.values(): + if not _lib.has("wasm_externref_retain", "cdecl"): + continue + wasm_externref_retain = _lib.get("wasm_externref_retain", "cdecl") + wasm_externref_retain.argtypes = [uint32_t] + wasm_externref_retain.restype = c_bool + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1277 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_dump_call_stack", "cdecl"): + continue + wasm_runtime_dump_call_stack = _lib.get("wasm_runtime_dump_call_stack", "cdecl") + wasm_runtime_dump_call_stack.argtypes = [wasm_exec_env_t] + wasm_runtime_dump_call_stack.restype = None + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1288 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_get_call_stack_buf_size", "cdecl"): + continue + wasm_runtime_get_call_stack_buf_size = _lib.get("wasm_runtime_get_call_stack_buf_size", "cdecl") + wasm_runtime_get_call_stack_buf_size.argtypes = [wasm_exec_env_t] + wasm_runtime_get_call_stack_buf_size.restype = uint32_t + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1304 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_dump_call_stack_to_buf", "cdecl"): + continue + wasm_runtime_dump_call_stack_to_buf = _lib.get("wasm_runtime_dump_call_stack_to_buf", "cdecl") + wasm_runtime_dump_call_stack_to_buf.argtypes = [wasm_exec_env_t, String, uint32_t] + wasm_runtime_dump_call_stack_to_buf.restype = uint32_t + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1317 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_get_custom_section", "cdecl"): + continue + wasm_runtime_get_custom_section = _lib.get("wasm_runtime_get_custom_section", "cdecl") + wasm_runtime_get_custom_section.argtypes = [wasm_module_t, String, POINTER(uint32_t)] + wasm_runtime_get_custom_section.restype = POINTER(uint8_t) + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1326 +if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_version", "cdecl"): + wasm_runtime_get_version = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_version", "cdecl") + wasm_runtime_get_version.argtypes = [POINTER(uint32_t), POINTER(uint32_t), POINTER(uint32_t)] + wasm_runtime_get_version.restype = None + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1333 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_is_import_func_linked", "cdecl"): + continue + wasm_runtime_is_import_func_linked = _lib.get("wasm_runtime_is_import_func_linked", "cdecl") + wasm_runtime_is_import_func_linked.argtypes = [String, String] + wasm_runtime_is_import_func_linked.restype = c_bool + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1341 +for _lib in _libs.values(): + if not _lib.has("wasm_runtime_is_import_global_linked", "cdecl"): + continue + wasm_runtime_is_import_global_linked = _lib.get("wasm_runtime_is_import_global_linked", "cdecl") + wasm_runtime_is_import_global_linked.argtypes = [String, String] + wasm_runtime_is_import_global_linked.restype = c_bool + break + +# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 31 +def get_module_inst(exec_env): + return (wasm_runtime_get_module_inst (exec_env)) + +WASMModuleCommon = struct_WASMModuleCommon# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 62 + +WASMModuleInstanceCommon = struct_WASMModuleInstanceCommon# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 67 + +wasm_section_t = struct_wasm_section_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 75 + +WASMExecEnv = struct_WASMExecEnv# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 86 + +MemAllocOption = union_MemAllocOption# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 124 + +mem_alloc_info_t = struct_mem_alloc_info_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 132 + +RuntimeInitArgs = struct_RuntimeInitArgs# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 170 + +wasm_val_t = struct_wasm_val_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 199 + +# No inserted files + +# No prefix-stripping + diff --git a/language-bindings/python/src/wamr/wamrapi/wamr.py b/language-bindings/python/src/wamr/wamrapi/wamr.py new file mode 100644 index 00000000..e8d496c3 --- /dev/null +++ b/language-bindings/python/src/wamr/wamrapi/wamr.py @@ -0,0 +1,123 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +from ctypes import Array +from ctypes import c_char +from ctypes import c_uint +from ctypes import c_uint8 +from ctypes import c_void_p +from ctypes import cast +from ctypes import create_string_buffer +from ctypes import POINTER +from ctypes import pointer + +from wamr.wamrapi.iwasm import Alloc_With_Pool +from wamr.wamrapi.iwasm import RuntimeInitArgs +from wamr.wamrapi.iwasm import wasm_exec_env_t +from wamr.wamrapi.iwasm import wasm_function_inst_t +from wamr.wamrapi.iwasm import wasm_module_inst_t +from wamr.wamrapi.iwasm import wasm_module_t +from wamr.wamrapi.iwasm import wasm_runtime_call_wasm +from wamr.wamrapi.iwasm import wasm_runtime_create_exec_env +from wamr.wamrapi.iwasm import wasm_runtime_deinstantiate +from wamr.wamrapi.iwasm import wasm_runtime_destroy +from wamr.wamrapi.iwasm import wasm_runtime_destroy_exec_env +from wamr.wamrapi.iwasm import wasm_runtime_full_init +from wamr.wamrapi.iwasm import wasm_runtime_instantiate +from wamr.wamrapi.iwasm import wasm_runtime_load +from wamr.wamrapi.iwasm import wasm_runtime_lookup_function +from wamr.wamrapi.iwasm import wasm_runtime_unload + + +class Engine: + def __init__(self): + self.init_args = self._get_init_args() + wasm_runtime_full_init(pointer(self.init_args)) + + def __del__(self): + print("deleting Engine") + wasm_runtime_destroy() + + def _get_init_args(self, heap_size: int = 1024 * 512) -> RuntimeInitArgs: + init_args = RuntimeInitArgs() + init_args.mem_alloc_type = Alloc_With_Pool + init_args.mem_alloc_option.pool.heap_buf = cast( + (c_char * heap_size)(), c_void_p + ) + init_args.mem_alloc_option.pool.heap_size = heap_size + return init_args + + +class Module: + __create_key = object() + + @classmethod + def from_file(cls, engine: Engine, fp: str) -> "Module": + return Module(cls.__create_key, engine, fp) + + def __init__(self, create_key: object, engine: Engine, fp: str) -> None: + assert ( + create_key == Module.__create_key + ), "Module objects must be created using Module.from_file" + self.engine = engine + self.module, self.file_data = self._create_module(fp) + + def __del__(self): + print("deleting Module") + wasm_runtime_unload(self.module) + + def _create_module(self, fp: str) -> tuple[wasm_module_t, Array[c_uint]]: + with open(fp, "rb") as f: + data = f.read() + data = (c_uint8 * len(data))(*data) + + error_buf = create_string_buffer(128) + module = wasm_runtime_load(data, len(data), error_buf, len(error_buf)) + if not module: + raise Exception("Error while creating module") + return module, data + + +class Instance: + def __init__(self, module: Module, stack_size: int = 65536, heap_size: int = 16384): + self.module = module + self.module_inst = self._create_module_inst(module, stack_size, heap_size) + + def __del__(self): + print("deleting Instance") + wasm_runtime_deinstantiate(self.module_inst) + + def lookup_function(self, name: str): + func = wasm_runtime_lookup_function(self.module_inst, name, None) + if not func: + raise Exception("Error while looking-up function") + return func + + def _create_module_inst(self, module: Module, stack_size: int, heap_size: int) -> wasm_module_inst_t: + error_buf = create_string_buffer(128) + module_inst = wasm_runtime_instantiate( + module.module, stack_size, heap_size, error_buf, len(error_buf) + ) + if not module_inst: + raise Exception("Error while creating module instance") + return module_inst + + +class ExecEnv: + def __init__(self, module_inst: Instance, stack_size: int = 65536): + self.module_inst = module_inst + self.exec_env = self._create_exec_env(module_inst, stack_size) + + def __del__(self): + print("deleting ExecEnv") + wasm_runtime_destroy_exec_env(self.exec_env) + + def call(self, func: wasm_function_inst_t, argc: int, argv: "POINTER[c_uint]"): + if not wasm_runtime_call_wasm(self.exec_env, func, argc, argv): + raise Exception("Error while calling function") + + def _create_exec_env(self, module_inst: Instance, stack_size: int) -> wasm_exec_env_t: + exec_env = wasm_runtime_create_exec_env(module_inst.module_inst, stack_size) + if not exec_env: + raise Exception("Error while creating execution environment") + return exec_env diff --git a/language-bindings/python/wamr/__init__.py b/language-bindings/python/src/wamr/wasmcapi/__init__.py similarity index 100% rename from language-bindings/python/wamr/__init__.py rename to language-bindings/python/src/wamr/wasmcapi/__init__.py diff --git a/language-bindings/python/wamr/binding.py b/language-bindings/python/src/wamr/wasmcapi/binding.py similarity index 100% rename from language-bindings/python/wamr/binding.py rename to language-bindings/python/src/wamr/wasmcapi/binding.py diff --git a/language-bindings/python/wamr/ffi.py b/language-bindings/python/src/wamr/wasmcapi/ffi.py similarity index 99% rename from language-bindings/python/wamr/ffi.py rename to language-bindings/python/src/wamr/wasmcapi/ffi.py index a29b607c..18b6bc90 100644 --- a/language-bindings/python/wamr/ffi.py +++ b/language-bindings/python/src/wamr/wasmcapi/ffi.py @@ -36,8 +36,8 @@ 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() +root_dir = current_dir.parents[4].resolve() +wamr_dir = root_dir.resolve() if not wamr_dir.exists(): raise RuntimeError(f"not found the repo of wasm-micro-runtime under {root_dir}") diff --git a/language-bindings/python/utils/create_lib.sh b/language-bindings/python/utils/create_lib.sh new file mode 100755 index 00000000..56e829e3 --- /dev/null +++ b/language-bindings/python/utils/create_lib.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +CUR_DIR=$(cd $(dirname $0) && pwd -P) +ROOT_DIR=${CUR_DIR}/../../.. + +WAMR_BUILD_PLATFORM=${WAMR_BUILD_PLATFORM:-"linux"} + +cd ${ROOT_DIR}/product-mini/platforms/${WAMR_BUILD_PLATFORM} + +mkdir -p build && cd build +cmake .. +make -j + +cp libiwasm.so ${CUR_DIR}/../src/wamr/libs diff --git a/language-bindings/python/wamr-api/README.md b/language-bindings/python/wamr-api/README.md new file mode 100644 index 00000000..eb89b421 --- /dev/null +++ b/language-bindings/python/wamr-api/README.md @@ -0,0 +1,25 @@ +# WARM API + +## Examples + +Copy in `language-bindings/python/wamr/libs` the library `libiwasm` generated from `product-mini/platforms`. + +There is a [simple example](./samples/main.py) to show how to use bindings. + +``` +python samples/main.py +``` + +## Update WAMR API bindings + +Install requirements, + +``` +pip install -r requirements.txt +``` + +Run the following command, + +```sh +ctypesgen ../../../../core/iwasm/include/wasm_export.h -l ../libs/libiwasm.so -o iwasm.py +``` diff --git a/language-bindings/python/wamr-api/requirements.txt b/language-bindings/python/wamr-api/requirements.txt new file mode 100644 index 00000000..923575a4 --- /dev/null +++ b/language-bindings/python/wamr-api/requirements.txt @@ -0,0 +1 @@ +ctypesgen==1.1.1 \ No newline at end of file diff --git a/language-bindings/python/wamr-api/samples/compile.sh b/language-bindings/python/wamr-api/samples/compile.sh new file mode 100644 index 00000000..637b919c --- /dev/null +++ b/language-bindings/python/wamr-api/samples/compile.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +/opt/wasi-sdk/bin/clang \ + -O0 -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--strip-all,--no-entry -nostdlib \ + -Wl,--export=sum\ + -Wl,--allow-undefined \ + -o test.wasm sum.c diff --git a/language-bindings/python/wamr-api/samples/main.py b/language-bindings/python/wamr-api/samples/main.py new file mode 100644 index 00000000..525aab81 --- /dev/null +++ b/language-bindings/python/wamr-api/samples/main.py @@ -0,0 +1,22 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +from wamr.wamrapi.wamr import Engine, Module, Instance, ExecEnv +from ctypes import c_uint +import pathlib + +def main(): + engine = Engine() + module = Module.from_file(engine, pathlib.Path(__file__).parent / "sum.wasm") + module_inst = Instance(module) + exec_env = ExecEnv(module_inst) + + func = module_inst.lookup_function("sum") + + argv = (c_uint * 2)(*[10, 11]) + exec_env.call(func, len(argv), argv) + print(argv[0]) + + +if __name__ == "__main__": + main() diff --git a/language-bindings/python/wamr-api/samples/sum.c b/language-bindings/python/wamr-api/samples/sum.c new file mode 100644 index 00000000..586c5bc6 --- /dev/null +++ b/language-bindings/python/wamr-api/samples/sum.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +int +sum(int a, int b) +{ + return a + b; +} diff --git a/language-bindings/python/wasm-c-api/README.md b/language-bindings/python/wasm-c-api/README.md new file mode 100644 index 00000000..1684afa5 --- /dev/null +++ b/language-bindings/python/wasm-c-api/README.md @@ -0,0 +1,7 @@ +# WASM-C-API + +## 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/wasm-c-api/docs/design.md similarity index 100% rename from language-bindings/python/docs/design.md rename to language-bindings/python/wasm-c-api/docs/design.md diff --git a/language-bindings/python/docs/images/python_package_life_cycle.png b/language-bindings/python/wasm-c-api/docs/images/python_package_life_cycle.png similarity index 100% rename from language-bindings/python/docs/images/python_package_life_cycle.png rename to language-bindings/python/wasm-c-api/docs/images/python_package_life_cycle.png diff --git a/language-bindings/python/docs/setup_dev_env.md b/language-bindings/python/wasm-c-api/docs/setup_dev_env.md similarity index 100% rename from language-bindings/python/docs/setup_dev_env.md rename to language-bindings/python/wasm-c-api/docs/setup_dev_env.md diff --git a/language-bindings/python/requirements.txt b/language-bindings/python/wasm-c-api/requirements.txt similarity index 100% rename from language-bindings/python/requirements.txt rename to language-bindings/python/wasm-c-api/requirements.txt diff --git a/language-bindings/python/samples/hello.wat b/language-bindings/python/wasm-c-api/samples/hello.wat similarity index 100% rename from language-bindings/python/samples/hello.wat rename to language-bindings/python/wasm-c-api/samples/hello.wat diff --git a/language-bindings/python/samples/hello_oop.py b/language-bindings/python/wasm-c-api/samples/hello_oop.py similarity index 100% rename from language-bindings/python/samples/hello_oop.py rename to language-bindings/python/wasm-c-api/samples/hello_oop.py diff --git a/language-bindings/python/samples/hello_procedural.py b/language-bindings/python/wasm-c-api/samples/hello_procedural.py similarity index 98% rename from language-bindings/python/samples/hello_procedural.py rename to language-bindings/python/wasm-c-api/samples/hello_procedural.py index ed3002d5..5924423b 100644 --- a/language-bindings/python/samples/hello_procedural.py +++ b/language-bindings/python/wasm-c-api/samples/hello_procedural.py @@ -5,7 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # import ctypes -import wamr.ffi as ffi +import wamr.wasmcapi.ffi as ffi WAMS_BINARY_CONTENT = ( b"\x00asm\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01`\x00\x00\x02\x8a\x80" diff --git a/language-bindings/python/tests/__init__.py b/language-bindings/python/wasm-c-api/tests/__init__.py similarity index 100% rename from language-bindings/python/tests/__init__.py rename to language-bindings/python/wasm-c-api/tests/__init__.py diff --git a/language-bindings/python/tests/context.py b/language-bindings/python/wasm-c-api/tests/context.py similarity index 100% rename from language-bindings/python/tests/context.py rename to language-bindings/python/wasm-c-api/tests/context.py diff --git a/language-bindings/python/tests/test_advanced.py b/language-bindings/python/wasm-c-api/tests/test_advanced.py similarity index 99% rename from language-bindings/python/tests/test_advanced.py rename to language-bindings/python/wasm-c-api/tests/test_advanced.py index ad074f2b..2e1c285e 100644 --- a/language-bindings/python/tests/test_advanced.py +++ b/language-bindings/python/wasm-c-api/tests/test_advanced.py @@ -12,7 +12,7 @@ import ctypes as c import math import unittest -import wamr.ffi as ffi +import wamr.wasmcapi.ffi as ffi # It is a module likes: diff --git a/language-bindings/python/tests/test_basic.py b/language-bindings/python/wasm-c-api/tests/test_basic.py similarity index 99% rename from language-bindings/python/tests/test_basic.py rename to language-bindings/python/wasm-c-api/tests/test_basic.py index 556162bd..632ad512 100644 --- a/language-bindings/python/tests/test_basic.py +++ b/language-bindings/python/wasm-c-api/tests/test_basic.py @@ -12,7 +12,7 @@ import ctypes as c import unittest from venv import create -from wamr.ffi import * +from wamr.wasmcapi.ffi import * # It is a module likes: # (module diff --git a/language-bindings/python/utils/bindgen.py b/language-bindings/python/wasm-c-api/utils/bindgen.py similarity index 98% rename from language-bindings/python/utils/bindgen.py rename to language-bindings/python/wasm-c-api/utils/bindgen.py index 6371ca65..a505404d 100644 --- a/language-bindings/python/utils/bindgen.py +++ b/language-bindings/python/wasm-c-api/utils/bindgen.py @@ -21,7 +21,7 @@ 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" +BINDING_PATH = "language-bindings/python/wamr/wasmcapi/binding.py" # 4 spaces as default indent INDENT = " " @@ -314,7 +314,7 @@ class Visitor(c_ast.NodeVisitor): def preflight_check(workspace): - wamr_repo = workspace.joinpath("wasm-micro-runtime") + wamr_repo = workspace file_check_list = [ wamr_repo.exists(), wamr_repo.joinpath(WASM_C_API_HEADER).exists(), @@ -369,12 +369,12 @@ def main(): current_file = pathlib.Path(os.readlink(current_file)) current_dir = current_file.parent.resolve() - root_dir = current_dir.joinpath("..").resolve() + root_dir = current_dir.joinpath("../../../..").resolve() if not preflight_check(root_dir): return False - wamr_repo = root_dir.joinpath("wasm-micro-runtime") + wamr_repo = root_dir 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)) diff --git a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp index 7cb9c3f4..30274359 100644 --- a/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp @@ -277,7 +277,6 @@ static void handle_cmd_unload_module(uint64 *args, uint32 argc) { EnclaveModule *enclave_module = *(EnclaveModule **)args++; - uint32 i; bh_assert(argc == 1); diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 06fd3209..8727ed38 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -32,12 +32,28 @@ print_help() #if WASM_ENABLE_LOG != 0 printf(" -v=n Set log verbose level (0 to 5, default is 2) larger\n" " level with more log\n"); +#endif +#if WASM_ENABLE_INTERP != 0 + printf(" --interp Run the wasm app with interpreter mode\n"); +#endif +#if WASM_ENABLE_FAST_JIT != 0 + printf(" --fast-jit Run the wasm app with fast jit mode\n"); +#endif +#if WASM_ENABLE_JIT != 0 + printf(" --llvm-jit Run the wasm app with llvm jit mode\n"); +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + printf(" --multi-tier-jit Run the wasm app with multi-tier jit mode\n"); #endif printf(" --stack-size=n Set maximum stack size in bytes, default is 64 KB\n"); printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); #if WASM_ENABLE_FAST_JIT != 0 printf(" --jit-codecache-size=n Set fast jit maximum code cache size in bytes,\n"); printf(" default is %u KB\n", FAST_JIT_DEFAULT_CODE_CACHE_SIZE / 1024); +#endif +#if WASM_ENABLE_JIT != 0 + printf(" --llvm-jit-size-level=n Set LLVM JIT size level, default is 3\n"); + printf(" --llvm-jit-opt-level=n Set LLVM JIT optimization level, default is 3\n"); #endif printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of \"FUNC ARG...\"\n"); @@ -347,9 +363,14 @@ main(int argc, char *argv[]) uint32 stack_size = 64 * 1024, heap_size = 16 * 1024; #if WASM_ENABLE_FAST_JIT != 0 uint32 jit_code_cache_size = FAST_JIT_DEFAULT_CODE_CACHE_SIZE; +#endif +#if WASM_ENABLE_JIT != 0 + uint32 llvm_jit_size_level = 3; + uint32 llvm_jit_opt_level = 3; #endif wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; + RunningMode running_mode = 0; RuntimeInitArgs init_args; char error_buf[128] = { 0 }; #if WASM_ENABLE_LOG != 0 @@ -387,6 +408,27 @@ main(int argc, char *argv[]) } func_name = argv[0]; } +#if WASM_ENABLE_INTERP != 0 + else if (!strcmp(argv[0], "--interp")) { + running_mode = Mode_Interp; + } +#endif +#if WASM_ENABLE_FAST_JIT != 0 + else if (!strcmp(argv[0], "--fast-jit")) { + running_mode = Mode_Fast_JIT; + } +#endif +#if WASM_ENABLE_JIT != 0 + else if (!strcmp(argv[0], "--llvm-jit")) { + running_mode = Mode_LLVM_JIT; + } +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + else if (!strcmp(argv[0], "--multi-tier-jit")) { + running_mode = Mode_Multi_Tier_JIT; + } +#endif #if WASM_ENABLE_LOG != 0 else if (!strncmp(argv[0], "-v=", 3)) { log_verbose_level = atoi(argv[0] + 3); @@ -414,6 +456,38 @@ main(int argc, char *argv[]) jit_code_cache_size = atoi(argv[0] + 21); } #endif +#if WASM_ENABLE_JIT != 0 + else if (!strncmp(argv[0], "--llvm-jit-size-level=", 22)) { + if (argv[0][22] == '\0') + return print_help(); + llvm_jit_size_level = atoi(argv[0] + 22); + if (llvm_jit_size_level < 1) { + printf("LLVM JIT size level shouldn't be smaller than 1, " + "setting it to 1\n"); + llvm_jit_size_level = 1; + } + else if (llvm_jit_size_level > 3) { + printf("LLVM JIT size level shouldn't be greater than 3, " + "setting it to 3\n"); + llvm_jit_size_level = 3; + } + } + else if (!strncmp(argv[0], "--llvm-jit-opt-level=", 21)) { + if (argv[0][21] == '\0') + return print_help(); + llvm_jit_opt_level = atoi(argv[0] + 21); + if (llvm_jit_opt_level < 1) { + printf("LLVM JIT opt level shouldn't be smaller than 1, " + "setting it to 1\n"); + llvm_jit_opt_level = 1; + } + else if (llvm_jit_opt_level > 3) { + printf("LLVM JIT opt level shouldn't be greater than 3, " + "setting it to 3\n"); + llvm_jit_opt_level = 3; + } + } +#endif #if WASM_ENABLE_LIBC_WASI != 0 else if (!strncmp(argv[0], "--dir=", 6)) { if (argv[0][6] == '\0') @@ -539,6 +613,7 @@ main(int argc, char *argv[]) memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.running_mode = running_mode; #if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 init_args.mem_alloc_type = Alloc_With_Pool; init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; @@ -554,6 +629,11 @@ main(int argc, char *argv[]) init_args.fast_jit_code_cache_size = jit_code_cache_size; #endif +#if WASM_ENABLE_JIT != 0 + init_args.llvm_jit_size_level = llvm_jit_size_level; + init_args.llvm_jit_opt_level = llvm_jit_opt_level; +#endif + #if WASM_ENABLE_DEBUG_INTERP != 0 init_args.instance_port = instance_port; if (ip_addr) diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index 6de76cca..05647b5d 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -26,9 +26,25 @@ print_help() #if WASM_ENABLE_LOG != 0 printf(" -v=n Set log verbose level (0 to 5, default is 2) larger\n" " level with more log\n"); +#endif +#if WASM_ENABLE_INTERP != 0 + printf(" --interp Run the wasm app with interpreter mode\n"); +#endif +#if WASM_ENABLE_FAST_JIT != 0 + printf(" --fast-jit Run the wasm app with fast jit mode\n"); +#endif +#if WASM_ENABLE_JIT != 0 + printf(" --llvm-jit Run the wasm app with llvm jit mode\n"); +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 + printf(" --multi-tier-jit Run the wasm app with multi-tier jit mode\n"); #endif printf(" --stack-size=n Set maximum stack size in bytes, default is 64 KB\n"); printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); +#if WASM_ENABLE_JIT != 0 + printf(" --llvm-jit-size-level=n Set LLVM JIT size level, default is 3\n"); + printf(" --llvm-jit-opt-level=n Set LLVM JIT optimization level, default is 3\n"); +#endif printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of `FUNC ARG...`\n"); #if WASM_ENABLE_LIBC_WASI != 0 @@ -228,8 +244,13 @@ main(int argc, char *argv[]) uint8 *wasm_file_buf = NULL; uint32 wasm_file_size; uint32 stack_size = 64 * 1024, heap_size = 16 * 1024; +#if WASM_ENABLE_JIT != 0 + uint32 llvm_jit_size_level = 3; + uint32 llvm_jit_opt_level = 3; +#endif wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; + RunningMode running_mode = 0; RuntimeInitArgs init_args; char error_buf[128] = { 0 }; #if WASM_ENABLE_LOG != 0 @@ -257,6 +278,26 @@ main(int argc, char *argv[]) } func_name = argv[0]; } +#if WASM_ENABLE_INTERP != 0 + else if (!strcmp(argv[0], "--interp")) { + running_mode = Mode_Interp; + } +#endif +#if WASM_ENABLE_FAST_JIT != 0 + else if (!strcmp(argv[0], "--fast-jit")) { + running_mode = Mode_Fast_JIT; + } +#endif +#if WASM_ENABLE_JIT != 0 + else if (!strcmp(argv[0], "--llvm-jit")) { + running_mode = Mode_LLVM_JIT; + } +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 + else if (!strcmp(argv[0], "--multi-tier-jit")) { + running_mode = Mode_Multi_Tier_JIT; + } +#endif #if WASM_ENABLE_LOG != 0 else if (!strncmp(argv[0], "-v=", 3)) { log_verbose_level = atoi(argv[0] + 3); @@ -277,6 +318,38 @@ main(int argc, char *argv[]) return print_help(); heap_size = atoi(argv[0] + 12); } +#if WASM_ENABLE_JIT != 0 + else if (!strncmp(argv[0], "--llvm-jit-size-level=", 22)) { + if (argv[0][22] == '\0') + return print_help(); + llvm_jit_size_level = atoi(argv[0] + 22); + if (llvm_jit_size_level < 1) { + printf("LLVM JIT size level shouldn't be smaller than 1, " + "setting it to 1\n"); + llvm_jit_size_level = 1; + } + else if (llvm_jit_size_level > 3) { + printf("LLVM JIT size level shouldn't be greater than 3, " + "setting it to 3\n"); + llvm_jit_size_level = 3; + } + } + else if (!strncmp(argv[0], "--llvm-jit-opt-level=", 21)) { + if (argv[0][21] == '\0') + return print_help(); + llvm_jit_opt_level = atoi(argv[0] + 21); + if (llvm_jit_opt_level < 1) { + printf("LLVM JIT opt level shouldn't be smaller than 1, " + "setting it to 1\n"); + llvm_jit_opt_level = 1; + } + else if (llvm_jit_opt_level > 3) { + printf("LLVM JIT opt level shouldn't be greater than 3, " + "setting it to 3\n"); + llvm_jit_opt_level = 3; + } + } +#endif #if WASM_ENABLE_LIBC_WASI != 0 else if (!strncmp(argv[0], "--dir=", 6)) { if (argv[0][6] == '\0') @@ -357,6 +430,7 @@ main(int argc, char *argv[]) memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.running_mode = running_mode; #if WASM_ENABLE_GLOBAL_HEAP_POOL != 0 init_args.mem_alloc_type = Alloc_With_Pool; init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; @@ -368,6 +442,11 @@ main(int argc, char *argv[]) init_args.mem_alloc_option.allocator.free_func = free; #endif +#if WASM_ENABLE_JIT != 0 + init_args.llvm_jit_size_level = llvm_jit_size_level; + init_args.llvm_jit_opt_level = llvm_jit_opt_level; +#endif + #if WASM_ENABLE_DEBUG_INTERP != 0 init_args.instance_port = instance_port; if (ip_addr) diff --git a/samples/file/wasm-app/main.c b/samples/file/wasm-app/main.c index caf6436d..f4363475 100644 --- a/samples/file/wasm-app/main.c +++ b/samples/file/wasm-app/main.c @@ -18,7 +18,7 @@ #define WORLD_OFFSET 7 #define NAME_REPLACMENT "James" #define NAME_REPLACMENT_LEN (sizeof(NAME_REPLACMENT) - 1) -#define ADDITIONAL_SPACE 10 +#define ADDITIONAL_SPACE 1 * 1024 * 1024 int main(int argc, char **argv) @@ -100,7 +100,7 @@ main(int argc, char **argv) printf("[Test] Reading at specified offset passed.\n"); // Test: allocate more space to the file (posix_fallocate) - printf("Allocate more space to the file..\n"); + printf("Allocate more space to the file (posix_fallocate)..\n"); posix_fallocate(fileno(file), ftell(file), ADDITIONAL_SPACE); printf("File current offset: %ld\n", ftell(file)); printf("Moving to the end..\n"); @@ -110,8 +110,8 @@ main(int argc, char **argv) printf("[Test] Allocation or more space passed.\n"); // Test: allocate more space to the file (ftruncate) - printf("Extend the file size of 10 bytes using ftruncate..\n"); - ftruncate(fileno(file), ftell(file) + 10); + printf("Allocate more space to the file (ftruncate)..\n"); + ftruncate(fileno(file), ftell(file) + ADDITIONAL_SPACE); assert(ftell(file) == strlen(text) + ADDITIONAL_SPACE); printf("File current offset: %ld\n", ftell(file)); printf("Moving to the end..\n"); @@ -120,6 +120,31 @@ main(int argc, char **argv) assert(ftell(file) == strlen(text) + 2 * ADDITIONAL_SPACE); printf("[Test] Extension of the file size passed.\n"); + // Test: allocate more space to the file (fseek) + printf("Allocate more space to the file (fseek) from the start..\n"); + printf("File current offset: %ld\n", ftell(file)); + fseek(file, 3 * ADDITIONAL_SPACE, SEEK_SET); + printf("File current offset: %ld\n", ftell(file)); + assert(ftell(file) == 3 * ADDITIONAL_SPACE); + printf("[Test] Extension of the file size passed.\n"); + + // Test: allocate more space to the file (fseek) + printf("Allocate more space to the file (fseek) from the end..\n"); + printf("File current offset: %ld\n", ftell(file)); + fseek(file, ADDITIONAL_SPACE, SEEK_END); + printf("File current offset: %ld\n", ftell(file)); + assert(ftell(file) == 4 * ADDITIONAL_SPACE); + printf("[Test] Extension of the file size passed.\n"); + + // Test: allocate more space to the file (fseek) + printf("Allocate more space to the file (fseek) from the middle..\n"); + fseek(file, 3 * ADDITIONAL_SPACE, SEEK_SET); + printf("File current offset: %ld\n", ftell(file)); + fseek(file, 2 * ADDITIONAL_SPACE, SEEK_CUR); + printf("File current offset: %ld\n", ftell(file)); + assert(ftell(file) == 5 * ADDITIONAL_SPACE); + printf("[Test] Extension of the file size passed.\n"); + // Display some debug information printf("Getting the size of the file on disk..\n"); struct stat st; diff --git a/samples/multi-thread/wasm-apps/CMakeLists.txt b/samples/multi-thread/wasm-apps/CMakeLists.txt index ec8f7eef..d7352e42 100644 --- a/samples/multi-thread/wasm-apps/CMakeLists.txt +++ b/samples/multi-thread/wasm-apps/CMakeLists.txt @@ -41,3 +41,6 @@ target_link_libraries(test.wasm) add_executable(main_thread_exception.wasm main_thread_exception.c) target_link_libraries(main_thread_exception.wasm) + +add_executable(main_global_atomic.wasm main_global_atomic.c) +target_link_libraries(main_global_atomic.wasm) \ No newline at end of file diff --git a/samples/multi-thread/wasm-apps/main_global_atomic.c b/samples/multi-thread/wasm-apps/main_global_atomic.c new file mode 100644 index 00000000..dafbea88 --- /dev/null +++ b/samples/multi-thread/wasm-apps/main_global_atomic.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include + +#define MAX_NUM_THREADS 4 +#define NUM_ITER 1000 + +int g_count = 0; + +static void * +thread(void *arg) +{ + for (int i = 0; i < NUM_ITER; i++) { + __atomic_fetch_add(&g_count, 1, __ATOMIC_SEQ_CST); + } + + return NULL; +} + +int +main(int argc, char **argv) +{ + pthread_t tids[MAX_NUM_THREADS]; + + for (int i = 0; i < MAX_NUM_THREADS; i++) { + if (pthread_create(&tids[i], NULL, thread, NULL) != 0) { + printf("Thread creation failed\n"); + } + } + + for (int i = 0; i < MAX_NUM_THREADS; i++) { + if (pthread_join(tids[i], NULL) != 0) { + printf("Thread join failed\n"); + } + } + + printf("Value of counter after update: %d (expected=%d)\n", g_count, + MAX_NUM_THREADS * NUM_ITER); + if (g_count != MAX_NUM_THREADS * NUM_ITER) { + __builtin_trap(); + } + + return -1; +} \ No newline at end of file diff --git a/samples/wasm-c-api-imports/.gitignore b/samples/wasm-c-api-imports/.gitignore new file mode 100644 index 00000000..ab998a6e --- /dev/null +++ b/samples/wasm-c-api-imports/.gitignore @@ -0,0 +1,2 @@ +/wasm/inc/** +!/wasm/inc/.* diff --git a/samples/wasm-c-api-imports/CMakeLists.txt b/samples/wasm-c-api-imports/CMakeLists.txt new file mode 100644 index 00000000..7d65c9b2 --- /dev/null +++ b/samples/wasm-c-api-imports/CMakeLists.txt @@ -0,0 +1,169 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) +project(how-to-deal-with-import) + +include(CMakePrintHelpers) +include(CTest) +include(ExternalProject) +include(FetchContent) + +# +# dependencies +# +set(WAMR_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../) +# wasm required headers +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${WARM_ROOT}/${WAMR_ROOT}/wamr-sdk/app/libc-builtin-sysroot/include/pthread.h + ${CMAKE_CURRENT_LIST_DIR}/wasm/inc +) + +# vmlib +################ runtime settings ################ +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +if (APPLE) + add_definitions(-DBH_PLATFORM_DARWIN) +endif () + +# Resetdefault linker flags +set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# WAMR features switch + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Release) +endif () + +set(WAMR_BUILD_AOT 1) +set(WAMR_BUILD_INTERP 0) +set(WAMR_BUILD_JIT 0) + +set(WAMR_BUILD_FAST_INTERP 1) +set(WAMR_BUILD_LIB_PTHREAD 1) +set(WAMR_BUILD_LIBC_BUILTIN 1) +set(WAMR_BUILD_LIBC_WASI 1) +set(WAMR_BUILD_SIMD 0) + +# compiling and linking flags +if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") +endif () +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") + +# build out vmlib +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +target_link_libraries(vmlib INTERFACE dl m pthread) +if(WAMR_BUILD_AOT EQUAL 1) + target_compile_definitions(vmlib INTERFACE -DWASM_ENABLE_AOT=1) +else() + target_compile_definitions(vmlib INTERFACE -DWASM_ENABLE_AOT=0) +endif() + +if(WAMR_BUILD_INTERP EQUAL 1) + target_compile_definitions(vmlib INTERFACE -DWASM_ENABLE_INTERP=1) +else() + target_compile_definitions(vmlib INTERFACE -DWASM_ENABLE_INTERP=0) +endif() + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + # ASAN + UBSAN + target_compile_options(vmlib INTERFACE -fsanitize=address,undefined) + target_link_options(vmlib INTERFACE -fsanitize=address,undefined) +endif() + +# # MSAN +# target_compile_options(vmlib INTERFACE -fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer) +# target_link_options(vmlib INTERFACE -fsanitize=memory) + +# wamrc +if(WAMR_BUILD_AOT EQUAL 1 AND WAMR_BUILD_INTERP EQUAL 0) + ExternalProject_Add(wamrc + PREFIX wamrc-build + SOURCE_DIR ${WAMR_ROOT}/wamr-compiler + CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${WAMR_ROOT}/wamr-compiler -B build + BUILD_COMMAND ${CMAKE_COMMAND} --build build --target wamrc + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different build/wamrc ${CMAKE_CURRENT_BINARY_DIR}/wamrc + ) +endif() + +# +# host +add_subdirectory(host) +add_custom_target( + install_host ALL + COMMAND ${CMAKE_COMMAND} -E copy_if_different ./host/example1 . + DEPENDS example1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) + +# TODO: replace it with a find_package() +set(WASI_SDK_DIR /opt/wasi-sdk-19.0/) +set(WASI_TOOLCHAIN_FILE ${WASI_SDK_DIR}/share/cmake/wasi-sdk.cmake) +set(WASI_SYS_ROOT ${WASI_SDK_DIR}/share/wasi-sysroot) + +# +# wasm +if(WAMR_BUILD_AOT EQUAL 1 AND WAMR_BUILD_INTERP EQUAL 0) + ExternalProject_Add(wasm + PREFIX wasm-build + DEPENDS wamrc + BUILD_ALWAYS TRUE + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/wasm + CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_LIST_DIR}/wasm -B build + -DWASI_SDK_PREFIX=${WASI_SDK_DIR} + -DCMAKE_TOOLCHAIN_FILE=${WASI_TOOLCHAIN_FILE} + -DCMAKE_SYSROOT=${WASI_SYS_ROOT} + -DWASM_TO_AOT=ON + -DWAMRC_PATH=${CMAKE_CURRENT_BINARY_DIR}/wamrc + -DSOCKET_WASI_CMAKE=${WAMR_ROOT}/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake + BUILD_COMMAND ${CMAKE_COMMAND} --build build + INSTALL_COMMAND ${CMAKE_COMMAND} --install build --prefix ${CMAKE_CURRENT_BINARY_DIR} + ) +else() + ExternalProject_Add(wasm + PREFIX wasm-build + BUILD_ALWAYS TRUE + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/wasm + CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_LIST_DIR}/wasm -B build + -DWASI_SDK_PREFIX=${WASI_SDK_DIR} + -DCMAKE_TOOLCHAIN_FILE=${WASI_TOOLCHAIN_FILE} + -DCMAKE_SYSROOT=${WASI_SYS_ROOT} + -DSOCKET_WASI_CMAKE=${WAMR_ROOT}/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake + BUILD_COMMAND ${CMAKE_COMMAND} --build build + INSTALL_COMMAND ${CMAKE_COMMAND} --install build --prefix ${CMAKE_CURRENT_BINARY_DIR} + ) +endif() + +# +# Test +# +add_test( + NAME run_example1 + COMMAND ./example1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) diff --git a/samples/wasm-c-api-imports/README.md b/samples/wasm-c-api-imports/README.md new file mode 100644 index 00000000..9b61a6e7 --- /dev/null +++ b/samples/wasm-c-api-imports/README.md @@ -0,0 +1,174 @@ +# How to create `imports` for wasm_instance_new() properly + +It's always been asked how to create `wasm_extern_vec_t *imports` for +`wasm_instance_new()`? + +```c +WASM_API_EXTERN own wasm_instance_t* wasm_instance_new( + wasm_store_t*, const wasm_module_t*, const wasm_extern_vec_t *imports, + own wasm_trap_t** trap +); +``` + +`wasm_extern_vec_t *imports` is required to match the requirement of _the +import section_ of a .wasm. + +```bash +$ /opt/wabt-1.0.31/bin/wasm-objdump -j Import -x .wasm + +Section Details: + +Import[27]: + - func[0] sig=2 <- env.pthread_mutex_lock + - func[1] sig=2 <- env.pthread_mutex_unlock + - func[2] sig=2 <- env.pthread_cond_signal + - func[3] sig=3 <- env.log + ... + - func[11] sig=4 <__imported_wasi_snapshot_preview1_sock_bind> <- wasi_snapshot_preview1.sock_bind + - func[12] sig=4 <__imported_wasi_snapshot_preview1_sock_connect> <- wasi_snapshot_preview1.sock_connect + - func[13] sig=4 <__imported_wasi_snapshot_preview1_sock_listen> <- wasi_snapshot_preview1.sock_listen + - func[14] sig=5 <__imported_wasi_snapshot_preview1_sock_open> <- wasi_snapshot_preview1.sock_open + - func[15] sig=4 <__imported_wasi_snapshot_preview1_sock_addr_remote> <- wasi_snapshot_preview1.sock_addr_remote + - func[16] sig=4 <__imported_wasi_snapshot_preview1_args_get> <- wasi_snapshot_preview1.args_get + - func[17] sig=4 <__imported_wasi_snapshot_preview1_args_sizes_get> <- wasi_snapshot_preview1.args_sizes_get + ... +``` + +Developers should fill in _imports_ with enough host functions and make sure +there are no linking problems during instantiation. + +```bash +TODO: linking warnings +``` + +## A natural way + +One natural answer is "to create a list which matches every item in _the import +section_" of the .wasm. Since developers can see the section details of +a .wasm by tools like _wasm-objdump_, the answer is doable. Most of the time, +if they also prepare Wasm modules, developers have full control over import +requirements, and they only need to take a look at the order of _the import +section_. + +Yes, _the order_. A proper `wasm_extern_vec_t *imports` includes two things: + +1. how many `wasm_extern_t` +2. and order of those + +Because there is no "name information" in a `wasm_extern_t`. The only way is let +`wasm_instance_new()` to tell which item in _the import section_ of a .wasm +should match any item in `wasm_extern_vec_t *imports` is based on **_index_**. + +The algorithm is quite straightforward. The first one of _the import section_ matches +`wasm_extern_vec_t *imports->data[0] `. The second one matches `wasm_extern_vec_t *imports->data[1]`. +And so on. + +So the order of `wasm_extern_vec_t *imports` becomes quite a burden. It requires +developers always checking _the import section_ visually. + +Until here, the natural way is still workable although involving some handy work. +Right? + +## A blocker + +Sorry, the situation changes a lot when driving wasm32-wasi Wasm modules with +wasm-c-api. + +As you know, WASI provides _a set of crossing-platform standard libraries_ for +Wasm modules, and leaves some _interfaces_ for native platform-dependent supports. +Those _interfaces_ are those import items with the module name `wasi_snapshot_preview1` +in a Wasm module. + +It seems not economical to let developers provide their version of host +implementations of the `wasi_snapshot_preview1.XXX` functions. All those support +should be packed into a common library and shared in different Wasm modules. +Like a [cargo WASI](https://github.com/bytecodealliance/cargo-wasi). + +WAMR chooses to integrate the WASI support library in the runtime to reduce +developers' compilation work. It brings developers a new thing of a proper +`wasm_extern_vec_t *imports` that developers should avoid overwriting those items +of _the import section_ of a Wasm module that will be provided by the runtime. It +also not economical to code for those functions. + +Using module names as a filter seems to be a simple way. But some private +additional c/c++ libraries are supported in WAMR. Those supporting will bring +more import items that don't use `wasi_snapshot_preview1` as module names but are still +covered by the WASM runtime. Like `env.pthread_`. Plus, [the native lib registeration](https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/export_native_api.md) +provides another possible way to fill in the requirement of _the import section_. + +Let's take summarize. A proper `wasm_extern_vec_t *imports` should include: + +1. provides all necessary host implementations for items in _the import section_ +2. should not override runtime provided implementation or covered by native + registrations. functinal or econmical. +3. keep them in a right order + +## A recommendation + +The recommendation is: + +- use `wasm_module_imports()` to build the order +- use `wasm_importtype_is_linked()` to avoid overwriting + +[wasm-c-api-imports](.) is a simple showcase of how to do that. + +First, let's take a look at the Wasm module. [send_recv](./wasm/send_recv.c) +uses both standard WASI and WAMR_BUILD_LIB_PTHREAD supporting. Plus a private +native function `host_log`. + +So, `wasm_extern_vec_t *imports` should only include the host implementation of +`host_log` and avoid WASI related(`wasm-c-api-imports.XXX`) and pthread related(`env.pthread_XXX`). + +[Here is how to do](./host/example1.c): + +- get import types with `wasm_module_imports(0)`. it contains name information + +```c + wasm_importtype_vec_t importtypes = { 0 }; + wasm_module_imports(module, &importtypes); +``` + +- traversal import types. The final `wasm_importvec_t *imports` should have the + same order with `wasm_importtype_vec_t` + +```c + for (unsigned i = 0; i < importtypes.num_elems; i++) +``` + +- use `wasm_importtype_is_linked()` to avoid those covered by the runtime and + registered natives. A little tip is use "wasm_extern_new_empty()" to create + a placeholder. + +```c + /* use wasm_extern_new_empty() to create a placeholder */ + if (wasm_importtype_is_linked(importtype)) { + externs[i] = wasm_extern_new_empty( + store, wasm_externtype_kind(wasm_importtype_type(importtype))); + continue; + } +``` + +- use `wasm_importtype_module()` to get the module name, use `wasm_importtype_name()` + to get the field name. + +```c + const wasm_name_t *module_name = + wasm_importtype_module(importtypes.data[i]); + const wasm_name_t *field_name = + wasm_importtype_name(importtypes.data[i]); +``` + +- fill in `wasm_externvec_t *imports` dynamically and programmatically. + +```c + if (strncmp(module_name->data, "env", strlen("env")) == 0 + && strncmp(field_name->data, "log", strlen("log")) == 0) { + wasm_functype_t *log_type = wasm_functype_new_2_0( + wasm_valtype_new_i64(), wasm_valtype_new_i32()); + wasm_func_t *log_func = wasm_func_new(store, log_type, host_logs); + wasm_functype_delete(log_type); + + externs[i] = wasm_func_as_extern(log_func); + } + } +``` diff --git a/samples/wasm-c-api-imports/host/CMakeLists.txt b/samples/wasm-c-api-imports/host/CMakeLists.txt new file mode 100644 index 00000000..e2636f09 --- /dev/null +++ b/samples/wasm-c-api-imports/host/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) +project(host) + +set(CMAKE_BUILD_TYPE Debug) + +# +# host +add_executable(example1 ./example1.c) +target_link_libraries(example1 vmlib) diff --git a/samples/wasm-c-api-imports/host/example1.c b/samples/wasm-c-api-imports/host/example1.c new file mode 100644 index 00000000..ccf574d7 --- /dev/null +++ b/samples/wasm-c-api-imports/host/example1.c @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include "wasm_c_api.h" +#include "wasm_export.h" + +static wasm_trap_t * +host_logs(const wasm_val_vec_t *args, wasm_val_vec_t *results) +{ + return NULL; +} + +static bool +build_imports(wasm_store_t *store, const wasm_module_t *module, + wasm_extern_vec_t *out) +{ + wasm_importtype_vec_t importtypes = { 0 }; + wasm_module_imports(module, &importtypes); + + wasm_extern_t *externs[32] = { 0 }; + + for (unsigned i = 0; i < importtypes.num_elems; i++) { + wasm_importtype_t *importtype = importtypes.data[i]; + + /* use wasm_extern_new_empty() to create a placeholder */ + if (wasm_importtype_is_linked(importtype)) { + externs[i] = wasm_extern_new_empty( + store, wasm_externtype_kind(wasm_importtype_type(importtype))); + continue; + } + + const wasm_name_t *module_name = + wasm_importtype_module(importtypes.data[i]); + const wasm_name_t *field_name = + wasm_importtype_name(importtypes.data[i]); + + if (strncmp(module_name->data, "env", strlen("env")) == 0 + && strncmp(field_name->data, "log", strlen("log")) == 0) { + wasm_functype_t *log_type = wasm_functype_new_2_0( + wasm_valtype_new_i64(), wasm_valtype_new_i32()); + wasm_func_t *log_func = wasm_func_new(store, log_type, host_logs); + wasm_functype_delete(log_type); + + externs[i] = wasm_func_as_extern(log_func); + } + } + + wasm_extern_vec_new(out, importtypes.num_elems, externs); + wasm_importtype_vec_delete(&importtypes); + return true; +} + +int +main() +{ + int main_ret = EXIT_FAILURE; + + // Initialize. + printf("Initializing...\n"); + wasm_engine_t *engine = wasm_engine_new(); + if (!engine) + goto quit; + + wasm_store_t *store = wasm_store_new(engine); + if (!store) + goto delete_engine; + + // Load binary. + printf("Loading binary...\n"); +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0 + FILE *file = fopen("send_recv.aot", "rb"); + printf("> Load .aot\n"); +#else + FILE *file = fopen("send_recv.wasm", "rb"); + printf("> Load .wasm\n"); +#endif + if (!file) { + printf("> Error loading module!\n"); + goto delete_store; + } + + int ret = fseek(file, 0L, SEEK_END); + if (ret == -1) { + printf("> Error loading module!\n"); + goto close_file; + } + + long file_size = ftell(file); + if (file_size == -1) { + printf("> Error loading module!\n"); + goto close_file; + } + + ret = fseek(file, 0L, SEEK_SET); + if (ret == -1) { + printf("> Error loading module!\n"); + goto close_file; + } + + wasm_byte_vec_t binary; + wasm_byte_vec_new_uninitialized(&binary, file_size); + + if (fread(binary.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + goto delete_binary; + } + + // Compile. + printf("Compiling module...\n"); + wasm_module_t *module = wasm_module_new(store, &binary); + if (!module) { + printf("> Error compiling module!\n"); + goto delete_binary; + } + + // Set Wasi Context + const char *addr_pool[1] = { "127.0.0.1" }; + wasm_runtime_set_wasi_addr_pool(*module, addr_pool, 1); + + // Instantiate. + printf("Instantiating module...\n"); + wasm_extern_vec_t imports = { 0 }; + ret = build_imports(store, module, &imports); + if (!ret) { + printf("> Error building imports!\n"); + goto delete_module; + } + + wasm_instance_t *instance = + wasm_instance_new(store, module, &imports, NULL); + if (!instance) { + printf("> Error instantiating module!\n"); + goto delete_imports; + } + + // Extract export. + printf("Extracting export...\n"); + wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + if (exports.size == 0) { + printf("> Error accessing exports!\n"); + goto delete_instance; + } + + /** + * should use information from wasm_module_exports to avoid hard coding "1" + */ + const wasm_func_t *start_func = wasm_extern_as_func(exports.data[1]); + if (start_func == NULL) { + printf("> Error accessing export!\n"); + goto delete_exports; + } + + // Call. "_start(nil) -> i32" + printf("Calling _start ...\n"); + wasm_val_t rs[1] = { WASM_I32_VAL(0) }; + wasm_val_vec_t args = WASM_EMPTY_VEC; + wasm_val_vec_t results = WASM_ARRAY_VEC(rs); + wasm_trap_t *trap = wasm_func_call(start_func, &args, &results); + if (trap) { + wasm_name_t message = { 0 }; + wasm_trap_message(trap, &message); + + printf("> Error calling function! %s\n", message.data); + + wasm_name_delete(&message); + wasm_trap_delete(trap); + goto delete_exports; + } + + // Print result. + printf("Printing result...\n"); + printf("> %u\n", rs[0].of.i32); + + // Shut down. + printf("Shutting down...\n"); + + // All done. + printf("Done.\n"); + main_ret = EXIT_SUCCESS; + +delete_exports: + wasm_extern_vec_delete(&exports); +delete_instance: + wasm_instance_delete(instance); +delete_imports: + wasm_extern_vec_delete(&imports); +delete_module: + wasm_module_delete(module); +delete_binary: + wasm_byte_vec_delete(&binary); +close_file: + fclose(file); +delete_store: + wasm_store_delete(store); +delete_engine: + wasm_engine_delete(engine); +quit: + return main_ret; +} \ No newline at end of file diff --git a/samples/wasm-c-api-imports/wasm/CMakeLists.txt b/samples/wasm-c-api-imports/wasm/CMakeLists.txt new file mode 100644 index 00000000..6b2743cb --- /dev/null +++ b/samples/wasm-c-api-imports/wasm/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) +project(wasm_modules) + +if(NOT SOCKET_WASI_CMAKE) + message(FATAL_ERROR "Require SOCKET_WASI_CMAKE") +endif() + +option(WASM_TO_AOT "transfer wasm to aot" OFF) +if(WASM_TO_AOT AND NOT WAMRC_PATH) + message(FATAL_ERROR "Require WAMRC_PATH when WASM_TO_AOT is ON") +endif() + +# +# c -> wasm +include(${SOCKET_WASI_CMAKE}) +add_executable(send_recv ${CMAKE_CURRENT_LIST_DIR}/send_recv.c) +set_target_properties(send_recv PROPERTIES SUFFIX .wasm) +target_include_directories(send_recv PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc) +target_link_libraries(send_recv socket_wasi_ext) +target_link_options(send_recv PRIVATE + LINKER:--export=__heap_base + LINKER:--export=__data_end + LINKER:--shared-memory,--max-memory=196608 + LINKER:--no-check-features + LINKER:--allow-undefined +) + +if(WASM_TO_AOT) + # wasm -> aot + add_custom_target(send_recv_aot ALL + COMMAND pwd && ${WAMRC_PATH} --enable-multi-thread -o ./send_recv.aot ./send_recv.wasm + DEPENDS send_recv + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) +endif() + +# +# install +if(WASM_TO_AOT) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/send_recv.aot DESTINATION . ) +else() + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/send_recv.wasm DESTINATION . ) +endif() + diff --git a/samples/wasm-c-api-imports/wasm/inc/.gitkeep b/samples/wasm-c-api-imports/wasm/inc/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/samples/wasm-c-api-imports/wasm/send_recv.c b/samples/wasm-c-api-imports/wasm/send_recv.c new file mode 100644 index 00000000..72e1a672 --- /dev/null +++ b/samples/wasm-c-api-imports/wasm/send_recv.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __wasi__ +#include +#include "pthread.h" +#else +#include +#endif + +static pthread_mutex_t lock = { 0 }; +static pthread_cond_t cond = { 0 }; +static bool server_is_ready = false; + +#ifdef __wasi__ +__attribute__((import_name("log"))) extern void +host_log(uint64_t message, uint32_t length); +#endif + +static void +local_printf(const char *formatter, ...) +{ + char buffer[128] = { 0 }; + va_list args; + + va_start(args, formatter); + vsnprintf(buffer, 128, formatter, args); + va_end(args); + +#ifdef __wasi__ + host_log((uint64_t)(void *)buffer, strlen(buffer)); +#endif + printf("--> %s", buffer); +} + +void * +run_as_server(void *arg) +{ + int sock = -1, on = 1; + struct sockaddr_in addr = { 0 }; + int addrlen = 0; + int new_sock = -1; + char *buf[] = { + "The stars shine down", "It brings us light", "Light comes down", + "To make us paths", "It watches us", "And mourns for us", + }; + struct iovec iov[] = { + { .iov_base = buf[0], .iov_len = strlen(buf[0]) + 1 }, + { .iov_base = buf[1], .iov_len = strlen(buf[1]) + 1 }, + { .iov_base = buf[2], .iov_len = strlen(buf[2]) + 1 }, + { .iov_base = buf[3], .iov_len = strlen(buf[3]) + 1 }, + { .iov_base = buf[4], .iov_len = strlen(buf[4]) + 1 }, + { .iov_base = buf[5], .iov_len = strlen(buf[5]) + 1 }, + }; + struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 6 }; + ssize_t send_len = 0; + + pthread_mutex_lock(&lock); + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + pthread_mutex_unlock(&lock); + perror("Create a socket failed"); + return NULL; + } + +#ifndef __wasi__ + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) { + pthread_mutex_unlock(&lock); + perror("Setsockopt failed"); + goto fail1; + } +#endif + + /* 0.0.0.0:1234 */ + addr.sin_family = AF_INET; + addr.sin_port = htons(1234); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + addrlen = sizeof(addr); + if (bind(sock, (struct sockaddr *)&addr, addrlen) < 0) { + pthread_mutex_unlock(&lock); + perror("Bind failed"); + goto fail1; + } + + if (listen(sock, 0) < 0) { + pthread_mutex_unlock(&lock); + perror("Listen failed"); + goto fail1; + } + + server_is_ready = true; + pthread_cond_signal(&cond); + pthread_mutex_unlock(&lock); + + local_printf("Server is online ... \n"); + + new_sock = accept(sock, (struct sockaddr *)&addr, (socklen_t *)&addrlen); + if (new_sock < 0) { + perror("Accept failed"); + goto fail1; + } + + local_printf("Start sending. \n"); + send_len = sendmsg(new_sock, &msg, 0); + if (send_len < 0) { + perror("Sendmsg failed"); + goto fail2; + } + local_printf("Send %ld bytes successfully!\n", send_len); + +fail2: + close(new_sock); +fail1: + shutdown(sock, SHUT_RD); + close(sock); + return NULL; +} + +void * +run_as_client(void *arg) +{ + int sock = -1; + struct sockaddr_in addr = { 0 }; + /* buf of server is 106 bytes */ + char buf[110] = { 0 }; + struct iovec iov = { .iov_base = buf, .iov_len = sizeof(buf) }; + struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 }; + ssize_t recv_len = 0; + + pthread_mutex_lock(&lock); + while (false == server_is_ready) { + pthread_cond_wait(&cond, &lock); + } + pthread_mutex_unlock(&lock); + + local_printf("Client is running...\n"); + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("Create a socket failed"); + return NULL; + } + + /* 127.0.0.1:1234 */ + addr.sin_family = AF_INET; + addr.sin_port = htons(1234); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("Connect failed"); + goto fail; + } + + local_printf("Start receiving. \n"); + recv_len = recvmsg(sock, &msg, 0); + if (recv_len < 0) { + perror("Recvmsg failed"); + goto fail; + } + + local_printf("Receive %ld bytes successlly!\n", recv_len); + assert(recv_len == 106); + + local_printf("Data:\n"); + char *s = msg.msg_iov->iov_base; + while (strlen(s) > 0) { + local_printf(" %s\n", s); + s += strlen(s) + 1; + } + +fail: + shutdown(sock, SHUT_RD); + close(sock); + return NULL; +} + +int +main(int argc, char *argv[]) +{ + pthread_t cs[2] = { 0 }; + uint8_t i = 0; + int ret = EXIT_SUCCESS; + + if (pthread_mutex_init(&lock, NULL)) { + perror("Initialize mutex failed"); + ret = EXIT_FAILURE; + goto RETURN; + } + + if (pthread_cond_init(&cond, NULL)) { + perror("Initialize condition failed"); + ret = EXIT_FAILURE; + goto DESTROY_MUTEX; + } + + if (pthread_create(&cs[0], NULL, run_as_server, NULL)) { + perror("Create a server thread failed"); + ret = EXIT_FAILURE; + goto DESTROY_COND; + } + + if (pthread_create(&cs[1], NULL, run_as_client, NULL)) { + perror("Create a client thread failed"); + ret = EXIT_FAILURE; + goto DESTROY_COND; + } + + for (i = 0; i < 2; i++) { + pthread_join(cs[i], NULL); + } + +DESTROY_COND: + pthread_cond_destroy(&cond); +DESTROY_MUTEX: + pthread_mutex_destroy(&lock); +RETURN: + return ret; +} diff --git a/samples/wasm-c-api/CMakeLists.txt b/samples/wasm-c-api/CMakeLists.txt index a6494624..e2be3b8f 100644 --- a/samples/wasm-c-api/CMakeLists.txt +++ b/samples/wasm-c-api/CMakeLists.txt @@ -136,26 +136,13 @@ include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) set(MM_UTIL src/utils/multi_module_utils.c) # build executable for each .c -set(EXAMPLES - callback - callback_chain - clone - empty_imports - global - hello - hostref - memory - reflect - table - threads - trap -) - -if(WAMR_BUILD_JIT AND WAMR_BUILD_LAZY_JIT) - if((${WAMR_BUILD_JIT} EQUAL 1) AND (${WAMR_BUILD_LAZY_JIT} EQUAL 1)) - list(APPEND EXAMPLES serialize) - endif() -endif() +list(APPEND EXAMPLES callback callback_chain empty_imports global hello hostref memory reflect table trap) +# FIXME enable both in the future +#list(APPEND EXAMPLES clone threads) +# FIXME +# if(WAMR_BUILD_JIT EQUAL 1 AND WAMR_BUILD_LAZY_JIT EQUAL 0) +# list(APPEND EXAMPLES serialize) +# endif() check_pie_supported() diff --git a/samples/wasm-c-api/README.md b/samples/wasm-c-api/README.md index 51b8642a..b2327670 100644 --- a/samples/wasm-c-api/README.md +++ b/samples/wasm-c-api/README.md @@ -4,9 +4,9 @@ Before staring, we need to download and intall [WABT](https://github.com/WebAsse ``` shell $ cd /opt -$ wget https://github.com/WebAssembly/wabt/releases/download/1.0.19/wabt-1.0.19-ubuntu.tar.gz -$ tar -xzf wabt-1.0.19-ubuntu.tar.gz -$ mv wabt-1.0.19 wabt +$ wget https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz +$ tar -xzf wabt-1.0.31-ubuntu.tar.gz +$ mv wabt-1.0.31 wabt ``` By default, all samples are compiled and run in "interpreter" mode. @@ -47,4 +47,4 @@ $ ./global $ ... $ ./callback $ ... -``` \ No newline at end of file +``` diff --git a/samples/workload/CMakeLists.txt b/samples/workload/CMakeLists.txt new file mode 100644 index 00000000..5e5dca28 --- /dev/null +++ b/samples/workload/CMakeLists.txt @@ -0,0 +1,116 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +project(wasm_workloads) + +####################################### +add_subdirectory(bwa) +add_subdirectory(meshoptimizer) +add_subdirectory(wasm-av1) + +####################################### +include(ExternalProject) + +################ iwasm ################ +ExternalProject_Add(iwasm + PREFIX + iwasm-build + BUILD_ALWAYS + YES + SOURCE_DIR + ${CMAKE_CURRENT_SOURCE_DIR}/../../product-mini/platforms/linux + CONFIGURE_COMMAND + ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR}/../../product-mini/platforms/linux -B build -DWAMR_BUILD_LIBC_EMCC=1 + BUILD_COMMAND + ${CMAKE_COMMAND} --build build + INSTALL_COMMAND + # FIXME: replace with --install + ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/iwasm-build/src/iwasm-build/build/iwasm + ${CMAKE_CURRENT_BINARY_DIR}/iwasm +) + +################ wamrc ################ +ExternalProject_Add(wamrc + PREFIX + wamrc-build + BUILD_ALWAYS + YES + SOURCE_DIR + ${CMAKE_CURRENT_SOURCE_DIR}/../../wamr-compiler + CONFIGURE_COMMAND + ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR}/../../wamr-compiler -B build + BUILD_COMMAND + ${CMAKE_COMMAND} --build build + INSTALL_COMMAND + # FIXME: replace with --install + ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/wamrc-build/src/wamrc-build/build/wamrc + ${CMAKE_CURRENT_BINARY_DIR}/wamrc +) + +################ .aot ################ +add_custom_target( + bwa_to_aot + ALL + DEPENDS + bwa wamrc + COMMAND + ./wamrc -o bwa.aot ./bwa/bwa.wasm + WORKING_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR} +) + +add_custom_target( + codecbench_to_aot + ALL + DEPENDS + codecbench wamrc + COMMAND + ./wamrc -o codecbench.aot ./meshoptimizer/codecbench.wasm + WORKING_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR} +) + +add_custom_target( + av1_to_aot + ALL + DEPENDS + av1 wamrc + COMMAND + ./wamrc -o testavx.aot ./wasm-av1/testavx.opt.wasm + WORKING_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR} +) + +################ smoking test ################ +include(CTest) + +add_test( + NAME + run_bwa + COMMAND + ./iwasm --dir=. ./bwa.aot index ./bwa/hs38DH-extra.fa + WORKING_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR} +) + +add_test( + NAME + run_codecbench + COMMAND + ./iwasm codecbench.aot + WORKING_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR} +) + +add_test( + NAME + run_av1 + COMMAND + ./iwasm --dir=. testavx.aot ./wasm-av1/elephants_dream_480p24.ivf + WORKING_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR} +) \ No newline at end of file diff --git a/samples/workload/README.md b/samples/workload/README.md index dd94e05c..0e6a3a41 100644 --- a/samples/workload/README.md +++ b/samples/workload/README.md @@ -1,41 +1,30 @@ -All workloads have similar requirment of software dependencies, including -**emsdk**, **wabt** and **binaryen** +All workloads have similar requirment of software dependencies, including **emsdk** and **binaryen** -> There might be slight differences when using MacOS and other Linux distro than Ubuntu. This document only target -Ubuntu 18.04 as example. +> There might be slight differences when using MacOS and other Linux distro than Ubuntu. This document targets +Ubuntu 20.04 as an example. ## Installation instructions -use [preparation.sh](./preparation.sh) to install all dependencies before compiling any workload. +use [preparation.sh](./preparation.sh) to install all dependencies before compiling any workload. Or use [*vscode DevContainer*](../../.devcontainer/) -for details, the script includes below steps: - -- **wabt**. Install - [latest release](https://github.com/WebAssembly/wabt/releases/download/1.0.23/wabt-1.0.23-ubuntu.tar.gz) - to */opt/wabt* - -``` bash -$ wget https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/${WABT_FILE} -$ tar zxf ${WABT_FILE} -C /opt -$ ln -sf /opt/wabt-${WABT_VER} /opt/wabt -``` +The script installs below software: - **emsdk**. Refer to [the guide](https://emscripten.org/docs/getting_started/downloads.html). Don't forget to activate emsdk and set up environment variables. Verify it with `echo ${EMSDK}`. Please be sure to install and activate the building - of 2.0.26 + of 3.0.0 ``` bash $ cd /opt $ git clone https://github.com/emscripten-core/emsdk.git $ cd emsdk $ git pull -$ ./emsdk install 2.0.26 -$ ./emsdk activate 2.0.26 +$ ./emsdk install 3.0.0 +$ ./emsdk activate 3.0.0 $ echo "source /opt/emsdk/emsdk_env.sh" >> "${HOME}"/.bashrc ``` - **binaryen**. Install - [latest release](https://github.com/WebAssembly/binaryen/releases/download/version_101/binaryen-version_101-x86_64-linux.tar.gz) + [latest release](https://github.com/WebAssembly/binaryen/releases/download/version_111/binaryen-version_111-x86_64-linux.tar.gz) to */opt/binaryen* ``` bash diff --git a/samples/workload/XNNPACK/CMakeLists.txt b/samples/workload/XNNPACK/CMakeLists.txt index 3f67367a..532544f9 100644 --- a/samples/workload/XNNPACK/CMakeLists.txt +++ b/samples/workload/XNNPACK/CMakeLists.txt @@ -15,8 +15,9 @@ ExternalProject_Add(xnnpack GIT_PROGRESS ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack UPDATE_COMMAND git checkout . - && git reset --hard 4d738aef36872669e4bba05a4b259149ba8e62e1 - && cmake -E copy ${CMAKE_CURRENT_SOURCE_DIR}/benchmark.patch ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/third_party + && git reset --hard 4570a7151aa4f3e57eca14a575eeff6bb13e26be + && cmake -E copy ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/google3/third_party/XNNPACK/microkernels.bzl + ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/ && git apply ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack.patch CONFIGURE_COMMAND "" # grep xnnpack_benchmark -A 1 BUILD.bazel \ @@ -24,70 +25,123 @@ ExternalProject_Add(xnnpack # | awk '{print $3}' \ # | sed -e 's/\"//g' -e 's/,//g' -e 's/^/\/\/:/g' BUILD_COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack - && bazel --output_user_root=build_user_output build -c opt --config=wasm + && bazel --output_user_root=build-user-output build -c opt --config=wasm //:qs8_dwconv_bench.wasm + //:qs8_f32_vcvt_bench.wasm //:qs8_gemm_bench.wasm //:qs8_requantization_bench.wasm //:qs8_vadd_bench.wasm //:qs8_vaddc_bench.wasm + //:qs8_vcvt_bench.wasm + //:qs8_vlrelu_bench.wasm + //:qs8_vmul_bench.wasm + //:qs8_vmulc_bench.wasm + //:qu8_f32_vcvt_bench.wasm //:qu8_gemm_bench.wasm //:qu8_requantization_bench.wasm //:qu8_vadd_bench.wasm //:qu8_vaddc_bench.wasm + //:qu8_vcvt_bench.wasm + //:qu8_vlrelu_bench.wasm + //:qu8_vmul_bench.wasm + //:qu8_vmulc_bench.wasm + //:bf16_gemm_bench.wasm //:f16_igemm_bench.wasm //:f16_gemm_bench.wasm + //:f16_raddstoreexpminusmax_bench.wasm //:f16_spmm_bench.wasm - //:f16_vrelu_bench.wasm + //:f16_vsigmoid_bench.wasm + //:f16_f32_vcvt_bench.wasm //:f32_igemm_bench.wasm //:f32_conv_hwc_bench.wasm + //:f16_conv_hwc2chw_bench.wasm + //:f16_gavgpool_cw_bench.wasm + //:f32_gavgpool_cw_bench.wasm //:f32_conv_hwc2chw_bench.wasm //:f16_dwconv_bench.wasm //:f32_dwconv_bench.wasm //:f32_dwconv2d_chw_bench.wasm + //:f16_dwconv2d_chw_bench.wasm + //:f32_f16_vcvt_bench.wasm + //:xx_transpose_bench.wasm + //:x8_transpose_bench.wasm + //:x16_transpose_bench.wasm + //:x24_transpose_bench.wasm + //:x32_transpose_bench.wasm + //:x64_transpose_bench.wasm //:f32_gemm_bench.wasm + //:f32_qs8_vcvt_bench.wasm + //:f32_qu8_vcvt_bench.wasm //:f32_raddexpminusmax_bench.wasm //:f32_raddextexp_bench.wasm //:f32_raddstoreexpminusmax_bench.wasm //:f32_rmax_bench.wasm //:f32_spmm_bench.wasm //:f32_softmax_bench.wasm + //:f16_velu_bench.wasm //:f32_velu_bench.wasm //:f32_vhswish_bench.wasm + //:f32_vlrelu_bench.wasm //:f32_vrelu_bench.wasm //:f32_vscaleexpminusmax_bench.wasm //:f32_vscaleextexp_bench.wasm //:f32_vsigmoid_bench.wasm + //:f16_vsqrt_bench.wasm //:f32_vsqrt_bench.wasm //:f32_im2col_gemm_bench.wasm //:rounding_bench.wasm + //:s16_rmaxabs_bench.wasm + //:s16_window_bench.wasm + //:u32_filterbank_accumulate_bench.wasm + //:u32_filterbank_subtract_bench.wasm + //:u32_vlog_bench.wasm + //:u64_u32_vsqrtshift_bench.wasm + //:i16_vlshift_bench.wasm + //:cs16_vsquareabs_bench.wasm + //:cs16_bfly4_bench.wasm + //:cs16_fftr_bench.wasm + //:x8_lut_bench.wasm + //:abs_bench.wasm //:average_pooling_bench.wasm //:bankers_rounding_bench.wasm //:ceiling_bench.wasm //:channel_shuffle_bench.wasm + //:convert_bench.wasm //:convolution_bench.wasm //:deconvolution_bench.wasm //:elu_bench.wasm //:floor_bench.wasm //:global_average_pooling_bench.wasm //:hardswish_bench.wasm + //:leaky_relu_bench.wasm //:max_pooling_bench.wasm + //:negate_bench.wasm //:sigmoid_bench.wasm //:prelu_bench.wasm //:softmax_bench.wasm + //:square_bench.wasm //:square_root_bench.wasm //:truncation_bench.wasm + //:f16_gemm_e2e_bench.wasm //:f32_dwconv_e2e_bench.wasm //:f32_gemm_e2e_bench.wasm //:qs8_dwconv_e2e_bench.wasm //:qs8_gemm_e2e_bench.wasm + //:qu8_gemm_e2e_bench.wasm //:qu8_dwconv_e2e_bench.wasm //:end2end_bench.wasm + //:f16_exp_ulp_eval.wasm + //:f16_expminus_ulp_eval.wasm + //:f16_expm1minus_ulp_eval.wasm + //:f16_sigmoid_ulp_eval.wasm + //:f16_sqrt_ulp_eval.wasm //:f32_exp_ulp_eval.wasm //:f32_expminus_ulp_eval.wasm //:f32_expm1minus_ulp_eval.wasm //:f32_extexp_ulp_eval.wasm //:f32_sigmoid_ulp_eval.wasm //:f32_sqrt_ulp_eval.wasm + //:f32_tanh_ulp_eval.wasm INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/xnnpack/bazel-out/wasm-opt/bin/ ${CMAKE_BINARY_DIR}/wasm-opt diff --git a/samples/workload/XNNPACK/README.md b/samples/workload/XNNPACK/README.md index f6a20729..7984d9ce 100644 --- a/samples/workload/XNNPACK/README.md +++ b/samples/workload/XNNPACK/README.md @@ -24,7 +24,7 @@ Firstly please build iwasm with simd, libc-emcc and lib-pthread support: ``` bash $ cd /product-mini/platforms/linux/ $ mkdir build && cd build -$ cmake .. -DWAMR_BUILD_SIMD=1 -DWAMR_BUILD_LIBC_EMCC=1 -DWAMR_BUILD_LIB_PTHREAD=1 +$ cmake .. -DWAMR_BUILD_LIBC_EMCC=1 -DWAMR_BUILD_LIB_PTHREAD=1 $ make ``` @@ -42,7 +42,7 @@ Then compile wasm file to aot file and run: ``` shell $ cd /samples/workload/XNNPACK/xnnpack/bazel-bin -$ wamrc --enable-simd -o average_pooling_bench.aot average_pooling_bench.wasm (or other wasm files) +$ wamrc -o average_pooling_bench.aot average_pooling_bench.wasm (or other wasm files) $ iwasm average_pooling_bench.aot ``` diff --git a/samples/workload/XNNPACK/build_workload.sh b/samples/workload/XNNPACK/build_workload.sh deleted file mode 120000 index a31afa92..00000000 --- a/samples/workload/XNNPACK/build_workload.sh +++ /dev/null @@ -1 +0,0 @@ -../docker/build_workload.sh \ No newline at end of file diff --git a/samples/workload/XNNPACK/xnnpack.patch b/samples/workload/XNNPACK/xnnpack.patch index 7eed678b..f7d0a01d 100644 --- a/samples/workload/XNNPACK/xnnpack.patch +++ b/samples/workload/XNNPACK/xnnpack.patch @@ -1,8 +1,8 @@ diff --git a/.bazelrc b/.bazelrc -index ec740f38..29f9d56e 100644 +index 688279da1..376996885 100644 --- a/.bazelrc +++ b/.bazelrc -@@ -49,4 +49,9 @@ build:ios_fat --watchos_cpus=armv7k +@@ -53,4 +53,9 @@ build:ios_fat --watchos_cpus=armv7k build:macos --apple_platform_type=macos build:macos_arm64 --config=macos @@ -11,42 +11,26 @@ index ec740f38..29f9d56e 100644 +build:macos_arm64 --cpu=darwin_arm64 + +build:wasm --cpu=wasm -+build:wasm --copt=-msimd128 ++build:wasm --features=wasm_simd +build:wasm --crosstool_top=@emsdk//emscripten_toolchain:everything +build:wasm --host_crosstool_top=@bazel_tools//tools/cpp:toolchain -diff --git a/BUILD.bazel b/BUILD.bazel -index 3fc8139f..c893356d 100644 ---- a/BUILD.bazel -+++ b/BUILD.bazel -@@ -11988,7 +11988,6 @@ config_setting( - values = { - "crosstool_top": "@emsdk//emscripten_toolchain:everything", - "cpu": "wasm", -- "copt": "-msimd128", - "copt": "-mrelaxed-simd", - }, - ) diff --git a/WORKSPACE b/WORKSPACE -index c58e76b6..30934678 100644 +index cd8960ffa..5d3e685f4 100644 --- a/WORKSPACE +++ b/WORKSPACE -@@ -21,6 +21,7 @@ http_archive( - name = "com_google_benchmark", - strip_prefix = "benchmark-master", - urls = ["https://github.com/google/benchmark/archive/master.zip"], -+ patches = ["@//third_party:benchmark.patch"], - ) - - # FP16 library, used for half-precision conversions -@@ -84,6 +85,19 @@ http_archive( - ], +@@ -92,8 +92,25 @@ http_archive( + ], ) ++load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +http_archive( -+ name = "emsdk", -+ strip_prefix = "emsdk-2.0.26/bazel", -+ url = "https://github.com/emscripten-core/emsdk/archive/refs/tags/2.0.26.tar.gz", -+ sha256 = "79e7166aa8eaae6e52cef1363b2d8db795d03684846066bc51f9dcf905dd58ad", ++ name = "emsdk", ++ # Use emsdk-3.0.0 since the larger version may: ++ # - compress the wasm file into a tar file but not directly generate wasm file ++ # - generate incomplete implementation of libc API, e.g. throw exception in getentropy ++ strip_prefix = "emsdk-3.0.0/bazel", ++ url = "https://github.com/emscripten-core/emsdk/archive/refs/tags/3.0.0.tar.gz", ++ sha256 = "a41dccfd15be9e85f923efaa0ac21943cbab77ec8d39e52f25eca1ec61a9ac9e" +) + +load("@emsdk//:deps.bzl", emsdk_deps = "deps") @@ -56,13 +40,17 @@ index c58e76b6..30934678 100644 +emsdk_emscripten_deps() + # Android NDK location and version is auto-detected from $ANDROID_NDK_HOME environment variable - android_ndk_repository(name = "androidndk") +-android_ndk_repository(name = "androidndk") ++#android_ndk_repository(name = "androidndk") + # Android SDK location and API is auto-detected from $ANDROID_HOME environment variable +-android_sdk_repository(name = "androidsdk") ++#android_sdk_repository(name = "androidsdk") diff --git a/build_defs.bzl b/build_defs.bzl -index fbadb400..e496b78d 100644 +index b8217a18d..da232966e 100644 --- a/build_defs.bzl +++ b/build_defs.bzl -@@ -430,7 +430,7 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): +@@ -380,7 +380,7 @@ def xnnpack_benchmark(name, srcs, copts = [], deps = [], tags = []): explicitly specified. """ native.cc_binary( @@ -72,7 +60,7 @@ index fbadb400..e496b78d 100644 copts = xnnpack_std_cxxopts() + [ "-Iinclude", diff --git a/emscripten.bzl b/emscripten.bzl -index 130d5f16..2696ad54 100644 +index f1557a7b1..7f964a094 100644 --- a/emscripten.bzl +++ b/emscripten.bzl @@ -25,12 +25,19 @@ def xnnpack_emscripten_benchmark_linkopts(): @@ -84,7 +72,7 @@ index 130d5f16..2696ad54 100644 - "-s EXIT_RUNTIME=1", + "-s ERROR_ON_UNDEFINED_SYMBOLS=0", "-s ALLOW_MEMORY_GROWTH=1", - "-s TOTAL_MEMORY=445644800", # 425M + "-s TOTAL_MEMORY=536870912", # 512M - "--pre-js $(location :preamble.js.lds)", + "-s USE_PTHREADS=0", + "-s STANDALONE_WASM=1", @@ -99,11 +87,33 @@ index 130d5f16..2696ad54 100644 ] def xnnpack_emscripten_deps(): +diff --git a/src/log.c b/src/log.c +index 5715f2f85..4b3e4261b 100644 +--- a/src/log.c ++++ b/src/log.c +@@ -55,7 +55,7 @@ + #endif + + #if XNN_LOG_TO_STDIO +-static void xnn_vlog(int output_handle, const char* prefix, size_t prefix_length, const char* format, va_list args) { ++void xnn_vlog(int output_handle, const char* prefix, size_t prefix_length, const char* format, va_list args) { + char stack_buffer[XNN_LOG_STACK_BUFFER_SIZE]; + char* heap_buffer = NULL; + char* out_buffer = &stack_buffer[0]; diff --git a/third_party/cpuinfo.BUILD b/third_party/cpuinfo.BUILD -index 128d683e..f6c287c4 100644 +index 1997f4e3a..5e03c43af 100644 --- a/third_party/cpuinfo.BUILD +++ b/third_party/cpuinfo.BUILD -@@ -343,5 +343,5 @@ config_setting( +@@ -150,7 +150,7 @@ cc_library( + "src/arm/midr.h", + ], + deps = [ +- "@clog", ++ "//deps/clog" + ], + ) + +@@ -352,5 +352,5 @@ config_setting( config_setting( name = "emscripten", diff --git a/samples/workload/bwa/CMakeLists.bwa_wasm.txt b/samples/workload/bwa/CMakeLists.bwa_wasm.txt index c68b942f..a8d1d882 100644 --- a/samples/workload/bwa/CMakeLists.bwa_wasm.txt +++ b/samples/workload/bwa/CMakeLists.bwa_wasm.txt @@ -1,11 +1,14 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required (VERSION 3.14) project(bwa_wasm C) -include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/preparation.cmake) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake) + +################ dependencies ################ +find_package(Binaryen 111 REQUIRED) ################ LIBZ ################ set(LIBZ_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../libz) @@ -86,12 +89,6 @@ add_executable(${PROJECT_NAME} ${BWA_SOURCE}) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME bwa.wasm) -target_include_directories(${PROJECT_NAME} - PRIVATE - ${WASI_SDK_HOME}/share/wasi-sysroot/include/libc/musl - ${WASI_SDK_HOME}/share/wasi-sysroot/include/sse -) - target_compile_definitions(${PROJECT_NAME} PRIVATE USE_MALLOC_WRAPPERS @@ -117,7 +114,7 @@ target_link_libraries(${PROJECT_NAME} z_wasm wasi-emulated-process-clocks) add_custom_target(bwa_wasm_opt ALL COMMAND - ${WASM_OPT} -Oz --enable-simd -o bwa.opt.wasm bwa.wasm + ${Binaryen_WASM_OPT} -Oz --enable-simd -o bwa.opt.wasm bwa.wasm BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/bwa.opt.wasm WORKING_DIRECTORY diff --git a/samples/workload/bwa/CMakeLists.txt b/samples/workload/bwa/CMakeLists.txt index 7f7e3182..731dd4c7 100644 --- a/samples/workload/bwa/CMakeLists.txt +++ b/samples/workload/bwa/CMakeLists.txt @@ -1,11 +1,19 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 2.8...3.16) +cmake_minimum_required (VERSION 3.14) project(bwa_wasm) -include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/preparation.cmake) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) + +################ dependencies ################ +find_package(Python3 REQUIRED) +find_package(WASISDK 16.0 REQUIRED) +execute_process( + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/../../../test-tools/pick-up-emscripten-headers/collect_files.py --install ../include --loglevel=ERROR + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) ####################################### include(ExternalProject) @@ -13,7 +21,7 @@ include(ExternalProject) ################ libz ################ ExternalProject_Add(libz_src GIT_REPOSITORY https://github.com/madler/zlib.git - GIT_TAG master + GIT_TAG 04f42ceca40f73e2978b50e93806c2a18c1281fc GIT_PROGRESS ON GIT_SHALLOW ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libz @@ -27,7 +35,7 @@ ExternalProject_Add(libz_src ################ bwa ################ ExternalProject_Add(bwa GIT_REPOSITORY https://github.com/lh3/bwa.git - GIT_TAG master + GIT_TAG 139f68fc4c3747813783a488aef2adc86626b01b GIT_PROGRESS ON GIT_SHALLOW ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bwa @@ -37,10 +45,29 @@ ExternalProject_Add(bwa && ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.bwa_wasm.txt CMakeLists.txt && git apply ../bwa.patch CONFIGURE_COMMAND ${CMAKE_COMMAND} - -DWASI_SDK_PREFIX=${WASI_SDK_HOME} - -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_HOME}/share/cmake/wasi-sdk.cmake - -DCMAKE_SYSROOT=${WASI_SDK_HOME}/share/wasi-sysroot + -DWASI_SDK_PREFIX=${WASISDK_HOME} + -DCMAKE_TOOLCHAIN_FILE=${WASISDK_TOOLCHAIN} + -DCMAKE_SYSROOT=${WASISDK_SYSROOT} + -DCMAKE_C_FLAGS=-isystem\ ${CMAKE_CURRENT_SOURCE_DIR}/../include/sse\ -isystem\ ${CMAKE_CURRENT_SOURCE_DIR}/../include/libc/musl ${CMAKE_CURRENT_SOURCE_DIR}/bwa BUILD_COMMAND make bwa_wasm_opt - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ./bwa.opt.wasm ${CMAKE_BINARY_DIR}/bwa.wasm + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different ./bwa.opt.wasm ${CMAKE_CURRENT_BINARY_DIR}/bwa.wasm ) + +################ bwa data ################ +ExternalProject_Add(bwa-kit + PREFIX bwa-kit + URL https://sourceforge.net/projects/bio-bwa/files/bwakit/bwakit-0.7.15_x64-linux.tar.bz2/download + URL_HASH SHA256=0a7b11971bc7916b68e9df35a364afe77cb3000df02ffb3a6fbd1aff9be5878c + DOWNLOAD_NAME bwakit-0.7.15_x64-linux.tar.bz2 + DOWNLOAD_EXTRACT_TIMESTAMP ON + DOWNLOAD_NO_EXTRACT OFF + DOWNLOAD_NO_PROGRESS ON + UPDATE_COMMAND "" + PATCH_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/bwa-kit/src/bwa-kit/resource-GRCh38/hs38DH-extra.fa + ${CMAKE_CURRENT_BINARY_DIR}/hs38DH-extra.fa +) \ No newline at end of file diff --git a/samples/workload/bwa/README.md b/samples/workload/bwa/README.md index e826bb61..a8fbe3e6 100644 --- a/samples/workload/bwa/README.md +++ b/samples/workload/bwa/README.md @@ -33,7 +33,7 @@ Firstly please build iwasm with simd support: ``` shell $ cd /product-mini/platforms/linux/ $ mkdir build && cd build -$ cmake .. -DWAMR_BUILD_SIMD=1 +$ cmake .. $ make ``` @@ -41,6 +41,6 @@ Then compile wasm file to aot file and run: ``` shell $ cd /samples/workload/bwa/build -$ /wamr-compiler/build/wamrc --enable-simd -o bwa.aot bwa.wasm +$ /wamr-compiler/build/wamrc -o bwa.aot bwa.wasm $ /product-mini/platforms/linux/iwasm --dir=. bwa.aot index hs38DH.fa ``` diff --git a/samples/workload/bwa/build_workload.sh b/samples/workload/bwa/build_workload.sh deleted file mode 120000 index a31afa92..00000000 --- a/samples/workload/bwa/build_workload.sh +++ /dev/null @@ -1 +0,0 @@ -../docker/build_workload.sh \ No newline at end of file diff --git a/samples/workload/cmake/FindBinaryen.cmake b/samples/workload/cmake/FindBinaryen.cmake new file mode 100644 index 00000000..b4a64786 --- /dev/null +++ b/samples/workload/cmake/FindBinaryen.cmake @@ -0,0 +1,43 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# +# Output below variables: +# - Binaryen_HOME. the installation location +# + +include(CMakePrintHelpers) +include(FindPackageHandleStandardArgs) + +file(GLOB Binaryen_SEARCH_PATH "/opt/binaryen*") +find_path(Binaryen_HOME + NAMES bin/wasm-opt + PATHS ${Binaryen_SEARCH_PATH} + NO_CMAKE_FIND_ROOT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + REQUIRED +) + +execute_process( + COMMAND ${Binaryen_HOME}/bin/wasm-opt --version + OUTPUT_VARIABLE WASM_OPT_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +string(REGEX MATCH version_[0-9]+ Binaryen_VERSION_tmp ${WASM_OPT_OUTPUT}) +string(REGEX MATCH [0-9]+ Binaryen_VERSION ${Binaryen_VERSION_tmp}) + +#cmake_print_variables(Binaryen_VERSION_tmp Binaryen_VERSION) + +find_package_handle_standard_args(Binaryen REQUIRED_VARS Binaryen_HOME VERSION_VAR Binaryen_VERSION) + +if(Binaryen_FOUND) + mark_as_advanced(Binaryen_SEARCH_PATH) + mark_as_advanced(Binaryen_VERSION_tmp) + mark_as_advanced(Binaryen_VERSION) + mark_as_advanced(WASM_OPT_OUTPUT) + + set(Binaryen_WASM_OPT ${Binaryen_HOME}/bin/wasm-opt) +else() + # TODO: install WASISDK +endif() diff --git a/samples/workload/cmake/FindWASISDK.cmake b/samples/workload/cmake/FindWASISDK.cmake new file mode 100644 index 00000000..fff8aea4 --- /dev/null +++ b/samples/workload/cmake/FindWASISDK.cmake @@ -0,0 +1,38 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# +# Output below variables: +# - WASISDK_HOME. the installation location +# - WASISDK_SYSROOT. where wasi-sysroot is +# - WASISDK_TOOLCHAIN. where wasi-sdk.cmake is +# + +include(CMakePrintHelpers) +include(FindPackageHandleStandardArgs) + +file(GLOB WASISDK_SEARCH_PATH "/opt/wasi-sdk-*") +find_path(WASISDK_HOME + NAMES share/wasi-sysroot + PATHS ${WASISDK_SEARCH_PATH} + NO_CMAKE_FIND_ROOT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + REQUIRED +) + +string(REGEX MATCH [0-9]+\.[0-9]+\.*[0-9]* WASISDK_VERSION ${WASISDK_HOME}) + +#cmake_print_variables(WASISDK_HOME WASISDK_VERSION) +find_package_handle_standard_args(WASISDK REQUIRED_VARS WASISDK_HOME VERSION_VAR WASISDK_VERSION) + +if(WASISDK_FOUND) + mark_as_advanced(WASISDK_SEARCH_PATH) + mark_as_advanced(WASISDK_VERSION) + + set(WASISDK_CC_COMMAND ${WASISDK_HOME}/bin/clang) + set(WASISDK_CXX_COMMAND ${WASISDK_HOME}/bin/clang++) + set(WASISDK_SYSROOT ${WASISDK_HOME}/share/wasi-sysroot) + set(WASISDK_TOOLCHAIN ${WASISDK_HOME}/share/cmake/wasi-sdk.cmake) +else() + # TODO: install WASISDK +endif() diff --git a/samples/workload/cmake/preparation.cmake b/samples/workload/cmake/preparation.cmake deleted file mode 100644 index 326943c8..00000000 --- a/samples/workload/cmake/preparation.cmake +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -####################################### -include(ExternalProject) - -file(REAL_PATH ../../.. WAMR_ROOT - BASE_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} -) - -find_path(WASI_SDK_PARENT - name wasi-sdk - PATHS ${WAMR_ROOT}/test-tools/ - NO_DEFAULT_PATH - NO_CMAKE_FIND_ROOT_PATH -) - -if(NOT WASI_SDK_PARENT) - message(FATAL_ERROR - "can not find 'wasi-sdk' under ${WAMR_ROOT}/test-tools, " - "please run ${WAMR_ROOT}/test-tools/build-wasi-sdk/build_wasi_sdk.py " - "to build wasi-sdk and try again" - ) -endif() - -set(WASI_SDK_HOME ${WASI_SDK_PARENT}/wasi-sdk) -message(CHECK_START "Detecting WASI-SDK at ${WASI_SDK_HOME}") -if(EXISTS "${WASI_SDK_HOME}/share/cmake/wasi-sdk.cmake") - message(CHECK_PASS "found") -else() - message(CHECK_FAIL "not found") -endif() - -################ BINARYEN ################ -find_program(WASM_OPT - NAMES wasm-opt - PATHS /opt/binaryen-version_101/bin /opt/binaryen/bin - NO_DEFAULT_PATH - NO_CMAKE_FIND_ROOT_PATH -) - -if(NOT WASM_OPT) - message(FATAL_ERROR - "can not find wasm-opt. " - "please download it from " - "https://github.com/WebAssembly/binaryen/releases/download/version_101/binaryen-version_101-x86_64-linux.tar.gz " - "and install it under /opt" - ) -endif() diff --git a/samples/workload/docker/build_workload.sh b/samples/workload/docker/build_workload.sh deleted file mode 100755 index 640cca97..00000000 --- a/samples/workload/docker/build_workload.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# - -readonly SCRIPT_PATH=$(dirname "$(realpath "$0")") -readonly ROOT=$(realpath "${SCRIPT_PATH}"/../../../) -readonly CURRENT_PATH=$(pwd) -readonly CURRENT_RELATIVE_ROOT=$(realpath --relative-base ${ROOT} ${CURRENT_PATH}) -readonly VARIANT=$(lsb_release -c | awk '{print $2}') - -docker build \ - --build-arg VARIANT=${VARIANT} \ - --memory 4G --cpu-quota 50000 \ - -t wamr_dev_${VARIANT}:0.1 -f "${ROOT}"/.devcontainer/Dockerfile "${ROOT}"/.devcontainer && - docker run --rm -it \ - --memory 4G \ - --cpus ".5" \ - --name workload_build_env \ - --mount type=bind,source="${ROOT}",target=/workspace \ - wamr_dev_${VARIANT}:0.1 \ - /bin/bash -c "\ - pwd \ - && pushd ${CURRENT_RELATIVE_ROOT} \ - && rm -rf build \ - && mkdir build \ - && pushd build \ - && cmake .. \ - && cmake --build . --config Release \ - && popd \ - && popd \ - && echo 'Go and find out results under ${CURRENT_RELATIVE_ROOT}/build' " diff --git a/samples/workload/include/.gitkeep b/samples/workload/include/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/samples/workload/meshoptimizer/CMakeLists.txt b/samples/workload/meshoptimizer/CMakeLists.txt index 172de8d6..cb490f91 100644 --- a/samples/workload/meshoptimizer/CMakeLists.txt +++ b/samples/workload/meshoptimizer/CMakeLists.txt @@ -1,11 +1,19 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required (VERSION 3.14) project(bench-meshoptimizer) -include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/preparation.cmake) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) + +################ dependencies ################ +find_package(Python3 REQUIRED) +find_package(WASISDK 16.0 REQUIRED) +execute_process( + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/../../../test-tools/pick-up-emscripten-headers/collect_files.py --install ../include --loglevel=ERROR + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) ################ MESHOPTIMIZER ################ include(ExternalProject) @@ -13,7 +21,7 @@ include(ExternalProject) ExternalProject_Add(codecbench PREFIX codecbench GIT_REPOSITORY https://github.com/zeux/meshoptimizer.git - GIT_TAG master + GIT_TAG f926b288264522e1b331a41b07ba40167f396913 GIT_SHALLOW ON GIT_PROGRESS ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/meshoptimizer @@ -21,10 +29,10 @@ ExternalProject_Add(codecbench && ${CMAKE_COMMAND} -E echo "Applying patch" && git apply ${CMAKE_CURRENT_SOURCE_DIR}/codecbench.patch CONFIGURE_COMMAND ${CMAKE_COMMAND} - -DWASI_SDK_PREFIX=${WASI_SDK_HOME} - -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_HOME}/share/cmake/wasi-sdk.cmake - -DCMAKE_SYSROOT=${WASI_SDK_HOME}/share/wasi-sysroot + -DWASI_SDK_PREFIX=${WASISDK_HOME} + -DCMAKE_TOOLCHAIN_FILE=${WASISDK_TOOLCHAIN} + -DCMAKE_SYSROOT=${WASISDK_SYSROOT} ${CMAKE_CURRENT_SOURCE_DIR}/meshoptimizer BUILD_COMMAND make codecbench - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ./codecbench.wasm ${CMAKE_BINARY_DIR}/codecbench.wasm + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different ./codecbench.wasm ${CMAKE_CURRENT_BINARY_DIR}/codecbench.wasm ) diff --git a/samples/workload/meshoptimizer/README.md b/samples/workload/meshoptimizer/README.md index ceefb572..466cd875 100644 --- a/samples/workload/meshoptimizer/README.md +++ b/samples/workload/meshoptimizer/README.md @@ -44,14 +44,14 @@ Firstly please build iwasm with simd support: ``` shell $ cd /product-mini/platforms/linux/ $ mkdir build && cd build -$ cmake .. -DWAMR_BUILD_SIMD=1 +$ cmake .. $ make ``` Then compile wasm file to aot file and run: ``` shell -$ /wamr-compiler/build/wamrc --enable-simd -o codecbench.aot codecbench.wasm +$ /wamr-compiler/build/wamrc -o codecbench.aot codecbench.wasm $ /product-mini/platforms/linux/build/iwasm codecbench.aot ``` diff --git a/samples/workload/meshoptimizer/build_workload.sh b/samples/workload/meshoptimizer/build_workload.sh deleted file mode 120000 index a31afa92..00000000 --- a/samples/workload/meshoptimizer/build_workload.sh +++ /dev/null @@ -1 +0,0 @@ -../docker/build_workload.sh \ No newline at end of file diff --git a/samples/workload/preparation.sh b/samples/workload/preparation.sh index 3f49f0cf..47b11ac5 100755 --- a/samples/workload/preparation.sh +++ b/samples/workload/preparation.sh @@ -5,13 +5,13 @@ # readonly BUILD_CONTENT="/tmp/build_content" -readonly WABT_VER=1.0.23 +readonly WABT_VER=1.0.31 readonly WABT_FILE="wabt-${WABT_VER}-ubuntu.tar.gz" -readonly CMAKE_VER=3.16.2 +readonly CMAKE_VER=3.25.1 readonly CMAKE_FILE="cmake-${CMAKE_VER}-Linux-x86_64.sh" -readonly BINARYEN_VER=version_101 +readonly BINARYEN_VER=version_111 readonly BINARYEN_FILE="binaryen-${BINARYEN_VER}-x86_64-linux.tar.gz" -readonly BAZEL_VER=3.7.0 +readonly BAZEL_VER=6.0.0 readonly BAZEL_FILE=bazel-${BAZEL_VER}-installer-linux-x86_64.sh function DEBUG() { @@ -57,8 +57,8 @@ function install_emsdk() { git clone https://github.com/emscripten-core/emsdk.git cd emsdk git pull - ./emsdk install 2.0.26 - ./emsdk activate 2.0.26 + ./emsdk install 3.1.28 + ./emsdk activate 3.1.28 echo "source /opt/emsdk/emsdk_env.sh" >> "${HOME}"/.bashrc } diff --git a/samples/workload/tensorflow/build.sh b/samples/workload/tensorflow/build.sh index 7289e617..d997113f 100755 --- a/samples/workload/tensorflow/build.sh +++ b/samples/workload/tensorflow/build.sh @@ -98,11 +98,11 @@ make WAMRC_CMD="$(pwd)/wamrc" cd ${OUT_DIR} if [[ $1 == '--sgx' ]]; then - ${WAMRC_CMD} --enable-simd -sgx -o benchmark_model.aot benchmark_model.wasm + ${WAMRC_CMD} -sgx -o benchmark_model.aot benchmark_model.wasm elif [[ $1 == '--threads' ]]; then - ${WAMRC_CMD} --enable-simd --enable-multi-thread -o benchmark_model.aot benchmark_model.wasm + ${WAMRC_CMD} --enable-multi-thread -o benchmark_model.aot benchmark_model.wasm else - ${WAMRC_CMD} --enable-simd -o benchmark_model.aot benchmark_model.wasm + ${WAMRC_CMD} -o benchmark_model.aot benchmark_model.wasm fi # 4. build iwasm with pthread and libc_emcc enable @@ -112,14 +112,14 @@ fi if [[ $1 == '--sgx' ]]; then cd ${WAMR_PLATFORM_DIR}/linux-sgx rm -fr build && mkdir build - cd build && cmake .. -DWAMR_BUILD_SIMD=1 -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_LIBC_EMCC=1 + cd build && cmake .. -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_LIBC_EMCC=1 make cd ../enclave-sample make else cd ${WAMR_PLATFORM_DIR}/linux rm -fr build && mkdir build - cd build && cmake .. -DWAMR_BUILD_SIMD=1 -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_LIBC_EMCC=1 + cd build && cmake .. -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_LIBC_EMCC=1 make fi diff --git a/samples/workload/wasm-av1/CMakeLists.avx_wasm.txt b/samples/workload/wasm-av1/CMakeLists.avx_wasm.txt index d1149612..409665b3 100644 --- a/samples/workload/wasm-av1/CMakeLists.avx_wasm.txt +++ b/samples/workload/wasm-av1/CMakeLists.avx_wasm.txt @@ -1,14 +1,14 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 2.8...3.16) +cmake_minimum_required (VERSION 3.14) project(testavx) -include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/preparation.cmake) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake) -# a workaround to let aom find our non-public headers -include_directories(${WASI_SDK_HOME}/share/wasi-sysroot/include/libc/musl) +################ dependencies ################ +find_package(Binaryen 111 REQUIRED) ################ AOM ################ set(ENABLE_CCACHE ON) @@ -62,7 +62,7 @@ add_dependencies(${PROJECT_NAME} aom) add_custom_target(${PROJECT_NAME}_opt ALL COMMAND - ${WASM_OPT} -Oz --enable-simd -o ${PROJECT_NAME}.opt.wasm ${PROJECT_NAME}.wasm + ${Binaryen_WASM_OPT} -Oz --enable-simd -o ${PROJECT_NAME}.opt.wasm ${PROJECT_NAME}.wasm BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.opt.wasm WORKING_DIRECTORY diff --git a/samples/workload/wasm-av1/CMakeLists.txt b/samples/workload/wasm-av1/CMakeLists.txt index 8b1f0df0..6fea31ea 100644 --- a/samples/workload/wasm-av1/CMakeLists.txt +++ b/samples/workload/wasm-av1/CMakeLists.txt @@ -1,11 +1,19 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 2.8...3.16) +cmake_minimum_required (VERSION 3.14) project(av1_wasm) -include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/preparation.cmake) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) + +################ dependencies ################ +find_package(Python3 REQUIRED) +find_package(WASISDK 16.0 REQUIRED) +execute_process( + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/../../../test-tools/pick-up-emscripten-headers/collect_files.py --install ../include --loglevel=ERROR + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) ####################################### include(ExternalProject) @@ -23,10 +31,14 @@ ExternalProject_Add(av1 && ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.avx_wasm.txt CMakeLists.txt && git apply ../av1-clang.patch CONFIGURE_COMMAND ${CMAKE_COMMAND} - -DWASI_SDK_PREFIX=${WASI_SDK_HOME} - -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_HOME}/share/cmake/wasi-sdk.cmake - -DCMAKE_SYSROOT=${WASI_SDK_HOME}/share/wasi-sysroot + -DWASI_SDK_PREFIX=${WASISDK_HOME} + -DCMAKE_TOOLCHAIN_FILE=${WASISDK_TOOLCHAIN} + -DCMAKE_SYSROOT=${WASISDK_SYSROOT} + -DCMAKE_C_FLAGS=-isystem\ ${CMAKE_CURRENT_SOURCE_DIR}/../include/sse\ -isystem\ ${CMAKE_CURRENT_SOURCE_DIR}/../include/libc/musl ${CMAKE_CURRENT_SOURCE_DIR}/av1 BUILD_COMMAND make testavx_opt - INSTALL_COMMAND ${CMAKE_COMMAND} -E copy testavx.opt.wasm ${CMAKE_CURRENT_BINARY_DIR}/testavx.wasm + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_if_different + testavx.opt.wasm + ${CMAKE_CURRENT_SOURCE_DIR}/av1/third_party/samples/elephants_dream_480p24.ivf + ${CMAKE_CURRENT_BINARY_DIR} ) diff --git a/samples/workload/wasm-av1/README.md b/samples/workload/wasm-av1/README.md index e7a92f2a..2166fe6a 100644 --- a/samples/workload/wasm-av1/README.md +++ b/samples/workload/wasm-av1/README.md @@ -39,7 +39,7 @@ Firstly please build iwasm with simd support: ``` shell $ cd /product-mini/platforms/linux/ $ mkdir build && cd build -$ cmake .. -DWAMR_BUILD_SIMD=1 -DWAMR_BUILD_LIBC_EMCC=1 +$ cmake .. -DWAMR_BUILD_LIBC_EMCC=1 $ make ``` @@ -47,7 +47,7 @@ Then compile wasm file to aot file and run: ``` shell $ cd -$ /wamr-compiler/build/wamrc --enable-simd -o testavx.aot testavx.wasm +$ /wamr-compiler/build/wamrc -o testavx.aot testavx.wasm # copy sample data like /samples/workload/wasm-av1/av1/third_party/samples/elephants_dream_480p24.ivf # make sure you declare the access priority of the directory in which the sample data is $ /product-mini/platforms/linux/build/iwasm --dir=. testavx.aot elephants_dream_480p24.ivf diff --git a/samples/workload/wasm-av1/build.sh b/samples/workload/wasm-av1/build.sh index 7f82c6c5..efa17eca 100755 --- a/samples/workload/wasm-av1/build.sh +++ b/samples/workload/wasm-av1/build.sh @@ -85,12 +85,12 @@ cd build && cmake .. make # 3.2 compile wasm-av1.wasm to wasm-av1.aot cd ${OUT_DIR} -${WAMRC_CMD} --enable-simd -o testavx.aot testavx.wasm +${WAMRC_CMD} -o testavx.aot testavx.wasm # 4. build iwasm with pthread and libc_emcc enable cd ${WAMR_PLATFORM_DIR}/linux rm -fr build && mkdir build -cd build && cmake .. -DWAMR_BUILD_SIMD=1 -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_LIBC_EMCC=1 +cd build && cmake .. -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_LIBC_EMCC=1 make # 5. run wasm-av1 with iwasm diff --git a/samples/workload/wasm-av1/build_workload.sh b/samples/workload/wasm-av1/build_workload.sh deleted file mode 120000 index a31afa92..00000000 --- a/samples/workload/wasm-av1/build_workload.sh +++ /dev/null @@ -1 +0,0 @@ -../docker/build_workload.sh \ No newline at end of file diff --git a/test-tools/build-wasi-sdk/patches/wasi_libc.patch b/test-tools/build-wasi-sdk/patches/wasi_libc.patch deleted file mode 100644 index e236735b..00000000 --- a/test-tools/build-wasi-sdk/patches/wasi_libc.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/expected/wasm32-wasi/predefined-macros.txt b/expected/wasm32-wasi/predefined-macros.txt -index c1bb19e..954f3b5 100644 ---- a/expected/wasm32-wasi/predefined-macros.txt -+++ b/expected/wasm32-wasi/predefined-macros.txt -@@ -3002,6 +3002,8 @@ - #define __alignof_is_defined 1 - #define __bitop(x,i,o) ((x)[(i)/8] o (1<<(i)%8)) - #define __bool_true_false_are_defined 1 -+#define __clang_literal_encoding__ "UTF-8" -+#define __clang_wide_literal_encoding__ "UTF-32" - #define __inline inline - #define __restrict restrict - #define __tg_complex(fun,x) (__RETCAST_CX(x)( __FLTCX((x)+I) && __IS_FP(x) ? fun ## f (x) : __LDBLCX((x)+I) ? fun ## l (x) : fun(x) )) diff --git a/test-tools/build-wasi-sdk/patches/wasi_sdk.patch b/test-tools/build-wasi-sdk/patches/wasi_sdk.patch deleted file mode 100644 index 0fc4caee..00000000 --- a/test-tools/build-wasi-sdk/patches/wasi_sdk.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/version.sh b/version.sh -index 8e7c44c..ff0d3ba 100755 ---- a/version.sh -+++ b/version.sh -@@ -1,5 +1,6 @@ - #!/usr/bin/env bash --set -e --GIT_DESCR=$(git describe --long --candidates=999 --match='wasi-sdk-*' --dirty='+m' --abbrev=12) --GIT_PACKAGE_VERSION=$(echo $GIT_DESCR | perl -ne 'if(/^wasi-sdk-(\d+)-(\d+)-g([0-9a-f]{7,12})([+]m)?$/) { if($2 == 0) { print "$1.$2$4" } else { print "$1.$2g$3$4" } exit } else { print "could not parse git description"; exit 1 }';) --echo $GIT_PACKAGE_VERSION -+#set -e -+#GIT_DESCR=$(git describe --long --candidates=999 --match='wasi-sdk-*' --dirty='+m' --abbrev=12) -+#GIT_PACKAGE_VERSION=$(echo $GIT_DESCR | perl -ne 'if(/^wasi-sdk-(\d+)-(\d+)-g([0-9a-f]{7,12})([+]m)?$/) { if($2 == 0) { print "$1.$2$4" } else { print "$1.$2g$3$4" } exit } else { print "could not parse git description"; exit 1 }';) -+#echo $GIT_PACKAGE_VERSION -+echo wasi-sdk-13-eng diff --git a/test-tools/build-wasi-sdk/build_wasi_sdk.py b/test-tools/pick-up-emscripten-headers/collect_files.py similarity index 50% rename from test-tools/build-wasi-sdk/build_wasi_sdk.py rename to test-tools/pick-up-emscripten-headers/collect_files.py index a87cdef6..7e832145 100755 --- a/test-tools/build-wasi-sdk/build_wasi_sdk.py +++ b/test-tools/pick-up-emscripten-headers/collect_files.py @@ -9,68 +9,35 @@ The script operates on such directories and files |-- core | `-- deps | |-- emscripten -| `-- wasi-sdk -| `-- src -| |-- llvm-project -| `-- wasi-libc +|-- samples +| `-- workloads +| |-- include `-- test-tools - |-- build-wasi-sdk - | |-- build_wasi_sdk.py - | |-- include - | `-- patches - `-- wasi-sdk - |-- bin - |-- lib - `-- share - `-- wasi-sysroot + |-- pick-up-emscripten_headers + | |-- collect_files.py """ +import argparse import hashlib import logging import os import pathlib -import shlex import shutil -import subprocess import sys import tarfile import tempfile import urllib import urllib.request -logger = logging.getLogger("build_wasi_sdk") +logger = logging.getLogger("pick-up-emscripten-headers") external_repos = { - "config": { - "sha256": "302e5e7f3c4996976c58efde8b2f28f71d51357e784330eeed738e129300dc33", - "store_dir": "core/deps/wasi-sdk/src/config", - "strip_prefix": "config-191bcb948f7191c36eefe634336f5fc5c0c4c2be", - "url": "https://git.savannah.gnu.org/cgit/config.git/snapshot/config-191bcb948f7191c36eefe634336f5fc5c0c4c2be.tar.gz", - }, "emscripten": { - "sha256": "0904a65379aea3ea94087b8c12985b2fee48599b473e3bef914fec2e3941532d", + "sha256": "c5524755b785d8f4b83eb3214fdd3ac4b2e1b1a4644df4c63f06e5968f48f90e", "store_dir": "core/deps/emscripten", - "strip_prefix": "emscripten-2.0.28", - "url": "https://github.com/emscripten-core/emscripten/archive/refs/tags/2.0.28.tar.gz", - }, - "llvm-project": { - "sha256": "dc5169e51919f2817d06615285e9da6a804f0f881dc55d6247baa25aed3cc143", - "store_dir": "core/deps/wasi-sdk/src/llvm-project", - "strip_prefix": "llvm-project-34ff6a75f58377f32a5046a29f55c4c0e58bee9e", - "url": "https://github.com/llvm/llvm-project/archive/34ff6a75f58377f32a5046a29f55c4c0e58bee9e.tar.gz", - }, - "wasi-sdk": { - "sha256": "fc4fdb0e97b915241f32209492a7d0fab42c24216f87c1d5d75f46f7c70a553d", - "store_dir": "core/deps/wasi-sdk", - "strip_prefix": "wasi-sdk-1a953299860bbcc198ad8c12a21d1b2e2f738355", - "url": "https://github.com/WebAssembly/wasi-sdk/archive/1a953299860bbcc198ad8c12a21d1b2e2f738355.tar.gz", - }, - "wasi-libc": { - "sha256": "f6316ca9479d3463eb1c4f6a1d1f659bf15f67cb3c1e2e83d9d11f188dccd864", - "store_dir": "core/deps/wasi-sdk/src/wasi-libc", - "strip_prefix": "wasi-libc-a78cd329aec717f149934d7362f57050c9401f60", - "url": "https://github.com/WebAssembly/wasi-libc/archive/a78cd329aec717f149934d7362f57050c9401f60.tar.gz", - }, + "strip_prefix": "emscripten-3.0.0", + "url": "https://github.com/emscripten-core/emscripten/archive/refs/tags/3.0.0.tar.gz", + } } # TOOD: can we use headers from wasi-libc and clang directly ? @@ -111,25 +78,25 @@ def unpack(tar_file, strip_prefix, dest_dir): with tempfile.TemporaryDirectory() as tmp: with tarfile.open(tar_file) as tar: logger.debug(f"extract to {tmp}") + def is_within_directory(directory, target): - + abs_directory = os.path.abspath(directory) abs_target = os.path.abspath(target) - + prefix = os.path.commonprefix([abs_directory, abs_target]) - + return prefix == abs_directory - + def safe_extract(tar, path=".", members=None, *, numeric_owner=False): - + for member in tar.getmembers(): member_path = os.path.join(path, member.name) if not is_within_directory(path, member_path): raise Exception("Attempted Path Traversal in Tar File") - - tar.extractall(path, members, numeric_owner=numeric_owner) - - + + tar.extractall(path, members, numeric_owner=numeric_owner) + safe_extract(tar, tmp) strip_prefix_dir = ( @@ -160,12 +127,12 @@ def download_repo(name, root): download_flag = store_dir.joinpath("DOWNLOADED") if store_dir.exists() and download_flag.exists(): logger.info( - f"keep using '{store_dir.relative_to(root)}'. Or to remove it and try again" + f"bypass downloading '{store_dir.relative_to(root)}'. Or to remove it and try again if needs a new release" ) return True # download only when the target is neither existed nor broken - download_dir = pathlib.Path("/tmp/build_wasi_sdk/") + download_dir = pathlib.Path("/tmp/pick-up-emscripten-headers/") download_dir.mkdir(exist_ok=True) tar_name = pathlib.Path(external_repos[name]["url"]).name @@ -192,104 +159,67 @@ def download_repo(name, root): download_flag.touch() # leave download files in /tmp + logger.info(f"Has downloaed and stored in {store_dir.relative_to(root)}") return True -def run_patch(patch_file, cwd): - if not patch_file.exists(): - logger.error(f"{patch_file} not found") +def collect_headers(root, install_location): + if not install_location.exists(): + logger.error(f"{install_location} does not found") return False - with open(patch_file, "r") as f: - try: - PATCH_DRY_RUN_CMD = "patch -f -p1 --dry-run" - if subprocess.check_call(shlex.split(PATCH_DRY_RUN_CMD), stdin=f, cwd=cwd): - logger.error(f"patch dry-run {cwd} failed") - return False + install_flag = install_location.joinpath("INSTALLED").resolve() + if install_flag.exists(): + logger.info( + f"bypass downloading '{install_location}'. Or to remove it and try again if needs a new one" + ) + return True - PATCH_CMD = "patch -f -p1" - f.seek(0) - if subprocess.check_call(shlex.split(PATCH_CMD), stdin=f, cwd=cwd): - logger.error(f"patch {cwd} failed") - return False - except subprocess.CalledProcessError: - logger.error(f"patch {cwd} failed") - return False - return True - - -def build_and_install_wasi_sdk(root): - store_dir = root.joinpath(f'{external_repos["wasi-sdk"]["store_dir"]}').resolve() - if not store_dir.exists(): - logger.error(f"{store_dir} does not found") + emscripten_home = root.joinpath( + f'{external_repos["emscripten"]["store_dir"]}' + ).resolve() + if not emscripten_home.exists(): + logger.error(f"{emscripten_home} does not found") return False - # patch wasi-libc and wasi-sdk - patch_flag = store_dir.joinpath("PATCHED") - if not patch_flag.exists(): - if not run_patch( - root.joinpath("test-tools/build-wasi-sdk/patches/wasi_libc.patch"), - store_dir.joinpath("src/wasi-libc"), - ): - return False - - if not run_patch( - root.joinpath("test-tools/build-wasi-sdk/patches/wasi_sdk.patch"), store_dir - ): - return False - - patch_flag.touch() - else: - logger.info("bypass the patch phase") - - # build - build_flag = store_dir.joinpath("BUILDED") - if not build_flag.exists(): - BUILD_CMD = "make build" - if subprocess.check_call(shlex.split(BUILD_CMD), cwd=store_dir): - logger.error(f"build wasi-sdk failed") - return False - - build_flag.touch() - else: - logger.info("bypass the build phase") - - # install - install_flag = store_dir.joinpath("INSTALLED") - binary_path = root.joinpath("test-tools").resolve() - if not install_flag.exists(): - shutil.copytree( - str(store_dir.joinpath("build/install/opt").resolve()), - str(binary_path), - dirs_exist_ok=True, - ) - - # install headers - emscripten_headers = ( - root.joinpath(external_repos["emscripten"]["store_dir"]) - .joinpath("system") - .resolve() - ) - wasi_sysroot_headers = binary_path.joinpath( - "wasi-sdk/share/wasi-sysroot/include" - ).resolve() - for (src, dst) in emscripten_headers_src_dst: - src = emscripten_headers.joinpath(src) - dst = wasi_sysroot_headers.joinpath(dst) - dst.parent.mkdir(parents=True, exist_ok=True) - shutil.copy(src, dst) - - install_flag.touch() - else: - logger.info("bypass the install phase") + emscripten_headers = emscripten_home.joinpath("system").resolve() + for (src, dst) in emscripten_headers_src_dst: + src = emscripten_headers.joinpath(src) + dst = install_location.joinpath(dst) + dst.parent.mkdir(parents=True, exist_ok=True) + shutil.copy(src, dst) + install_flag.touch() + logger.info(f"Has installed in {install_location}") return True def main(): + parser = argparse.ArgumentParser( + description="collect headers from emscripten for workload compilation" + ) + parser.add_argument( + "--install", + type=str, + required=True, + help="identify installation location", + ) + parser.add_argument( + "--loglevel", + type=str, + default="INFO", + choices=[ + "ERROR", + "WARNING", + "INFO", + ], + help="the logging level", + ) + options = parser.parse_args() + console = logging.StreamHandler() console.setFormatter(logging.Formatter("%(asctime)s - %(message)s")) - logger.setLevel(logging.INFO) + logger.setLevel(getattr(logging, options.loglevel)) logger.addHandler(console) logger.propagate = False @@ -305,12 +235,9 @@ def main(): if not download_repo(repo, root): return False - # build wasi_sdk and install - if not build_and_install_wasi_sdk(root): + if not collect_headers(root, pathlib.Path(options.install)): return False - # TODO install headers from emscripten - return True diff --git a/test-tools/wamr-ide/VSCode-Extension/package.json b/test-tools/wamr-ide/VSCode-Extension/package.json index 9b67e3a1..71cc7487 100644 --- a/test-tools/wamr-ide/VSCode-Extension/package.json +++ b/test-tools/wamr-ide/VSCode-Extension/package.json @@ -6,7 +6,7 @@ }, "displayName": "WAMR-IDE", "description": "An Integrated Development Environment for WASM", - "version": "1.0.0", + "version": "1.1.2", "engines": { "vscode": "^1.59.0" }, diff --git a/test-tools/wamr-ide/VSCode-Extension/src/constants.ts b/test-tools/wamr-ide/VSCode-Extension/src/constants.ts new file mode 100644 index 00000000..cf8bb710 --- /dev/null +++ b/test-tools/wamr-ide/VSCode-Extension/src/constants.ts @@ -0,0 +1,7 @@ +export const enum SelectionOfPrompt { + skip = 'skip', + setUp = 'setup', +} +export const enum Status { + done = 'done', +} diff --git a/test-tools/wamr-ide/VSCode-Extension/src/extension.ts b/test-tools/wamr-ide/VSCode-Extension/src/extension.ts index 17dda949..9d979b7a 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/extension.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/extension.ts @@ -24,6 +24,13 @@ import { getWAMRExtensionVersion, } from './utilities/lldbUtilities'; +import { + checkIfDockerStarted, + checkIfDockerImagesExist, + promptSetupDockerImages, +} from './utilities/dockerUtilities'; +import { SelectionOfPrompt } from './constants'; + let wasmTaskProvider: WasmTaskProvider; let wasmDebugConfigProvider: WasmDebugConfigurationProvider; let currentPrjDir = ''; @@ -304,7 +311,7 @@ export async function activate(context: vscode.ExtensionContext) { const disposableBuild = vscode.commands.registerCommand( 'wamride.build', - () => { + async () => { if (!isWasmProject) { vscode.window.showErrorMessage('Build failed', { modal: true, @@ -313,6 +320,28 @@ export async function activate(context: vscode.ExtensionContext) { return; } + try { + /* check if docker images are ready before building */ + if ( + (await checkIfDockerStarted()) && + !(await checkIfDockerImagesExist(context)) + ) { + /**NOTE - if users select to skip install, + * we should return rather than continue + * the execution + */ + if ( + (await promptSetupDockerImages(context)) === + SelectionOfPrompt.skip + ) { + return; + } + } + } catch (e) { + vscode.window.showWarningMessage((e as Error).message); + return; + } + generateCMakeFile(includePathArr, excludeFileArr); /* destroy the wasm-toolchain-ctr if it exists */ vscode.commands @@ -382,10 +411,35 @@ export async function activate(context: vscode.ExtensionContext) { /* we should check again whether the user installed lldb, as this can be skipped during activation */ try { if (!isLLDBInstalled(context)) { - await promptInstallLLDB(context); + /**NOTE - if users select to skip install, + * we should return rather than continue + * the execution + */ + if ( + (await promptInstallLLDB(context)) === + SelectionOfPrompt.skip + ) { + return; + } + } + + if ( + (await checkIfDockerStarted()) && + !(await checkIfDockerImagesExist(context)) + ) { + /**NOTE - save as above lldb, should return if + * users select to skip set up + */ + if ( + (await promptSetupDockerImages(context)) === + SelectionOfPrompt.skip + ) { + return; + } } } catch (e) { vscode.window.showWarningMessage((e as Error).message); + return; } /* refuse to debug if build process failed */ @@ -461,48 +515,70 @@ export async function activate(context: vscode.ExtensionContext) { } ); - const disposableRun = vscode.commands.registerCommand('wamride.run', () => { - if (!isWasmProject) { - vscode.window.showErrorMessage('run failed', { - modal: true, - detail: 'Current project is not wasm project, please open wasm project and try again.', - }); - return; - } - - /* refuse to debug if build process failed */ - if (!checkIfBuildSuccess()) { - vscode.window.showErrorMessage('Debug failed', { - modal: true, - detail: 'Can not find WASM binary, please build WASM firstly.', - }); - return; - } - vscode.commands - .executeCommand( - 'workbench.action.tasks.runTask', - 'Destroy: Wasm-Container-Before-Run' - ) - .then(() => { - const disposableAft = vscode.tasks.onDidEndTaskProcess(e => { - if (e.execution.task.name === 'Wasm-Container-Before-Run') { - /* make sure that run wasm task will be executed after destroy task finish */ - vscode.commands - .executeCommand( - 'workbench.action.tasks.runTask', - 'Run: Wasm' - ) - .then(() => { - if (e.exitCode !== 0) { - disposableAft.dispose(); - return; - } - }); - disposableAft.dispose(); - } + const disposableRun = vscode.commands.registerCommand( + 'wamride.run', + async () => { + if (!isWasmProject) { + vscode.window.showErrorMessage('run failed', { + modal: true, + detail: 'Current project is not wasm project, please open wasm project and try again.', }); - }); - }); + return; + } + + try { + /* check if docker images are set up before building */ + if ( + (await checkIfDockerStarted()) && + !(await checkIfDockerImagesExist(context)) + ) { + await promptSetupDockerImages(context); + } + } catch (e) { + vscode.window.showWarningMessage((e as Error).message); + return; + } + + /* refuse to debug if build process failed */ + if (!checkIfBuildSuccess()) { + vscode.window.showErrorMessage('Debug failed', { + modal: true, + detail: 'Can not find WASM binary, please build WASM firstly.', + }); + return; + } + + vscode.commands + .executeCommand( + 'workbench.action.tasks.runTask', + 'Destroy: Wasm-Container-Before-Run' + ) + .then(() => { + const disposableAft = vscode.tasks.onDidEndTaskProcess( + e => { + if ( + e.execution.task.name === + 'Wasm-Container-Before-Run' + ) { + /* make sure that run wasm task will be executed when destroy task finish */ + vscode.commands + .executeCommand( + 'workbench.action.tasks.runTask', + 'Run: Wasm' + ) + .then(() => { + if (e.exitCode !== 0) { + disposableAft.dispose(); + return; + } + }); + disposableAft.dispose(); + } + } + ); + }); + } + ); const disposableToggleIncludePath = vscode.commands.registerCommand( 'wamride.build.toggleStateIncludePath', @@ -700,6 +776,13 @@ export async function activate(context: vscode.ExtensionContext) { if (!isLLDBInstalled(context)) { await promptInstallLLDB(context); } + + if ( + (await checkIfDockerStarted()) && + !(await checkIfDockerImagesExist(context)) + ) { + await promptSetupDockerImages(context); + } } catch (e) { vscode.window.showWarningMessage((e as Error).message); } diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/dockerUtilities.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/dockerUtilities.ts new file mode 100644 index 00000000..0a749ba1 --- /dev/null +++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/dockerUtilities.ts @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +import * as vscode from 'vscode'; +import * as cp from 'child_process'; +import * as path from 'path'; +import * as fs from 'fs'; +import { getWAMRExtensionVersion } from './lldbUtilities'; +import { downloadFile, unzipFile } from './directoryUtilities'; +import { SelectionOfPrompt, Status } from '../constants'; + +const DOCKER_IMAGES_TEM_FOLDER_NAME = 'docker-resource'; + +type SelectionStatus = SelectionOfPrompt | Status; + +const execShell = (cmd: string) => + new Promise((resolve, reject) => { + cp.exec(cmd, (error, result) => { + if (error) { + return reject(error); + } + return resolve(result); + }); + }); + +export async function promptSetupDockerImages( + context: vscode.ExtensionContext +): Promise { + const extensionPath = context.extensionPath; + const response = await vscode.window.showWarningMessage( + 'Necessary docker images are not found. Setup now?', + SelectionOfPrompt.setUp, + SelectionOfPrompt.skip + ); + + if (response === SelectionOfPrompt.skip) { + return response; + } + + const downloadUrlArray = getDockerImagesDownloadUrl(context); + + const destinationFolder = path.resolve( + extensionPath, + 'resource', + DOCKER_IMAGES_TEM_FOLDER_NAME + ); + + if (!fs.existsSync(destinationFolder)) { + fs.mkdirSync(destinationFolder); + } + + vscode.window.showInformationMessage(`Downloading Docker Images...`); + + for (const url of downloadUrlArray) { + const imageZipName = path.basename(url); + const imageStorePath = path.join(destinationFolder, imageZipName); + await downloadFile(url, imageStorePath); + + /** + * extract docker image tar package to + * '${destinationFolder}' + */ + const dockerImageFile = await unzipFile(imageStorePath, filename => + path.join(destinationFolder, filename) + ); + /* give access before loading */ + dockerImageFile.forEach(file => fs.chmodSync(file, '0775')); + + /**NOTE - load docker image tar package to host + * right now there are just one file + * `docker-image-name.tar` inside so we can + * directly use files[0] here, should be modified + * if the package's files change + */ + await execShell(`docker load -i ${dockerImageFile[0]}`); + } + + /* remove the DOCKER_IMAGES_TEM_FOLDER */ + fs.rmSync(destinationFolder, { recursive: true, force: true }); + + vscode.window.showInformationMessage( + `Docker images are ready, please run '$docker images' to check.` + ); + + return Status.done; +} + +export async function checkIfDockerStarted(): Promise { + try { + await execShell('docker images'); + return true; + } catch (e) { + vscode.window.showWarningMessage((e as Error).message); + return false; + } +} + +export async function checkIfDockerImagesExist( + context: vscode.ExtensionContext +): Promise { + try { + /* the tag of images is equal to extension's version */ + const imageTag = getWAMRExtensionVersion(context); + await execShell( + `docker image inspect wasm-debug-server:${imageTag} wasm-toolchain:${imageTag}` + ); + return true; + } catch (e) { + return false; + } +} + +function getDockerImagesDownloadUrl( + context: vscode.ExtensionContext +): string[] { + const wamrVersion = getWAMRExtensionVersion(context); + const wamrReleaseUrl = `https://github.com/bytecodealliance/wasm-micro-runtime/releases/download/WAMR`; + + return [ + `${wamrReleaseUrl}-${wamrVersion}/wasm-debug-server-${wamrVersion}.zip`, + `${wamrReleaseUrl}-${wamrVersion}/wasm-toolchain-${wamrVersion}.zip`, + ]; +} diff --git a/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts b/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts index a1729ab9..210ad020 100644 --- a/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts +++ b/test-tools/wamr-ide/VSCode-Extension/src/utilities/lldbUtilities.ts @@ -12,6 +12,7 @@ import { downloadFile, unzipFile, } from './directoryUtilities'; +import { SelectionOfPrompt, Status } from '../constants'; const LLDB_RESOURCE_DIR = 'resource/debug'; const LLDB_OS_DOWNLOAD_URL_SUFFIX_MAP: Partial< @@ -67,18 +68,17 @@ export function isLLDBInstalled(context: vscode.ExtensionContext): boolean { export async function promptInstallLLDB( context: vscode.ExtensionContext -): Promise { +): Promise { const extensionPath = context.extensionPath; - const setupPrompt = 'setup'; - const skipPrompt = 'skip'; + const response = await vscode.window.showWarningMessage( 'No LLDB instance found. Setup now?', - setupPrompt, - skipPrompt + SelectionOfPrompt.setUp, + SelectionOfPrompt.skip ); - if (response === skipPrompt) { - return; + if (response === SelectionOfPrompt.skip) { + return response; } const downloadUrl = getLLDBDownloadUrl(context); @@ -114,7 +114,6 @@ export async function promptInstallLLDB( ); // Remove the bundle.zip - fs.unlink(lldbZipPath, () => { - return; - }); + fs.unlinkSync(lldbZipPath); + return SelectionOfPrompt.setUp; } diff --git a/test-tools/wamr-ide/WASM-Toolchain/Docker/Dockerfile b/test-tools/wamr-ide/WASM-Toolchain/Docker/Dockerfile index f96a2261..6ca21094 100644 --- a/test-tools/wamr-ide/WASM-Toolchain/Docker/Dockerfile +++ b/test-tools/wamr-ide/WASM-Toolchain/Docker/Dockerfile @@ -25,17 +25,17 @@ RUN wget --progress=dot:giga https://github.com/Kitware/CMake/releases/download/ # - wamr-sdk ## - download wasi-sdk with wget and set up to /opt/wasi-sdk -RUN wget --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-14/wasi-sdk-14.0-linux.tar.gz \ - && tar -zxvf wasi-sdk-14.0-linux.tar.gz \ - && mv wasi-sdk-14.0 /opt/wasi-sdk/ \ - && rm -f wasi-sdk-14.0-linux.tar.gz +RUN wget --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz \ + && tar -zxvf wasi-sdk-*-linux.tar.gz \ + && mv wasi-sdk-19.0 /opt/wasi-sdk/ \ + && rm -f wasi-sdk-*-linux.tar.gz ## - clone wamr repo -RUN git clone -b main --depth=1 https://github.com/bytecodealliance/wasm-micro-runtime.git +RUN git clone -b main --depth=1 https://github.com/bytecodealliance/wasm-micro-runtime.git WORKDIR /root/wasm-micro-runtime/wamr-compiler RUN ./build_llvm.sh \ - && mkdir build + && mkdir build WORKDIR /root/wasm-micro-runtime/wamr-compiler/build RUN cmake .. \ diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index 04883520..7b29bcba 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -111,6 +111,7 @@ def test_case( verbose_flag=True, qemu_flag=False, qemu_firmware='', + log='', ): case_path = pathlib.Path(case_path).resolve() case_name = case_path.stem @@ -170,6 +171,10 @@ def test_case( if not clean_up_flag: CMD.append("--no_cleanup") + if log != '': + CMD.append("--log-dir") + CMD.append(log) + CMD.append(case_path) print(f"============> run {case_name} ", end="") with subprocess.Popen( @@ -228,7 +233,8 @@ def test_suite( verbose_flag=True, parl_flag=False, qemu_flag=False, - qemu_firmware='' + qemu_firmware='', + log='', ): suite_path = pathlib.Path(SPEC_TEST_DIR).resolve() if not suite_path.exists(): @@ -264,6 +270,7 @@ def test_suite( verbose_flag, qemu_flag, qemu_firmware, + log, ], ) @@ -299,6 +306,7 @@ def test_suite( verbose_flag, qemu_flag, qemu_firmware, + log, ) successful_case += 1 except Exception as e: @@ -393,6 +401,12 @@ def main(): dest="qemu_firmware", help="Firmware required by qemu", ) + parser.add_argument( + "--log", + default='', + dest="log", + help="Log directory", + ) parser.add_argument( "--quiet", action="store_false", @@ -435,6 +449,7 @@ def main(): options.parl_flag, options.qemu_flag, options.qemu_firmware, + options.log, ) end = time.time_ns() print( @@ -455,7 +470,8 @@ def main(): options.clean_up_flag, options.verbose_flag, options.qemu_flag, - options.qemu_firmware + options.qemu_firmware, + options.log ) else: ret = True diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index a61f03b1..ef887c79 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -200,6 +200,8 @@ parser.add_argument('--no-pty', action='store_true', help="Use direct pipes instead of pseudo-tty") parser.add_argument('--log-file', type=str, help="Write messages to the named file in addition the screen") +parser.add_argument('--log-dir', type=str, + help="The log directory to save the case file if test failed") parser.add_argument('--debug-file', type=str, help="Write all test interaction the named file") @@ -1092,6 +1094,7 @@ def test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, if __name__ == "__main__": opts = parser.parse_args(sys.argv[1:]) + print('Input param :',opts) if opts.aot: test_aot = True # default x86_64 @@ -1271,12 +1274,16 @@ if __name__ == "__main__": print("THE FINAL EXCEPTION IS {}".format(e)) ret_code = 101 + shutil.copyfile(wasm_tempfile, os.path.join(opts.log_dir, os.path.basename(wasm_tempfile))) + if opts.aot or opts.xip: + shutil.copyfile(aot_tempfile, os.path.join(opts.log_dir,os.path.basename(aot_tempfile))) if "indirect-mode" in str(e): compile_wasm_to_aot(wasm_tempfile, aot_tempfile, None, opts, None, "object") + shutil.copyfile(aot_tempfile, os.path.join(opts.log_dir,os.path.basename(aot_tempfile)+'.o')) subprocess.check_call(["llvm-objdump", "-r", aot_tempfile]) compile_wasm_to_aot(wasm_tempfile, aot_tempfile, None, opts, None, "ir") - subprocess.check_call(["cat", aot_tempfile]) + shutil.copyfile(aot_tempfile, os.path.join(opts.log_dir,os.path.basename(aot_tempfile)+".ir")) else: ret_code = 0 diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 00797b31..342b3b93 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -360,16 +360,16 @@ function spec_test() exit 1 ;; esac - if [ ! -f /tmp/wabt-1.0.29-${WABT_PLATFORM}.tar.gz ]; then + if [ ! -f /tmp/wabt-1.0.31-${WABT_PLATFORM}.tar.gz ]; then wget \ - https://github.com/WebAssembly/wabt/releases/download/1.0.29/wabt-1.0.29-${WABT_PLATFORM}.tar.gz \ + https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-${WABT_PLATFORM}.tar.gz \ -P /tmp fi cd /tmp \ - && tar zxf wabt-1.0.29-${WABT_PLATFORM}.tar.gz \ + && tar zxf wabt-1.0.31-${WABT_PLATFORM}.tar.gz \ && mkdir -p ${WORK_DIR}/wabt/out/gcc/Release/ \ - && install wabt-1.0.29/bin/wa* ${WORK_DIR}/wabt/out/gcc/Release/ \ + && install wabt-1.0.31/bin/wa* ${WORK_DIR}/wabt/out/gcc/Release/ \ && cd - fi else @@ -429,7 +429,7 @@ function spec_test() fi # set the current running target - ARGS_FOR_SPEC_TEST+="-m ${TARGET} " + ARGS_FOR_SPEC_TEST+="-m ${TARGET} " # require warmc only in aot mode if [[ $1 == 'aot' ]]; then @@ -442,9 +442,12 @@ function spec_test() if [[ ${ENABLE_QEMU} == 1 ]]; then ARGS_FOR_SPEC_TEST+="--qemu " - ARGS_FOR_SPEC_TEST+="--qemu-firmware ${QEMU_FIRMWARE}" + ARGS_FOR_SPEC_TEST+="--qemu-firmware ${QEMU_FIRMWARE} " fi + # set log directory + ARGS_FOR_SPEC_TEST+="--log ${REPORT_DIR}" + cd ${WORK_DIR} echo "python3 ./all.py ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt" python3 ./all.py ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index 28986e86..f185a17b 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -59,6 +59,7 @@ print_help() printf(" --disable-aux-stack-check Disable auxiliary stack overflow/underflow check\n"); printf(" --enable-dump-call-stack Enable stack trace feature\n"); printf(" --enable-perf-profiling Enable function performance profiling\n"); + printf(" --enable-memory-profiling Enable memory usage profiling\n"); printf(" --enable-indirect-mode Enalbe call function through symbol table but not direct call\n"); printf(" --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n"); printf(" --disable-llvm-lto Disable the LLVM link time optimization\n"); @@ -254,6 +255,9 @@ main(int argc, char *argv[]) else if (!strcmp(argv[0], "--enable-perf-profiling")) { option.enable_aux_stack_frame = true; } + else if (!strcmp(argv[0], "--enable-memory-profiling")) { + option.enable_stack_estimation = true; + } else if (!strcmp(argv[0], "--enable-indirect-mode")) { option.is_indirect_mode = true; }