mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-09 13:16:26 +00:00
Merge branch main into dev/wasi_threads
This commit is contained in:
commit
e170c355a2
|
@ -12,7 +12,7 @@ ENV TZ=Asian/Shanghai
|
||||||
# hadolint ignore=DL3008
|
# hadolint ignore=DL3008
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y apt-transport-https apt-utils build-essential \
|
&& 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 \
|
libgcc-9-dev lib32gcc-9-dev lsb-release \
|
||||||
ninja-build ocaml ocamlbuild python2.7 \
|
ninja-build ocaml ocamlbuild python2.7 \
|
||||||
software-properties-common tree tzdata \
|
software-properties-common tree tzdata \
|
||||||
|
@ -20,6 +20,15 @@ RUN apt-get update \
|
||||||
&& apt-get clean -y \
|
&& apt-get clean -y \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& 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/)
|
# CMAKE (https://apt.kitware.com/)
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
|
@ -38,18 +47,19 @@ RUN wget --progress=dot:giga -O - https://apt.kitware.com/keys/kitware-archive-l
|
||||||
WORKDIR /opt
|
WORKDIR /opt
|
||||||
RUN git clone https://github.com/emscripten-core/emsdk.git
|
RUN git clone https://github.com/emscripten-core/emsdk.git
|
||||||
|
|
||||||
|
ARG EMSDK_VER=3.0.0
|
||||||
WORKDIR /opt/emsdk
|
WORKDIR /opt/emsdk
|
||||||
RUN git pull \
|
RUN git pull \
|
||||||
&& ./emsdk install 2.0.26 \
|
&& ./emsdk install ${EMSDK_VER} \
|
||||||
&& ./emsdk activate 2.0.26 \
|
&& ./emsdk activate ${EMSDK_VER} \
|
||||||
&& echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc
|
&& echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc
|
||||||
|
|
||||||
#
|
#
|
||||||
# install wasi-sdk
|
# 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 \
|
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 \
|
&& 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
|
&& rm /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -57,7 +67,7 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases
|
||||||
ARG WABT_VER=1.0.29
|
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 \
|
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 \
|
&& 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
|
&& rm /opt/wabt-${WABT_VER}-ubuntu.tar.gz
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -70,6 +80,8 @@ RUN mkdir /opt/bazelisk \
|
||||||
|
|
||||||
#
|
#
|
||||||
# install clang+llvm
|
# 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
|
WORKDIR /etc/apt/apt.conf.d
|
||||||
RUN touch 99verfiy-peer.conf \
|
RUN touch 99verfiy-peer.conf \
|
||||||
&& echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf
|
&& echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf
|
||||||
|
@ -77,9 +89,7 @@ RUN touch 99verfiy-peer.conf \
|
||||||
WORKDIR /tmp
|
WORKDIR /tmp
|
||||||
RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
|
RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
|
||||||
&& chmod a+x ./llvm.sh \
|
&& chmod a+x ./llvm.sh \
|
||||||
&& /tmp/llvm.sh 12 all \
|
&& ./llvm.sh ${LLVM_VER} all
|
||||||
&& ln -sf /usr/bin/clang-format-12 /usr/bin/clang-format \
|
|
||||||
&& rm -rf /tmp/*
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# [Optional]
|
# [Optional]
|
||||||
|
@ -96,17 +106,28 @@ RUN apt-get update \
|
||||||
# Install required python packages
|
# Install required python packages
|
||||||
# hadolint ignore=DL3013
|
# hadolint ignore=DL3013
|
||||||
RUN python3 -m pip install --no-cache-dir --upgrade pip \
|
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}"
|
# Install github-cli. It doens't work as a feature of devcontainer.json
|
||||||
RUN echo "export PATH=/opt/bazelisk:/opt/clang-llvm/bin:${PATH}" >> /root/.bashrc \
|
RUN cd /tmp \
|
||||||
&& printf "%s\n" "PS1='\n[ \u@wamr-dev-docker \W ]\n$ '" >> /root/.bashrc \
|
&& 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 autoremove -y \
|
||||||
&& apt-get clean -y \
|
&& apt-get clean -y \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& rm -rf /tmp/*
|
&& rm -rf /tmp/*
|
||||||
|
|
||||||
# set workdir when container run
|
# set workdir when container run
|
||||||
VOLUME /workspace
|
VOLUME /workspaces
|
||||||
WORKDIR /workspace
|
WORKDIR /workspaces
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright (C) 2019 Intel Corporation. All rights reserved.
|
// Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
// 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:
|
// 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
|
// 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
|
// 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
|
// Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon
|
||||||
"args": {
|
"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": [
|
"runArgs": [
|
||||||
|
@ -27,12 +31,10 @@
|
||||||
// Add the IDs of extensions you want installed when the container is created.
|
// Add the IDs of extensions you want installed when the container is created.
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"dtsvet.vscode-wasm",
|
"dtsvet.vscode-wasm",
|
||||||
"esbenp.prettier-vscode",
|
"llvm-vs-code-extensions.vscode-clangd",
|
||||||
"ms-python.python",
|
"ms-python.python",
|
||||||
"ms-python.vscode-pylance",
|
"ms-python.vscode-pylance",
|
||||||
"ms-vscode.cmake-tools",
|
"ms-vscode.cmake-tools",
|
||||||
"ms-vscode.cpptools",
|
|
||||||
"twxs.cmake"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
2
.github/workflows/build_iwasm_release.yml
vendored
2
.github/workflows/build_iwasm_release.yml
vendored
|
@ -36,7 +36,7 @@ jobs:
|
||||||
- name: generate iwasm binary release
|
- name: generate iwasm binary release
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B build \
|
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_CUSTOM_NAME_SECTION=0 \
|
||||||
-DWAMR_BUILD_DEBUG_INTERP=0 \
|
-DWAMR_BUILD_DEBUG_INTERP=0 \
|
||||||
-DWAMR_BUILD_DEBUG_AOT=0 \
|
-DWAMR_BUILD_DEBUG_AOT=0 \
|
||||||
|
|
74
.github/workflows/build_llvm_libraries.yml
vendored
74
.github/workflows/build_llvm_libraries.yml
vendored
|
@ -5,23 +5,46 @@ name: Reusable workflow-build_llvm_libraries
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
runs-on:
|
os:
|
||||||
required: true
|
required: true
|
||||||
type: string
|
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:
|
jobs:
|
||||||
build_llvm_libraries:
|
build_llvm_libraries:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ inputs.os }}
|
||||||
strategy:
|
outputs:
|
||||||
matrix:
|
key: ${{ steps.create_lib_cache_key.outputs.key}}
|
||||||
os: ${{ fromJson(inputs.runs-on) }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
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
|
- name: Cache LLVM libraries
|
||||||
id: cache_llvm
|
id: retrieve_llvm_libs
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -30,10 +53,39 @@ jobs:
|
||||||
./core/deps/llvm/build/lib
|
./core/deps/llvm/build/lib
|
||||||
./core/deps/llvm/build/libexec
|
./core/deps/llvm/build/libexec
|
||||||
./core/deps/llvm/build/share
|
./core/deps/llvm/build/share
|
||||||
key: ${{ matrix.os }}-build-llvm_libraries_ex
|
key: ${{ steps.create_lib_cache_key.outputs.key}}
|
||||||
|
|
||||||
- name: Build llvm
|
- uses: actions/cache@v3
|
||||||
id: build_llvm
|
with:
|
||||||
if: ${{ steps.cache_llvm.outputs.cache-hit != 'true' }}
|
path: ~/.ccache
|
||||||
run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly
|
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
|
working-directory: build-scripts
|
||||||
|
|
|
@ -15,7 +15,7 @@ concurrency:
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
complinace_job:
|
compliance_job:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
160
.github/workflows/compilation_on_android_ubuntu.yml
vendored
160
.github/workflows/compilation_on_android_ubuntu.yml
vendored
|
@ -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"
|
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_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_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
|
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"
|
||||||
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
|
|
||||||
# For Spec Test
|
# For Spec Test
|
||||||
DEFAULT_TEST_OPTIONS: "-s spec -b -P"
|
DEFAULT_TEST_OPTIONS: "-s spec -b -P"
|
||||||
MULTI_MODULES_TEST_OPTIONS: "-s spec -b -M -P"
|
MULTI_MODULES_TEST_OPTIONS: "-s spec -b -M -P"
|
||||||
|
@ -64,23 +63,37 @@ env:
|
||||||
WASI_TEST_OPTIONS: "-s wasi_certification"
|
WASI_TEST_OPTIONS: "-s wasi_certification"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_llvm_libraries:
|
build_llvm_libraries_on_ubuntu_2004:
|
||||||
uses: ./.github/workflows/build_llvm_libraries.yml
|
uses: ./.github/workflows/build_llvm_libraries.yml
|
||||||
with:
|
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:
|
build_wamrc:
|
||||||
needs: [build_llvm_libraries]
|
needs:
|
||||||
|
[build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2204]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
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:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
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
|
- name: Get LLVM libraries
|
||||||
id: cache_llvm
|
id: retrieve_llvm_libs
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -89,10 +102,10 @@ jobs:
|
||||||
./core/deps/llvm/build/lib
|
./core/deps/llvm/build/lib
|
||||||
./core/deps/llvm/build/libexec
|
./core/deps/llvm/build/libexec
|
||||||
./core/deps/llvm/build/share
|
./core/deps/llvm/build/share
|
||||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
key: ${{ matrix.llvm_cache_key }}
|
||||||
|
|
||||||
- name: Quit if cache miss
|
- 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
|
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||||
|
|
||||||
- name: Build wamrc
|
- name: Build wamrc
|
||||||
|
@ -103,7 +116,8 @@ jobs:
|
||||||
working-directory: wamr-compiler
|
working-directory: wamr-compiler
|
||||||
|
|
||||||
build_iwasm:
|
build_iwasm:
|
||||||
needs: [build_llvm_libraries]
|
needs:
|
||||||
|
[build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2204]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
@ -115,6 +129,7 @@ jobs:
|
||||||
$FAST_JIT_BUILD_OPTIONS,
|
$FAST_JIT_BUILD_OPTIONS,
|
||||||
$LLVM_LAZY_JIT_BUILD_OPTIONS,
|
$LLVM_LAZY_JIT_BUILD_OPTIONS,
|
||||||
$LLVM_EAGER_JIT_BUILD_OPTIONS,
|
$LLVM_EAGER_JIT_BUILD_OPTIONS,
|
||||||
|
$MULTI_TIER_JIT_BUILD_OPTIONS,
|
||||||
]
|
]
|
||||||
make_options_feature: [
|
make_options_feature: [
|
||||||
# Features
|
# Features
|
||||||
|
@ -147,6 +162,8 @@ jobs:
|
||||||
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
|
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
|
||||||
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
||||||
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
|
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
|
# SIMD only on JIT/AOT mode
|
||||||
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
|
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
|
||||||
make_options_feature: "-DWAMR_BUILD_SIMD=1"
|
make_options_feature: "-DWAMR_BUILD_SIMD=1"
|
||||||
|
@ -163,6 +180,8 @@ jobs:
|
||||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||||
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
||||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
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
|
# DEBUG_AOT only on JIT/AOT mode
|
||||||
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
|
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
|
||||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||||
|
@ -175,6 +194,8 @@ jobs:
|
||||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||||
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
||||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
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
|
# MINI_LOADER only on INTERP mode
|
||||||
- make_options_run_mode: $AOT_BUILD_OPTIONS
|
- make_options_run_mode: $AOT_BUILD_OPTIONS
|
||||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||||
|
@ -184,16 +205,28 @@ jobs:
|
||||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||||
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
||||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
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
|
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
|
||||||
platform: android
|
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:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
# only download llvm cache when needed
|
# only download llvm cache when needed
|
||||||
- name: Get LLVM libraries
|
- name: Get LLVM libraries
|
||||||
id: cache_llvm
|
id: retrieve_llvm_libs
|
||||||
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
|
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
|
@ -203,10 +236,10 @@ jobs:
|
||||||
./core/deps/llvm/build/lib
|
./core/deps/llvm/build/lib
|
||||||
./core/deps/llvm/build/libexec
|
./core/deps/llvm/build/libexec
|
||||||
./core/deps/llvm/build/share
|
./core/deps/llvm/build/share
|
||||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
key: ${{ matrix.llvm_cache_key }}
|
||||||
|
|
||||||
- name: Quit if cache miss
|
- 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
|
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||||
|
|
||||||
- name: Build iwasm
|
- name: Build iwasm
|
||||||
|
@ -217,7 +250,13 @@ jobs:
|
||||||
working-directory: product-mini/platforms/${{ matrix.platform }}
|
working-directory: product-mini/platforms/${{ matrix.platform }}
|
||||||
|
|
||||||
build_samples_wasm_c_api:
|
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 }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
@ -229,22 +268,28 @@ jobs:
|
||||||
$FAST_JIT_BUILD_OPTIONS,
|
$FAST_JIT_BUILD_OPTIONS,
|
||||||
$LLVM_LAZY_JIT_BUILD_OPTIONS,
|
$LLVM_LAZY_JIT_BUILD_OPTIONS,
|
||||||
$LLVM_EAGER_JIT_BUILD_OPTIONS,
|
$LLVM_EAGER_JIT_BUILD_OPTIONS,
|
||||||
|
$MULTI_TIER_JIT_BUILD_OPTIONS,
|
||||||
]
|
]
|
||||||
os: [ubuntu-20.04, ubuntu-22.04]
|
os: [ubuntu-20.04, ubuntu-22.04]
|
||||||
wasi_sdk_release:
|
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:
|
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:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Get LLVM libraries
|
- name: Get LLVM libraries
|
||||||
id: cache_llvm
|
id: retrieve_llvm_libs
|
||||||
if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
|
if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
|
@ -254,18 +299,18 @@ jobs:
|
||||||
./core/deps/llvm/build/lib
|
./core/deps/llvm/build/lib
|
||||||
./core/deps/llvm/build/libexec
|
./core/deps/llvm/build/libexec
|
||||||
./core/deps/llvm/build/share
|
./core/deps/llvm/build/share
|
||||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
key: ${{ matrix.llvm_cache_key }}
|
||||||
|
|
||||||
- name: Quit if cache miss
|
- 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
|
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||||
|
|
||||||
- name: download and install wabt
|
- name: download and install wabt
|
||||||
run: |
|
run: |
|
||||||
cd /opt
|
cd /opt
|
||||||
sudo wget ${{ matrix.wabt_release }}
|
sudo wget ${{ matrix.wabt_release }}
|
||||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||||
sudo mv wabt-1.0.24 wabt
|
sudo mv wabt-1.0.31 wabt
|
||||||
|
|
||||||
- name: Build wamrc
|
- name: Build wamrc
|
||||||
if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
|
if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
|
||||||
|
@ -277,19 +322,9 @@ jobs:
|
||||||
|
|
||||||
- name: Build Sample [wasm-c-api]
|
- name: Build Sample [wasm-c-api]
|
||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
cmake -S . -B build ${{ matrix.make_options }}
|
||||||
cmake .. ${{ matrix.make_options }}
|
cmake --build build --config Release --parallel 4
|
||||||
cmake --build . --config Release --parallel 4
|
ctest --test-dir build
|
||||||
./callback
|
|
||||||
./callback_chain
|
|
||||||
./empty_imports
|
|
||||||
./global
|
|
||||||
./hello
|
|
||||||
./hostref
|
|
||||||
./memory
|
|
||||||
./reflect
|
|
||||||
./table
|
|
||||||
./trap
|
|
||||||
working-directory: samples/wasm-c-api
|
working-directory: samples/wasm-c-api
|
||||||
|
|
||||||
build_samples_others:
|
build_samples_others:
|
||||||
|
@ -298,14 +333,13 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-20.04, ubuntu-22.04]
|
os: [ubuntu-20.04, ubuntu-22.04]
|
||||||
wasi_sdk_release:
|
include:
|
||||||
[
|
- os: ubuntu-20.04
|
||||||
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-linux.tar.gz",
|
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"
|
||||||
wabt_release:
|
- 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"
|
||||||
"https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz",
|
wabt_release: "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz"
|
||||||
]
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
@ -314,15 +348,15 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
cd /opt
|
cd /opt
|
||||||
sudo wget ${{ matrix.wasi_sdk_release }}
|
sudo wget ${{ matrix.wasi_sdk_release }}
|
||||||
sudo tar -xzf wasi-sdk-16.0-*.tar.gz
|
sudo tar -xzf wasi-sdk-*.tar.gz
|
||||||
sudo mv wasi-sdk-16.0 wasi-sdk
|
sudo mv wasi-sdk-19.0 wasi-sdk
|
||||||
|
|
||||||
- name: download and install wabt
|
- name: download and install wabt
|
||||||
run: |
|
run: |
|
||||||
cd /opt
|
cd /opt
|
||||||
sudo wget ${{ matrix.wabt_release }}
|
sudo wget ${{ matrix.wabt_release }}
|
||||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||||
sudo mv wabt-1.0.24 wabt
|
sudo mv wabt-1.0.31 wabt
|
||||||
|
|
||||||
- name: build wasi-libc (needed for wasi-threads)
|
- name: build wasi-libc (needed for wasi-threads)
|
||||||
run: |
|
run: |
|
||||||
|
@ -402,12 +436,19 @@ jobs:
|
||||||
./iwasm wasm-apps/no_pthread.wasm
|
./iwasm wasm-apps/no_pthread.wasm
|
||||||
|
|
||||||
test:
|
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
|
runs-on: ubuntu-20.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
running_mode:
|
running_mode:
|
||||||
["classic-interp", "fast-interp", "jit", "aot", "fast-jit"]
|
[
|
||||||
|
"classic-interp",
|
||||||
|
"fast-interp",
|
||||||
|
"jit",
|
||||||
|
"aot",
|
||||||
|
"fast-jit",
|
||||||
|
"multi-tier-jit",
|
||||||
|
]
|
||||||
test_option:
|
test_option:
|
||||||
[
|
[
|
||||||
$DEFAULT_TEST_OPTIONS,
|
$DEFAULT_TEST_OPTIONS,
|
||||||
|
@ -416,6 +457,8 @@ jobs:
|
||||||
$THREADS_TEST_OPTIONS,
|
$THREADS_TEST_OPTIONS,
|
||||||
$WASI_TEST_OPTIONS,
|
$WASI_TEST_OPTIONS,
|
||||||
]
|
]
|
||||||
|
llvm_cache_key:
|
||||||
|
["${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}"]
|
||||||
exclude:
|
exclude:
|
||||||
# uncompatiable modes and features
|
# uncompatiable modes and features
|
||||||
# classic-interp and fast-interp don't support simd
|
# classic-interp and fast-interp don't support simd
|
||||||
|
@ -431,32 +474,39 @@ jobs:
|
||||||
test_option: $WASI_TEST_OPTIONS
|
test_option: $WASI_TEST_OPTIONS
|
||||||
- running_mode: "jit"
|
- running_mode: "jit"
|
||||||
test_option: $MULTI_MODULES_TEST_OPTIONS
|
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"
|
- running_mode: "fast-jit"
|
||||||
test_option: $MULTI_MODULES_TEST_OPTIONS
|
test_option: $MULTI_MODULES_TEST_OPTIONS
|
||||||
- running_mode: "fast-jit"
|
- running_mode: "fast-jit"
|
||||||
test_option: $SIMD_TEST_OPTIONS
|
test_option: $SIMD_TEST_OPTIONS
|
||||||
- running_mode: "fast-jit"
|
- running_mode: "fast-jit"
|
||||||
test_option: $THREADS_TEST_OPTIONS
|
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:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: set env variable(if llvm are used)
|
- 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
|
run: echo "USE_LLVM=true" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: set env variable(if x86_32 test needed)
|
- name: set env variable(if x86_32 test needed)
|
||||||
if: >
|
if: >
|
||||||
(matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS'
|
(matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS'
|
||||||
|| matrix.test_option == '$WASI_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
|
run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV
|
||||||
|
|
||||||
#only download llvm libraries in jit and aot mode
|
#only download llvm libraries in jit and aot mode
|
||||||
- name: Get LLVM libraries
|
- name: Get LLVM libraries
|
||||||
if: env.USE_LLVM == 'true'
|
if: env.USE_LLVM == 'true'
|
||||||
id: cache_llvm
|
id: retrieve_llvm_libs
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -465,10 +515,10 @@ jobs:
|
||||||
./core/deps/llvm/build/lib
|
./core/deps/llvm/build/lib
|
||||||
./core/deps/llvm/build/libexec
|
./core/deps/llvm/build/libexec
|
||||||
./core/deps/llvm/build/share
|
./core/deps/llvm/build/share
|
||||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
key: ${{ matrix.llvm_cache_key }}
|
||||||
|
|
||||||
- name: Quit if cache miss
|
- 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
|
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||||
|
|
||||||
- name: run tests
|
- name: run tests
|
||||||
|
|
71
.github/workflows/compilation_on_macos.yml
vendored
71
.github/workflows/compilation_on_macos.yml
vendored
|
@ -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"
|
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_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_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:
|
jobs:
|
||||||
build_llvm_libraries:
|
build_llvm_libraries:
|
||||||
uses: ./.github/workflows/build_llvm_libraries.yml
|
uses: ./.github/workflows/build_llvm_libraries.yml
|
||||||
with:
|
with:
|
||||||
runs-on: "['macos-latest']"
|
os: "macos-latest"
|
||||||
|
arch: "X86"
|
||||||
|
|
||||||
build_wamrc:
|
build_wamrc:
|
||||||
needs: [build_llvm_libraries]
|
needs: [build_llvm_libraries]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-latest]
|
include:
|
||||||
|
- os: macos-latest
|
||||||
|
llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Get LLVM libraries
|
- name: Get LLVM libraries
|
||||||
id: cache_llvm
|
id: retrieve_llvm_libs
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -79,10 +81,10 @@ jobs:
|
||||||
./core/deps/llvm/build/lib
|
./core/deps/llvm/build/lib
|
||||||
./core/deps/llvm/build/libexec
|
./core/deps/llvm/build/libexec
|
||||||
./core/deps/llvm/build/share
|
./core/deps/llvm/build/share
|
||||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
key: ${{ matrix.llvm_cache_key }}
|
||||||
|
|
||||||
- name: Quit if cache miss
|
- 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
|
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||||
|
|
||||||
- name: Build wamrc
|
- name: Build wamrc
|
||||||
|
@ -166,13 +168,16 @@ jobs:
|
||||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||||
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
||||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||||
|
include:
|
||||||
|
- os: macos-latest
|
||||||
|
llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
# only download llvm cache when needed
|
# only download llvm cache when needed
|
||||||
- name: Get LLVM libraries
|
- name: Get LLVM libraries
|
||||||
id: cache_llvm
|
id: retrieve_llvm_libs
|
||||||
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
|
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
|
@ -182,10 +187,10 @@ jobs:
|
||||||
./core/deps/llvm/build/lib
|
./core/deps/llvm/build/lib
|
||||||
./core/deps/llvm/build/libexec
|
./core/deps/llvm/build/libexec
|
||||||
./core/deps/llvm/build/share
|
./core/deps/llvm/build/share
|
||||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
key: ${{ matrix.llvm_cache_key }}
|
||||||
|
|
||||||
- name: Quit if cache miss
|
- 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
|
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||||
|
|
||||||
- name: Build iwasm
|
- name: Build iwasm
|
||||||
|
@ -210,8 +215,14 @@ jobs:
|
||||||
#$AOT_BUILD_OPTIONS,
|
#$AOT_BUILD_OPTIONS,
|
||||||
]
|
]
|
||||||
os: [macos-latest]
|
os: [macos-latest]
|
||||||
wasi_sdk_release: ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-macos.tar.gz"]
|
wasi_sdk_release:
|
||||||
wabt_release: ["https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz"]
|
[
|
||||||
|
"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:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
@ -220,24 +231,14 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
cd /opt
|
cd /opt
|
||||||
sudo wget ${{ matrix.wabt_release }}
|
sudo wget ${{ matrix.wabt_release }}
|
||||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||||
sudo mv wabt-1.0.24 wabt
|
sudo mv wabt-1.0.31 wabt
|
||||||
|
|
||||||
- name: Build Sample [wasm-c-api]
|
- name: Build Sample [wasm-c-api]
|
||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
cmake -S . -B build ${{ matrix.make_options }}
|
||||||
cmake .. ${{ matrix.make_options }}
|
cmake --build build --config Release --parallel 4
|
||||||
cmake --build . --config Release --parallel 4
|
ctest --test-dir build
|
||||||
./callback
|
|
||||||
./callback_chain
|
|
||||||
./empty_imports
|
|
||||||
./global
|
|
||||||
./hello
|
|
||||||
./hostref
|
|
||||||
./memory
|
|
||||||
./reflect
|
|
||||||
./table
|
|
||||||
./trap
|
|
||||||
working-directory: samples/wasm-c-api
|
working-directory: samples/wasm-c-api
|
||||||
|
|
||||||
build_samples_others:
|
build_samples_others:
|
||||||
|
@ -246,8 +247,14 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-latest]
|
os: [macos-latest]
|
||||||
wasi_sdk_release: ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-macos.tar.gz"]
|
wasi_sdk_release:
|
||||||
wabt_release: ["https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz"]
|
[
|
||||||
|
"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:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
@ -256,15 +263,15 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
cd /opt
|
cd /opt
|
||||||
sudo wget ${{ matrix.wasi_sdk_release }}
|
sudo wget ${{ matrix.wasi_sdk_release }}
|
||||||
sudo tar -xzf wasi-sdk-16.0-*.tar.gz
|
sudo tar -xzf wasi-sdk-*.tar.gz
|
||||||
sudo mv wasi-sdk-16.0 wasi-sdk
|
sudo mv wasi-sdk-19.0 wasi-sdk
|
||||||
|
|
||||||
- name: download and install wabt
|
- name: download and install wabt
|
||||||
run: |
|
run: |
|
||||||
cd /opt
|
cd /opt
|
||||||
sudo wget ${{ matrix.wabt_release }}
|
sudo wget ${{ matrix.wabt_release }}
|
||||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||||
sudo mv wabt-1.0.24 wabt
|
sudo mv wabt-1.0.31 wabt
|
||||||
|
|
||||||
- name: build wasi-libc (needed for wasi-threads)
|
- name: build wasi-libc (needed for wasi-threads)
|
||||||
run: |
|
run: |
|
||||||
|
|
7
.github/workflows/compilation_on_nuttx.yml
vendored
7
.github/workflows/compilation_on_nuttx.yml
vendored
|
@ -65,9 +65,12 @@ jobs:
|
||||||
"boards/risc-v/k210/maix-bit/configs/nsh",
|
"boards/risc-v/k210/maix-bit/configs/nsh",
|
||||||
]
|
]
|
||||||
wamr_config_option: [
|
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\\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\\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\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n",
|
||||||
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\n",
|
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\n",
|
||||||
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n",
|
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n",
|
||||||
|
@ -112,7 +115,7 @@ jobs:
|
||||||
|
|
||||||
- name: Enable WAMR for NuttX
|
- name: Enable WAMR for NuttX
|
||||||
run: |
|
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'
|
find nuttx/boards/sim -name defconfig | xargs sed -i '$a\CONFIG_LIBM=y\n'
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|
57
.github/workflows/compilation_on_sgx.yml
vendored
57
.github/workflows/compilation_on_sgx.yml
vendored
|
@ -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"
|
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_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_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:
|
jobs:
|
||||||
build_llvm_libraries:
|
build_llvm_libraries:
|
||||||
uses: ./.github/workflows/build_llvm_libraries.yml
|
uses: ./.github/workflows/build_llvm_libraries.yml
|
||||||
with:
|
with:
|
||||||
runs-on: "['ubuntu-20.04']"
|
os: "ubuntu-20.04"
|
||||||
|
arch: "X86"
|
||||||
|
|
||||||
build_iwasm:
|
build_iwasm:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
@ -131,7 +131,9 @@ jobs:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-20.04]
|
include:
|
||||||
|
- os: ubuntu-20.04
|
||||||
|
llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
|
||||||
steps:
|
steps:
|
||||||
- name: install SGX SDK and necessary libraries
|
- name: install SGX SDK and necessary libraries
|
||||||
run: |
|
run: |
|
||||||
|
@ -150,7 +152,7 @@ jobs:
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Get LLVM libraries
|
- name: Get LLVM libraries
|
||||||
id: cache_llvm
|
id: retrieve_llvm_libs
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -159,10 +161,10 @@ jobs:
|
||||||
./core/deps/llvm/build/lib
|
./core/deps/llvm/build/lib
|
||||||
./core/deps/llvm/build/libexec
|
./core/deps/llvm/build/libexec
|
||||||
./core/deps/llvm/build/share
|
./core/deps/llvm/build/share
|
||||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
key: ${{ matrix.llvm_cache_key }}
|
||||||
|
|
||||||
- name: Quit if cache miss
|
- 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
|
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||||
|
|
||||||
- name: Build wamrc
|
- name: Build wamrc
|
||||||
|
@ -189,11 +191,11 @@ jobs:
|
||||||
os: [ubuntu-20.04]
|
os: [ubuntu-20.04]
|
||||||
wasi_sdk_release:
|
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:
|
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:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
|
@ -203,8 +205,8 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
cd /opt
|
cd /opt
|
||||||
sudo wget ${{ matrix.wabt_release }}
|
sudo wget ${{ matrix.wabt_release }}
|
||||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||||
sudo mv wabt-1.0.24 wabt
|
sudo mv wabt-1.0.31 wabt
|
||||||
|
|
||||||
- name: install SGX SDK and necessary libraries
|
- name: install SGX SDK and necessary libraries
|
||||||
run: |
|
run: |
|
||||||
|
@ -221,19 +223,9 @@ jobs:
|
||||||
|
|
||||||
- name: Build Sample [wasm-c-api]
|
- name: Build Sample [wasm-c-api]
|
||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
cmake -S . -B build ${{ matrix.make_options }}
|
||||||
cmake .. ${{ matrix.make_options }}
|
cmake --build build --config Release --parallel 4
|
||||||
cmake --build . --config Release --parallel 4
|
ctest --test-dir build
|
||||||
./callback
|
|
||||||
./callback_chain
|
|
||||||
./empty_imports
|
|
||||||
./global
|
|
||||||
./hello
|
|
||||||
./hostref
|
|
||||||
./memory
|
|
||||||
./reflect
|
|
||||||
./table
|
|
||||||
./trap
|
|
||||||
working-directory: samples/wasm-c-api
|
working-directory: samples/wasm-c-api
|
||||||
|
|
||||||
build_samples_others:
|
build_samples_others:
|
||||||
|
@ -244,11 +236,11 @@ jobs:
|
||||||
os: [ubuntu-20.04]
|
os: [ubuntu-20.04]
|
||||||
wasi_sdk_release:
|
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:
|
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:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
|
@ -258,15 +250,15 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
cd /opt
|
cd /opt
|
||||||
sudo wget ${{ matrix.wasi_sdk_release }}
|
sudo wget ${{ matrix.wasi_sdk_release }}
|
||||||
sudo tar -xzf wasi-sdk-16.0-*.tar.gz
|
sudo tar -xzf wasi-sdk-*.tar.gz
|
||||||
sudo mv wasi-sdk-16.0 wasi-sdk
|
sudo mv wasi-sdk-19.0 wasi-sdk
|
||||||
|
|
||||||
- name: download and install wabt
|
- name: download and install wabt
|
||||||
run: |
|
run: |
|
||||||
cd /opt
|
cd /opt
|
||||||
sudo wget ${{ matrix.wabt_release }}
|
sudo wget ${{ matrix.wabt_release }}
|
||||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||||
sudo mv wabt-1.0.24 wabt
|
sudo mv wabt-1.0.31 wabt
|
||||||
|
|
||||||
- name: build wasi-libc (needed for wasi-threads)
|
- name: build wasi-libc (needed for wasi-threads)
|
||||||
run: |
|
run: |
|
||||||
|
@ -358,6 +350,7 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
running_mode: ["classic-interp", "fast-interp", "aot"]
|
running_mode: ["classic-interp", "fast-interp", "aot"]
|
||||||
test_option: ["-x -p -s spec -b -P", "-x -p -s spec -S -b -P"]
|
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
|
# classic-interp and fast-interp don't support simd
|
||||||
exclude:
|
exclude:
|
||||||
- running_mode: "classic-interp"
|
- running_mode: "classic-interp"
|
||||||
|
@ -371,7 +364,7 @@ jobs:
|
||||||
|
|
||||||
- name: Get LLVM libraries
|
- name: Get LLVM libraries
|
||||||
if: matrix.running_mode == 'aot'
|
if: matrix.running_mode == 'aot'
|
||||||
id: cache_llvm
|
id: retrieve_llvm_libs
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -380,10 +373,10 @@ jobs:
|
||||||
./core/deps/llvm/build/lib
|
./core/deps/llvm/build/lib
|
||||||
./core/deps/llvm/build/libexec
|
./core/deps/llvm/build/libexec
|
||||||
./core/deps/llvm/build/share
|
./core/deps/llvm/build/share
|
||||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
key: ${{ matrix.llvm_cache_key }}
|
||||||
|
|
||||||
- name: Quit if cache miss
|
- 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
|
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||||
|
|
||||||
- name: install SGX SDK and necessary libraries
|
- name: install SGX SDK and necessary libraries
|
||||||
|
|
6
.github/workflows/release_process.yml
vendored
6
.github/workflows/release_process.yml
vendored
|
@ -123,7 +123,7 @@ jobs:
|
||||||
runner: ubuntu-20.04
|
runner: ubuntu-20.04
|
||||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
||||||
ver_num: ${{ needs.create_tag.outputs.new_ver}}
|
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:
|
release_wamr_sdk_on_ubuntu_2204:
|
||||||
needs: [create_tag, create_release]
|
needs: [create_tag, create_release]
|
||||||
|
@ -133,7 +133,7 @@ jobs:
|
||||||
runner: ubuntu-22.04
|
runner: ubuntu-22.04
|
||||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
||||||
ver_num: ${{ needs.create_tag.outputs.new_ver}}
|
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:
|
release_wamr_sdk_on_macos:
|
||||||
needs: [create_tag, create_release]
|
needs: [create_tag, create_release]
|
||||||
|
@ -143,7 +143,7 @@ jobs:
|
||||||
runner: macos-latest
|
runner: macos-latest
|
||||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
||||||
ver_num: ${{ needs.create_tag.outputs.new_ver}}
|
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
|
# vscode extension cross-platform
|
||||||
|
|
10
.github/workflows/spec_test_on_nuttx.yml
vendored
10
.github/workflows/spec_test_on_nuttx.yml
vendored
|
@ -16,7 +16,8 @@ jobs:
|
||||||
build_llvm_libraries:
|
build_llvm_libraries:
|
||||||
uses: ./.github/workflows/build_llvm_libraries.yml
|
uses: ./.github/workflows/build_llvm_libraries.yml
|
||||||
with:
|
with:
|
||||||
runs-on: "['ubuntu-22.04']"
|
os: "ubuntu-22.04"
|
||||||
|
arch: "ARM RISCV AArch64"
|
||||||
|
|
||||||
spec_test_on_qemu:
|
spec_test_on_qemu:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
@ -37,6 +38,7 @@ jobs:
|
||||||
"-t aot",
|
"-t aot",
|
||||||
"-t aot -X"
|
"-t aot -X"
|
||||||
]
|
]
|
||||||
|
llvm_cache_key: [ "${{ needs.build_llvm_libraries.outputs.cache_key }}" ]
|
||||||
steps:
|
steps:
|
||||||
- name: Install Utilities
|
- name: Install Utilities
|
||||||
run: |
|
run: |
|
||||||
|
@ -72,7 +74,7 @@ jobs:
|
||||||
path: apps/interpreters/wamr/wamr
|
path: apps/interpreters/wamr/wamr
|
||||||
|
|
||||||
- name: Get LLVM libraries
|
- name: Get LLVM libraries
|
||||||
id: cache_llvm
|
id: retrieve_llvm_libs
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -81,10 +83,10 @@ jobs:
|
||||||
./core/deps/llvm/build/lib
|
./core/deps/llvm/build/lib
|
||||||
./core/deps/llvm/build/libexec
|
./core/deps/llvm/build/libexec
|
||||||
./core/deps/llvm/build/share
|
./core/deps/llvm/build/share
|
||||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
key: ${{ matrix.llvm_cache_key }}
|
||||||
|
|
||||||
- name: Quit if cache miss
|
- 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
|
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||||
|
|
||||||
- name: Copy LLVM
|
- name: Copy LLVM
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -32,3 +32,6 @@ samples/socket-api/wasm-src/inc/pthread.h
|
||||||
**/__pycache__
|
**/__pycache__
|
||||||
|
|
||||||
tests/benchmarks/coremark/coremark*
|
tests/benchmarks/coremark/coremark*
|
||||||
|
|
||||||
|
samples/workload/include/**
|
||||||
|
!samples/workload/include/.gitkeep
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import requests
|
||||||
import shlex
|
import shlex
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -21,28 +22,43 @@ def clone_llvm(dst_dir, llvm_repo, llvm_branch):
|
||||||
llvm_dir = dst_dir.joinpath("llvm").resolve()
|
llvm_dir = dst_dir.joinpath("llvm").resolve()
|
||||||
|
|
||||||
if not llvm_dir.exists():
|
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"
|
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)
|
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
|
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 = [
|
LLVM_COMPILE_OPTIONS = [
|
||||||
'-DCMAKE_BUILD_TYPE:STRING="Release"',
|
'-DCMAKE_BUILD_TYPE:STRING="Release"',
|
||||||
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
|
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
|
||||||
"-DLLVM_APPEND_VC_REV:BOOL=ON",
|
"-DLLVM_APPEND_VC_REV:BOOL=ON",
|
||||||
"-DLLVM_BUILD_BENCHMARKS:BOOL=OFF",
|
|
||||||
"-DLLVM_BUILD_DOCS:BOOL=OFF",
|
|
||||||
"-DLLVM_BUILD_EXAMPLES:BOOL=OFF",
|
"-DLLVM_BUILD_EXAMPLES:BOOL=OFF",
|
||||||
"-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF",
|
"-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF",
|
||||||
"-DLLVM_BUILD_TESTS:BOOL=OFF",
|
"-DLLVM_BUILD_TESTS:BOOL=OFF",
|
||||||
"-DLLVM_CCACHE_BUILD:BOOL=OFF",
|
"-DLLVM_CCACHE_BUILD:BOOL=ON",
|
||||||
"-DLLVM_ENABLE_BINDINGS:BOOL=OFF",
|
"-DLLVM_ENABLE_BINDINGS:BOOL=OFF",
|
||||||
"-DLLVM_ENABLE_IDE:BOOL=OFF",
|
"-DLLVM_ENABLE_IDE:BOOL=OFF",
|
||||||
|
"-DLLVM_ENABLE_LIBEDIT=OFF",
|
||||||
"-DLLVM_ENABLE_TERMINFO:BOOL=OFF",
|
"-DLLVM_ENABLE_TERMINFO:BOOL=OFF",
|
||||||
"-DLLVM_ENABLE_ZLIB:BOOL=OFF",
|
"-DLLVM_ENABLE_ZLIB:BOOL=OFF",
|
||||||
"-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF",
|
"-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF",
|
||||||
|
@ -54,6 +70,18 @@ def build_llvm(llvm_dir, platform, backends, projects):
|
||||||
"-DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON",
|
"-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 = {
|
LLVM_EXTRA_COMPILE_OPTIONS = {
|
||||||
"arc": [
|
"arc": [
|
||||||
'-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="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()
|
lib_llvm_core_library = build_dir.joinpath("lib/libLLVMCore.a").resolve()
|
||||||
if lib_llvm_core_library.exists():
|
if lib_llvm_core_library.exists():
|
||||||
print(f"Please remove {build_dir} manually and try again")
|
print(
|
||||||
return build_dir
|
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(
|
compile_options = " ".join(
|
||||||
LLVM_COMPILE_OPTIONS
|
LLVM_COMPILE_OPTIONS
|
||||||
|
@ -119,10 +149,11 @@ def build_llvm(llvm_dir, platform, backends, projects):
|
||||||
CONFIG_CMD += " -G'Unix Makefiles'"
|
CONFIG_CMD += " -G'Unix Makefiles'"
|
||||||
else:
|
else:
|
||||||
CONFIG_CMD += " -A x64"
|
CONFIG_CMD += " -A x64"
|
||||||
print(f"{CONFIG_CMD}")
|
else:
|
||||||
|
CONFIG_CMD += " -G'Ninja'"
|
||||||
subprocess.check_call(shlex.split(CONFIG_CMD), cwd=build_dir)
|
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 ""
|
" --config Release" if "windows" == platform else ""
|
||||||
)
|
)
|
||||||
subprocess.check_call(shlex.split(BUILD_CMD), cwd=build_dir)
|
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):
|
def repackage_llvm(llvm_dir):
|
||||||
build_dir = llvm_dir.joinpath("./build").resolve()
|
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:
|
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:
|
if not packs:
|
||||||
return
|
return
|
||||||
|
|
||||||
llvm_package = packs[0].name
|
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))
|
shutil.move(str(build_dir.joinpath(llvm_package).resolve()), str(llvm_dir))
|
||||||
# rm -r build
|
# rm -r build
|
||||||
shutil.rmtree(str(build_dir))
|
shutil.rmtree(str(build_dir))
|
||||||
# mkdir build
|
# mkdir build
|
||||||
build_dir.mkdir()
|
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}"
|
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)
|
subprocess.check_call(shlex.split(CMD), cwd=llvm_dir)
|
||||||
|
# rm ./LLVM-1*.gz
|
||||||
|
os.remove(llvm_dir.joinpath(llvm_package).resolve())
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -184,8 +217,17 @@ def main():
|
||||||
choices=["clang", "lldb"],
|
choices=["clang", "lldb"],
|
||||||
help="identify extra LLVM projects, separate by space, like '--project 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()
|
options = parser.parse_args()
|
||||||
print(f"options={options}")
|
|
||||||
|
|
||||||
# if the "platform" is not identified in the command line option,
|
# if the "platform" is not identified in the command line option,
|
||||||
# detect it
|
# detect it
|
||||||
|
@ -199,12 +241,10 @@ def main():
|
||||||
else:
|
else:
|
||||||
platform = options.platform
|
platform = options.platform
|
||||||
|
|
||||||
print(f"========== Build LLVM for {platform} ==========\n")
|
|
||||||
|
|
||||||
llvm_repo_and_branch = {
|
llvm_repo_and_branch = {
|
||||||
"arc": {
|
"arc": {
|
||||||
"repo": "https://github.com/llvm/llvm-project.git",
|
"repo": "https://github.com/llvm/llvm-project.git",
|
||||||
"branch": "release/13.x",
|
"branch": "release/15.x",
|
||||||
},
|
},
|
||||||
"xtensa": {
|
"xtensa": {
|
||||||
"repo": "https://github.com/espressif/llvm-project.git",
|
"repo": "https://github.com/espressif/llvm-project.git",
|
||||||
|
@ -212,7 +252,7 @@ def main():
|
||||||
},
|
},
|
||||||
"default": {
|
"default": {
|
||||||
"repo": "https://github.com/llvm/llvm-project.git",
|
"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()
|
deps_dir = current_dir.joinpath("../core/deps").resolve()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print(f"==================== CLONE LLVM ====================")
|
|
||||||
llvm_info = llvm_repo_and_branch.get(platform, llvm_repo_and_branch["default"])
|
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"])
|
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
|
return True
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
return False
|
return False
|
||||||
|
|
1
build-scripts/requirements.txt
Normal file
1
build-scripts/requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
requests==2.28.2
|
|
@ -19,6 +19,11 @@ endif ()
|
||||||
if (NOT DEFINED DEPS_DIR)
|
if (NOT DEFINED DEPS_DIR)
|
||||||
set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps)
|
set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps)
|
||||||
endif ()
|
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)
|
if (DEFINED EXTRA_SDK_INCLUDE_PATH)
|
||||||
message(STATUS, "EXTRA_SDK_INCLUDE_PATH = ${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 ()
|
endif ()
|
||||||
|
|
||||||
if (WAMR_BUILD_WASI_NN EQUAL 1)
|
if (WAMR_BUILD_WASI_NN EQUAL 1)
|
||||||
execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh
|
if (NOT EXISTS "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
|
||||||
RESULT_VARIABLE TENSORFLOW_RESULT
|
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")
|
set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
|
||||||
include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include)
|
include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include)
|
||||||
include_directories (${TENSORFLOW_SOURCE_DIR})
|
include_directories (${TENSORFLOW_SOURCE_DIR})
|
||||||
|
@ -169,7 +178,7 @@ LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
|
||||||
|
|
||||||
enable_language (ASM)
|
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 (${SHARED_DIR}/mem-alloc/mem_alloc.cmake)
|
||||||
include (${IWASM_DIR}/common/iwasm_common.cmake)
|
include (${IWASM_DIR}/common/iwasm_common.cmake)
|
||||||
include (${SHARED_DIR}/utils/shared_utils.cmake)
|
include (${SHARED_DIR}/utils/shared_utils.cmake)
|
||||||
|
|
|
@ -30,6 +30,8 @@ bh_static_assert(offsetof(WASMExecEnv, aux_stack_boundary)
|
||||||
bh_static_assert(offsetof(WASMExecEnv, aux_stack_bottom)
|
bh_static_assert(offsetof(WASMExecEnv, aux_stack_bottom)
|
||||||
== 7 * sizeof(uintptr_t));
|
== 7 * sizeof(uintptr_t));
|
||||||
bh_static_assert(offsetof(WASMExecEnv, native_symbol) == 8 * 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, memories) == 1 * sizeof(uint64));
|
||||||
bh_static_assert(offsetof(AOTModuleInstance, func_ptrs) == 5 * 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
|
#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 */
|
/* Initialize the thread related data */
|
||||||
if (stack_size == 0)
|
if (stack_size == 0)
|
||||||
stack_size = DEFAULT_WASM_STACK_SIZE;
|
stack_size = DEFAULT_WASM_STACK_SIZE;
|
||||||
|
@ -1194,6 +1207,15 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
|
||||||
wasm_runtime_free(
|
wasm_runtime_free(
|
||||||
((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports);
|
((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);
|
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
|
/* Check native stack overflow firstly to ensure we have enough
|
||||||
native stack to run the following codes before actually calling
|
native stack to run the following codes before actually calling
|
||||||
the aot function in invokeNative function. */
|
the aot function in invokeNative function. */
|
||||||
|
RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst);
|
||||||
if ((uint8 *)&module_inst < exec_env->native_stack_boundary
|
if ((uint8 *)&module_inst < exec_env->native_stack_boundary
|
||||||
+ page_size * (guard_page_count + 1)) {
|
+ page_size * (guard_page_count + 1)) {
|
||||||
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
|
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
|
exec_env->native_stack_boundary must have been set, we don't set
|
||||||
it again */
|
it again */
|
||||||
|
|
||||||
|
RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst);
|
||||||
if ((uint8 *)&module_inst < exec_env->native_stack_boundary) {
|
if ((uint8 *)&module_inst < exec_env->native_stack_boundary) {
|
||||||
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
|
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
#include "../interpreter/wasm_runtime.h"
|
#include "../interpreter/wasm_runtime.h"
|
||||||
#include "../compilation/aot.h"
|
#include "../compilation/aot.h"
|
||||||
|
|
||||||
|
#if WASM_ENABLE_WASI_NN != 0
|
||||||
|
#include "../libraries/wasi-nn/src/wasi_nn_private.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -75,6 +79,9 @@ typedef struct AOTFunctionInstance {
|
||||||
|
|
||||||
typedef struct AOTModuleInstanceExtra {
|
typedef struct AOTModuleInstanceExtra {
|
||||||
CApiFuncImport *c_api_func_imports;
|
CApiFuncImport *c_api_func_imports;
|
||||||
|
#if WASM_ENABLE_WASI_NN != 0
|
||||||
|
WASINNContext *wasi_nn_ctx;
|
||||||
|
#endif
|
||||||
} AOTModuleInstanceExtra;
|
} AOTModuleInstanceExtra;
|
||||||
|
|
||||||
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
|
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
|
||||||
|
|
|
@ -16,9 +16,14 @@ _invokeNative:
|
||||||
push %ebp
|
push %ebp
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
movl 16(%ebp), %ecx /* ecx = argc */
|
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
|
test %ecx, %ecx
|
||||||
jz skip_push_args /* if ecx == 0, skip pushing arguments */
|
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 */
|
leal -4(%edx,%ecx,4), %edx /* edx = edx + ecx * 4 - 4 */
|
||||||
subl %esp, %edx /* edx = edx - esp */
|
subl %esp, %edx /* edx = edx - esp */
|
||||||
1:
|
1:
|
||||||
|
|
|
@ -276,7 +276,7 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
|
||||||
WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
|
WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#if WAMR_BUILD_MEMORY_PROFILING != 0
|
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||||
#define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM()
|
#define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM()
|
||||||
#else
|
#else
|
||||||
#define WASM_C_DUMP_PROC_MEM() (void)0
|
#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 */
|
/* global engine instance */
|
||||||
static wasm_engine_t *singleton_engine = NULL;
|
static wasm_engine_t *singleton_engine;
|
||||||
#ifdef os_thread_local_attribute
|
#ifdef os_thread_local_attribute
|
||||||
/* categorize wasm_store_t as threads*/
|
/* categorize wasm_store_t as threads*/
|
||||||
static os_thread_local_attribute unsigned thread_local_stores_num = 0;
|
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;
|
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 *
|
own wasm_exporttype_t *
|
||||||
wasm_exporttype_new(own wasm_byte_vec_t *name,
|
wasm_exporttype_new(own wasm_byte_vec_t *name,
|
||||||
own wasm_externtype_t *extern_type)
|
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);
|
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) {
|
if (strlen(module_name_rt) && !module_name.data) {
|
||||||
goto failed;
|
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) {
|
if (strlen(field_name_rt) && !name.data) {
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
@ -2622,7 +2646,7 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* byte* -> wasm_byte_vec_t */
|
/* 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) {
|
if (strlen(export->name) && !name.data) {
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
@ -3008,6 +3032,20 @@ failed:
|
||||||
return NULL;
|
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
|
void
|
||||||
wasm_func_delete(wasm_func_t *func)
|
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_name_t message = { 0 };
|
||||||
wasm_trap_t *trap;
|
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);
|
trap = wasm_trap_new(func->store, &message);
|
||||||
wasm_byte_vec_delete(&message);
|
wasm_byte_vec_delete(&message);
|
||||||
|
|
||||||
|
@ -3371,6 +3410,25 @@ failed:
|
||||||
return NULL;
|
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 */
|
/* almost same with wasm_global_new */
|
||||||
wasm_global_t *
|
wasm_global_t *
|
||||||
wasm_global_copy(const wasm_global_t *src)
|
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;
|
(WASMModuleInstance *)module_inst_comm;
|
||||||
WASMMemoryInstance *memory_inst =
|
WASMMemoryInstance *memory_inst =
|
||||||
module_inst->memories[memory->memory_idx_rt];
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -4215,7 +4274,8 @@ wasm_memory_data_size(const wasm_memory_t *memory)
|
||||||
AOTMemoryInstance *memory_inst =
|
AOTMemoryInstance *memory_inst =
|
||||||
((AOTMemoryInstance **)
|
((AOTMemoryInstance **)
|
||||||
module_inst->memories)[memory->memory_idx_rt];
|
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
|
#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;
|
imported_func_interp = module_interp->import_functions + func_idx_rt;
|
||||||
bh_assert(imported_func_interp);
|
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 */
|
/* type comparison */
|
||||||
if (!wasm_functype_same_internal(
|
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;
|
imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb;
|
||||||
else
|
else
|
||||||
imported_func_interp->u.function.func_ptr_linked = import->u.cb;
|
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;
|
import->func_idx_rt = func_idx_rt;
|
||||||
|
|
||||||
(void)inst;
|
(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;
|
imported_global_interp = module_interp->import_globals + global_idx_rt;
|
||||||
bh_assert(imported_global_interp);
|
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),
|
if (!cmp_val_kind_with_val_type(wasm_valtype_kind(import->type->val_type),
|
||||||
imported_global_interp->u.global.type))
|
imported_global_interp->u.global.type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* set init value */
|
/* set init value */
|
||||||
|
bh_assert(import->init);
|
||||||
switch (wasm_valtype_kind(import->type->val_type)) {
|
switch (wasm_valtype_kind(import->type->val_type)) {
|
||||||
case WASM_I32:
|
case WASM_I32:
|
||||||
imported_global_interp->u.global.global_data_linked.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;
|
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
|
static bool
|
||||||
interp_process_export(wasm_store_t *store,
|
interp_process_export(wasm_store_t *store,
|
||||||
const WASMModuleInstance *inst_interp,
|
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;
|
import_aot_func = module_aot->import_funcs + import_func_idx_rt;
|
||||||
bh_assert(import_aot_func);
|
bh_assert(import_aot_func);
|
||||||
|
|
||||||
|
/* it is a placeholder and let's skip it*/
|
||||||
|
if (!import->type)
|
||||||
|
return true;
|
||||||
|
|
||||||
/* type comparison */
|
/* type comparison */
|
||||||
if (!wasm_functype_same_internal(import->type, import_aot_func->func_type))
|
if (!wasm_functype_same_internal(import->type, import_aot_func->func_type))
|
||||||
return false;
|
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;
|
import_aot_func->func_ptr_linked = import->u.cb_env.cb;
|
||||||
else
|
else
|
||||||
import_aot_func->func_ptr_linked = import->u.cb;
|
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;
|
import->func_idx_rt = import_func_idx_rt;
|
||||||
|
|
||||||
return true;
|
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;
|
import_aot_global = module_aot->import_globals + global_idx_rt;
|
||||||
bh_assert(import_aot_global);
|
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);
|
val_type = wasm_globaltype_content(import->type);
|
||||||
bh_assert(val_type);
|
bh_assert(val_type);
|
||||||
|
|
||||||
|
@ -4537,6 +4569,7 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
|
||||||
import_aot_global->type))
|
import_aot_global->type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
bh_assert(import->init);
|
||||||
switch (wasm_valtype_kind(val_type)) {
|
switch (wasm_valtype_kind(val_type)) {
|
||||||
case WASM_I32:
|
case WASM_I32:
|
||||||
import_aot_global->global_data_linked.i32 = import->init->of.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->global_idx_rt = global_idx_rt;
|
||||||
import_aot_global->is_linked = true;
|
import_aot_global->is_linked = true;
|
||||||
return 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:
|
failed:
|
||||||
LOG_DEBUG("%s failed", __FUNCTION__);
|
LOG_DEBUG("%s failed", __FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
|
@ -4693,7 +4670,7 @@ aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot,
|
||||||
goto failed;
|
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) {
|
if (strlen(export->name) && !external->name->data) {
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
@ -4711,6 +4688,95 @@ failed:
|
||||||
}
|
}
|
||||||
#endif /* WASM_ENABLE_AOT */
|
#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_t *
|
||||||
wasm_instance_new(wasm_store_t *store, const wasm_module_t *module,
|
wasm_instance_new(wasm_store_t *store, const wasm_module_t *module,
|
||||||
const wasm_extern_vec_t *imports, own wasm_trap_t **trap)
|
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));
|
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_t *
|
||||||
wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||||
const wasm_extern_vec_t *imports,
|
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 sub_error_buf[128] = { 0 };
|
||||||
char error_buf[256] = { 0 };
|
char error_buf[256] = { 0 };
|
||||||
wasm_instance_t *instance = NULL;
|
wasm_instance_t *instance = NULL;
|
||||||
WASMModuleInstance *inst_rt;
|
|
||||||
CApiFuncImport *func_import = NULL, **p_func_imports = NULL;
|
CApiFuncImport *func_import = NULL, **p_func_imports = NULL;
|
||||||
uint32 i = 0, import_func_count = 0;
|
uint32 i = 0, import_func_count = 0;
|
||||||
uint64 total_size;
|
uint64 total_size;
|
||||||
|
@ -4790,11 +4804,9 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||||
if (!module)
|
if (!module)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!compare_imports(module, imports)) {
|
/*
|
||||||
snprintf(sub_error_buf, sizeof(sub_error_buf),
|
* will do the check at the end of wasm_runtime_instantiate
|
||||||
"Failed to match imports");
|
*/
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
WASM_C_DUMP_PROC_MEM();
|
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;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* link module and imports */
|
/* executes the instantiate-time linking if provided */
|
||||||
if (imports && imports->num_elems) {
|
if (imports) {
|
||||||
bool link = false;
|
if (!do_link(instance, module, imports)) {
|
||||||
#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) {
|
|
||||||
snprintf(sub_error_buf, sizeof(sub_error_buf),
|
snprintf(sub_error_buf, sizeof(sub_error_buf),
|
||||||
"Failed to verify import count");
|
"Failed to validate imports");
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* will do the linking result check at the end of wasm_runtime_instantiate
|
||||||
|
*/
|
||||||
|
|
||||||
instance->inst_comm_rt = wasm_runtime_instantiate(
|
instance->inst_comm_rt = wasm_runtime_instantiate(
|
||||||
*module, stack_size, heap_size, sub_error_buf, sizeof(sub_error_buf));
|
*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 */
|
/* create the c-api func import list */
|
||||||
inst_rt = (WASMModuleInstance *)instance->inst_comm_rt;
|
|
||||||
#if WASM_ENABLE_INTERP != 0
|
#if WASM_ENABLE_INTERP != 0
|
||||||
if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||||
p_func_imports = &inst_rt->e->c_api_func_imports;
|
WASMModuleInstanceExtra *e =
|
||||||
import_func_count = inst_rt->module->import_function_count;
|
((WASMModuleInstance *)instance->inst_comm_rt)->e;
|
||||||
|
p_func_imports = &(e->c_api_func_imports);
|
||||||
|
import_func_count = MODULE_INTERP(module)->import_function_count;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_AOT != 0
|
#if WASM_ENABLE_AOT != 0
|
||||||
if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) {
|
if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||||
p_func_imports =
|
AOTModuleInstanceExtra *e =
|
||||||
&((AOTModuleInstanceExtra *)inst_rt->e)->c_api_func_imports;
|
(AOTModuleInstanceExtra *)((AOTModuleInstance *)
|
||||||
import_func_count = ((AOTModule *)inst_rt->module)->import_func_count;
|
instance->inst_comm_rt)
|
||||||
|
->e;
|
||||||
|
p_func_imports = &(e->c_api_func_imports);
|
||||||
|
import_func_count = MODULE_AOT(module)->import_func_count;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
bh_assert(p_func_imports);
|
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;
|
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++) {
|
for (i = 0; imports && i < imports->num_elems; i++) {
|
||||||
wasm_func_t *func_host;
|
wasm_func_t *func_host = NULL;
|
||||||
wasm_extern_t *in;
|
wasm_extern_t *in = imports->data[i];
|
||||||
|
bh_assert(in);
|
||||||
|
|
||||||
in = imports->data[i];
|
|
||||||
if (wasm_extern_kind(in) != WASM_EXTERN_FUNC)
|
if (wasm_extern_kind(in) != WASM_EXTERN_FUNC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
func_host = wasm_extern_as_func(in);
|
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;
|
func_import->with_env_arg = func_host->with_env;
|
||||||
if (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->func_ptr_linked = func_host->u.cb;
|
||||||
func_import->env_arg = NULL;
|
func_import->env_arg = NULL;
|
||||||
}
|
}
|
||||||
|
bh_assert(func_import->func_ptr_linked);
|
||||||
|
|
||||||
func_import++;
|
func_import++;
|
||||||
}
|
}
|
||||||
|
@ -4907,6 +4903,8 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||||
/* fill with inst */
|
/* fill with inst */
|
||||||
for (i = 0; imports && imports->data && i < imports->num_elems; ++i) {
|
for (i = 0; imports && imports->data && i < imports->num_elems; ++i) {
|
||||||
wasm_extern_t *import = imports->data[i];
|
wasm_extern_t *import = imports->data[i];
|
||||||
|
bh_assert(import);
|
||||||
|
|
||||||
switch (import->kind) {
|
switch (import->kind) {
|
||||||
case WASM_EXTERN_FUNC:
|
case WASM_EXTERN_FUNC:
|
||||||
wasm_extern_as_func(import)->inst_comm_rt =
|
wasm_extern_as_func(import)->inst_comm_rt =
|
||||||
|
@ -5002,7 +5000,7 @@ failed:
|
||||||
sub_error_buf);
|
sub_error_buf);
|
||||||
if (trap != NULL) {
|
if (trap != NULL) {
|
||||||
wasm_message_t message = { 0 };
|
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);
|
*trap = wasm_trap_new(store, &message);
|
||||||
wasm_byte_vec_delete(&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)
|
BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN_CONST)
|
||||||
#undef 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;
|
||||||
|
}
|
||||||
|
|
|
@ -211,6 +211,7 @@ wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
|
||||||
exec_env->handle = os_self_thread();
|
exec_env->handle = os_self_thread();
|
||||||
exec_env->native_stack_boundary =
|
exec_env->native_stack_boundary =
|
||||||
stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL;
|
stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL;
|
||||||
|
exec_env->native_stack_top_min = (void *)UINTPTR_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WASM_ENABLE_THREAD_MGR != 0
|
#if WASM_ENABLE_THREAD_MGR != 0
|
||||||
|
|
|
@ -84,6 +84,12 @@ typedef struct WASMExecEnv {
|
||||||
void **native_symbol;
|
void **native_symbol;
|
||||||
#endif
|
#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
|
#if WASM_ENABLE_FAST_JIT != 0
|
||||||
/**
|
/**
|
||||||
* Cache for
|
* Cache for
|
||||||
|
@ -165,6 +171,17 @@ typedef struct WASMExecEnv {
|
||||||
} wasm_stack;
|
} wasm_stack;
|
||||||
} WASMExecEnv;
|
} 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 *
|
WASMExecEnv *
|
||||||
wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
|
wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
|
||||||
uint32 stack_size);
|
uint32 stack_size);
|
||||||
|
|
|
@ -250,6 +250,10 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* allow func_type and all outputs, like p_signature, p_attachment and
|
||||||
|
* p_call_conv_raw to be NULL
|
||||||
|
*/
|
||||||
void *
|
void *
|
||||||
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
||||||
const WASMType *func_type, const char **p_signature,
|
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;
|
node = node_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!p_signature || !p_attachment || !p_call_conv_raw)
|
||||||
|
return func_ptr;
|
||||||
|
|
||||||
if (func_ptr) {
|
if (func_ptr) {
|
||||||
if (signature && signature[0] != '\0') {
|
if (signature && signature[0] != '\0') {
|
||||||
/* signature is not empty, check its format */
|
/* 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
|
#if WASM_ENABLE_WAMR_COMPILER == 0
|
||||||
/* Output warning except running aot compiler */
|
/* Output warning except running aot compiler */
|
||||||
LOG_WARNING("failed to check signature '%s' and resolve "
|
LOG_WARNING("failed to check signature '%s' and resolve "
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "bh_common.h"
|
#include "bh_common.h"
|
||||||
#include "bh_assert.h"
|
#include "bh_assert.h"
|
||||||
#include "bh_log.h"
|
#include "bh_log.h"
|
||||||
|
#include "wasm_native.h"
|
||||||
#include "wasm_runtime_common.h"
|
#include "wasm_runtime_common.h"
|
||||||
#include "wasm_memory.h"
|
#include "wasm_memory.h"
|
||||||
#if WASM_ENABLE_INTERP != 0
|
#if WASM_ENABLE_INTERP != 0
|
||||||
|
@ -128,6 +129,12 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
|
||||||
static JitCompOptions jit_options = { 0 };
|
static JitCompOptions jit_options = { 0 };
|
||||||
#endif
|
#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
|
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||||
/* The exec_env of thread local storage, set before calling function
|
/* The exec_env of thread local storage, set before calling function
|
||||||
and used in signal handler, as we cannot get it from the argument
|
and used in signal handler, as we cannot get it from the argument
|
||||||
|
@ -514,6 +521,20 @@ wasm_runtime_destroy()
|
||||||
wasm_runtime_memory_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
|
bool
|
||||||
wasm_runtime_full_init(RuntimeInitArgs *init_args)
|
wasm_runtime_full_init(RuntimeInitArgs *init_args)
|
||||||
{
|
{
|
||||||
|
@ -521,10 +542,20 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
|
||||||
&init_args->mem_alloc_option))
|
&init_args->mem_alloc_option))
|
||||||
return false;
|
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
|
#if WASM_ENABLE_FAST_JIT != 0
|
||||||
jit_options.code_cache_size = init_args->fast_jit_code_cache_size;
|
jit_options.code_cache_size = init_args->fast_jit_code_cache_size;
|
||||||
#endif
|
#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()) {
|
if (!wasm_runtime_env_init()) {
|
||||||
wasm_runtime_memory_destroy();
|
wasm_runtime_memory_destroy();
|
||||||
return false;
|
return false;
|
||||||
|
@ -554,6 +585,47 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
|
||||||
return true;
|
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
|
PackageType
|
||||||
get_package_type(const uint8 *buf, uint32 size)
|
get_package_type(const uint8 *buf, uint32 size)
|
||||||
{
|
{
|
||||||
|
@ -1171,6 +1243,41 @@ wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
|
||||||
#endif
|
#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
|
void
|
||||||
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst)
|
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst)
|
||||||
{
|
{
|
||||||
|
@ -1399,6 +1506,22 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env)
|
||||||
else
|
else
|
||||||
os_printf("Total aux stack used: no enough info to profile\n");
|
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);
|
os_printf("Total app heap used: %u\n", app_heap_peak_size);
|
||||||
}
|
}
|
||||||
#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
|
#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
|
||||||
|
@ -2195,6 +2318,12 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
|
||||||
if (exec_env) {
|
if (exec_env) {
|
||||||
wasm_cluster_spread_exception(exec_env, exception ? false : true);
|
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
|
#else
|
||||||
(void)exec_env;
|
(void)exec_env;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2219,9 +2348,7 @@ static const char *exception_msgs[] = {
|
||||||
"wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
|
"wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
|
||||||
"out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
|
"out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
|
||||||
"wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */
|
"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 */
|
"failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
|
||||||
#endif
|
|
||||||
"", /* EXCE_ALREADY_THROWN */
|
"", /* EXCE_ALREADY_THROWN */
|
||||||
};
|
};
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
@ -5205,3 +5332,24 @@ wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
|
||||||
*minor = WAMR_VERSION_MINOR;
|
*minor = WAMR_VERSION_MINOR;
|
||||||
*patch = WAMR_VERSION_PATCH;
|
*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
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Internal use for setting default running mode */
|
||||||
|
#define Mode_Default 0
|
||||||
|
|
||||||
#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
|
#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
|
||||||
|
|
||||||
#define PUT_I64_TO_ADDR(addr, value) \
|
#define PUT_I64_TO_ADDR(addr, value) \
|
||||||
|
@ -413,6 +416,13 @@ typedef struct wasm_frame_t {
|
||||||
const char *func_name_wp;
|
const char *func_name_wp;
|
||||||
} WASMCApiFrame;
|
} WASMCApiFrame;
|
||||||
|
|
||||||
|
#ifdef WASM_ENABLE_JIT
|
||||||
|
typedef struct LLVMJITOptions {
|
||||||
|
uint32 opt_level;
|
||||||
|
uint32 size_level;
|
||||||
|
} LLVMJITOptions;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||||
/* Signal info passing to interp/aot signal handler */
|
/* Signal info passing to interp/aot signal handler */
|
||||||
typedef struct WASMSignalInfo {
|
typedef struct WASMSignalInfo {
|
||||||
|
@ -437,10 +447,28 @@ wasm_runtime_get_exec_env_tls(void);
|
||||||
WASM_RUNTIME_API_EXTERN bool
|
WASM_RUNTIME_API_EXTERN bool
|
||||||
wasm_runtime_init(void);
|
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 */
|
/* See wasm_export.h for description */
|
||||||
WASM_RUNTIME_API_EXTERN bool
|
WASM_RUNTIME_API_EXTERN bool
|
||||||
wasm_runtime_full_init(RuntimeInitArgs *init_args);
|
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 */
|
/* See wasm_export.h for description */
|
||||||
WASM_RUNTIME_API_EXTERN void
|
WASM_RUNTIME_API_EXTERN void
|
||||||
wasm_runtime_destroy(void);
|
wasm_runtime_destroy(void);
|
||||||
|
@ -484,6 +512,15 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size,
|
||||||
uint32 heap_size, char *error_buf,
|
uint32 heap_size, char *error_buf,
|
||||||
uint32 error_buf_size);
|
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 */
|
/* See wasm_export.h for description */
|
||||||
WASM_RUNTIME_API_EXTERN void
|
WASM_RUNTIME_API_EXTERN void
|
||||||
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst);
|
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst);
|
||||||
|
@ -956,6 +993,14 @@ void
|
||||||
wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list);
|
wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list);
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,6 +30,11 @@ typedef struct AtomicWaitNode {
|
||||||
korp_cond wait_cond;
|
korp_cond wait_cond;
|
||||||
} AtomicWaitNode;
|
} AtomicWaitNode;
|
||||||
|
|
||||||
|
typedef struct AtomicWaitAddressArgs {
|
||||||
|
uint32 index;
|
||||||
|
void **addr;
|
||||||
|
} AtomicWaitAddressArgs;
|
||||||
|
|
||||||
/* Atomic wait map */
|
/* Atomic wait map */
|
||||||
static HashMap *wait_map;
|
static HashMap *wait_map;
|
||||||
|
|
||||||
|
@ -87,6 +92,61 @@ search_module(WASMModuleCommon *module)
|
||||||
return NULL;
|
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 *
|
WASMSharedMemNode *
|
||||||
wasm_module_get_shared_memory(WASMModuleCommon *module)
|
wasm_module_get_shared_memory(WASMModuleCommon *module)
|
||||||
{
|
{
|
||||||
|
@ -120,6 +180,7 @@ shared_memory_dec_reference(WASMModuleCommon *module)
|
||||||
bh_list_remove(shared_memory_list, node);
|
bh_list_remove(shared_memory_list, node);
|
||||||
os_mutex_unlock(&shared_memory_list_lock);
|
os_mutex_unlock(&shared_memory_list_lock);
|
||||||
|
|
||||||
|
os_mutex_destroy(&node->shared_mem_lock);
|
||||||
os_mutex_destroy(&node->lock);
|
os_mutex_destroy(&node->lock);
|
||||||
wasm_runtime_free(node);
|
wasm_runtime_free(node);
|
||||||
}
|
}
|
||||||
|
@ -148,7 +209,14 @@ shared_memory_set_memory_inst(WASMModuleCommon *module,
|
||||||
node->module = module;
|
node->module = module;
|
||||||
node->memory_inst = memory;
|
node->memory_inst = memory;
|
||||||
node->ref_count = 1;
|
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) {
|
if (os_mutex_init(&node->lock) != 0) {
|
||||||
|
os_mutex_destroy(&node->shared_mem_lock);
|
||||||
wasm_runtime_free(node);
|
wasm_runtime_free(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -322,6 +390,10 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||||
bh_assert(module->module_type == Wasm_Module_Bytecode
|
bh_assert(module->module_type == Wasm_Module_Bytecode
|
||||||
|| module->module_type == Wasm_Module_AoT);
|
|| module->module_type == Wasm_Module_AoT);
|
||||||
|
|
||||||
|
if (wasm_get_exception(module_inst)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Currently we have only one memory instance */
|
/* Currently we have only one memory instance */
|
||||||
if (!module_inst->memories[0]->is_shared) {
|
if (!module_inst->memories[0]->is_shared) {
|
||||||
wasm_runtime_set_exception(module, "expected shared memory");
|
wasm_runtime_set_exception(module, "expected shared memory");
|
||||||
|
|
|
@ -26,6 +26,8 @@ typedef struct WASMSharedMemNode {
|
||||||
WASMModuleCommon *module;
|
WASMModuleCommon *module;
|
||||||
/* The memory information */
|
/* The memory information */
|
||||||
WASMMemoryInstanceCommon *memory_inst;
|
WASMMemoryInstanceCommon *memory_inst;
|
||||||
|
/* Lock used for atomic operations */
|
||||||
|
korp_mutex shared_mem_lock;
|
||||||
|
|
||||||
/* reference count */
|
/* reference count */
|
||||||
uint32 ref_count;
|
uint32 ref_count;
|
||||||
|
@ -37,6 +39,9 @@ wasm_shared_memory_init();
|
||||||
void
|
void
|
||||||
wasm_shared_memory_destroy();
|
wasm_shared_memory_destroy();
|
||||||
|
|
||||||
|
void
|
||||||
|
notify_stale_threads_on_exception(WASMModuleInstanceCommon *module);
|
||||||
|
|
||||||
WASMSharedMemNode *
|
WASMSharedMemNode *
|
||||||
wasm_module_get_shared_memory(WASMModuleCommon *module);
|
wasm_module_get_shared_memory(WASMModuleCommon *module);
|
||||||
|
|
||||||
|
|
|
@ -259,6 +259,7 @@ check_type_compatible(uint8 src_type, uint8 dst_type)
|
||||||
#define I32_SIX LLVM_CONST(i32_six)
|
#define I32_SIX LLVM_CONST(i32_six)
|
||||||
#define I32_SEVEN LLVM_CONST(i32_seven)
|
#define I32_SEVEN LLVM_CONST(i32_seven)
|
||||||
#define I32_EIGHT LLVM_CONST(i32_eight)
|
#define I32_EIGHT LLVM_CONST(i32_eight)
|
||||||
|
#define I32_NINE LLVM_CONST(i32_nine)
|
||||||
#define I32_NEG_ONE LLVM_CONST(i32_neg_one)
|
#define I32_NEG_ONE LLVM_CONST(i32_neg_one)
|
||||||
#define I64_NEG_ONE LLVM_CONST(i64_neg_one)
|
#define I64_NEG_ONE LLVM_CONST(i64_neg_one)
|
||||||
#define I32_MIN LLVM_CONST(i32_min)
|
#define I32_MIN LLVM_CONST(i32_min)
|
||||||
|
|
|
@ -366,6 +366,87 @@ fail:
|
||||||
#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \
|
#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \
|
||||||
|| (WASM_ENABLE_PERF_PROFILING != 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
|
static bool
|
||||||
check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
uint32 callee_cell_num)
|
uint32 callee_cell_num)
|
||||||
|
@ -409,6 +490,19 @@ check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
return true;
|
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,
|
* Check whether the app address and its buffer are inside the linear memory,
|
||||||
* if no, throw exception
|
* if no, throw exception
|
||||||
|
@ -852,8 +946,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
callee_cell_num =
|
callee_cell_num =
|
||||||
aot_func->param_cell_num + aot_func->local_cell_num + 1;
|
aot_func->param_cell_num + aot_func->local_cell_num + 1;
|
||||||
|
|
||||||
if (comp_ctx->enable_stack_bound_check
|
if (!check_stack(comp_ctx, func_ctx, callee_cell_num))
|
||||||
&& !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR >= 14
|
#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 */
|
/* Translate call non-import block */
|
||||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import);
|
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import);
|
||||||
|
|
||||||
if (comp_ctx->enable_stack_bound_check
|
if (!check_stack(comp_ctx, func_ctx,
|
||||||
&& !check_stack_boundary(comp_ctx, func_ctx,
|
param_cell_num + ext_cell_num
|
||||||
param_cell_num + ext_cell_num
|
+ 1
|
||||||
+ 1
|
/* Reserve some local variables */
|
||||||
/* Reserve some local variables */
|
+ 16))
|
||||||
+ 16))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Load function pointer */
|
/* Load function pointer */
|
||||||
|
|
|
@ -286,6 +286,21 @@ create_native_stack_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||||
return true;
|
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
|
static bool
|
||||||
create_aux_stack_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
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) {
|
if (aot_func_type->param_count + func->local_count > 0) {
|
||||||
func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count
|
func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count
|
||||||
+ func->local_count - 1];
|
+ 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)) {
|
&& !create_native_stack_bound(comp_ctx, func_ctx)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (comp_ctx->enable_stack_estimation
|
||||||
|
&& !create_native_stack_top_min(comp_ctx, func_ctx)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get auxiliary stack info */
|
/* Get auxiliary stack info */
|
||||||
if (wasm_func->has_op_set_global_aux_stack
|
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)
|
if (option->disable_llvm_lto)
|
||||||
comp_ctx->disable_llvm_lto = true;
|
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->opt_level = option->opt_level;
|
||||||
comp_ctx->size_level = option->size_level;
|
comp_ctx->size_level = option->size_level;
|
||||||
|
|
||||||
|
|
|
@ -163,6 +163,7 @@ typedef struct AOTFuncContext {
|
||||||
LLVMValueRef aot_inst;
|
LLVMValueRef aot_inst;
|
||||||
LLVMValueRef argv_buf;
|
LLVMValueRef argv_buf;
|
||||||
LLVMValueRef native_stack_bound;
|
LLVMValueRef native_stack_bound;
|
||||||
|
LLVMValueRef native_stack_top_min_addr;
|
||||||
LLVMValueRef aux_stack_bound;
|
LLVMValueRef aux_stack_bound;
|
||||||
LLVMValueRef aux_stack_bottom;
|
LLVMValueRef aux_stack_bottom;
|
||||||
LLVMValueRef native_symbol;
|
LLVMValueRef native_symbol;
|
||||||
|
@ -313,6 +314,9 @@ typedef struct AOTCompContext {
|
||||||
/* Native stack bounday Check */
|
/* Native stack bounday Check */
|
||||||
bool enable_stack_bound_check;
|
bool enable_stack_bound_check;
|
||||||
|
|
||||||
|
/* Native stack usage estimation */
|
||||||
|
bool enable_stack_estimation;
|
||||||
|
|
||||||
/* 128-bit SIMD */
|
/* 128-bit SIMD */
|
||||||
bool enable_simd;
|
bool enable_simd;
|
||||||
|
|
||||||
|
@ -403,6 +407,7 @@ typedef struct AOTCompOption {
|
||||||
bool enable_aux_stack_frame;
|
bool enable_aux_stack_frame;
|
||||||
bool disable_llvm_intrinsics;
|
bool disable_llvm_intrinsics;
|
||||||
bool disable_llvm_lto;
|
bool disable_llvm_lto;
|
||||||
|
bool enable_stack_estimation;
|
||||||
uint32 opt_level;
|
uint32 opt_level;
|
||||||
uint32 size_level;
|
uint32 size_level;
|
||||||
uint32 output_format;
|
uint32 output_format;
|
||||||
|
|
|
@ -135,7 +135,8 @@ check_and_seek(JitCompContext *cc, JitReg addr, uint32 offset, uint32 bytes)
|
||||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||||
/* ---------- check ---------- */
|
/* ---------- check ---------- */
|
||||||
/* 1. shortcut if the memory size is 0 */
|
/* 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;
|
JitReg module_inst, cur_page_count;
|
||||||
uint32 cur_page_count_offset =
|
uint32 cur_page_count_offset =
|
||||||
(uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
|
(uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
|
||||||
|
@ -176,6 +177,18 @@ fail:
|
||||||
return 0;
|
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
|
bool
|
||||||
jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset,
|
jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset,
|
||||||
uint32 bytes, bool sign, bool atomic)
|
uint32 bytes, bool sign, bool atomic)
|
||||||
|
@ -779,6 +792,51 @@ bool
|
||||||
jit_compile_op_atomic_wait(JitCompContext *cc, uint8 op_type, uint32 align,
|
jit_compile_op_atomic_wait(JitCompContext *cc, uint8 op_type, uint32 align,
|
||||||
uint32 offset, uint32 bytes)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,6 +844,39 @@ bool
|
||||||
jit_compiler_op_atomic_notify(JitCompContext *cc, uint32 align, uint32 offset,
|
jit_compiler_op_atomic_notify(JitCompContext *cc, uint32 align, uint32 offset,
|
||||||
uint32 bytes)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -56,9 +56,31 @@ jit_code_cache_free(void *ptr)
|
||||||
bool
|
bool
|
||||||
jit_pass_register_jitted_code(JitCompContext *cc)
|
jit_pass_register_jitted_code(JitCompContext *cc)
|
||||||
{
|
{
|
||||||
uint32 jit_func_idx =
|
WASMModuleInstance *instance;
|
||||||
cc->cur_wasm_func_idx - cc->cur_wasm_module->import_function_count;
|
WASMModule *module = cc->cur_wasm_module;
|
||||||
cc->cur_wasm_module->fast_jit_func_ptrs[jit_func_idx] =
|
WASMFunction *func = cc->cur_wasm_func;
|
||||||
cc->cur_wasm_func->fast_jit_jitted_code = cc->jitted_addr_begin;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,8 +157,16 @@ jit_compiler_compile(WASMModule *module, uint32 func_idx)
|
||||||
/* Apply compiler passes */
|
/* Apply compiler passes */
|
||||||
if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) {
|
if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) {
|
||||||
last_error = 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",
|
os_printf("fast jit compilation failed: %s\n",
|
||||||
last_error ? last_error : "unknown error");
|
last_error ? last_error : "unknown error");
|
||||||
|
#endif
|
||||||
|
|
||||||
goto fail;
|
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);
|
func_ptr = jit_codegen_compile_call_to_fast_jit(module, func_idx);
|
||||||
if (func_ptr) {
|
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);
|
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;
|
WASMModuleInstance *instance;
|
||||||
uint32 i = func_idx - module->import_function_count;
|
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);
|
os_mutex_lock(&module->instance_list_lock);
|
||||||
|
|
||||||
|
module->func_ptrs[i] = func_ptr;
|
||||||
|
|
||||||
instance = module->instance_list;
|
instance = module->instance_list;
|
||||||
while (instance) {
|
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;
|
instance = instance->e->next;
|
||||||
}
|
}
|
||||||
os_mutex_unlock(&module->instance_list_lock);
|
os_mutex_unlock(&module->instance_list_lock);
|
||||||
|
|
|
@ -55,6 +55,7 @@ typedef struct AOTCompOption {
|
||||||
bool enable_aux_stack_frame;
|
bool enable_aux_stack_frame;
|
||||||
bool disable_llvm_intrinsics;
|
bool disable_llvm_intrinsics;
|
||||||
bool disable_llvm_lto;
|
bool disable_llvm_lto;
|
||||||
|
bool enable_stack_estimation;
|
||||||
uint32_t opt_level;
|
uint32_t opt_level;
|
||||||
uint32_t size_level;
|
uint32_t size_level;
|
||||||
uint32_t output_format;
|
uint32_t output_format;
|
||||||
|
|
|
@ -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_module(const wasm_importtype_t*);
|
||||||
WASM_API_EXTERN const wasm_name_t* wasm_importtype_name(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 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
|
// Export Types
|
||||||
|
@ -797,6 +798,9 @@ static inline void* wasm_val_ptr(const wasm_val_t* val) {
|
||||||
|
|
||||||
#define KILOBYTE(n) ((n) * 1024)
|
#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
|
#undef own
|
||||||
|
|
|
@ -131,6 +131,14 @@ typedef struct mem_alloc_info_t {
|
||||||
uint32_t highmark_size;
|
uint32_t highmark_size;
|
||||||
} mem_alloc_info_t;
|
} 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 */
|
/* WASM runtime initialize arguments */
|
||||||
typedef struct RuntimeInitArgs {
|
typedef struct RuntimeInitArgs {
|
||||||
mem_alloc_type_t mem_alloc_type;
|
mem_alloc_type_t mem_alloc_type;
|
||||||
|
@ -152,6 +160,13 @@ typedef struct RuntimeInitArgs {
|
||||||
|
|
||||||
/* Fast JIT code cache size */
|
/* Fast JIT code cache size */
|
||||||
uint32_t 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;
|
} RuntimeInitArgs;
|
||||||
|
|
||||||
#ifndef WASM_VALKIND_T_DEFINED
|
#ifndef WASM_VALKIND_T_DEFINED
|
||||||
|
@ -195,9 +210,9 @@ WASM_RUNTIME_API_EXTERN bool
|
||||||
wasm_runtime_init(void);
|
wasm_runtime_init(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the WASM runtime environment, and also initialize
|
* Initialize the WASM runtime environment, WASM running mode,
|
||||||
* the memory allocator and register native symbols, which are specified
|
* and also initialize the memory allocator and register native symbols,
|
||||||
* with init arguments
|
* which are specified with init arguments
|
||||||
*
|
*
|
||||||
* @param init_args specifies the init arguments
|
* @param init_args specifies the init arguments
|
||||||
*
|
*
|
||||||
|
@ -206,6 +221,28 @@ wasm_runtime_init(void);
|
||||||
WASM_RUNTIME_API_EXTERN bool
|
WASM_RUNTIME_API_EXTERN bool
|
||||||
wasm_runtime_full_init(RuntimeInitArgs *init_args);
|
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.
|
* 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,
|
uint32_t stack_size, uint32_t heap_size,
|
||||||
char *error_buf, uint32_t error_buf_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.
|
* 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_API_EXTERN void
|
||||||
wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch);
|
wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether an import func `(import <module_name> <func_name> (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 <module_name> <global_name> (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 */
|
/* clang-format on */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -278,9 +278,14 @@ struct WASMFunction {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_FAST_JIT != 0
|
#if WASM_ENABLE_FAST_JIT != 0
|
||||||
|
/* The compiled fast jit jitted code block of this function */
|
||||||
void *fast_jit_jitted_code;
|
void *fast_jit_jitted_code;
|
||||||
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
|
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
|
||||||
|
/* The compiled llvm jit func ptr of this function */
|
||||||
void *llvm_jit_func_ptr;
|
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
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -505,15 +510,14 @@ struct WASMModule {
|
||||||
uint64 load_size;
|
uint64 load_size;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
||||||
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
|
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
|
||||||
&& WASM_ENABLE_LAZY_JIT != 0)
|
&& WASM_ENABLE_LAZY_JIT != 0)
|
||||||
/**
|
/**
|
||||||
* List of instances referred to this module. When source debugging
|
* List of instances referred to this module. When source debugging
|
||||||
* feature is enabled, the debugger may modify the code section of
|
* feature is enabled, the debugger may modify the code section of
|
||||||
* the module, so we need to report a warning if user create several
|
* the module, so we need to report a warning if user create several
|
||||||
* instances based on the same module. Sub instances created by
|
* instances based on the same module.
|
||||||
* lib-pthread or spawn API won't be added into the list.
|
|
||||||
*
|
*
|
||||||
* Also add the instance to the list for Fast JIT to LLVM JIT
|
* 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
|
* tier-up, since we need to lazily update the LLVM func pointers
|
||||||
|
@ -533,7 +537,22 @@ struct WASMModule {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_FAST_JIT != 0
|
#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;
|
void **fast_jit_func_ptrs;
|
||||||
/* locks for Fast JIT lazy compilation */
|
/* locks for Fast JIT lazy compilation */
|
||||||
korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM];
|
korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM];
|
||||||
|
@ -543,7 +562,16 @@ struct WASMModule {
|
||||||
#if WASM_ENABLE_JIT != 0
|
#if WASM_ENABLE_JIT != 0
|
||||||
struct AOTCompData *comp_data;
|
struct AOTCompData *comp_data;
|
||||||
struct AOTCompContext *comp_ctx;
|
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;
|
void **func_ptrs;
|
||||||
/* whether the func pointers are compiled */
|
/* whether the func pointers are compiled */
|
||||||
bool *func_ptrs_compiled;
|
bool *func_ptrs_compiled;
|
||||||
|
@ -568,6 +596,12 @@ struct WASMModule {
|
||||||
korp_tid llvm_jit_init_thread;
|
korp_tid llvm_jit_init_thread;
|
||||||
/* whether the llvm jit is initialized */
|
/* whether the llvm jit is initialized */
|
||||||
bool llvm_jit_inited;
|
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
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint32)(*(uint8 *)maddr); \
|
readv = (uint32)(*(uint8 *)maddr); \
|
||||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
*(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) { \
|
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint32)LOAD_U16(maddr); \
|
readv = (uint32)LOAD_U16(maddr); \
|
||||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||||
os_mutex_unlock(&module->e->mem_lock); \
|
os_mutex_unlock(&node->shared_mem_lock); \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = LOAD_I32(maddr); \
|
readv = LOAD_I32(maddr); \
|
||||||
STORE_U32(maddr, readv op sval); \
|
STORE_U32(maddr, readv op sval); \
|
||||||
os_mutex_unlock(&module->e->mem_lock); \
|
os_mutex_unlock(&node->shared_mem_lock); \
|
||||||
} \
|
} \
|
||||||
PUSH_I32(readv); \
|
PUSH_I32(readv); \
|
||||||
break; \
|
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_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint64)(*(uint8 *)maddr); \
|
readv = (uint64)(*(uint8 *)maddr); \
|
||||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
*(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) { \
|
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint64)LOAD_U16(maddr); \
|
readv = (uint64)LOAD_U16(maddr); \
|
||||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
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) { \
|
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint64)LOAD_U32(maddr); \
|
readv = (uint64)LOAD_U32(maddr); \
|
||||||
STORE_U32(maddr, (uint32)(readv op sval)); \
|
STORE_U32(maddr, (uint32)(readv op sval)); \
|
||||||
os_mutex_unlock(&module->e->mem_lock); \
|
os_mutex_unlock(&node->shared_mem_lock); \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
uint64 op_result; \
|
uint64 op_result; \
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint64)LOAD_I64(maddr); \
|
readv = (uint64)LOAD_I64(maddr); \
|
||||||
op_result = readv op sval; \
|
op_result = readv op sval; \
|
||||||
STORE_I64(maddr, op_result); \
|
STORE_I64(maddr, op_result); \
|
||||||
os_mutex_unlock(&module->e->mem_lock); \
|
os_mutex_unlock(&node->shared_mem_lock); \
|
||||||
} \
|
} \
|
||||||
PUSH_I64(readv); \
|
PUSH_I64(readv); \
|
||||||
break; \
|
break; \
|
||||||
|
@ -1151,6 +1151,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
uint32 cache_index, type_index, param_cell_num, cell_num;
|
uint32 cache_index, type_index, param_cell_num, cell_num;
|
||||||
uint8 value_type;
|
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
|
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||||
uint8 *frame_ip_orig = NULL;
|
uint8 *frame_ip_orig = NULL;
|
||||||
WASMDebugInstance *debug_instance = wasm_exec_env_get_instance(exec_env);
|
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) {
|
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint32)(*(uint8 *)maddr);
|
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) {
|
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint32)LOAD_U16(maddr);
|
readv = (uint32)LOAD_U16(maddr);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = LOAD_I32(maddr);
|
readv = LOAD_I32(maddr);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUSH_I32(readv);
|
PUSH_I32(readv);
|
||||||
|
@ -3493,30 +3498,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
|
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)(*(uint8 *)maddr);
|
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) {
|
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)LOAD_U16(maddr);
|
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) {
|
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)LOAD_U32(maddr);
|
readv = (uint64)LOAD_U32(maddr);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = LOAD_I64(maddr);
|
readv = LOAD_I64(maddr);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUSH_I64(readv);
|
PUSH_I64(readv);
|
||||||
|
@ -3535,23 +3540,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
|
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
*(uint8 *)maddr = (uint8)sval;
|
*(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) {
|
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
STORE_U16(maddr, (uint16)sval);
|
STORE_U16(maddr, (uint16)sval);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
STORE_U32(maddr, frame_sp[1]);
|
STORE_U32(maddr, frame_sp[1]);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3569,31 +3574,31 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
|
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
*(uint8 *)maddr = (uint8)sval;
|
*(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) {
|
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
STORE_U16(maddr, (uint16)sval);
|
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) {
|
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
STORE_U32(maddr, (uint32)sval);
|
STORE_U32(maddr, (uint32)sval);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
PUT_I64_TO_ADDR((uint32 *)maddr,
|
PUT_I64_TO_ADDR((uint32 *)maddr,
|
||||||
GET_I64_FROM_ADDR(frame_sp + 1));
|
GET_I64_FROM_ADDR(frame_sp + 1));
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3613,32 +3618,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
|
|
||||||
expect = (uint8)expect;
|
expect = (uint8)expect;
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint32)(*(uint8 *)maddr);
|
readv = (uint32)(*(uint8 *)maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
*(uint8 *)maddr = (uint8)(sval);
|
*(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) {
|
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
|
|
||||||
expect = (uint16)expect;
|
expect = (uint16)expect;
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint32)LOAD_U16(maddr);
|
readv = (uint32)LOAD_U16(maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
STORE_U16(maddr, (uint16)(sval));
|
STORE_U16(maddr, (uint16)(sval));
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
|
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = LOAD_I32(maddr);
|
readv = LOAD_I32(maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
STORE_U32(maddr, sval);
|
STORE_U32(maddr, sval);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
PUSH_I32(readv);
|
PUSH_I32(readv);
|
||||||
break;
|
break;
|
||||||
|
@ -3659,44 +3664,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
|
|
||||||
expect = (uint8)expect;
|
expect = (uint8)expect;
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)(*(uint8 *)maddr);
|
readv = (uint64)(*(uint8 *)maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
*(uint8 *)maddr = (uint8)(sval);
|
*(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) {
|
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
|
|
||||||
expect = (uint16)expect;
|
expect = (uint16)expect;
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)LOAD_U16(maddr);
|
readv = (uint64)LOAD_U16(maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
STORE_U16(maddr, (uint16)(sval));
|
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) {
|
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
|
|
||||||
expect = (uint32)expect;
|
expect = (uint32)expect;
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)LOAD_U32(maddr);
|
readv = (uint64)LOAD_U32(maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
STORE_U32(maddr, (uint32)(sval));
|
STORE_U32(maddr, (uint32)(sval));
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||||
|
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)LOAD_I64(maddr);
|
readv = (uint64)LOAD_I64(maddr);
|
||||||
if (readv == expect) {
|
if (readv == expect) {
|
||||||
STORE_I64(maddr, sval);
|
STORE_I64(maddr, sval);
|
||||||
}
|
}
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
PUSH_I64(readv);
|
PUSH_I64(readv);
|
||||||
break;
|
break;
|
||||||
|
@ -4150,6 +4155,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||||
}
|
}
|
||||||
argc = function->param_cell_num;
|
argc = function->param_cell_num;
|
||||||
|
|
||||||
|
RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame);
|
||||||
#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
|
#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||||
&& WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
|
&& WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
|
||||||
if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
|
if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
|
||||||
|
@ -4194,58 +4200,51 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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 (running_mode == Mode_Interp) {
|
||||||
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0
|
wasm_interp_call_func_bytecode(module_inst, exec_env, function,
|
||||||
/* Fast JIT and LLVM JIT are both enabled, call llvm jit function
|
frame);
|
||||||
if it is compiled, else call fast jit function */
|
}
|
||||||
uint32 func_idx = (uint32)(function - module_inst->e->functions);
|
#if WASM_ENABLE_FAST_JIT != 0
|
||||||
if (module_inst->module->func_ptrs_compiled
|
else if (running_mode == Mode_Fast_JIT) {
|
||||||
[func_idx - module_inst->module->import_function_count]) {
|
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,
|
llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
|
||||||
argv);
|
argv);
|
||||||
/* For llvm jit, the results have been stored in argv,
|
/* For llvm jit, the results have been stored in argv,
|
||||||
no need to copy them from stack frame again */
|
no need to copy them from stack frame again */
|
||||||
copy_argv_from_frame = false;
|
copy_argv_from_frame = false;
|
||||||
}
|
}
|
||||||
else {
|
#endif
|
||||||
fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
|
#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
|
#endif
|
||||||
|
else {
|
||||||
#else /* else of WASM_ENABLE_LAZY_JIT != 0 */
|
/* There should always be a supported running mode selected */
|
||||||
|
bh_assert(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 */
|
|
||||||
|
|
||||||
(void)wasm_interp_call_func_bytecode;
|
(void)wasm_interp_call_func_bytecode;
|
||||||
#if WASM_ENABLE_FAST_JIT != 0
|
#if WASM_ENABLE_FAST_JIT != 0
|
||||||
|
|
|
@ -469,28 +469,28 @@ LOAD_PTR(void *addr)
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(1); \
|
CHECK_ATOMIC_MEMORY_ACCESS(1); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint32)(*(uint8 *)maddr); \
|
readv = (uint32)(*(uint8 *)maddr); \
|
||||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
*(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) { \
|
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(2); \
|
CHECK_ATOMIC_MEMORY_ACCESS(2); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint32)LOAD_U16(maddr); \
|
readv = (uint32)LOAD_U16(maddr); \
|
||||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||||
os_mutex_unlock(&module->e->mem_lock); \
|
os_mutex_unlock(&node->shared_mem_lock); \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(4); \
|
CHECK_ATOMIC_MEMORY_ACCESS(4); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = LOAD_I32(maddr); \
|
readv = LOAD_I32(maddr); \
|
||||||
STORE_U32(maddr, readv op sval); \
|
STORE_U32(maddr, readv op sval); \
|
||||||
os_mutex_unlock(&module->e->mem_lock); \
|
os_mutex_unlock(&node->shared_mem_lock); \
|
||||||
} \
|
} \
|
||||||
PUSH_I32(readv); \
|
PUSH_I32(readv); \
|
||||||
break; \
|
break; \
|
||||||
|
@ -509,39 +509,39 @@ LOAD_PTR(void *addr)
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(1); \
|
CHECK_ATOMIC_MEMORY_ACCESS(1); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint64)(*(uint8 *)maddr); \
|
readv = (uint64)(*(uint8 *)maddr); \
|
||||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
*(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) { \
|
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(2); \
|
CHECK_ATOMIC_MEMORY_ACCESS(2); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint64)LOAD_U16(maddr); \
|
readv = (uint64)LOAD_U16(maddr); \
|
||||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
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) { \
|
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(4); \
|
CHECK_ATOMIC_MEMORY_ACCESS(4); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint64)LOAD_U32(maddr); \
|
readv = (uint64)LOAD_U32(maddr); \
|
||||||
STORE_U32(maddr, (uint32)(readv op sval)); \
|
STORE_U32(maddr, (uint32)(readv op sval)); \
|
||||||
os_mutex_unlock(&module->e->mem_lock); \
|
os_mutex_unlock(&node->shared_mem_lock); \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
uint64 op_result; \
|
uint64 op_result; \
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(8); \
|
CHECK_ATOMIC_MEMORY_ACCESS(8); \
|
||||||
\
|
\
|
||||||
os_mutex_lock(&module->e->mem_lock); \
|
os_mutex_lock(&node->shared_mem_lock); \
|
||||||
readv = (uint64)LOAD_I64(maddr); \
|
readv = (uint64)LOAD_I64(maddr); \
|
||||||
op_result = readv op sval; \
|
op_result = readv op sval; \
|
||||||
STORE_I64(maddr, op_result); \
|
STORE_I64(maddr, op_result); \
|
||||||
os_mutex_unlock(&module->e->mem_lock); \
|
os_mutex_unlock(&node->shared_mem_lock); \
|
||||||
} \
|
} \
|
||||||
PUSH_I64(readv); \
|
PUSH_I64(readv); \
|
||||||
break; \
|
break; \
|
||||||
|
@ -1183,6 +1183,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
uint32 local_idx, local_offset, global_idx;
|
uint32 local_idx, local_offset, global_idx;
|
||||||
uint8 opcode, local_type, *global_addr;
|
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
|
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||||
#define HANDLE_OPCODE(op) &&HANDLE_##op
|
#define HANDLE_OPCODE(op) &&HANDLE_##op
|
||||||
DEFINE_GOTO_TABLE(const void *, handle_table);
|
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) {
|
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint32)(*(uint8 *)maddr);
|
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) {
|
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint32)LOAD_U16(maddr);
|
readv = (uint32)LOAD_U16(maddr);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = LOAD_I32(maddr);
|
readv = LOAD_I32(maddr);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUSH_I32(readv);
|
PUSH_I32(readv);
|
||||||
|
@ -3331,30 +3336,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
|
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)(*(uint8 *)maddr);
|
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) {
|
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)LOAD_U16(maddr);
|
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) {
|
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)LOAD_U32(maddr);
|
readv = (uint64)LOAD_U32(maddr);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = LOAD_I64(maddr);
|
readv = LOAD_I64(maddr);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUSH_I64(readv);
|
PUSH_I64(readv);
|
||||||
|
@ -3372,23 +3377,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
|
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
*(uint8 *)maddr = (uint8)sval;
|
*(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) {
|
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
STORE_U16(maddr, (uint16)sval);
|
STORE_U16(maddr, (uint16)sval);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
STORE_U32(maddr, sval);
|
STORE_U32(maddr, sval);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3406,30 +3411,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
|
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
*(uint8 *)maddr = (uint8)sval;
|
*(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) {
|
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
STORE_U16(maddr, (uint16)sval);
|
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) {
|
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
STORE_U32(maddr, (uint32)sval);
|
STORE_U32(maddr, (uint32)sval);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
STORE_I64(maddr, sval);
|
STORE_I64(maddr, sval);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3449,32 +3454,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||||
|
|
||||||
expect = (uint8)expect;
|
expect = (uint8)expect;
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint32)(*(uint8 *)maddr);
|
readv = (uint32)(*(uint8 *)maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
*(uint8 *)maddr = (uint8)(sval);
|
*(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) {
|
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||||
|
|
||||||
expect = (uint16)expect;
|
expect = (uint16)expect;
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint32)LOAD_U16(maddr);
|
readv = (uint32)LOAD_U16(maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
STORE_U16(maddr, (uint16)(sval));
|
STORE_U16(maddr, (uint16)(sval));
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||||
|
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = LOAD_I32(maddr);
|
readv = LOAD_I32(maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
STORE_U32(maddr, sval);
|
STORE_U32(maddr, sval);
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
PUSH_I32(readv);
|
PUSH_I32(readv);
|
||||||
break;
|
break;
|
||||||
|
@ -3495,44 +3500,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||||
|
|
||||||
expect = (uint8)expect;
|
expect = (uint8)expect;
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)(*(uint8 *)maddr);
|
readv = (uint64)(*(uint8 *)maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
*(uint8 *)maddr = (uint8)(sval);
|
*(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) {
|
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||||
|
|
||||||
expect = (uint16)expect;
|
expect = (uint16)expect;
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)LOAD_U16(maddr);
|
readv = (uint64)LOAD_U16(maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
STORE_U16(maddr, (uint16)(sval));
|
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) {
|
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||||
|
|
||||||
expect = (uint32)expect;
|
expect = (uint32)expect;
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)LOAD_U32(maddr);
|
readv = (uint64)LOAD_U32(maddr);
|
||||||
if (readv == expect)
|
if (readv == expect)
|
||||||
STORE_U32(maddr, (uint32)(sval));
|
STORE_U32(maddr, (uint32)(sval));
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||||
|
|
||||||
os_mutex_lock(&module->e->mem_lock);
|
os_mutex_lock(&node->shared_mem_lock);
|
||||||
readv = (uint64)LOAD_I64(maddr);
|
readv = (uint64)LOAD_I64(maddr);
|
||||||
if (readv == expect) {
|
if (readv == expect) {
|
||||||
STORE_I64(maddr, sval);
|
STORE_I64(maddr, sval);
|
||||||
}
|
}
|
||||||
os_mutex_unlock(&module->e->mem_lock);
|
os_mutex_unlock(&node->shared_mem_lock);
|
||||||
}
|
}
|
||||||
PUSH_I64(readv);
|
PUSH_I64(readv);
|
||||||
break;
|
break;
|
||||||
|
@ -3901,6 +3906,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||||
}
|
}
|
||||||
argc = function->param_cell_num;
|
argc = function->param_cell_num;
|
||||||
|
|
||||||
|
RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame);
|
||||||
#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
|
#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||||
&& WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
|
&& WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
|
||||||
if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
|
if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
|
||||||
|
|
|
@ -1399,6 +1399,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
WASMModule *sub_module = NULL;
|
WASMModule *sub_module = NULL;
|
||||||
WASMGlobal *linked_global = NULL;
|
WASMGlobal *linked_global = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
CHECK_BUF(p, p_end, 2);
|
CHECK_BUF(p, p_end, 2);
|
||||||
declare_type = read_uint8(p);
|
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
|
#if WASM_ENABLE_LIBC_BUILTIN != 0
|
||||||
global->is_linked = wasm_native_lookup_libc_builtin_global(
|
ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name,
|
||||||
sub_module_name, global_name, global);
|
global);
|
||||||
if (global->is_linked) {
|
if (ret) {
|
||||||
if (global->type != declare_type
|
if (global->type != declare_type
|
||||||
|| global->is_mutable != declare_mutable) {
|
|| global->is_mutable != declare_mutable) {
|
||||||
set_error_buf(error_buf, error_buf_size,
|
set_error_buf(error_buf, error_buf_size,
|
||||||
"incompatible import type");
|
"incompatible import type");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
global->is_linked = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
#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);
|
global->is_mutable = (declare_mutable == 1);
|
||||||
|
|
||||||
(void)parent_module;
|
(void)parent_module;
|
||||||
|
(void)ret;
|
||||||
return true;
|
return true;
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
|
@ -2989,6 +2992,7 @@ static bool
|
||||||
init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
||||||
uint32 error_buf_size)
|
uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
|
LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
|
||||||
AOTCompOption option = { 0 };
|
AOTCompOption option = { 0 };
|
||||||
char *aot_last_error;
|
char *aot_last_error;
|
||||||
uint64 size;
|
uint64 size;
|
||||||
|
@ -3027,8 +3031,11 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
option.is_jit_mode = true;
|
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
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
option.enable_bulk_memory = true;
|
option.enable_bulk_memory = true;
|
||||||
#endif
|
#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)
|
#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
|
||||||
option.enable_aux_stack_frame = true;
|
option.enable_aux_stack_frame = true;
|
||||||
#endif
|
#endif
|
||||||
|
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||||
|
option.enable_stack_estimation = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
|
module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
|
||||||
if (!module->comp_ctx) {
|
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;
|
module->func_ptrs[i] = (void *)func_addr;
|
||||||
|
|
||||||
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
|
#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)
|
if (module->orcjit_stop_compiling)
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -3199,9 +3211,9 @@ orcjit_thread_callback(void *arg)
|
||||||
|
|
||||||
/* Wait until init_llvm_jit_functions_stage2 finishes */
|
/* Wait until init_llvm_jit_functions_stage2 finishes */
|
||||||
os_mutex_lock(&module->tierup_wait_lock);
|
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,
|
os_cond_reltimedwait(&module->tierup_wait_cond,
|
||||||
&module->tierup_wait_lock, 10);
|
&module->tierup_wait_lock, 10000);
|
||||||
if (module->orcjit_stop_compiling) {
|
if (module->orcjit_stop_compiling) {
|
||||||
/* init_llvm_jit_functions_stage2 failed */
|
/* init_llvm_jit_functions_stage2 failed */
|
||||||
os_mutex_unlock(&module->tierup_wait_lock);
|
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);
|
bh_assert(ret == BH_LIST_SUCCESS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
||||||
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
|
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
|
||||||
&& WASM_ENABLE_LAZY_JIT != 0)
|
&& WASM_ENABLE_LAZY_JIT != 0)
|
||||||
if (os_mutex_init(&module->instance_list_lock) != 0) {
|
if (os_mutex_init(&module->instance_list_lock) != 0) {
|
||||||
set_error_buf(error_buf, error_buf_size,
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
@ -4148,10 +4160,8 @@ check_wasi_abi_compatibility(const WASMModule *module,
|
||||||
|
|
||||||
/* should have one at least */
|
/* should have one at least */
|
||||||
if (module->import_wasi_api && !start && !initialize) {
|
if (module->import_wasi_api && !start && !initialize) {
|
||||||
set_error_buf(
|
LOG_WARNING("warning: a module with WASI apis should be either "
|
||||||
error_buf, error_buf_size,
|
"a command or a reactor");
|
||||||
"a module with WASI apis must be either a command or a reactor");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4256,7 +4266,8 @@ wasm_loader_unload(WASMModule *module)
|
||||||
if (!module)
|
if (!module)
|
||||||
return;
|
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;
|
module->orcjit_stop_compiling = true;
|
||||||
if (module->llvm_jit_init_thread)
|
if (module->llvm_jit_init_thread)
|
||||||
os_thread_join(module->llvm_jit_init_thread, NULL);
|
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);
|
aot_destroy_comp_data(module->comp_data);
|
||||||
#endif
|
#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) {
|
if (module->tierup_wait_lock_inited) {
|
||||||
os_mutex_destroy(&module->tierup_wait_lock);
|
os_mutex_destroy(&module->tierup_wait_lock);
|
||||||
os_cond_destroy(&module->tierup_wait_cond);
|
os_cond_destroy(&module->tierup_wait_cond);
|
||||||
|
@ -4312,9 +4324,9 @@ wasm_loader_unload(WASMModule *module)
|
||||||
module->functions[i]->fast_jit_jitted_code);
|
module->functions[i]->fast_jit_jitted_code);
|
||||||
}
|
}
|
||||||
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
|
#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(
|
jit_code_cache_free(
|
||||||
module->functions[i]->llvm_jit_func_ptr);
|
module->functions[i]->call_to_fast_jit_from_llvm_jit);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -4406,8 +4418,8 @@ wasm_loader_unload(WASMModule *module)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
||||||
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
|
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
|
||||||
&& WASM_ENABLE_LAZY_JIT != 0)
|
&& WASM_ENABLE_LAZY_JIT != 0)
|
||||||
os_mutex_destroy(&module->instance_list_lock);
|
os_mutex_destroy(&module->instance_list_lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1835,6 +1835,7 @@ static bool
|
||||||
init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
||||||
uint32 error_buf_size)
|
uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
|
LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
|
||||||
AOTCompOption option = { 0 };
|
AOTCompOption option = { 0 };
|
||||||
char *aot_last_error;
|
char *aot_last_error;
|
||||||
uint64 size;
|
uint64 size;
|
||||||
|
@ -1873,8 +1874,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
option.is_jit_mode = true;
|
option.is_jit_mode = true;
|
||||||
option.opt_level = 3;
|
option.opt_level = llvm_jit_options.opt_level;
|
||||||
option.size_level = 3;
|
option.size_level = llvm_jit_options.size_level;
|
||||||
|
|
||||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
option.enable_bulk_memory = true;
|
option.enable_bulk_memory = true;
|
||||||
#endif
|
#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)
|
#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
|
||||||
option.enable_aux_stack_frame = true;
|
option.enable_aux_stack_frame = true;
|
||||||
#endif
|
#endif
|
||||||
|
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||||
|
option.enable_stack_estimation = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
|
module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
|
||||||
if (!module->comp_ctx) {
|
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;
|
module->func_ptrs[i] = (void *)func_addr;
|
||||||
|
|
||||||
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
|
#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)
|
if (module->orcjit_stop_compiling)
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2047,9 +2054,9 @@ orcjit_thread_callback(void *arg)
|
||||||
|
|
||||||
/* Wait until init_llvm_jit_functions_stage2 finishes */
|
/* Wait until init_llvm_jit_functions_stage2 finishes */
|
||||||
os_mutex_lock(&module->tierup_wait_lock);
|
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,
|
os_cond_reltimedwait(&module->tierup_wait_cond,
|
||||||
&module->tierup_wait_lock, 10);
|
&module->tierup_wait_lock, 10000);
|
||||||
if (module->orcjit_stop_compiling) {
|
if (module->orcjit_stop_compiling) {
|
||||||
/* init_llvm_jit_functions_stage2 failed */
|
/* init_llvm_jit_functions_stage2 failed */
|
||||||
os_mutex_unlock(&module->tierup_wait_lock);
|
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);
|
bh_assert(ret == BH_LIST_SUCCESS);
|
||||||
#endif
|
#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) {
|
if (os_mutex_init(&module->instance_list_lock) != 0) {
|
||||||
set_error_buf(error_buf, error_buf_size,
|
set_error_buf(error_buf, error_buf_size,
|
||||||
"init instance list lock failed");
|
"init instance list lock failed");
|
||||||
|
@ -2939,7 +2947,8 @@ wasm_loader_unload(WASMModule *module)
|
||||||
if (!module)
|
if (!module)
|
||||||
return;
|
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;
|
module->orcjit_stop_compiling = true;
|
||||||
if (module->llvm_jit_init_thread)
|
if (module->llvm_jit_init_thread)
|
||||||
os_thread_join(module->llvm_jit_init_thread, NULL);
|
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);
|
aot_destroy_comp_data(module->comp_data);
|
||||||
#endif
|
#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) {
|
if (module->tierup_wait_lock_inited) {
|
||||||
os_mutex_destroy(&module->tierup_wait_lock);
|
os_mutex_destroy(&module->tierup_wait_lock);
|
||||||
os_cond_destroy(&module->tierup_wait_cond);
|
os_cond_destroy(&module->tierup_wait_cond);
|
||||||
|
@ -2995,9 +3005,9 @@ wasm_loader_unload(WASMModule *module)
|
||||||
module->functions[i]->fast_jit_jitted_code);
|
module->functions[i]->fast_jit_jitted_code);
|
||||||
}
|
}
|
||||||
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
|
#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(
|
jit_code_cache_free(
|
||||||
module->functions[i]->llvm_jit_func_ptr);
|
module->functions[i]->call_to_fast_jit_from_llvm_jit);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -3056,7 +3066,8 @@ wasm_loader_unload(WASMModule *module)
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
os_mutex_destroy(&module->instance_list_lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -737,13 +737,12 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
|
||||||
|
|
||||||
function++;
|
function++;
|
||||||
}
|
}
|
||||||
|
bh_assert((uint32)(function - functions) == function_count);
|
||||||
|
|
||||||
#if WASM_ENABLE_FAST_JIT != 0
|
#if WASM_ENABLE_FAST_JIT != 0
|
||||||
module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs;
|
module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bh_assert((uint32)(function - functions) == function_count);
|
|
||||||
(void)module_inst;
|
|
||||||
return functions;
|
return functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1288,9 +1287,8 @@ init_func_ptrs(WASMModuleInstance *module_inst, WASMModule *module,
|
||||||
*func_ptrs = import_func->func_ptr_linked;
|
*func_ptrs = import_func->func_ptr_linked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set defined function pointers */
|
/* The defined function pointers will be set in
|
||||||
bh_memcpy_s(func_ptrs, sizeof(void *) * module->function_count,
|
wasm_runtime_set_running_mode, no need to set them here */
|
||||||
module->func_ptrs, sizeof(void *) * module->function_count);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif /* end of WASM_ENABLE_JIT != 0 */
|
#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 */
|
#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
|
* Instantiate module
|
||||||
*/
|
*/
|
||||||
|
@ -1422,15 +1587,6 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
|
||||||
module_inst->e =
|
module_inst->e =
|
||||||
(WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset);
|
(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
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
module_inst->e->sub_module_inst_list =
|
module_inst->e->sub_module_inst_list =
|
||||||
&module_inst->e->sub_module_inst_list_head;
|
&module_inst->e->sub_module_inst_list_head;
|
||||||
|
@ -1803,33 +1959,39 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
#if WASM_ENABLE_WASI_NN != 0
|
||||||
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
|
if (!is_sub_inst) {
|
||||||
&& WASM_ENABLE_LAZY_JIT != 0)
|
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) {
|
if (!is_sub_inst) {
|
||||||
/* Add module instance into module's instance list */
|
/* Add module instance into module's instance list */
|
||||||
os_mutex_lock(&module->instance_list_lock);
|
os_mutex_lock(&module->instance_list_lock);
|
||||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
|
||||||
if (module->instance_list) {
|
if (module->instance_list) {
|
||||||
LOG_WARNING(
|
LOG_WARNING(
|
||||||
"warning: multiple instances referencing to the same module "
|
"warning: multiple instances referencing to the same module "
|
||||||
"may cause unexpected behaviour during debugging");
|
"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_inst->e->next = module->instance_list;
|
||||||
module->instance_list = module_inst;
|
module->instance_list = module_inst;
|
||||||
os_mutex_unlock(&module->instance_list_lock);
|
os_mutex_unlock(&module->instance_list_lock);
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
if (module->start_function != (uint32)-1) {
|
||||||
/* TODO: fix start function can be import function issue */
|
/* TODO: fix start function can be import function issue */
|
||||||
if (module->start_function >= module->import_function_count)
|
if (module->start_function >= module->import_function_count)
|
||||||
|
@ -1895,11 +2057,48 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
||||||
if (!module_inst)
|
if (!module_inst)
|
||||||
return;
|
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 WASM_ENABLE_JIT != 0
|
||||||
if (module_inst->func_ptrs)
|
if (module_inst->func_ptrs)
|
||||||
wasm_runtime_free(module_inst->func_ptrs);
|
wasm_runtime_free(module_inst->func_ptrs);
|
||||||
#endif
|
#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 WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
|
||||||
if (module_inst->func_type_indexes)
|
if (module_inst->func_type_indexes)
|
||||||
wasm_runtime_free(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
|
#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)
|
if (module_inst->e->c_api_func_imports)
|
||||||
wasm_runtime_free(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);
|
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
|
/* Check native stack overflow firstly to ensure we have enough
|
||||||
native stack to run the following codes before actually calling
|
native stack to run the following codes before actually calling
|
||||||
the aot function in invokeNative function. */
|
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
|
if ((uint8 *)&exec_env_tls < exec_env->native_stack_boundary
|
||||||
+ page_size * (guard_page_count + 1)) {
|
+ page_size * (guard_page_count + 1)) {
|
||||||
wasm_set_exception(module_inst, "native stack overflow");
|
wasm_set_exception(module_inst, "native stack overflow");
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
#include "../common/wasm_runtime_common.h"
|
#include "../common/wasm_runtime_common.h"
|
||||||
#include "../common/wasm_exec_env.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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,9 +63,7 @@ typedef enum WASMExceptionID {
|
||||||
EXCE_AUX_STACK_UNDERFLOW,
|
EXCE_AUX_STACK_UNDERFLOW,
|
||||||
EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
|
EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
|
||||||
EXCE_OPERAND_STACK_OVERFLOW,
|
EXCE_OPERAND_STACK_OVERFLOW,
|
||||||
#if WASM_ENABLE_FAST_JIT != 0
|
|
||||||
EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC,
|
EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC,
|
||||||
#endif
|
|
||||||
EXCE_ALREADY_THROWN,
|
EXCE_ALREADY_THROWN,
|
||||||
EXCE_NUM,
|
EXCE_NUM,
|
||||||
} WASMExceptionID;
|
} WASMExceptionID;
|
||||||
|
@ -219,12 +221,7 @@ typedef struct WASMModuleInstanceExtra {
|
||||||
WASMFunctionInstance *retain_function;
|
WASMFunctionInstance *retain_function;
|
||||||
|
|
||||||
CApiFuncImport *c_api_func_imports;
|
CApiFuncImport *c_api_func_imports;
|
||||||
|
RunningMode running_mode;
|
||||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
|
||||||
/* lock for shared memory atomic operations */
|
|
||||||
korp_mutex mem_lock;
|
|
||||||
bool mem_lock_inited;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||||
bh_list sub_module_inst_list_head;
|
bh_list sub_module_inst_list_head;
|
||||||
|
@ -237,11 +234,15 @@ typedef struct WASMModuleInstanceExtra {
|
||||||
uint32 max_aux_stack_used;
|
uint32 max_aux_stack_used;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
||||||
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
|
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
|
||||||
&& WASM_ENABLE_LAZY_JIT != 0)
|
&& WASM_ENABLE_LAZY_JIT != 0)
|
||||||
WASMModuleInstance *next;
|
WASMModuleInstance *next;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_WASI_NN != 0
|
||||||
|
WASINNContext *wasi_nn_ctx;
|
||||||
|
#endif
|
||||||
} WASMModuleInstanceExtra;
|
} WASMModuleInstanceExtra;
|
||||||
|
|
||||||
struct AOTFuncPerfProfInfo;
|
struct AOTFuncPerfProfInfo;
|
||||||
|
@ -298,7 +299,11 @@ struct WASMModuleInstance {
|
||||||
not available in AOTModuleInstance */
|
not available in AOTModuleInstance */
|
||||||
DefPointer(void **, import_func_ptrs);
|
DefPointer(void **, import_func_ptrs);
|
||||||
/* Array of function pointers to fast jit functions,
|
/* 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);
|
DefPointer(void **, fast_jit_func_ptrs);
|
||||||
/* The custom data that can be set/get by wasm_{get|set}_custom_data */
|
/* The custom data that can be set/get by wasm_{get|set}_custom_data */
|
||||||
DefPointer(void *, custom_data);
|
DefPointer(void *, custom_data);
|
||||||
|
@ -402,6 +407,10 @@ wasm_dump_perf_profiling(const WASMModuleInstance *module_inst);
|
||||||
void
|
void
|
||||||
wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst);
|
wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst);
|
||||||
|
|
||||||
|
bool
|
||||||
|
wasm_set_running_mode(WASMModuleInstance *module_inst,
|
||||||
|
RunningMode running_mode);
|
||||||
|
|
||||||
WASMFunctionInstance *
|
WASMFunctionInstance *
|
||||||
wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name,
|
wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name,
|
||||||
const char *signature);
|
const char *signature);
|
||||||
|
|
|
@ -565,6 +565,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
|
||||||
#if WASM_ENABLE_LIBC_WASI != 0
|
#if WASM_ENABLE_LIBC_WASI != 0
|
||||||
WASIContext *wasi_ctx;
|
WASIContext *wasi_ctx;
|
||||||
#endif
|
#endif
|
||||||
|
CApiFuncImport **new_c_api_func_imports = NULL;
|
||||||
|
|
||||||
bh_assert(module);
|
bh_assert(module);
|
||||||
bh_assert(module_inst);
|
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);
|
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
|
||||||
#endif
|
#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))))
|
if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,12 @@ typedef struct WASIContext {
|
||||||
wasi_ctx_t
|
wasi_ctx_t
|
||||||
wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst);
|
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 *
|
static inline struct fd_table *
|
||||||
wasi_ctx_get_curfds(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
|
wasi_ctx_get_curfds(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
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
|
static wasi_errno_t
|
||||||
wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
|
wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
|
||||||
wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app)
|
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);
|
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||||
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
|
||||||
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
|
||||||
size_t nevents;
|
size_t nevents = 0;
|
||||||
wasi_errno_t err;
|
wasi_errno_t err;
|
||||||
|
|
||||||
if (!wasi_ctx)
|
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)))
|
|| !validate_native_addr(nevents_app, sizeof(uint32)))
|
||||||
return (wasi_errno_t)-1;
|
return (wasi_errno_t)-1;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_THREAD_MGR == 0
|
||||||
err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents);
|
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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -1861,12 +1963,6 @@ allocate_iovec_app_buffer(wasm_module_inst_t module_inst,
|
||||||
return __WASI_ESUCCESS;
|
return __WASI_ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t
|
|
||||||
min(size_t a, size_t b)
|
|
||||||
{
|
|
||||||
return a > b ? b : a;
|
|
||||||
}
|
|
||||||
|
|
||||||
static wasi_errno_t
|
static wasi_errno_t
|
||||||
copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin,
|
copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin,
|
||||||
uint32 buf_size, iovec_app_t *data, uint32 data_len,
|
uint32 buf_size, iovec_app_t *data, uint32 data_len,
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "bh_platform.h"
|
#include "bh_platform.h"
|
||||||
#include "wasmtime_ssp.h"
|
#include "wasmtime_ssp.h"
|
||||||
#include "locking.h"
|
#include "locking.h"
|
||||||
#include "numeric_limits.h"
|
|
||||||
#include "posix.h"
|
#include "posix.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "refcount.h"
|
#include "refcount.h"
|
||||||
|
@ -2257,8 +2256,7 @@ convert_timestamp(__wasi_timestamp_t in, struct timespec *out)
|
||||||
in /= 1000000000;
|
in /= 1000000000;
|
||||||
|
|
||||||
// Clamp to the maximum in case it would overflow our system's time_t.
|
// Clamp to the maximum in case it would overflow our system's time_t.
|
||||||
out->tv_sec =
|
out->tv_sec = (time_t)in < BH_TIME_T_MAX ? (time_t)in : BH_TIME_T_MAX;
|
||||||
(time_t)in < NUMERIC_MAX(time_t) ? (time_t)in : NUMERIC_MAX(time_t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts the provided timestamps and flags to a set of arguments for
|
// Converts the provided timestamps and flags to a set of arguments for
|
||||||
|
@ -3226,6 +3224,7 @@ wasi_ssp_sock_get_reuse_port(
|
||||||
#else
|
#else
|
||||||
errno = ENOTSUP;
|
errno = ENOTSUP;
|
||||||
ret = BHT_ERROR;
|
ret = BHT_ERROR;
|
||||||
|
optval = 0;
|
||||||
#endif /* defined(SO_REUSEPORT) */
|
#endif /* defined(SO_REUSEPORT) */
|
||||||
|
|
||||||
fd_object_release(fo);
|
fd_object_release(fo);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "bh_platform.h"
|
#include "bh_platform.h"
|
||||||
#include "locking.h"
|
#include "locking.h"
|
||||||
|
#include "gnuc.h"
|
||||||
|
|
||||||
#define PRODUCES(...) LOCKS_SHARED(__VA_ARGS__) NO_LOCK_ANALYSIS
|
#define PRODUCES(...) LOCKS_SHARED(__VA_ARGS__) NO_LOCK_ANALYSIS
|
||||||
#define CONSUMES(...) UNLOCKS(__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;
|
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 */
|
#else /* else of CONFIG_HAS_STD_ATOMIC */
|
||||||
#error "Reference counter isn't implemented"
|
#error "Reference counter isn't implemented"
|
||||||
#endif /* end of CONFIG_HAS_STD_ATOMIC */
|
#endif /* end of CONFIG_HAS_STD_ATOMIC */
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#ifndef SSP_CONFIG_H
|
#ifndef SSP_CONFIG_H
|
||||||
#define SSP_CONFIG_H
|
#define SSP_CONFIG_H
|
||||||
|
|
||||||
|
#include "gnuc.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__APPLE__) \
|
#if defined(__FreeBSD__) || defined(__APPLE__) \
|
||||||
|
@ -107,10 +108,31 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(BH_PLATFORM_LINUX_SGX)
|
#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
|
#define CONFIG_HAS_STD_ATOMIC 1
|
||||||
#else
|
#else
|
||||||
#define CONFIG_HAS_STD_ATOMIC 0
|
#define CONFIG_HAS_STD_ATOMIC 0
|
||||||
#endif
|
#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__)
|
#if !defined(__NuttX__)
|
||||||
#define CONFIG_HAS_D_INO 1
|
#define CONFIG_HAS_D_INO 1
|
||||||
|
|
|
@ -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 */
|
/* The caller must lock cluster->lock */
|
||||||
static bool
|
static bool
|
||||||
allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size)
|
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);
|
os_mutex_unlock(&cluster->debug_inst->wait_lock);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0)
|
if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0)
|
||||||
ret = false;
|
ret = false;
|
||||||
|
|
||||||
|
@ -478,7 +529,7 @@ fail4:
|
||||||
/* free the allocated aux stack space */
|
/* free the allocated aux stack space */
|
||||||
free_aux_stack(exec_env, aux_stack_start);
|
free_aux_stack(exec_env, aux_stack_start);
|
||||||
fail3:
|
fail3:
|
||||||
wasm_exec_env_destroy(new_exec_env);
|
wasm_exec_env_destroy_internal(new_exec_env);
|
||||||
fail2:
|
fail2:
|
||||||
wasm_runtime_deinstantiate_internal(new_module_inst, true);
|
wasm_runtime_deinstantiate_internal(new_module_inst, true);
|
||||||
fail1:
|
fail1:
|
||||||
|
@ -616,7 +667,7 @@ fail3:
|
||||||
if (alloc_aux_stack)
|
if (alloc_aux_stack)
|
||||||
free_aux_stack(exec_env, aux_stack_start);
|
free_aux_stack(exec_env, aux_stack_start);
|
||||||
fail2:
|
fail2:
|
||||||
wasm_exec_env_destroy(new_exec_env);
|
wasm_exec_env_destroy_internal(new_exec_env);
|
||||||
fail1:
|
fail1:
|
||||||
os_mutex_unlock(&cluster->lock);
|
os_mutex_unlock(&cluster->lock);
|
||||||
|
|
||||||
|
@ -786,16 +837,22 @@ wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val)
|
||||||
korp_tid handle;
|
korp_tid handle;
|
||||||
|
|
||||||
os_mutex_lock(&cluster_list_lock);
|
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) {
|
if (!clusters_have_exec_env(exec_env) || exec_env->thread_is_detached) {
|
||||||
/* Invalid thread, thread has exited or thread has been detached */
|
/* Invalid thread, thread has exited or thread has been detached */
|
||||||
if (ret_val)
|
if (ret_val)
|
||||||
*ret_val = NULL;
|
*ret_val = NULL;
|
||||||
|
os_mutex_unlock(&exec_env->cluster->lock);
|
||||||
os_mutex_unlock(&cluster_list_lock);
|
os_mutex_unlock(&cluster_list_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
exec_env->wait_count++;
|
exec_env->wait_count++;
|
||||||
handle = exec_env->handle;
|
handle = exec_env->handle;
|
||||||
|
|
||||||
|
os_mutex_unlock(&exec_env->cluster->lock);
|
||||||
os_mutex_unlock(&cluster_list_lock);
|
os_mutex_unlock(&cluster_list_lock);
|
||||||
|
|
||||||
return os_thread_join(handle, ret_val);
|
return os_thread_join(handle, ret_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,15 +935,22 @@ int32
|
||||||
wasm_cluster_cancel_thread(WASMExecEnv *exec_env)
|
wasm_cluster_cancel_thread(WASMExecEnv *exec_env)
|
||||||
{
|
{
|
||||||
os_mutex_lock(&cluster_list_lock);
|
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)) {
|
if (!clusters_have_exec_env(exec_env)) {
|
||||||
/* Invalid thread or the thread has exited */
|
/* Invalid thread or the thread has exited */
|
||||||
os_mutex_unlock(&cluster_list_lock);
|
goto final;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
os_mutex_unlock(&cluster_list_lock);
|
|
||||||
|
|
||||||
set_thread_cancel_flags(exec_env);
|
set_thread_cancel_flags(exec_env);
|
||||||
|
|
||||||
|
final:
|
||||||
|
os_mutex_unlock(&exec_env->cluster->lock);
|
||||||
|
os_mutex_unlock(&cluster_list_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,11 +972,9 @@ wasm_cluster_terminate_all(WASMCluster *cluster)
|
||||||
{
|
{
|
||||||
os_mutex_lock(&cluster->lock);
|
os_mutex_lock(&cluster->lock);
|
||||||
cluster->processing = true;
|
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;
|
cluster->processing = false;
|
||||||
os_mutex_unlock(&cluster->lock);
|
os_mutex_unlock(&cluster->lock);
|
||||||
}
|
}
|
||||||
|
@ -923,12 +985,10 @@ wasm_cluster_terminate_all_except_self(WASMCluster *cluster,
|
||||||
{
|
{
|
||||||
os_mutex_lock(&cluster->lock);
|
os_mutex_lock(&cluster->lock);
|
||||||
cluster->processing = true;
|
cluster->processing = true;
|
||||||
os_mutex_unlock(&cluster->lock);
|
|
||||||
|
|
||||||
traverse_list(&cluster->exec_env_list, terminate_thread_visitor,
|
safe_traverse_exec_env_list(cluster, terminate_thread_visitor,
|
||||||
(void *)exec_env);
|
(void *)exec_env);
|
||||||
|
|
||||||
os_mutex_lock(&cluster->lock);
|
|
||||||
cluster->processing = false;
|
cluster->processing = false;
|
||||||
os_mutex_unlock(&cluster->lock);
|
os_mutex_unlock(&cluster->lock);
|
||||||
}
|
}
|
||||||
|
@ -950,11 +1010,9 @@ wams_cluster_wait_for_all(WASMCluster *cluster)
|
||||||
{
|
{
|
||||||
os_mutex_lock(&cluster->lock);
|
os_mutex_lock(&cluster->lock);
|
||||||
cluster->processing = true;
|
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;
|
cluster->processing = false;
|
||||||
os_mutex_unlock(&cluster->lock);
|
os_mutex_unlock(&cluster->lock);
|
||||||
}
|
}
|
||||||
|
@ -965,12 +1023,10 @@ wasm_cluster_wait_for_all_except_self(WASMCluster *cluster,
|
||||||
{
|
{
|
||||||
os_mutex_lock(&cluster->lock);
|
os_mutex_lock(&cluster->lock);
|
||||||
cluster->processing = true;
|
cluster->processing = true;
|
||||||
os_mutex_unlock(&cluster->lock);
|
|
||||||
|
|
||||||
traverse_list(&cluster->exec_env_list, wait_for_thread_visitor,
|
safe_traverse_exec_env_list(cluster, wait_for_thread_visitor,
|
||||||
(void *)exec_env);
|
(void *)exec_env);
|
||||||
|
|
||||||
os_mutex_lock(&cluster->lock);
|
|
||||||
cluster->processing = false;
|
cluster->processing = false;
|
||||||
os_mutex_unlock(&cluster->lock);
|
os_mutex_unlock(&cluster->lock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
**/Dockerfile
|
|
|
@ -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.
|
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,
|
If all the tests have run properly you will the the following message in the terminal,
|
||||||
|
|
||||||
```
|
```
|
||||||
Tests: passed!
|
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
|
## 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.
|
* `graph` and `graph-execution-context` are ignored.
|
||||||
* Only `tensorflow` (lite) is supported.
|
* Graph encoding: `tensorflowlite`.
|
||||||
* Only `cpu` is supported.
|
* Execution target: `cpu` and `gpu`.
|
||||||
|
* Tensor type: `fp32`.
|
||||||
|
|
|
@ -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 <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#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
|
|
63
core/iwasm/libraries/wasi-nn/src/utils/logger.h
Normal file
63
core/iwasm/libraries/wasi-nn/src/utils/logger.h
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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
|
163
core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c
Normal file
163
core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c
Normal file
|
@ -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;
|
||||||
|
}
|
51
core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h
Normal file
51
core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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
|
302
core/iwasm/libraries/wasi-nn/src/wasi_nn.c
Normal file
302
core/iwasm/libraries/wasi-nn/src/wasi_nn.c
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
30
core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h
Normal file
30
core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h
Normal file
|
@ -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
|
|
@ -3,8 +3,10 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "wasi_nn_tensorflow.hpp"
|
#include "wasi_nn.h"
|
||||||
#include "wasi_nn_common.h"
|
#include "wasi_nn_tensorflowlite.hpp"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
#include "bh_common.h"
|
#include "bh_common.h"
|
||||||
#include "bh_platform.h"
|
#include "bh_platform.h"
|
||||||
#include "platform_common.h"
|
#include "platform_common.h"
|
||||||
|
@ -14,6 +16,7 @@
|
||||||
#include <tensorflow/lite/model.h>
|
#include <tensorflow/lite/model.h>
|
||||||
#include <tensorflow/lite/optional_debug_tools.h>
|
#include <tensorflow/lite/optional_debug_tools.h>
|
||||||
#include <tensorflow/lite/error_reporter.h>
|
#include <tensorflow/lite/error_reporter.h>
|
||||||
|
#include <tensorflow/lite/delegates/gpu/delegate.h>
|
||||||
|
|
||||||
/* Global variables */
|
/* Global variables */
|
||||||
|
|
||||||
|
@ -25,30 +28,30 @@ static char *model_pointer = NULL;
|
||||||
/* WASI-NN (tensorflow) implementation */
|
/* WASI-NN (tensorflow) implementation */
|
||||||
|
|
||||||
error
|
error
|
||||||
tensorflow_load(graph_builder_array builder, graph_encoding encoding,
|
tensorflowlite_load(graph_builder_array *builder, graph_encoding encoding,
|
||||||
execution_target target, graph *graph)
|
execution_target target, graph *g)
|
||||||
{
|
{
|
||||||
if (model_pointer != NULL) {
|
if (model_pointer != NULL) {
|
||||||
wasm_runtime_free(model_pointer);
|
wasm_runtime_free(model_pointer);
|
||||||
model_pointer = NULL;
|
model_pointer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (builder.size != 1) {
|
if (builder->size != 1) {
|
||||||
NN_ERR_PRINTF("Unexpected builder format.");
|
NN_ERR_PRINTF("Unexpected builder format.");
|
||||||
return invalid_argument;
|
return invalid_argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encoding != tensorflow) {
|
if (encoding != tensorflowlite) {
|
||||||
NN_ERR_PRINTF("Encoding is not tensorflow.");
|
NN_ERR_PRINTF("Encoding is not tensorflowlite.");
|
||||||
return invalid_argument;
|
return invalid_argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target != cpu) {
|
if (target != cpu && target != gpu) {
|
||||||
NN_ERR_PRINTF("Only CPU target is supported.");
|
NN_ERR_PRINTF("Only CPU and GPU target is supported.");
|
||||||
return invalid_argument;
|
return invalid_argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t size = builder.buf[0].size;
|
uint32_t size = builder->buf[0].size;
|
||||||
|
|
||||||
model_pointer = (char *)wasm_runtime_malloc(size);
|
model_pointer = (char *)wasm_runtime_malloc(size);
|
||||||
if (model_pointer == NULL) {
|
if (model_pointer == NULL) {
|
||||||
|
@ -56,7 +59,7 @@ tensorflow_load(graph_builder_array builder, graph_encoding encoding,
|
||||||
return missing_memory;
|
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);
|
model = tflite::FlatBufferModel::BuildFromBuffer(model_pointer, size, NULL);
|
||||||
if (model == NULL) {
|
if (model == NULL) {
|
||||||
|
@ -77,11 +80,34 @@ tensorflow_load(graph_builder_array builder, graph_encoding encoding,
|
||||||
return missing_memory;
|
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;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
error
|
error
|
||||||
tensorflow_init_execution_context(graph graph)
|
tensorflowlite_init_execution_context(graph g, graph_execution_context *ctx)
|
||||||
{
|
{
|
||||||
if (interpreter == NULL) {
|
if (interpreter == NULL) {
|
||||||
NN_ERR_PRINTF("Non-initialized interpreter.");
|
NN_ERR_PRINTF("Non-initialized interpreter.");
|
||||||
|
@ -92,8 +118,8 @@ tensorflow_init_execution_context(graph graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
error
|
error
|
||||||
tensorflow_set_input(graph_execution_context ctx, uint32_t index,
|
tensorflowlite_set_input(graph_execution_context ctx, uint32_t index,
|
||||||
tensor *input_tensor)
|
tensor *input_tensor)
|
||||||
{
|
{
|
||||||
if (interpreter == NULL) {
|
if (interpreter == NULL) {
|
||||||
NN_ERR_PRINTF("Non-initialized interpreter.");
|
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;
|
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];
|
model_tensor_size *= (uint32_t)tensor->dims->data[i];
|
||||||
|
|
||||||
uint32_t input_tensor_size = 1;
|
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];
|
input_tensor_size *= (uint32_t)input_tensor->dimensions->buf[i];
|
||||||
|
|
||||||
if (model_tensor_size != input_tensor_size) {
|
if (model_tensor_size != input_tensor_size) {
|
||||||
|
@ -136,7 +162,7 @@ tensorflow_set_input(graph_execution_context ctx, uint32_t index,
|
||||||
}
|
}
|
||||||
|
|
||||||
error
|
error
|
||||||
tensorflow_compute(graph_execution_context ctx)
|
tensorflowlite_compute(graph_execution_context ctx)
|
||||||
{
|
{
|
||||||
if (interpreter == NULL) {
|
if (interpreter == NULL) {
|
||||||
NN_ERR_PRINTF("Non-initialized interpreter.");
|
NN_ERR_PRINTF("Non-initialized interpreter.");
|
||||||
|
@ -147,8 +173,9 @@ tensorflow_compute(graph_execution_context ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
error
|
error
|
||||||
tensorflow_get_output(graph_execution_context context, uint32_t index,
|
tensorflowlite_get_output(graph_execution_context ctx, uint32_t index,
|
||||||
tensor_data output_tensor, uint32_t *output_tensor_size)
|
tensor_data output_tensor,
|
||||||
|
uint32_t *output_tensor_size)
|
||||||
{
|
{
|
||||||
if (interpreter == NULL) {
|
if (interpreter == NULL) {
|
||||||
NN_ERR_PRINTF("Non-initialized interpreter.");
|
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<float>(index);
|
float *tensor_f = interpreter->typed_output_tensor<float>(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]);
|
NN_DBG_PRINTF("output: %f", tensor_f[i]);
|
||||||
|
|
||||||
*output_tensor_size = model_tensor_size;
|
*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));
|
model_tensor_size * sizeof(float));
|
||||||
return success;
|
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.");
|
||||||
|
}
|
41
core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp
Normal file
41
core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp
Normal file
|
@ -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
|
|
@ -7,10 +7,10 @@ project (iwasm)
|
||||||
|
|
||||||
set (CMAKE_VERBOSE_MAKEFILE OFF)
|
set (CMAKE_VERBOSE_MAKEFILE OFF)
|
||||||
# Reset default linker flags
|
# 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_C_STANDARD 99)
|
||||||
set (CMAKE_CXX_STANDARD 14)
|
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)
|
if (NOT DEFINED WAMR_BUILD_PLATFORM)
|
||||||
set (WAMR_BUILD_PLATFORM "linux")
|
set (WAMR_BUILD_PLATFORM "linux")
|
||||||
|
|
|
@ -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" ]
|
|
22
core/iwasm/libraries/wasi-nn/test/Dockerfile.base
Normal file
22
core/iwasm/libraries/wasi-nn/test/Dockerfile.base
Normal file
|
@ -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)
|
23
core/iwasm/libraries/wasi-nn/test/Dockerfile.compile
Normal file
23
core/iwasm/libraries/wasi-nn/test/Dockerfile.compile
Normal file
|
@ -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" ]
|
8
core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu
Normal file
8
core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu
Normal file
|
@ -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" ]
|
20
core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu
Normal file
20
core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu
Normal file
|
@ -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" ]
|
|
@ -7,7 +7,7 @@
|
||||||
-Wl,--allow-undefined \
|
-Wl,--allow-undefined \
|
||||||
-Wl,--strip-all,--no-entry \
|
-Wl,--strip-all,--no-entry \
|
||||||
--sysroot=/opt/wasi-sdk/share/wasi-sysroot \
|
--sysroot=/opt/wasi-sdk/share/wasi-sysroot \
|
||||||
-I/home/wamr/core/iwasm/libraries/wasi-nn \
|
-I.. \
|
||||||
-o test_tensorflow.wasm test_tensorflow.c
|
-o test_tensorflow.wasm test_tensorflow.c
|
||||||
|
|
||||||
# TFLite models to use in the tests
|
# TFLite models to use in the tests
|
||||||
|
|
78
core/iwasm/libraries/wasi-nn/test/test_tensorflow.c
Executable file → Normal file
78
core/iwasm/libraries/wasi-nn/test/test_tensorflow.c
Executable file → Normal file
|
@ -28,7 +28,7 @@ typedef struct {
|
||||||
// WASI-NN wrappers
|
// WASI-NN wrappers
|
||||||
|
|
||||||
error
|
error
|
||||||
wasm_load(char *model_name, graph *graph)
|
wasm_load(char *model_name, graph *g, execution_target target)
|
||||||
{
|
{
|
||||||
FILE *pFile = fopen(model_name, "r");
|
FILE *pFile = fopen(model_name, "r");
|
||||||
if (pFile == NULL)
|
if (pFile == NULL)
|
||||||
|
@ -64,7 +64,7 @@ wasm_load(char *model_name, graph *graph)
|
||||||
arr.buf[0].size = result;
|
arr.buf[0].size = result;
|
||||||
arr.buf[0].buf = buffer;
|
arr.buf[0].buf = buffer;
|
||||||
|
|
||||||
error res = load(&arr, tensorflow, cpu, graph);
|
error res = load(&arr, tensorflowlite, target, g);
|
||||||
|
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
@ -73,13 +73,13 @@ wasm_load(char *model_name, graph *graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
error
|
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
|
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;
|
tensor_dimensions dims;
|
||||||
dims.size = INPUT_TENSOR_DIMS;
|
dims.size = INPUT_TENSOR_DIMS;
|
||||||
|
@ -115,11 +115,12 @@ wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
|
||||||
// Inference
|
// Inference
|
||||||
|
|
||||||
float *
|
float *
|
||||||
run_inference(float *input, uint32_t *input_size, uint32_t *output_size,
|
run_inference(execution_target target, float *input, uint32_t *input_size,
|
||||||
char *model_name, uint32_t num_output_tensors)
|
uint32_t *output_size, char *model_name,
|
||||||
|
uint32_t num_output_tensors)
|
||||||
{
|
{
|
||||||
graph graph;
|
graph graph;
|
||||||
if (wasm_load(model_name, &graph) != success) {
|
if (wasm_load(model_name, &graph, target) != success) {
|
||||||
fprintf(stderr, "Error when loading model.");
|
fprintf(stderr, "Error when loading model.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -130,7 +131,7 @@ run_inference(float *input, uint32_t *input_size, uint32_t *output_size,
|
||||||
exit(1);
|
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.");
|
fprintf(stderr, "Error when setting input tensor.");
|
||||||
exit(1);
|
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;
|
*output_size = MAX_OUTPUT_TENSOR_SIZE - *output_size;
|
||||||
if (wasm_get_output(ctx, i, &out_tensor[offset], output_size)
|
if (wasm_get_output(ctx, i, &out_tensor[offset], output_size)
|
||||||
!= success) {
|
!= success) {
|
||||||
fprintf(stderr, "Error when getting input .");
|
fprintf(stderr, "Error when getting output .");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,14 +186,14 @@ create_input(int *dims)
|
||||||
// TESTS
|
// TESTS
|
||||||
|
|
||||||
void
|
void
|
||||||
test_sum()
|
test_sum(execution_target target)
|
||||||
{
|
{
|
||||||
int dims[] = { 1, 5, 5, 1 };
|
int dims[] = { 1, 5, 5, 1 };
|
||||||
input_info input = create_input(dims);
|
input_info input = create_input(dims);
|
||||||
|
|
||||||
uint32_t output_size = 0;
|
uint32_t output_size = 0;
|
||||||
float *output = run_inference(input.input_tensor, input.dim, &output_size,
|
float *output = run_inference(target, input.input_tensor, input.dim,
|
||||||
"models/sum.tflite", 1);
|
&output_size, "/assets/models/sum.tflite", 1);
|
||||||
|
|
||||||
assert(output_size == 1);
|
assert(output_size == 1);
|
||||||
assert(fabs(output[0] - 300.0) < EPSILON);
|
assert(fabs(output[0] - 300.0) < EPSILON);
|
||||||
|
@ -203,14 +204,14 @@ test_sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_max()
|
test_max(execution_target target)
|
||||||
{
|
{
|
||||||
int dims[] = { 1, 5, 5, 1 };
|
int dims[] = { 1, 5, 5, 1 };
|
||||||
input_info input = create_input(dims);
|
input_info input = create_input(dims);
|
||||||
|
|
||||||
uint32_t output_size = 0;
|
uint32_t output_size = 0;
|
||||||
float *output = run_inference(input.input_tensor, input.dim, &output_size,
|
float *output = run_inference(target, input.input_tensor, input.dim,
|
||||||
"models/max.tflite", 1);
|
&output_size, "/assets/models/max.tflite", 1);
|
||||||
|
|
||||||
assert(output_size == 1);
|
assert(output_size == 1);
|
||||||
assert(fabs(output[0] - 24.0) < EPSILON);
|
assert(fabs(output[0] - 24.0) < EPSILON);
|
||||||
|
@ -222,14 +223,15 @@ test_max()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_average()
|
test_average(execution_target target)
|
||||||
{
|
{
|
||||||
int dims[] = { 1, 5, 5, 1 };
|
int dims[] = { 1, 5, 5, 1 };
|
||||||
input_info input = create_input(dims);
|
input_info input = create_input(dims);
|
||||||
|
|
||||||
uint32_t output_size = 0;
|
uint32_t output_size = 0;
|
||||||
float *output = run_inference(input.input_tensor, input.dim, &output_size,
|
float *output =
|
||||||
"models/average.tflite", 1);
|
run_inference(target, input.input_tensor, input.dim, &output_size,
|
||||||
|
"/assets/models/average.tflite", 1);
|
||||||
|
|
||||||
assert(output_size == 1);
|
assert(output_size == 1);
|
||||||
assert(fabs(output[0] - 12.0) < EPSILON);
|
assert(fabs(output[0] - 12.0) < EPSILON);
|
||||||
|
@ -241,14 +243,15 @@ test_average()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_mult_dimensions()
|
test_mult_dimensions(execution_target target)
|
||||||
{
|
{
|
||||||
int dims[] = { 1, 3, 3, 1 };
|
int dims[] = { 1, 3, 3, 1 };
|
||||||
input_info input = create_input(dims);
|
input_info input = create_input(dims);
|
||||||
|
|
||||||
uint32_t output_size = 0;
|
uint32_t output_size = 0;
|
||||||
float *output = run_inference(input.input_tensor, input.dim, &output_size,
|
float *output =
|
||||||
"models/mult_dim.tflite", 1);
|
run_inference(target, input.input_tensor, input.dim, &output_size,
|
||||||
|
"/assets/models/mult_dim.tflite", 1);
|
||||||
|
|
||||||
assert(output_size == 9);
|
assert(output_size == 9);
|
||||||
for (int i = 0; i < 9; i++)
|
for (int i = 0; i < 9; i++)
|
||||||
|
@ -260,14 +263,15 @@ test_mult_dimensions()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_mult_outputs()
|
test_mult_outputs(execution_target target)
|
||||||
{
|
{
|
||||||
int dims[] = { 1, 4, 4, 1 };
|
int dims[] = { 1, 4, 4, 1 };
|
||||||
input_info input = create_input(dims);
|
input_info input = create_input(dims);
|
||||||
|
|
||||||
uint32_t output_size = 0;
|
uint32_t output_size = 0;
|
||||||
float *output = run_inference(input.input_tensor, input.dim, &output_size,
|
float *output =
|
||||||
"models/mult_out.tflite", 2);
|
run_inference(target, input.input_tensor, input.dim, &output_size,
|
||||||
|
"/assets/models/mult_out.tflite", 2);
|
||||||
|
|
||||||
assert(output_size == 8);
|
assert(output_size == 8);
|
||||||
// first tensor check
|
// first tensor check
|
||||||
|
@ -285,16 +289,30 @@ test_mult_outputs()
|
||||||
int
|
int
|
||||||
main()
|
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");
|
printf("################### Testing sum...\n");
|
||||||
test_sum();
|
test_sum(target);
|
||||||
printf("################### Testing max...\n");
|
printf("################### Testing max...\n");
|
||||||
test_max();
|
test_max(target);
|
||||||
printf("################### Testing average...\n");
|
printf("################### Testing average...\n");
|
||||||
test_average();
|
test_average(target);
|
||||||
printf("################### Testing multiple dimensions...\n");
|
printf("################### Testing multiple dimensions...\n");
|
||||||
test_mult_dimensions();
|
test_mult_dimensions(target);
|
||||||
printf("################### Testing multiple outputs...\n");
|
printf("################### Testing multiple outputs...\n");
|
||||||
test_mult_outputs();
|
test_mult_outputs(target);
|
||||||
|
|
||||||
printf("Tests: passed!\n");
|
printf("Tests: passed!\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -5,6 +5,15 @@ set (WASI_NN_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
||||||
add_definitions (-DWASM_ENABLE_WASI_NN=1)
|
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)
|
set (TENSORFLOW_LIB tensorflow-lite)
|
||||||
|
|
|
@ -3,63 +3,17 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
* 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:
|
* Following definition from:
|
||||||
* [Aug 10th, 2022]
|
* [Oct 25th, 2022]
|
||||||
* https://github.com/WebAssembly/wasi-nn/blob/e5e1a6c31f424c7cd63026cd270e9746775675a0/wasi-nn.wit.md
|
* 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
|
#include <stdint.h>
|
||||||
// their graph IR in parts (e.g., OpenVINO stores its IR and weights
|
#include "wasi_nn_types.h"
|
||||||
// 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load an opaque sequence of bytes to use for inference.
|
* @brief Load an opaque sequence of bytes to use for inference.
|
||||||
|
@ -67,25 +21,31 @@ typedef struct {
|
||||||
* @param builder Model builder.
|
* @param builder Model builder.
|
||||||
* @param encoding Model encoding.
|
* @param encoding Model encoding.
|
||||||
* @param target Execution target.
|
* @param target Execution target.
|
||||||
* @param graph Graph.
|
* @param g Graph.
|
||||||
* @return error Execution status.
|
* @return error Execution status.
|
||||||
*/
|
*/
|
||||||
error
|
error
|
||||||
load(graph_builder_array *builder, graph_encoding encoding,
|
load(graph_builder_array *builder, graph_encoding encoding,
|
||||||
execution_target target, graph *graph)
|
execution_target target, graph *g)
|
||||||
__attribute__((export_module("wasi_nn")))
|
|
||||||
__attribute__((import_module("wasi_nn")));
|
__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.
|
* @brief Create an execution instance of a loaded graph.
|
||||||
*
|
*
|
||||||
* @param graph Graph.
|
* @param g Graph.
|
||||||
* @param ctx Execution context.
|
* @param ctx Execution context.
|
||||||
* @return error Execution status.
|
* @return error Execution status.
|
||||||
*/
|
*/
|
||||||
error
|
error
|
||||||
init_execution_context(graph graph, graph_execution_context *ctx)
|
init_execution_context(graph g, graph_execution_context *ctx)
|
||||||
__attribute__((export_module("wasi_nn")))
|
|
||||||
__attribute__((import_module("wasi_nn")));
|
__attribute__((import_module("wasi_nn")));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,7 +58,6 @@ init_execution_context(graph graph, graph_execution_context *ctx)
|
||||||
*/
|
*/
|
||||||
error
|
error
|
||||||
set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
|
set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
|
||||||
__attribute__((export_module("wasi_nn")))
|
|
||||||
__attribute__((import_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.
|
* @return error Execution status.
|
||||||
*/
|
*/
|
||||||
error
|
error
|
||||||
compute(graph_execution_context ctx) __attribute__((export_module("wasi_nn")))
|
compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn")));
|
||||||
__attribute__((import_module("wasi_nn")));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Extract the outputs after inference.
|
* @brief Extract the outputs after inference.
|
||||||
|
@ -126,7 +84,6 @@ __attribute__((import_module("wasi_nn")));
|
||||||
error
|
error
|
||||||
get_output(graph_execution_context ctx, uint32_t index,
|
get_output(graph_execution_context ctx, uint32_t index,
|
||||||
tensor_data output_tensor, uint32_t *output_tensor_size)
|
tensor_data output_tensor, uint32_t *output_tensor_size)
|
||||||
__attribute__((export_module("wasi_nn")))
|
|
||||||
__attribute__((import_module("wasi_nn")));
|
__attribute__((import_module("wasi_nn")));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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 <stdint.h>
|
|
||||||
|
|
||||||
// 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
|
|
|
@ -1,264 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
|
||||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
|
@ -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 <stdio.h>
|
|
||||||
|
|
||||||
#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
|
|
106
core/iwasm/libraries/wasi-nn/wasi_nn_types.h
Normal file
106
core/iwasm/libraries/wasi-nn/wasi_nn_types.h
Normal file
|
@ -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
|
|
@ -77,7 +77,7 @@ os_socket_bind(bh_socket_t socket, const char *host, int *port)
|
||||||
}
|
}
|
||||||
|
|
||||||
socklen = sizeof(addr);
|
socklen = sizeof(addr);
|
||||||
if (getsockname(socket, (void *)&addr, &socklen) == -1) {
|
if (getsockname(socket, (struct sockaddr *)&addr, &socklen) == -1) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
|
||||||
unsigned int *addrlen)
|
unsigned int *addrlen)
|
||||||
{
|
{
|
||||||
struct sockaddr addr_tmp;
|
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);
|
*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;
|
struct sockaddr_in addr;
|
||||||
socklen_t addr_len = sizeof(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;
|
return BHT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
socklen_t addr_len = sizeof(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;
|
return BHT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,11 @@
|
||||||
#define SGX_ERROR_FILE_LOWEST_ERROR_ID SGX_ERROR_FILE_BAD_STATUS
|
#define SGX_ERROR_FILE_LOWEST_ERROR_ID SGX_ERROR_FILE_BAD_STATUS
|
||||||
#define SGX_ERROR_FILE_HIGHEST_ERROR_ID SGX_ERROR_FILE_CLOSE_FAILED
|
#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.
|
// The mapping between file descriptors and IPFS file pointers.
|
||||||
static HashMap *ipfs_file_list;
|
static HashMap *ipfs_file_list;
|
||||||
|
|
||||||
|
@ -78,6 +83,27 @@ ipfs_file_destroy(void *sgx_file)
|
||||||
sgx_fclose(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
|
int
|
||||||
ipfs_init()
|
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 wrapper for fseek takes care of extending the file if sought beyond
|
||||||
// the end
|
// the end
|
||||||
if (ipfs_lseek(fd, offset + len, SEEK_CUR) == -1) {
|
if (ipfs_lseek(fd, offset + len, SEEK_SET) == -1) {
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,7 +380,7 @@ ipfs_fflush(int fd)
|
||||||
off_t
|
off_t
|
||||||
ipfs_lseek(int fd, off_t offset, int nwhence)
|
ipfs_lseek(int fd, off_t offset, int nwhence)
|
||||||
{
|
{
|
||||||
off_t new_offset;
|
off_t cursor_current_location;
|
||||||
void *sgx_file = fd2file(fd);
|
void *sgx_file = fd2file(fd);
|
||||||
if (!sgx_file) {
|
if (!sgx_file) {
|
||||||
errno = EBADF;
|
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,
|
// Optimization: if the offset is 0 and the whence is SEEK_CUR,
|
||||||
// this is equivalent of a call to ftell.
|
// this is equivalent of a call to ftell.
|
||||||
if (offset == 0 && nwhence == SEEK_CUR) {
|
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));
|
errno = convert_sgx_errno(sgx_ferror(sgx_file));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ftell_result;
|
return cursor_current_location;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fseek_result = sgx_fseek(sgx_file, offset, nwhence);
|
int fseek_result = sgx_fseek(sgx_file, offset, nwhence);
|
||||||
|
|
||||||
if (fseek_result == 0) {
|
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) {
|
if (new_offset == -1) {
|
||||||
errno = convert_sgx_errno(sgx_ferror(sgx_file));
|
errno = convert_sgx_errno(sgx_ferror(sgx_file));
|
||||||
|
@ -405,17 +431,39 @@ ipfs_lseek(int fd, off_t offset, int nwhence)
|
||||||
// manually.
|
// manually.
|
||||||
|
|
||||||
// Assume the error is raised because the cursor is moved beyond the end
|
// 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) {
|
if (sgx_fseek(sgx_file, 0, SEEK_END) == -1) {
|
||||||
errno = convert_sgx_errno(sgx_ferror(sgx_file));
|
errno = convert_sgx_errno(sgx_ferror(sgx_file));
|
||||||
return -1;
|
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
|
// Write the missing zeroes
|
||||||
char zero = 0;
|
if (ipfs_write_zeroes(sgx_file, number_of_zeroes) != 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));
|
|
||||||
return -1;
|
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
|
// Increasing the size is equal to writing from the end of the file
|
||||||
// with null bytes.
|
// with null bytes.
|
||||||
char null_byte = 0;
|
if (ipfs_write_zeroes(sgx_file, len - file_size) != 0) {
|
||||||
if (sgx_fwrite(&null_byte, 1, len - file_size, sgx_file) == 0) {
|
|
||||||
errno = convert_sgx_errno(sgx_ferror(sgx_file));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
Prepare WASM building environments
|
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`.
|
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
|
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.
|
And [sample workloads](../samples/workload) are using the self-compiled wasi-sdk.
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,13 @@ This document describes how to port WAMR to a new platform "**new-os**"
|
||||||
# Step 1: Implement platform API layer
|
# 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:
|
- `shared_platform.cmake`: the cmake file will be included by the building script. It is recommended to add a definition for your platform:
|
||||||
|
|
||||||
|
@ -20,16 +24,16 @@ Firstly create the folder **`core/shared/platform/new-os`** for platform API lay
|
||||||
add_definitions(-DBH_PLATFORM_YOUR_NAME)
|
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`.
|
- [`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:**
|
**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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +46,7 @@ Some platforms such as ZephyrOS don't provide math functions e.g. sqrt, fabs and
|
||||||
# Step 2: Create the mini product for the platform
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,6 +62,11 @@ 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.
|
Refer to [build_wamr.md](./build_wamr.md) for the building configurations and parameters.
|
||||||
|
|
1
language-bindings/python/MANIFEST.in
Normal file
1
language-bindings/python/MANIFEST.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
include src/wamr/libs/*
|
|
@ -1,31 +1,34 @@
|
||||||
# wamr-python
|
# wamr-python
|
||||||
|
|
||||||
|
The WAMR Python package contains a set of high-level bindings for WAMR API and WASM-C-API.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### Installing from the source code
|
To Install from local source tree in _development mode_ run the following command,
|
||||||
|
|
||||||
Installing from local source tree is in _development mode_. The package appears to be installed but still is editable from the source tree.
|
|
||||||
|
|
||||||
```bash
|
```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
|
## Usage
|
||||||
|
|
||||||
```python
|
From the same package you can use two set of APIs.
|
||||||
import wamr.ffi as ffi
|
|
||||||
|
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`.
|
* [WAMR API](./wamr_api)
|
||||||
|
* [WASM-C-API](./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.
|
|
||||||
|
|
|
@ -8,7 +8,28 @@
|
||||||
# pylint: disable=missing-function-docstring
|
# pylint: disable=missing-function-docstring
|
||||||
# pylint: disable=missing-module-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:
|
with open("README.md") as f:
|
||||||
|
@ -24,7 +45,11 @@ setup(
|
||||||
long_description=readme,
|
long_description=readme,
|
||||||
author="The WAMR Project Developers",
|
author="The WAMR Project Developers",
|
||||||
author_email="hello@bytecodealliance.org",
|
author_email="hello@bytecodealliance.org",
|
||||||
url="https://github.com/bytecodealliance/wamr-python",
|
url="https://github.com/bytecodealliance/wasm-micro-runtime",
|
||||||
license=license,
|
license=license,
|
||||||
packages=["wamr"],
|
include_package_data=True,
|
||||||
|
cmdclass={
|
||||||
|
'develop': PreDevelopCommand,
|
||||||
|
'install': PreInstallCommand,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
0
language-bindings/python/src/wamr/__init__.py
Normal file
0
language-bindings/python/src/wamr/__init__.py
Normal file
0
language-bindings/python/src/wamr/libs/.placeholder
Normal file
0
language-bindings/python/src/wamr/libs/.placeholder
Normal file
1779
language-bindings/python/src/wamr/wamrapi/iwasm.py
Normal file
1779
language-bindings/python/src/wamr/wamrapi/iwasm.py
Normal file
File diff suppressed because it is too large
Load Diff
123
language-bindings/python/src/wamr/wamrapi/wamr.py
Normal file
123
language-bindings/python/src/wamr/wamrapi/wamr.py
Normal file
|
@ -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
|
|
@ -36,8 +36,8 @@ current_file = Path(__file__)
|
||||||
if current_file.is_symlink():
|
if current_file.is_symlink():
|
||||||
current_file = Path(os.readlink(current_file))
|
current_file = Path(os.readlink(current_file))
|
||||||
current_dir = current_file.parent.resolve()
|
current_dir = current_file.parent.resolve()
|
||||||
root_dir = current_dir.parent.parent.parent.parent.resolve()
|
root_dir = current_dir.parents[4].resolve()
|
||||||
wamr_dir = root_dir.joinpath("wasm-micro-runtime").resolve()
|
wamr_dir = root_dir.resolve()
|
||||||
if not wamr_dir.exists():
|
if not wamr_dir.exists():
|
||||||
raise RuntimeError(f"not found the repo of wasm-micro-runtime under {root_dir}")
|
raise RuntimeError(f"not found the repo of wasm-micro-runtime under {root_dir}")
|
||||||
|
|
17
language-bindings/python/utils/create_lib.sh
Executable file
17
language-bindings/python/utils/create_lib.sh
Executable file
|
@ -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
|
25
language-bindings/python/wamr-api/README.md
Normal file
25
language-bindings/python/wamr-api/README.md
Normal file
|
@ -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
|
||||||
|
```
|
1
language-bindings/python/wamr-api/requirements.txt
Normal file
1
language-bindings/python/wamr-api/requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ctypesgen==1.1.1
|
11
language-bindings/python/wamr-api/samples/compile.sh
Normal file
11
language-bindings/python/wamr-api/samples/compile.sh
Normal file
|
@ -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
|
22
language-bindings/python/wamr-api/samples/main.py
Normal file
22
language-bindings/python/wamr-api/samples/main.py
Normal file
|
@ -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()
|
12
language-bindings/python/wamr-api/samples/sum.c
Normal file
12
language-bindings/python/wamr-api/samples/sum.c
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
sum(int a, int b)
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
}
|
7
language-bindings/python/wasm-c-api/README.md
Normal file
7
language-bindings/python/wasm-c-api/README.md
Normal file
|
@ -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.
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user