Merge pull request #2545 from bytecodealliance/main

Merge branch main into dev/thread_suspension
This commit is contained in:
Wenyong Huang 2023-09-12 16:11:46 +08:00 committed by GitHub
commit a8c26b602a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
189 changed files with 7801 additions and 3217 deletions

View File

@ -1,20 +1,21 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp/.devcontainer/base.Dockerfile
# [Choice] Debian / Ubuntu version (use Debian 11/9, Ubuntu 18.04/21.04 on local arm64/Apple Silicon): debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04
ARG VARIANT=ubuntu-20.04
FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-${VARIANT}
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/cpp/.devcontainer/base.Dockerfile
# [Choice] Debian / Ubuntu version (use Debian 12/11/9, Ubuntu 18.04/21.04 on local arm64/Apple Silicon): debian-12, debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04
ARG VARIANT=debian-12
FROM mcr.microsoft.com/vscode/devcontainers/cpp:${VARIANT}
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Asian/Shanghai
# hadolint ignore=DL3008
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y apt-transport-https apt-utils build-essential \
ca-certificates ccache curl g++-multilib git gnupg \
libgcc-9-dev lib32gcc-9-dev lsb-release \
ninja-build ocaml ocamlbuild python2.7 \
ca-certificates ccache cmake curl g++-multilib git gnupg \
libgcc-12-dev lib32gcc-12-dev lsb-release \
ninja-build ocaml ocamlbuild \
software-properties-common tree tzdata \
unzip valgrind vim wget zip --no-install-recommends \
&& apt-get clean -y \
@ -22,32 +23,32 @@ RUN apt-get update \
#
# binaryen
ARG BINARYEN_VER=111
ARG BINARYEN_VER=114
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 \
&& ln -sf /opt/binaryen-version_${BINARYEN_VER} /opt/binaryen \
&& rm binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz
#
# CMAKE (https://apt.kitware.com/)
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# hadolint ignore=DL3008
RUN wget --progress=dot:giga -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg > /dev/null \
&& echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ bionic main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null \
&& apt-get update \
&& rm /usr/share/keyrings/kitware-archive-keyring.gpg \
&& apt-get install -y kitware-archive-keyring --no-install-recommends \
&& apt-get install -y cmake --no-install-recommends \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
ARG CMAKE_VER=3.27.0
RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh \
-q -O /tmp/cmake-install.sh \
&& chmod u+x /tmp/cmake-install.sh \
&& mkdir /opt/cmake-${CMAKE_VER} \
&& /tmp/cmake-install.sh --skip-license --prefix=/opt/cmake-${CMAKE_VER} \
&& rm /tmp/cmake-install.sh \
&& ln -s /opt/cmake-${CMAKE_VER}/bin/* /usr/local/bin
#
# install emsdk
WORKDIR /opt
RUN git clone https://github.com/emscripten-core/emsdk.git
ARG EMSDK_VER=3.0.0
ARG EMSDK_VER=3.1.43
WORKDIR /opt/emsdk
RUN git pull \
&& ./emsdk install ${EMSDK_VER} \
@ -56,7 +57,7 @@ RUN git pull \
#
# install wasi-sdk
ARG WASI_SDK_VER=19
ARG WASI_SDK_VER=20
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 -sf /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \
@ -64,7 +65,7 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases
#
#install wabt
ARG WABT_VER=1.0.29
ARG WABT_VER=1.0.33
RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -P /opt \
&& tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \
&& ln -sf /opt/wabt-${WABT_VER} /opt/wabt \
@ -72,7 +73,7 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/dow
#
# install bazelisk
ARG BAZELISK_VER=1.12.0
ARG BAZELISK_VER=1.17.0
RUN mkdir /opt/bazelisk \
&& wget -c --progress=dot:giga https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -P /opt/bazelisk \
&& chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \
@ -80,16 +81,30 @@ RUN mkdir /opt/bazelisk \
#
# install clang+llvm
ARG LLVM_VER=14
RUN apt-get purge -y clang-10 llvm-10 && apt-get autoremove -y
ARG LLVM_VER=16
RUN apt-get purge -y clang-14 llvm-14 && apt-get autoremove -y
WORKDIR /etc/apt/apt.conf.d
RUN touch 99verfiy-peer.conf \
&& echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf
WORKDIR /tmp
RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
&& chmod a+x ./llvm.sh \
&& ./llvm.sh ${LLVM_VER} all
#RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
# && chmod a+x ./llvm.sh \
# && ./llvm.sh ${LLVM_VER} all
# Workaround due to https://github.com/llvm/llvm-project/issues/62475
# hadolint ignore=DL3008
RUN set -ex \
&& echo "deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-${LLVM_VER} main" > /etc/apt/sources.list.d/apt.llvm.org.list \
&& wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc \
&& apt-get update \
&& apt-get install -y \
clang-${LLVM_VER} lldb-${LLVM_VER} lld-${LLVM_VER} clangd-${LLVM_VER} clang-tidy-${LLVM_VER} clang-format-${LLVM_VER} clang-tools-${LLVM_VER} \
llvm-${LLVM_VER}-dev lld-${LLVM_VER} lldb-${LLVM_VER} llvm-${LLVM_VER}-tools libomp-${LLVM_VER}-dev libc++-${LLVM_VER}-dev libc++abi-${LLVM_VER}-dev \
libclang-common-${LLVM_VER}-dev libclang-${LLVM_VER}-dev libclang-cpp${LLVM_VER}-dev libunwind-${LLVM_VER}-dev \
libclang-rt-${LLVM_VER}-dev libpolly-${LLVM_VER}-dev --no-install-recommends \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
#
# [Optional]
@ -105,18 +120,19 @@ RUN apt-get update \
#
# Install required python packages
# hadolint ignore=DL3013
RUN python3 -m pip install --no-cache-dir --upgrade pip \
&& pip3 install --no-cache-dir black nose pycparser pylint
RUN python3 -m pip install --no-cache-dir --break-system-packages --upgrade pip \
&& pip3 install --no-cache-dir --break-system-packages black nose pycparser pylint
#
# Install github-cli. It doens't work as a feature of devcontainer.json
ARG GH_CLI_VER=2.32.0
WORKDIR /tmp
RUN wget -q 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
RUN wget -q https://github.com/cli/cli/releases/download/v${GH_CLI_VER}/gh_${GH_CLI_VER}_linux_amd64.deb \
&& dpkg -i gh_${GH_CLI_VER}_linux_amd64.deb
#
# Install NodeJS
RUN wget -qO- https://deb.nodesource.com/setup_19.x | bash -
RUN wget -qO- https://deb.nodesource.com/setup_20.x | bash -
# hadolint ignore=DL3008
RUN apt-get install -y nodejs --no-install-recommends

View File

@ -1,20 +1,23 @@
// Copyright (C) 2019 Intel Corporation. All rights reserved.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp
// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/cpp
{
"name": "WAMR-Dev",
"build": {
"dockerfile": "Dockerfile",
// 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
// Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-12, debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04
// Use Debian 12, Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon
"args": {
"BINARYEN_VER": "111",
"EMSDK_VER": "3.0.0",
"LLVM_VER": "15",
"VARIANT": "ubuntu-20.04",
"WASI_SDK_VER": "19",
"WABT_VER": "1.0.31"
"BINARYEN_VER": "114",
"BAZELISK_VER": "1.17.0",
"CMAKE_VER": "3.27.0",
"EMSDK_VER": "3.1.43",
"GH_CLI_VER": "2.32.0",
"LLVM_VER": "16",
"VARIANT": "debian-12",
"WASI_SDK_VER": "20",
"WABT_VER": "1.0.33"
}
},
"runArgs": [
@ -34,7 +37,7 @@
"llvm-vs-code-extensions.vscode-clangd",
"ms-python.python",
"ms-python.vscode-pylance",
"ms-vscode.cmake-tools",
"ms-vscode.cmake-tools"
]
}
},

View File

@ -22,6 +22,11 @@ on:
description: a semantic version number
type: string
required: true
wasi_sdk_url:
description: download WASI_SDK from this URL
type: string
required: false
default: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz"
jobs:
try_reuse:
@ -29,7 +34,7 @@ jobs:
with:
binary_name_stem: "wamr-lldb-${{ inputs.ver_num }}-${{ inputs.arch }}-${{ inputs.runner }}"
last_commit: "ea63ba4bd010c2285623ad4acc0262a4d63bcfea"
the_path: "./build-scripts/lldb-wasm.patch"
the_path: "./build-scripts/lldb_wasm.patch"
upload_url: ${{ inputs.upload_url }}
build:
@ -44,6 +49,15 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: download and install wasi-sdk
run: |
cd /opt
basename=$(basename ${{ inputs.wasi_sdk_url }})
sudo wget --progress=dot:giga ${{ inputs.wasi_sdk_url }}
sudo tar -xzf ${basename}
sudo rm ${basename}
sudo mv wasi-sdk-* wasi-sdk
- name: Cache build
id: lldb_build_cache
uses: actions/cache@v3
@ -69,8 +83,8 @@ jobs:
if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos')
run: |
brew remove swig
brew install swig@3 cmake ninja libedit
brew link --overwrite swig@3
brew install swig@4.1 cmake ninja libedit
brew link --overwrite swig@4.1
sudo rm -rf /Library/Developer/CommandLineTools
- name: install utils ubuntu
@ -92,7 +106,7 @@ jobs:
git init
git config user.email "action@github.com"
git config user.name "github action"
git apply ../../../build-scripts/lldb-wasm.patch
git apply ../../../build-scripts/lldb_wasm.patch
working-directory: core/deps/llvm-project
- name: get stand-alone python ubuntu
@ -141,6 +155,17 @@ jobs:
cmake --build build --target lldb install --parallel $(nproc)
working-directory: core/deps/llvm-project
- name: validate lldb ubuntu
if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'ubuntu')
run: |
echo "start to validate lldb..."
mkdir -p wamr-debug
cmake -S product-mini/platforms/linux -B wamr-debug -DWAMR_BUILD_DEBUG_INTERP=1
cmake --build wamr-debug --parallel $(nproc)
export LD_LIBRARY_PATH=$(pwd)/core/deps/python/lib:${LD_LIBRARY_PATH}
python3 ci/validate_lldb.py --port 1239 --lldb core/deps/wamr-lldb/bin/lldb --wamr wamr-debug/iwasm --verbose
working-directory: .
- name: build lldb macos
if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos')
run: |
@ -180,7 +205,7 @@ jobs:
mkdir -p wamr-lldb/lib
cp build/bin/lldb* wamr-lldb/bin
cp lldb/tools/lldb-vscode/package.json wamr-lldb
cp -r lldb/tools/lldb-vscode/syntaxes/ wamr-lldb
cp -r lldb/tools/lldb-vscode/syntaxes/ wamr-lldb
working-directory: core/deps/llvm-project
- name: pack ubuntu specific libraries
@ -201,7 +226,7 @@ jobs:
cp -R ../python/lib/python* wamr-lldb/lib
cp ../python/lib/libpython*.dylib wamr-lldb/lib
install_name_tool -change /install/lib/libpython${{ env.PYTHON_VERSION }}.dylib @rpath/libpython${{ env.PYTHON_VERSION }}.dylib wamr-lldb/lib/liblldb.*.dylib
# Patch path of python library -> https://github.com/indygreg/python-build-standalone/blob/85923ca3911784e6978b85d56e06e9ae75cb2dc4/docs/quirks.rst?plain=1#L412-L446
# Patch path of python library -> https://github.com/indygreg/python-build-standalone/blob/85923ca3911784e6978b85d56e06e9ae75cb2dc4/docs/quirks.rst?plain=1#L412-L446
working-directory: core/deps/llvm-project
- name: compress the binary

View File

@ -72,7 +72,7 @@ jobs:
with:
os: "ubuntu-22.04"
arch: "X86"
build_wamrc:
needs:
[build_llvm_libraries_on_ubuntu_2204]
@ -241,6 +241,14 @@ jobs:
cmake --build . --config Release --parallel 4
working-directory: product-mini/platforms/${{ matrix.platform }}
- name: Build and run unit tests
run: |
mkdir build-unittests && cd build-unittests
cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }}
cmake --build . --config Release --parallel 4
ctest
working-directory: tests/unit
build_samples_wasm_c_api:
needs:
[
@ -483,6 +491,16 @@ jobs:
sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-20.0 wasi-sdk
# It is a temporary solution until new wasi-sdk that includes bug fixes is released
- name: build wasi-libc from source
if: matrix.test_option == '$WASI_TEST_OPTIONS'
run: |
git clone https://github.com/WebAssembly/wasi-libc
cd wasi-libc
make -j AR=/opt/wasi-sdk/bin/llvm-ar NM=/opt/wasi-sdk/bin/llvm-nm CC=/opt/wasi-sdk/bin/clang THREAD_MODEL=posix
echo "SYSROOT_PATH=$PWD/sysroot" >> $GITHUB_ENV
- name: set env variable(if llvm are used)
if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit'
run: echo "USE_LLVM=true" >> $GITHUB_ENV
@ -518,7 +536,7 @@ jobs:
- name: Build WASI thread tests
if: matrix.test_option == '$WASI_TEST_OPTIONS'
run: bash build.sh
run: bash build.sh --sysroot "$SYSROOT_PATH"
working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/
- name: build socket api tests
@ -527,7 +545,7 @@ jobs:
working-directory: ./core/iwasm/libraries/lib-socket/test/
- name: run tests
timeout-minutes: 10
timeout-minutes: 30
run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
working-directory: ./tests/wamr-test-suites
@ -543,7 +561,7 @@ jobs:
sudo apt install -y g++-multilib lib32gcc-9-dev
- name: run tests x86_32
timeout-minutes: 10
timeout-minutes: 30
if: env.TEST_ON_X86_32 == 'true'
run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
working-directory: ./tests/wamr-test-suites
@ -584,7 +602,7 @@ jobs:
cache-name: cache-lldb-vscode
with:
path: test-tools/wamr-ide/VSCode-Extension/resource/debug/linux
key: ${{ env.cache-name }}-${{ hashFiles('build-scripts/lldb-wasm.patch') }}-${{ env.PYTHON_UBUNTU_STANDALONE_BUILD }}
key: ${{ env.cache-name }}-${{ hashFiles('build-scripts/lldb_wasm.patch') }}-${{ env.PYTHON_UBUNTU_STANDALONE_BUILD }}
- if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }}
name: get stand-alone python ubuntu
@ -607,7 +625,7 @@ jobs:
git init
git config user.email "action@github.com"
git config user.name "github action"
git apply ../../../build-scripts/lldb-wasm.patch
git apply ../../../build-scripts/lldb_wasm.patch
working-directory: core/deps/llvm-project
- if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }}

View File

@ -0,0 +1,47 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
name: hadolint dockerfiles
on:
# will be triggered on PR events
pull_request:
types:
- opened
- synchronize
paths:
- "**/Dockerfile*"
- ".github/workflows/hadolint_dockerfiles.yml"
push:
branches:
- main
- "dev/**"
paths:
- "**/Dockerfile*"
- ".github/workflows/hadolint_dockerfiles.yml"
# allow to be triggered manually
workflow_dispatch:
# Cancel any in-flight jobs for the same PR/branch so there's only one active
# at a time
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
run-hadolint-on-dockerfiles:
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v3
# on default, hadolint will fail on warnings and errors
- name: Run hadolint on dockerfiles
run: |
docker pull hadolint/hadolint:latest-debian
find . -name "*Dockerfile*" | while read dockerfile; do
echo "run hadolint on $dockerfile:"
docker run --rm -i hadolint/hadolint:latest-debian hadolint - <"$dockerfile"
echo "successful"
done

View File

@ -548,6 +548,16 @@ jobs:
sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-20.0 wasi-sdk
# It is a temporary solution until new wasi-sdk that includes bug fixes is released
- name: build wasi-libc from source
if: matrix.test_option == '$WASI_TEST_OPTIONS'
run: |
git clone https://github.com/WebAssembly/wasi-libc
cd wasi-libc
make -j AR=/opt/wasi-sdk/bin/llvm-ar NM=/opt/wasi-sdk/bin/llvm-nm CC=/opt/wasi-sdk/bin/clang THREAD_MODEL=posix
echo "SYSROOT_PATH=$PWD/sysroot" >> $GITHUB_ENV
- name: set env variable(if llvm are used)
if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit'
run: echo "USE_LLVM=true" >> $GITHUB_ENV
@ -586,16 +596,21 @@ jobs:
- name: Build WASI thread tests
if: matrix.test_option == '$WASI_TEST_OPTIONS'
run: bash build.sh
run: bash build.sh --sysroot "$SYSROOT_PATH"
working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/
- name: Build WASI thread stress tests
if: matrix.test_option == '$WASI_TEST_OPTIONS'
run: bash build.sh --sysroot "$SYSROOT_PATH"
working-directory: ./core/iwasm/libraries/lib-wasi-threads/stress-test/
- name: build socket api tests
if: matrix.test_option == '$WASI_TEST_OPTIONS'
run: bash build.sh
working-directory: ./core/iwasm/libraries/lib-socket/test/
- name: run tests
timeout-minutes: 10
timeout-minutes: 40
run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
working-directory: ./tests/wamr-test-suites
@ -611,7 +626,7 @@ jobs:
sudo apt install -y g++-multilib lib32gcc-9-dev
- name: run tests x86_32
timeout-minutes: 10
timeout-minutes: 40
if: env.TEST_ON_X86_32 == 'true'
run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
working-directory: ./tests/wamr-test-suites

View File

@ -22,7 +22,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
| third party components | version number | latest release | vendor pages | CVE details |
| --- | --- | --- | --- | --- |
| cjson | 1.7.10 | 1.7.14 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html |
| cjson | 1.7.16 | 1.7.16 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html |
| contiki-ng (er-coap) | unspecified | 3.0 | https://github.com/contiki-os/contiki | https://www.cvedetails.com/vendor/16528/Contiki-os.html |
| freebsd libm | unspecified | 13.0 | https://www.freebsd.org/ | https://www.cvedetails.com/vendor/6/Freebsd.html |
| LVGL | 6.0.1 | 7.11.0 | https://lvgl.io/ | |
@ -31,7 +31,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
| wasmtime | unspecified | v0.26.0 | https://github.com/bytecodealliance/wasmtime | |
| zephyr | unspecified | v2.5.0 | https://www.zephyrproject.org/ | https://www.cvedetails.com/vendor/19255/Zephyrproject.html |
| WebAssembly debugging patch for LLDB | unspecified | unspecified | https://reviews.llvm.org/D78801 | |
| libuv | v1.42.0 | v1.44.1 | https://github.com/libuv/libuv | https://www.cvedetails.com/vendor/15402/Libuv-Project.html |
| libuv | v1.46.0 | v1.46.0 | https://github.com/libuv/libuv | https://www.cvedetails.com/vendor/15402/Libuv-Project.html |
| uvwasi | unspecified | v0.0.12 | https://github.com/nodejs/uvwasi | |
| asmjit | unspecified | unspecified | https://github.com/asmjit/asmjit | |
| zydis | unspecified | e14a07895136182a5b53e181eec3b1c6e0b434de | https://github.com/zyantific/zydis | |

View File

@ -107,6 +107,11 @@ endif ()
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
# Set the strip command based on the system (GNU or Clang)
if (CMAKE_STRIP)
set (CMAKE_STRIP_FLAGS "--strip-all")
endif ()
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wshadow -Wno-unused-parameter")
@ -141,6 +146,15 @@ endif ()
install (TARGETS iwasm_static ARCHIVE DESTINATION lib)
# If it's a Release build, strip the static library
if (CMAKE_STRIP AND CMAKE_BUILD_TYPE STREQUAL "Release")
# Strip static library
message (STATUS "Stripping static library after build!")
add_custom_command (TARGET iwasm_static POST_BUILD
COMMAND ${CMAKE_STRIP} ${CMAKE_STRIP_FLAGS} $<TARGET_FILE:iwasm_static>
)
endif ()
# SHARED LIBRARY
add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE})
set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm)
@ -162,3 +176,12 @@ install (FILES
${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h
${WAMR_ROOT_DIR}/core/iwasm/include/lib_export.h
DESTINATION include)
# If it's a Release build, strip the shared library
if (CMAKE_STRIP AND CMAKE_BUILD_TYPE STREQUAL "Release")
# Strip shared library
message (STATUS "Stripping shared library after build!")
add_custom_command (TARGET iwasm_shared POST_BUILD
COMMAND ${CMAKE_STRIP} ${CMAKE_STRIP_FLAGS} $<TARGET_FILE:iwasm_shared>
)
endif ()

View File

@ -1,3 +1,139 @@
## WAMR-1.2.3
### Breaking Changes
- Increase default native stack size (#2332)
### New Features
- Implement the segue optimization for LLVM AOT/JIT (#2230)
- Implement AOT static PGO (#2243)
- Enable static PGO for Linux SGX (#2270)
- Add Rust Formatters to Debugger (Vector, Map etc.) (#2219)
### Bug Fixes
- The Python language-binding needs python>=3.9 (#2228)
- aot_compile_op_call: Remove a wrong optimization (#2233)
- Fix typo in samples/ref-types (#2236)
- Update thread proposal ignore cases (#2246)
- Disable writting GS register on linux-sgx platform (#2255)
- Fix compile error of wamrc with llvm-13/llvm-14 (#2261)
- aot/jit: Set module layout (#2260)
- Fix build error with LLVM 16 (#2259)
- spec-test-script: Disable conversions.wast on i386 (#2269)
- Fix a heap corruption bug in ems realloc (#2279)
- Fix fast-interp issue of LAST_OP_OUTPUT_I32/64 check (#2295)
- Fix wamrc build issues with LLVM 13 and LLVM 16 (#2313)
- aot: Move stack_sizes table to a dedicated section (#2317)
- product-mini/platforms/linux: Mark vmlib POSITION_INDEPENDENT_CODE (#2323)
- aot: Avoid possible relocations around "stack_sizes" for XIP mode (#2322)
- Avoid switch lowering to lookup tables for XIP (#2339)
- Fix typo in zephyr's Dockerfile.old (#2354)
- Fix typo (dwarf) in the codebase (#2367)
- Implement suspend flags as atomic variable (#2361)
- Fix llvm jit failed to lookup aot_stack_sizes symbol issue (#2384)
- Fix some check issues on table operations (#2392)
- Fix ExpandMemoryOpPass doesn't work properly (#2399)
- Fix non-builtin BH_ATOMIC_32_FETCH_OR and BH_ATOMIC_32_FETCH_AND (#2400)
- Fix wasi-sockets tests (#2389)
- Fix result arity check on select_t opcode (#2406)
- Re-organize intrinsics in aot_reloc_riscv.c to fix some FPU issues (#2414)
- Fix lib-pthread issues (#2410)
- Fix typo in test_wamr.sh (#2421)
- Fix memory sharing (#2415)
- wasm_export.h: Fix struct wasm_val_t (#2435)
- Fix typos in wamrc print_help() (#2442)
- iwasm: Fix native lib cleanup after error occurs (#2443)
- Correct --heap-size option in messages (#2458)
- wasm_instantiate: Fix a potential integer overflow issue (#2459)
- Fix windows link error and clear windows warnings (#2463)
- aot: Disable musttail for mips (#2457)
- Fix opcode overwrite issue in fast interp (#2476)
- wamrc: Fix windows relocation to `aot_func_internal#n` (#2474)
- Fix windows AOT hw bound check (#2475)
- Fix typo in aot_emit_aot_file.c (#2478)
### Enhancements
- A few changes related to WAMRC_LLC_COMPILER (#2218)
- Enhance linux-sgx CI (#2102)
- Add asan and ubsan to WAMR CI (#2161)
- Update doc on WAMR_DISABLE_HW_BOUND_CHECK 32-bit (#2262)
- wamrc: Add an incompatibility note in the help message (#2276)
- Add cmake variable to disable writing gs register (#2284)
- Make hmu_tree_node 4 byte aligned to reduce compiler warning (#2268)
- Appease unused warning on min_uint64 (#2277)
- Fix format warning by PRIu32 in [wasm|aot] dump call stack (#2251)
- Fix a compile warning due to missing include (#2293)
- Fix dockerfile linter warnings (#2291)
- Enable windows x86-32 AOT relocations (#2285)
- wamr-ide: Add vscode extension tests (#2292)
- AOT/JIT native stack bound check improvement (#2244)
- Add retries to flaky step in nightly run CI (#2306)
- Use system libuv if available (#1861)
- wasi-nn: Simplify cmake and headers' location (#2308)
- wasi-nn: Improve tests paths for local dev (#2309)
- aot: Implement a few more relocation types for riscv (#2318)
- wasi-nn: Add support of wasi-nn as shared lib (#2310)
- Add a few more assertions on structures to which aot abi is sensitive (#2326)
- Fix sanitizer errors in posix socket (#2331)
- Add "--xip" option for wamrc (#2336)
- Add "--enable-llvm-passes=<passes>" option to wamrc (#2335)
- Make memory access boundary check behavior configurable (#2289)
- Migrate ExpandMemoryOpPass to llvm new pass manager (#2334)
- Allow defining hints without exact socket type or address family (#2337)
- wamrc: Warn on text relocations for XIP (#2340)
- Add scripts to validate lldb source debugger (#2150)
- Add docker file to fix Zephy ESP32 linking issue (#2314)
- Add "--native-lib=<lib>" option to wamrc (#2342)
- Fix unused warnings on disable_bounds_checks (#2347)
- Add "--enable-builtin-intrinsics=<flags>" option to wamrc (#2341)
- nuttx: Add a kconfig for wasi-threads (#2343)
- iwasm: Disable app heap by default if wasi is enabled (#2346)
- Fix some static scan issues (#2362)
- Bring up WAMR on esp32-s3 device (#2348)
- ESP-IDF platform supports to load AOT to PSRAM and run it (#2385)
- Add hadolint CI for Dockerfile linting (#2387)
- Move generic parts of wasm_suspend_flags.h to bh_atomic.h (#2393)
- bh_atomic.h: Add comments (#2398)
- bh_atomic.h: Add BH_ATOMIC_32_FETCH_ADD/BH_ATOMIC_32_FETCH_SUB (#2408)
- Update libuv version to v1.46.0 (#2405)
- Remove a few unused functions (#2409)
- Add initial stress test (#2364)
- Move wasm_runtime_destroy_wasi and wasi_nn_destroy calls together (#2418)
- embed_wamr.md: Improvements about threads (#2420)
- Add runtime inited checks in Enclave command handlings to improve security (#2416)
- Add some relocation symbols for xtensa target (#2422)
- Remove unnecessary and extra zero length check in mem functions' macro (#2428)
- Introduce WASMModuleInstanceExtraCommon (#2429)
- Strip static and shared libraries of iwasm to reduce the binary size (#2431)
- Auto-check wrgsbase in cmake script (#2437)
- iwasm: call native lib init/deinit if exists (#2439)
- wasi-nn: Support uint8 quantized networks (#2433)
- Implement `wasm_externref_objdel` and `wasm_externref_set_cleanup` (#2455)
- wasi-nn: Improve TPU support (#2447)
- wamr-python: Enable debugging WASM and grant dir access (#2449)
- Build wasi-libc from source in WAMR CI (#2465)
- wamrc: More friendly to print help info (#2451)
- Add another wamr test (#2411)
- Fix issues reported by Coverity and clear windows warnings (#2467)
- Clone the input binary during wasm_module_validate (#2483)
### Others
- Nuttx CI: Ignore the expired certificate for riscv gcc toolchain (#2222)
- core/iwasm/compilation: constify a bit (#2223)
- Bump requests from 2.28.2 to 2.31.0 in /build-scripts (#2229)
- dwarf_extractor: Constify a bit (#2278)
- AOTFuncContext: Remove a stale comment (#2283)
- Add performance tunning document (#2286)
- Reduce CI jobs number (#2296)
- CI: Update used node version to 16 (#2303)
- Update Docker image for latest version of external libraries & tools (#2374)
- Upgrade cJSON version to v1.7.16 (#2404)
- Upgrade XNNPACK workload (#2394)
- Build more benchmarks in workload XNNPACK (#2417)
- Upgrade SGX-RA integration for 0.1.2 and Ubuntu 20.04 (#2454)
- Add sample pre-commit hook (#2470)
---
## WAMR-1.2.2
### Breaking Changes

View File

@ -359,16 +359,16 @@ endif ()
if (WAMR_BUILD_WASI_NN EQUAL 1)
message (" WASI-NN enabled")
add_definitions (-DWASM_ENABLE_WASI_NN=1)
if (WASI_NN_ENABLE_GPU EQUAL 1)
if (WAMR_BUILD_WASI_NN_ENABLE_GPU EQUAL 1)
message (" WASI-NN: GPU enabled")
add_definitions (-DWASI_NN_ENABLE_GPU=1)
add_definitions (-DWASM_ENABLE_WASI_NN_GPU=1)
endif ()
if (WAMR_BUILD_WASI_NN_ENABLE_EXT EQUAL 1)
if (WAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE EQUAL 1)
message (" WASI-NN: External Delegation enabled")
add_definitions (-DWASI_NN_ENABLE_EXTERNAL_DELEGATE=1)
add_definitions (-DWASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE=1)
endif ()
if (DEFINED WASI_NN_EXT_DELEGATE_PATH)
add_definitions (-DWASI_NN_EXT_DELEGATE_PATH="${WASI_NN_EXT_DELEGATE_PATH}")
if (DEFINED WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH)
add_definitions (-DWASM_WASI_NN_EXTERNAL_DELEGATE_PATH="${WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH}")
endif ()
endif ()
if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 1)
@ -378,6 +378,10 @@ if (WAMR_BUILD_WASM_CACHE EQUAL 1)
add_definitions (-DWASM_ENABLE_WASM_CACHE=1)
message (" Wasm files cache enabled")
endif ()
if (WAMR_BUILD_MODULE_INST_CONTEXT EQUAL 1)
add_definitions (-DWASM_ENABLE_MODULE_INST_CONTEXT=1)
message (" Module instance context enabled")
endif ()
if (WAMR_BUILD_GC_HEAP_VERIFY EQUAL 1)
add_definitions (-DWASM_ENABLE_GC_VERIFY=1)
message (" GC heap verification enabled")
@ -395,4 +399,32 @@ endif ()
if (WAMR_DISABLE_WRITE_GS_BASE EQUAL 1)
add_definitions (-DWASM_DISABLE_WRITE_GS_BASE=1)
message (" Write linear memory base addr to x86 GS register disabled")
elseif (WAMR_BUILD_TARGET STREQUAL "X86_64"
AND WAMR_BUILD_PLATFORM STREQUAL "linux")
set (TEST_WRGSBASE_SOURCE "${CMAKE_BINARY_DIR}/test_wrgsbase.c")
file (WRITE "${TEST_WRGSBASE_SOURCE}" "
#include <stdio.h>
#include <stdint.h>
int main() {
uint64_t value;
asm volatile (\"wrgsbase %0\" : : \"r\"(value));
printf(\"WRGSBASE instruction is available.\\n\");
return 0;
}")
# Try to compile and run the test program
try_run (TEST_WRGSBASE_RESULT
TEST_WRGSBASE_COMPILED
${CMAKE_BINARY_DIR}/test_wrgsbase
SOURCES ${TEST_WRGSBASE_SOURCE}
CMAKE_FLAGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
)
#message("${TEST_WRGSBASE_COMPILED}, ${TEST_WRGSBASE_RESULT}")
if (NOT TEST_WRGSBASE_RESULT EQUAL 0)
add_definitions (-DWASM_DISABLE_WRITE_GS_BASE=1)
message (" Write linear memory base addr to x86 GS register disabled")
endif ()
endif ()
if (WAMR_CONFIGUABLE_BOUNDS_CHECKS EQUAL 1)
add_definitions (-DWASM_CONFIGURABLE_BOUNDS_CHECKS=1)
message (" Configurable bounds checks enabled")
endif ()

View File

@ -1,5 +1,44 @@
diff --git a/lldb/bindings/CMakeLists.txt b/lldb/bindings/CMakeLists.txt
index 9759b069fdc4..25b427f8bcf2 100644
--- a/lldb/bindings/CMakeLists.txt
+++ b/lldb/bindings/CMakeLists.txt
@@ -26,8 +26,6 @@ set(SWIG_COMMON_FLAGS
-features autodoc
-I${LLDB_SOURCE_DIR}/include
-I${CMAKE_CURRENT_SOURCE_DIR}
- -D__STDC_LIMIT_MACROS
- -D__STDC_CONSTANT_MACROS
${DARWIN_EXTRAS}
)
diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig
index c9a6d0f06056..021c7683d170 100644
--- a/lldb/bindings/interfaces.swig
+++ b/lldb/bindings/interfaces.swig
@@ -1,8 +1,5 @@
/* Various liblldb typedefs that SWIG needs to know about. */
#define __extension__ /* Undefine GCC keyword to make Swig happy when processing glibc's stdint.h. */
-/* The ISO C99 standard specifies that in C++ implementations limit macros such
- as INT32_MAX should only be defined if __STDC_LIMIT_MACROS is. */
-#define __STDC_LIMIT_MACROS
%include "stdint.i"
%include "lldb/lldb-defines.h"
diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig
index b1ace4ff3b1e..5f8f4aa678c4 100644
--- a/lldb/bindings/python/python-typemaps.swig
+++ b/lldb/bindings/python/python-typemaps.swig
@@ -439,7 +439,7 @@ bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
%typemap(out) lldb::FileSP {
$result = nullptr;
- lldb::FileSP &sp = $1;
+ const lldb::FileSP &sp = $1;
if (sp) {
PythonFile pyfile = unwrapOrSetPythonException(PythonFile::FromFile(*sp));
if (!pyfile.IsValid())
diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h
index f2e2a0d22..426d1129b 100644
index f2e2a0d22784..426d1129bd10 100644
--- a/lldb/include/lldb/Breakpoint/Breakpoint.h
+++ b/lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -9,6 +9,7 @@
@ -11,7 +50,7 @@ index f2e2a0d22..426d1129b 100644
#include <string>
#include <unordered_set>
diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index dd7100c46..97d70daad 100644
index dd7100c4616c..97d70daadbdc 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -41,6 +41,7 @@
@ -41,7 +80,7 @@ index dd7100c46..97d70daad 100644
///
/// Tries to resolve \a vm_addr as a file address (if \a
diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h
index be91929c6..8d876fc1f 100644
index be91929c62e1..8d876fc1fa2f 100644
--- a/lldb/include/lldb/Core/PluginManager.h
+++ b/lldb/include/lldb/Core/PluginManager.h
@@ -508,6 +508,17 @@ public:
@ -64,7 +103,7 @@ index be91929c6..8d876fc1f 100644
} // namespace lldb_private
diff --git a/lldb/include/lldb/Expression/DWARFEvaluator.h b/lldb/include/lldb/Expression/DWARFEvaluator.h
new file mode 100644
index 000000000..6811cbeae
index 000000000000..6811cbeae3d3
--- /dev/null
+++ b/lldb/include/lldb/Expression/DWARFEvaluator.h
@@ -0,0 +1,110 @@
@ -180,7 +219,7 @@ index 000000000..6811cbeae
+#endif // LLDB_EXPRESSION_DWARFEVALUATOR_H
diff --git a/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h b/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h
new file mode 100644
index 000000000..f3b496c58
index 000000000000..f3b496c580e4
--- /dev/null
+++ b/lldb/include/lldb/Expression/DWARFEvaluatorFactory.h
@@ -0,0 +1,56 @@
@ -241,7 +280,7 @@ index 000000000..f3b496c58
+
+#endif // LLDB_EXPRESSION_DWARFEVALUATORFACTORY_H
diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h
index 1490ac2d6..35c741d4e 100644
index 1490ac2d614a..35c741d4e6ba 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -120,6 +120,10 @@ public:
@ -275,7 +314,7 @@ index 1490ac2d6..35c741d4e 100644
GetLocationExpression(lldb::addr_t load_function_start,
lldb::addr_t addr) const;
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index aaa2470d2..c15f2db52 100644
index aaa2470d2931..c15f2db52fbc 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1434,7 +1434,7 @@ public:
@ -288,7 +327,7 @@ index aaa2470d2..c15f2db52 100644
/// Read of memory from a process.
///
diff --git a/lldb/include/lldb/Target/ProcessTrace.h b/lldb/include/lldb/Target/ProcessTrace.h
index 7b9d6b13d..9525fc975 100644
index 7b9d6b13dd6f..9525fc9750fd 100644
--- a/lldb/include/lldb/Target/ProcessTrace.h
+++ b/lldb/include/lldb/Target/ProcessTrace.h
@@ -59,7 +59,7 @@ public:
@ -301,7 +340,7 @@ index 7b9d6b13d..9525fc975 100644
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) override;
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index ad5298151..5a3c0b27a 100644
index ad5298151e4a..5a3c0b27a738 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -74,6 +74,7 @@ class Disassembler;
@ -313,7 +352,7 @@ index ad5298151..5a3c0b27a 100644
class EmulateInstruction;
class Environment;
diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h
index 2ed083ec8..f4d500d19 100644
index 2ed083ec8ae9..f4d500d198e8 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -113,6 +113,8 @@ typedef lldb::REPLSP (*REPLCreateInstance)(Status &error,
@ -326,7 +365,7 @@ index 2ed083ec8..f4d500d19 100644
/// \{
typedef llvm::Expected<lldb::TraceSP> (*TraceCreateInstanceForSessionFile)(
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 19c97be15..1647f93ec 100644
index 19c97be15066..1647f93ec4f3 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -16,6 +16,7 @@
@ -348,7 +387,7 @@ index 19c97be15..1647f93ec 100644
+ return m_dwarf_evaluator_factory.get();
+}
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index fcaa868b0..59a404d4a 100644
index fcaa868b083e..59a404d4a7e1 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -1597,3 +1597,32 @@ bool PluginManager::CreateSettingForStructuredDataPlugin(
@ -385,7 +424,7 @@ index fcaa868b0..59a404d4a 100644
+ return GetDWARFEvaluatorFactoryInstances().GetCallbackAtIndex(idx);
+}
diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp
index fb57c0fed..f92d6a54d 100644
index fb57c0fedf04..f92d6a54de94 100644
--- a/lldb/source/Core/Value.cpp
+++ b/lldb/source/Core/Value.cpp
@@ -538,7 +538,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
@ -398,7 +437,7 @@ index fb57c0fed..f92d6a54d 100644
error.SetErrorStringWithFormat(
"read memory from 0x%" PRIx64 " failed (%u of %u bytes read)",
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 9c1ba99da..b15b214b2 100644
index 9c1ba99da1d0..b15b214b2a2f 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -735,7 +735,7 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
@ -411,7 +450,7 @@ index 9c1ba99da..b15b214b2 100644
data.SetData(data_sp);
return bytes_read;
diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt
index bf94361dd..4e76d547a 100644
index bf94361dd6c1..4e76d547aeaf 100644
--- a/lldb/source/Expression/CMakeLists.txt
+++ b/lldb/source/Expression/CMakeLists.txt
@@ -1,5 +1,7 @@
@ -424,7 +463,7 @@ index bf94361dd..4e76d547a 100644
ExpressionVariable.cpp
diff --git a/lldb/source/Expression/DWARFEvaluator.cpp b/lldb/source/Expression/DWARFEvaluator.cpp
new file mode 100644
index 000000000..06107e136
index 000000000000..06107e136197
--- /dev/null
+++ b/lldb/source/Expression/DWARFEvaluator.cpp
@@ -0,0 +1,1952 @@
@ -2382,7 +2421,7 @@ index 000000000..06107e136
+}
diff --git a/lldb/source/Expression/DWARFEvaluatorFactory.cpp b/lldb/source/Expression/DWARFEvaluatorFactory.cpp
new file mode 100644
index 000000000..c06126412
index 000000000000..c0612641204a
--- /dev/null
+++ b/lldb/source/Expression/DWARFEvaluatorFactory.cpp
@@ -0,0 +1,57 @@
@ -2444,7 +2483,7 @@ index 000000000..c06126412
+ object_address_ptr);
+}
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index a10546c1d..4d13e4642 100644
index a10546c1deae..4d13e4642af3 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -15,6 +15,8 @@
@ -4261,7 +4300,7 @@ index a10546c1d..4d13e4642 100644
static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc,
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 00e9ccb76..2137a1ac8 100644
index 00e9ccb762c3..2137a1ac8324 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -759,6 +759,24 @@ void CommandInterpreter::LoadCommandDictionary() {
@ -4290,7 +4329,7 @@ index 00e9ccb76..2137a1ac8 100644
new CommandObjectRegexCommand(
*this, "kdp-remote",
diff --git a/lldb/source/Plugins/CMakeLists.txt b/lldb/source/Plugins/CMakeLists.txt
index 9181a4e47..2be6ec365 100644
index 9181a4e47675..2be6ec3657c0 100644
--- a/lldb/source/Plugins/CMakeLists.txt
+++ b/lldb/source/Plugins/CMakeLists.txt
@@ -2,6 +2,7 @@ add_subdirectory(ABI)
@ -4320,14 +4359,14 @@ index 9181a4e47..2be6ec365 100644
endif()
diff --git a/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt b/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt
new file mode 100644
index 000000000..73fad41e1
index 000000000000..73fad41e1a72
--- /dev/null
+++ b/lldb/source/Plugins/DWARFEvaluator/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(wasm)
diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt b/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt
new file mode 100644
index 000000000..e50b1bef7
index 000000000000..e50b1bef7e69
--- /dev/null
+++ b/lldb/source/Plugins/DWARFEvaluator/wasm/CMakeLists.txt
@@ -0,0 +1,10 @@
@ -4343,7 +4382,7 @@ index 000000000..e50b1bef7
+ )
diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp
new file mode 100644
index 000000000..fdda1991d
index 000000000000..fdda1991d19f
--- /dev/null
+++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.cpp
@@ -0,0 +1,126 @@
@ -4475,7 +4514,7 @@ index 000000000..fdda1991d
+}
diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h
new file mode 100644
index 000000000..a01159064
index 000000000000..a01159064a39
--- /dev/null
+++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluator.h
@@ -0,0 +1,47 @@
@ -4528,7 +4567,7 @@ index 000000000..a01159064
+#endif // LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATOR_H
diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp
new file mode 100644
index 000000000..d43e96a34
index 000000000000..d43e96a34d37
--- /dev/null
+++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.cpp
@@ -0,0 +1,64 @@
@ -4598,7 +4637,7 @@ index 000000000..d43e96a34
+}
diff --git a/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h
new file mode 100644
index 000000000..8a946592a
index 000000000000..8a946592a09a
--- /dev/null
+++ b/lldb/source/Plugins/DWARFEvaluator/wasm/WasmDWARFEvaluatorFactory.h
@@ -0,0 +1,55 @@
@ -4658,7 +4697,7 @@ index 000000000..8a946592a
+
+#endif // LLDB_SOURCE_PLUGINS_DWARFEVALUATOR_WASM_WASMDWARFEVALUATORFACTORY_H
diff --git a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp
index ae7e011ea..24ea75d19 100644
index ae7e011eaa52..24ea75d1971c 100644
--- a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp
@@ -62,6 +62,15 @@ void DynamicLoaderWasmDYLD::DidAttach() {
@ -4678,7 +4717,7 @@ index ae7e011ea..24ea75d19 100644
ThreadPlanSP DynamicLoaderWasmDYLD::GetStepThroughTrampolinePlan(Thread &thread,
diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
index 5272da9ab..abc5523bf 100644
index 5272da9ab33a..abc5523bfd70 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
@@ -23,6 +23,7 @@
@ -4718,7 +4757,7 @@ index 5272da9ab..abc5523bf 100644
}
}
diff --git a/lldb/source/Plugins/Platform/CMakeLists.txt b/lldb/source/Plugins/Platform/CMakeLists.txt
index 5f284e517..6084cbc93 100644
index 5f284e517dca..6084cbc9378d 100644
--- a/lldb/source/Plugins/Platform/CMakeLists.txt
+++ b/lldb/source/Plugins/Platform/CMakeLists.txt
@@ -15,3 +15,4 @@
@ -4728,7 +4767,7 @@ index 5f284e517..6084cbc93 100644
+add_subdirectory(wasm-remote)
diff --git a/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt b/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt
new file mode 100644
index 000000000..4a65765a5
index 000000000000..4a65765a5659
--- /dev/null
+++ b/lldb/source/Plugins/Platform/wasm-remote/CMakeLists.txt
@@ -0,0 +1,10 @@
@ -4744,7 +4783,7 @@ index 000000000..4a65765a5
+ )
diff --git a/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp
new file mode 100644
index 000000000..f26d11f00
index 000000000000..f26d11f00e5c
--- /dev/null
+++ b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.cpp
@@ -0,0 +1,139 @@
@ -4890,7 +4929,7 @@ index 000000000..f26d11f00
\ No newline at end of file
diff --git a/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h
new file mode 100644
index 000000000..f306a79d3
index 000000000000..f306a79d3f4f
--- /dev/null
+++ b/lldb/source/Plugins/Platform/wasm-remote/PlatformRemoteWasmServer.h
@@ -0,0 +1,37 @@
@ -4933,7 +4972,7 @@ index 000000000..f306a79d3
+#endif
\ No newline at end of file
diff --git a/lldb/source/Plugins/Plugins.def.in b/lldb/source/Plugins/Plugins.def.in
index bf54598fb..b0bd7b996 100644
index bf54598fb2f3..b0bd7b9965fe 100644
--- a/lldb/source/Plugins/Plugins.def.in
+++ b/lldb/source/Plugins/Plugins.def.in
@@ -31,6 +31,7 @@
@ -4945,7 +4984,7 @@ index bf54598fb..b0bd7b996 100644
#undef LLDB_PLUGIN
diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt
index bea5bac9e..7a0855e02 100644
index bea5bac9eb21..7a0855e02ca2 100644
--- a/lldb/source/Plugins/Process/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/CMakeLists.txt
@@ -18,3 +18,4 @@ add_subdirectory(Utility)
@ -4954,7 +4993,7 @@ index bea5bac9e..7a0855e02 100644
add_subdirectory(minidump)
+add_subdirectory(wasm)
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 12bc7390c..707ab85e5 100644
index 12bc7390c729..707ab85e5615 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -285,7 +285,7 @@ bool ProcessElfCore::IsAlive() { return true; }
@ -4967,7 +5006,7 @@ index 12bc7390c..707ab85e5 100644
// in core files we have it all cached our our core file anyway.
return DoReadMemory(addr, buf, size, error);
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
index d8e3cc9ae..f0bf9c4d3 100644
index d8e3cc9ae3e1..f0bf9c4d3b00 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -84,7 +84,8 @@ public:
@ -4981,7 +5020,7 @@ index d8e3cc9ae..f0bf9c4d3 100644
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
lldb_private::Status &error) override;
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 6914b3734..bb8a05604 100644
index 6914b37348ea..bb8a056049f3 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -334,6 +334,11 @@ ConstString ProcessGDBRemote::GetPluginName() { return GetPluginNameStatic(); }
@ -5015,7 +5054,7 @@ index 6914b3734..bb8a05604 100644
}
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index fe04cdddd..e4a14c645 100644
index fe04cdddd0f5..e4a14c64579a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -237,6 +237,8 @@ protected:
@ -5028,7 +5067,7 @@ index fe04cdddd..e4a14c645 100644
enum {
eBroadcastBitAsyncContinue = (1 << 0),
diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
index 84548edb5..0ae6f7e4a 100644
index 84548edb5caa..0ae6f7e4a177 100644
--- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
+++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
@@ -596,7 +596,7 @@ bool ProcessMachCore::WarnBeforeDetach() const { return false; }
@ -5041,7 +5080,7 @@ index 84548edb5..0ae6f7e4a 100644
// in core files we have it all cached our our core file anyway.
return DoReadMemory(addr, buf, size, error);
diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h
index db77e96f1..1c930896c 100644
index db77e96f1072..1c930896c743 100644
--- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h
+++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h
@@ -65,7 +65,8 @@ public:
@ -5055,7 +5094,7 @@ index db77e96f1..1c930896c 100644
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
lldb_private::Status &error) override;
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index 385557422..d8bb21581 100644
index 385557422758..d8bb21581086 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -374,7 +374,7 @@ bool ProcessMinidump::IsAlive() { return true; }
@ -5068,7 +5107,7 @@ index 385557422..d8bb21581 100644
// we have it all cached in our dump file anyway.
return DoReadMemory(addr, buf, size, error);
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
index 27b0da004..e94ecab43 100644
index 27b0da0047a5..e94ecab430c1 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
@@ -69,8 +69,8 @@ public:
@ -5084,7 +5123,7 @@ index 27b0da004..e94ecab43 100644
Status &error) override;
diff --git a/lldb/source/Plugins/Process/wasm/CMakeLists.txt b/lldb/source/Plugins/Process/wasm/CMakeLists.txt
new file mode 100644
index 000000000..61efb933f
index 000000000000..61efb933fa62
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/CMakeLists.txt
@@ -0,0 +1,12 @@
@ -5102,7 +5141,7 @@ index 000000000..61efb933f
+ )
diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
new file mode 100644
index 000000000..9c0fc7b7f
index 000000000000..9c0fc7b7f270
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
@@ -0,0 +1,261 @@
@ -5369,7 +5408,7 @@ index 000000000..9c0fc7b7f
+}
diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h
new file mode 100644
index 000000000..d3aece7a6
index 000000000000..d3aece7a6554
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h
@@ -0,0 +1,128 @@
@ -5503,7 +5542,7 @@ index 000000000..d3aece7a6
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H
diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
new file mode 100644
index 000000000..fa02073e7
index 000000000000..fa02073e7a52
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
@@ -0,0 +1,35 @@
@ -5544,7 +5583,7 @@ index 000000000..fa02073e7
+}
diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.h b/lldb/source/Plugins/Process/wasm/ThreadWasm.h
new file mode 100644
index 000000000..0a33c07de
index 000000000000..0a33c07de994
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.h
@@ -0,0 +1,41 @@
@ -5591,7 +5630,7 @@ index 000000000..0a33c07de
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_WASM_THREADWASM_H
diff --git a/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp b/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp
new file mode 100644
index 000000000..1a195cb93
index 000000000000..1a195cb9361a
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp
@@ -0,0 +1,74 @@
@ -5672,7 +5711,7 @@ index 000000000..1a195cb93
\ No newline at end of file
diff --git a/lldb/source/Plugins/Process/wasm/UnwindWasm.h b/lldb/source/Plugins/Process/wasm/UnwindWasm.h
new file mode 100644
index 000000000..9bd1dac9a
index 000000000000..9bd1dac9a98a
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/UnwindWasm.h
@@ -0,0 +1,55 @@
@ -5732,7 +5771,7 @@ index 000000000..9bd1dac9a
+
+#endif // lldb_UnwindWasm_h_
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index ccaf31317..c3ef5aebd 100644
index ccaf31317d75..c3ef5aebd46d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3212,8 +3212,13 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
@ -5751,7 +5790,7 @@ index ccaf31317..c3ef5aebd 100644
// DWARF doesn't specify if a DW_TAG_variable is a local, global
// or static variable, so we have to do a little digging:
diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp
index b660c310e..cd76421ce 100644
index b660c310ef31..cd76421cec18 100644
--- a/lldb/source/Target/PathMappingList.cpp
+++ b/lldb/source/Target/PathMappingList.cpp
@@ -218,7 +218,12 @@ bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) co
@ -5769,7 +5808,7 @@ index b660c310e..cd76421ce 100644
return {};
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index a77ecddfb..e257f9350 100644
index a77ecddfbab6..e257f93508f6 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -1970,6 +1970,12 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target,
@ -5786,7 +5825,7 @@ index a77ecddfb..e257f9350 100644
return 0;
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 8ecc66b59..f14898791 100644
index 8ecc66b592ea..f148987915de 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -1892,7 +1892,8 @@ Status Process::DisableSoftwareBreakpoint(BreakpointSite *bp_site) {
@ -5800,7 +5839,7 @@ index 8ecc66b59..f14898791 100644
if (!GetDisableMemoryCache()) {
#if defined(VERIFY_MEMORY_READS)
diff --git a/lldb/source/Target/ProcessTrace.cpp b/lldb/source/Target/ProcessTrace.cpp
index c878a2ac4..ad5945b0a 100644
index c878a2ac4eb9..ad5945b0ad1f 100644
--- a/lldb/source/Target/ProcessTrace.cpp
+++ b/lldb/source/Target/ProcessTrace.cpp
@@ -88,7 +88,7 @@ void ProcessTrace::RefreshStateAfterStop() {}
@ -5813,7 +5852,7 @@ index c878a2ac4..ad5945b0a 100644
// we have it all cached in the trace files.
return DoReadMemory(addr, buf, size, error);
diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp
index 896e647bb..f76307016 100644
index 896e647bbb52..f76307016102 100644
--- a/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -334,7 +334,10 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
@ -5829,7 +5868,7 @@ index 896e647bb..f76307016 100644
instructions->GetInstructionAtIndex(last_index);
size_t last_inst_size = last_inst->GetOpcode().GetByteSize();
diff --git a/lldb/source/Target/UnixSignals.cpp b/lldb/source/Target/UnixSignals.cpp
index 4ec2e25c7..24c88fe9a 100644
index 4ec2e25c7e3b..24c88fe9ae4f 100644
--- a/lldb/source/Target/UnixSignals.cpp
+++ b/lldb/source/Target/UnixSignals.cpp
@@ -46,6 +46,8 @@ lldb::UnixSignalsSP UnixSignals::Create(const ArchSpec &arch) {
@ -5842,7 +5881,7 @@ index 4ec2e25c7..24c88fe9a 100644
return std::make_shared<UnixSignals>();
}
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h
index 4310ba9ce..297b33879 100644
index 4310ba9ce9e0..297b3387999d 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h
@@ -13,6 +13,7 @@
@ -5854,7 +5893,7 @@ index 4310ba9ce..297b33879 100644
#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h"
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index 753b1998c..27370c62d 100644
index 753b1998c40c..27370c62dd6e 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -16,6 +16,7 @@

View File

@ -91,8 +91,10 @@ endif ()
if (WAMR_BUILD_LIBC_UVWASI EQUAL 1)
include (${IWASM_DIR}/libraries/libc-uvwasi/libc_uvwasi.cmake)
set (WAMR_BUILD_MODULE_INST_CONTEXT 1)
elseif (WAMR_BUILD_LIBC_WASI EQUAL 1)
include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake)
set (WAMR_BUILD_MODULE_INST_CONTEXT 1)
endif ()
if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1)

32
ci/pre_commit_hook_sample Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
# Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
# This is a sample of pre-commit hook that can be used to make your code fit the WAMR CI code style requirements.
# You need to have clang-format-12 installed to use this hook.
# To add this pre-commit hook, copy it to <path_to_wamr>/.git/hooks/pre-commit
# (you don't need any extensions here)
# Function to check if a file has a C or C++ extension
is_c_or_cpp_file() {
file="$1"
if [[ "$filename" =~ \.(h|c|cpp)$ ]]; then
return 0
else
return 1
fi
}
# Loop through staged files and apply command "abc" to C and C++ files
for staged_file in $(git diff --cached --name-only); do
if is_c_or_cpp_file "$staged_file"; then
clang-format-12 -Werror --style file --dry-run "$staged_file" 2>/dev/null
if [ $? -ne 0 ]; then
echo "Issues are found in $staged_file. Applying the fix"
clang-format-12 --style file -i "$staged_file"
fi
git add "$staged_file" # Add the modified file back to staging
fi
done

15
ci/setup.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
# Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
# This script executes some commands to make your onboarding with WAMR easier.
# For example, setting pre-commit hook that will make your code complaint with the
# code style requirements checked in WAMR CI
echo "Copy the pre-commit hook to your hooks folder"
cp pre_commit_hook_sample ../.git/hooks/pre-commit
# Feel free to propose your commands to this script to make developing WAMR easier
echo "Setup is done"

128
ci/validate_lldb.py Executable file
View File

@ -0,0 +1,128 @@
#!/usr/bin/env python3
#
# Copyright (C) 2023 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import argparse
import time
from pathlib import Path
import subprocess, shlex
SCRIPT_DIR = Path(__file__).parent.resolve()
REPO_ROOT_DIR = SCRIPT_DIR.parent
SAMPLE_CODE_FILE = REPO_ROOT_DIR / 'product-mini/app-samples/hello-world/main.c'
WASM_OUT_FILE = SCRIPT_DIR / 'out.wasm'
parser = argparse.ArgumentParser(
description="Validate the customized lldb with sample code"
)
parser.add_argument(
"-l", "--lldb", dest='lldb', default='lldb', help="path to lldb executable"
)
parser.add_argument(
"-w", "--wamr", dest='wamr', default='iwasm', help="path to iwasm executable"
)
parser.add_argument(
"-p", "--port", dest='port', default='1234', help="debug server listen port"
)
parser.add_argument(
"-v", "--verbose", dest='verbose', action='store_true', default=False, help="display lldb stdout"
)
options = parser.parse_args()
lldb_command_epilogue = '-o q'
test_cases = {
'run_to_exit': '-o c',
'func_breakpoint': '-o "b main" -o c -o c',
'line_breakpoint': '-o "b main.c:12" -o c -o c',
'break_on_unknown_func': '-o "b not_a_func" -o c',
'watch_point': '-o "b main" -o c -o "watchpoint set variable buf" -o c -o "fr v buf" -o c',
}
# Step1: Build wasm module with debug information
build_cmd = f'/opt/wasi-sdk/bin/clang -g -O0 -o {WASM_OUT_FILE} {SAMPLE_CODE_FILE}'
try:
print(f'building wasm module ...', end='', flush=True)
subprocess.check_call(shlex.split(build_cmd))
print(f'\t OK')
except subprocess.CalledProcessError:
print("Failed to build wasm module with debug information")
exit(1)
def print_process_output(p):
try:
outs, errs = p.communicate(timeout=2)
print("stdout:")
print(outs)
print("stderr:")
print(errs)
except subprocess.TimeoutExpired:
print("Failed to get process output")
# Step2: Launch WAMR in debug mode and validate lldb commands
iteration = 0
for case, cmd in test_cases.items():
lldb_command_prologue = f'{options.lldb} -o "process connect -p wasm connect://127.0.0.1:{int(options.port) + iteration}"'
wamr_cmd = f'{options.wamr} -g=127.0.0.1:{int(options.port) + iteration} {WASM_OUT_FILE}'
iteration += 1
has_error = False
print(f'validating case [{case}] ...', end='', flush=True)
lldb_cmd = f'{lldb_command_prologue} {cmd} {lldb_command_epilogue}'
wamr_process = subprocess.Popen(shlex.split(
wamr_cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
time.sleep(0.1)
if (wamr_process.poll() != None):
print("\nWAMR doesn't wait for lldb connection")
print_process_output(wamr_process)
exit(1)
lldb_process = subprocess.Popen(shlex.split(
lldb_cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
if (options.verbose):
while (lldb_process.poll() is None):
print(lldb_process.stdout.read(), end='', flush=True)
try:
if (lldb_process.wait(5) != 0):
print(f"\nFailed to validate case [{case}]")
print_process_output(lldb_process)
has_error = True
if wamr_process.wait(2) != 0:
print("\nWAMR process doesn't exit normally")
print_process_output(wamr_process)
has_error = True
except subprocess.TimeoutExpired:
print(f"\nFailed to validate case [{case}]")
print("wamr output:")
print_process_output(wamr_process)
print("lldb output:")
print_process_output(lldb_process)
has_error = True
finally:
if (lldb_process.poll() == None):
print(f'\nterminating lldb process [{lldb_process.pid}]')
lldb_process.kill()
if (wamr_process.poll() == None):
print(f'terminating wamr process [{wamr_process.pid}]')
wamr_process.kill()
if (has_error):
exit(1)
print(f'\t OK')
# wait 100ms to ensure the socket is closed
time.sleep(0.1)
print('Validate lldb success')
exit(0)

View File

@ -144,6 +144,14 @@
#define WASM_ENABLE_WASI_NN 0
#endif
#ifndef WASM_ENABLE_WASI_NN_GPU
#define WASM_ENABLE_WASI_NN_GPU 0
#endif
#ifndef WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE
#define WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE 0
#endif
/* Default disable libc emcc */
#ifndef WASM_ENABLE_LIBC_EMCC
#define WASM_ENABLE_LIBC_EMCC 0
@ -384,7 +392,7 @@
#define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024)
#define APP_THREAD_STACK_SIZE_MIN (48 * 1024)
#else
#define APP_THREAD_STACK_SIZE_DEFAULT (32 * 1024)
#define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024)
#define APP_THREAD_STACK_SIZE_MIN (24 * 1024)
#endif
#endif /* end of !(defined(APP_THREAD_STACK_SIZE_DEFAULT) \
@ -456,4 +464,25 @@
#define WASM_DISABLE_WRITE_GS_BASE 0
#endif
/* Configurable bounds checks */
#ifndef WASM_CONFIGURABLE_BOUNDS_CHECKS
#define WASM_CONFIGURABLE_BOUNDS_CHECKS 0
#endif
/* Some chip cannot support external ram with rwx attr at the same time,
it has to map it into 2 spaces of idbus and dbus, code in dbus can be
read/written and read/executed in ibus. so there are 2 steps to execute
the code, first, copy&do relocaiton in dbus space, and second execute
it in ibus space, since in the 2 spaces the contents are the same,
so we call it bus mirror.
*/
#ifndef WASM_MEM_DUAL_BUS_MIRROR
#define WASM_MEM_DUAL_BUS_MIRROR 0
#endif
/* The max number of module instance contexts. */
#ifndef WASM_MAX_INSTANCE_CONTEXTS
#define WASM_MAX_INSTANCE_CONTEXTS 8
#endif
#endif /* end of _CONFIG_H_ */

View File

@ -648,6 +648,42 @@ add_f64_common_intrinsics(AOTCompContext *comp_ctx)
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CMP);
}
static void
add_f32xi32_intrinsics(AOTCompContext *comp_ctx)
{
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I32);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U32);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F32);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F32);
}
static void
add_f64xi32_intrinsics(AOTCompContext *comp_ctx)
{
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I32);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U32);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F64);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F64);
}
static void
add_f32xi64_intrinsics(AOTCompContext *comp_ctx)
{
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I64);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U64);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F32);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F32);
}
static void
add_f64xi64_intrinsics(AOTCompContext *comp_ctx)
{
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I64);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U64);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F64);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F64);
}
static void
add_common_float_integer_convertion(AOTCompContext *comp_ctx)
{
@ -705,8 +741,101 @@ aot_intrinsic_check_capability(const AOTCompContext *comp_ctx,
void
aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx)
{
uint32 i;
memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags));
/* Intrinsics from command line have highest priority */
if (comp_ctx->builtin_intrinsics) {
/* Handle 'all' group */
if (strstr(comp_ctx->builtin_intrinsics, "all")) {
for (i = 0; i < g_intrinsic_count; i++) {
add_intrinsic_capability(comp_ctx, g_intrinsic_mapping[i].flag);
}
return;
}
/* Handle 'i32.common' group */
if (strstr(comp_ctx->builtin_intrinsics, "i32.common")) {
add_i32_common_intrinsics(comp_ctx);
}
/* Handle 'i64.common' group */
if (strstr(comp_ctx->builtin_intrinsics, "i64.common")) {
add_i64_common_intrinsics(comp_ctx);
}
/* Handle 'fp.common' group */
if (strstr(comp_ctx->builtin_intrinsics, "fp.common")) {
add_f32_common_intrinsics(comp_ctx);
add_f64_common_intrinsics(comp_ctx);
}
/* Handle 'f32.common' group */
if (strstr(comp_ctx->builtin_intrinsics, "f32.common")) {
add_f32_common_intrinsics(comp_ctx);
}
/* Handle 'f64.common' group */
if (strstr(comp_ctx->builtin_intrinsics, "f64.common")) {
add_f64_common_intrinsics(comp_ctx);
}
/* Handle 'f32xi32' group */
if (strstr(comp_ctx->builtin_intrinsics, "f32xi32")) {
add_f32xi32_intrinsics(comp_ctx);
}
/* Handle 'f64xi32' group */
if (strstr(comp_ctx->builtin_intrinsics, "f64xi32")) {
add_f64xi32_intrinsics(comp_ctx);
}
/* Handle 'f32xi64' group */
if (strstr(comp_ctx->builtin_intrinsics, "f32xi64")) {
add_f32xi64_intrinsics(comp_ctx);
}
/* Handle 'f64xi64' group */
if (strstr(comp_ctx->builtin_intrinsics, "f64xi64")) {
add_f64xi64_intrinsics(comp_ctx);
}
/* Handle 'fpxint' group */
if (strstr(comp_ctx->builtin_intrinsics, "fpxint")) {
add_f32xi32_intrinsics(comp_ctx);
add_f64xi32_intrinsics(comp_ctx);
add_f32xi64_intrinsics(comp_ctx);
add_f64xi64_intrinsics(comp_ctx);
}
/* Handle 'constop' group */
if (strstr(comp_ctx->builtin_intrinsics, "constop")) {
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_CONST);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CONST);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CONST);
}
/* Handle 'fp.common' group */
if (strstr(comp_ctx->builtin_intrinsics, "fp.common")) {
add_f32_common_intrinsics(comp_ctx);
add_f64_common_intrinsics(comp_ctx);
}
/* Handle other single items */
for (i = 0; i < g_intrinsic_count; i++) {
if (strstr(comp_ctx->builtin_intrinsics,
g_intrinsic_mapping[i].llvm_intrinsic)) {
add_intrinsic_capability(comp_ctx, g_intrinsic_mapping[i].flag);
}
}
return;
}
if (!comp_ctx->target_cpu)
return;

View File

@ -1644,27 +1644,6 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
const uint8 *p = buf, *p_end = buf_end;
uint32 i;
uint64 size, text_offset;
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
RUNTIME_FUNCTION *rtl_func_table;
AOTUnwindInfo *unwind_info;
uint32 unwind_info_offset = module->code_size - sizeof(AOTUnwindInfo);
uint32 unwind_code_offset = unwind_info_offset - PLT_ITEM_SIZE;
#endif
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
unwind_info = (AOTUnwindInfo *)((uint8 *)module->code + module->code_size
- sizeof(AOTUnwindInfo));
unwind_info->Version = 1;
unwind_info->Flags = UNW_FLAG_NHANDLER;
*(uint32 *)&unwind_info->UnwindCode[0] = unwind_code_offset;
size = sizeof(RUNTIME_FUNCTION) * (uint64)module->func_count;
if (size > 0
&& !(rtl_func_table = module->rtl_func_table =
loader_malloc(size, error_buf, error_buf_size))) {
return false;
}
#endif
size = sizeof(void *) * (uint64)module->func_count;
if (size > 0
@ -1691,33 +1670,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
#if defined(BUILD_TARGET_THUMB) || defined(BUILD_TARGET_THUMB_VFP)
/* bits[0] of thumb function address must be 1 */
module->func_ptrs[i] = (void *)((uintptr_t)module->func_ptrs[i] | 1);
#endif
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
rtl_func_table[i].BeginAddress = (DWORD)text_offset;
if (i > 0) {
rtl_func_table[i - 1].EndAddress = rtl_func_table[i].BeginAddress;
}
rtl_func_table[i].UnwindInfoAddress = (DWORD)unwind_info_offset;
#endif
}
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
if (module->func_count > 0) {
uint32 plt_table_size =
module->is_indirect_mode ? 0 : get_plt_table_size();
rtl_func_table[module->func_count - 1].EndAddress =
(DWORD)(module->code_size - plt_table_size);
if (!RtlAddFunctionTable(rtl_func_table, module->func_count,
(DWORD64)(uintptr_t)module->code)) {
set_error_buf(error_buf, error_buf_size,
"add dynamic function table failed");
return false;
}
module->rtl_func_table_registered = true;
}
#endif
/* Set start function when function pointers are resolved */
if (module->start_func_index != (uint32)-1) {
if (module->start_func_index >= module->import_func_count)
@ -1843,6 +1798,13 @@ get_data_section_addr(AOTModule *module, const char *section_name,
return NULL;
}
const void *
aot_get_data_section_addr(AOTModule *module, const char *section_name,
uint32 *p_data_size)
{
return get_data_section_addr(module, section_name, p_data_size);
}
static void *
resolve_target_sym(const char *symbol, int32 *p_index)
{
@ -2020,6 +1982,7 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group,
|| !strncmp(symbol, ".rodata.cst", strlen(".rodata.cst"))
/* ".rodata.strn.m" */
|| !strncmp(symbol, ".rodata.str", strlen(".rodata.str"))
|| !strcmp(symbol, AOT_STACK_SIZES_SECTION_NAME)
#if WASM_ENABLE_STATIC_PGO != 0
|| !strncmp(symbol, "__llvm_prf_cnts", 15)
|| !strncmp(symbol, "__llvm_prf_data", 15)
@ -3005,6 +2968,9 @@ create_sections(AOTModule *module, const uint8 *buf, uint32 size,
uint32 section_size;
uint64 total_size;
uint8 *aot_text;
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
uint8 *mirrored_text;
#endif
if (!resolve_execute_mode(buf, size, &is_indirect_mode, error_buf,
error_buf_size)) {
@ -3063,8 +3029,17 @@ create_sections(AOTModule *module, const uint8 *buf, uint32 size,
bh_assert((uintptr_t)aot_text < INT32_MAX);
#endif
#endif
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
mirrored_text = os_get_dbus_mirror(aot_text);
bh_assert(mirrored_text != NULL);
bh_memcpy_s(mirrored_text, (uint32)total_size,
section->section_body, (uint32)section_size);
os_dcache_flush();
#else
bh_memcpy_s(aot_text, (uint32)total_size,
section->section_body, (uint32)section_size);
#endif
section->section_body = aot_text;
destroy_aot_text = true;
@ -3241,14 +3216,6 @@ aot_unload(AOTModule *module)
}
#endif
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
if (module->rtl_func_table) {
if (module->rtl_func_table_registered)
RtlDeleteFunctionTable(module->rtl_func_table);
wasm_runtime_free(module->rtl_func_table);
}
#endif
#if (defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)) \
&& !defined(BH_PLATFORM_WINDOWS)
{

View File

@ -42,6 +42,11 @@ bh_static_assert(offsetof(AOTModuleInstance, cur_exception)
bh_static_assert(offsetof(AOTModuleInstance, global_table_data)
== 13 * sizeof(uint64) + 128 + 11 * sizeof(uint64));
bh_static_assert(sizeof(AOTMemoryInstance) == 104);
bh_static_assert(offsetof(AOTTableInstance, elems) == 8);
bh_static_assert(offsetof(AOTModuleInstanceExtra, stack_sizes) == 0);
static void
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
{
@ -334,11 +339,8 @@ memories_deinstantiate(AOTModuleInstance *module_inst)
memory_inst = module_inst->memories[i];
if (memory_inst) {
#if WASM_ENABLE_SHARED_MEMORY != 0
if (memory_inst->is_shared) {
int32 ref_count = shared_memory_dec_reference(
(WASMModuleCommon *)module_inst->module);
bh_assert(ref_count >= 0);
if (shared_memory_is_shared(memory_inst)) {
uint32 ref_count = shared_memory_dec_reference(memory_inst);
/* if the reference count is not zero,
don't free the memory */
if (ref_count > 0)
@ -368,9 +370,10 @@ memories_deinstantiate(AOTModuleInstance *module_inst)
}
static AOTMemoryInstance *
memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
AOTMemoryInstance *memory_inst, AOTMemory *memory,
uint32 heap_size, char *error_buf, uint32 error_buf_size)
memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
AOTModule *module, AOTMemoryInstance *memory_inst,
AOTMemory *memory, uint32 memory_idx, uint32 heap_size,
char *error_buf, uint32 error_buf_size)
{
void *heap_handle;
uint32 num_bytes_per_page = memory->num_bytes_per_page;
@ -391,23 +394,13 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
bool is_shared_memory = memory->memory_flags & 0x02 ? true : false;
/* Shared memory */
if (is_shared_memory) {
if (is_shared_memory && parent != NULL) {
AOTMemoryInstance *shared_memory_instance;
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module);
/* If the memory of this module has been instantiated,
return the memory instance directly */
if (node) {
uint32 ref_count;
ref_count = shared_memory_inc_reference((WASMModuleCommon *)module);
bh_assert(ref_count > 0);
shared_memory_instance =
(AOTMemoryInstance *)shared_memory_get_memory_inst(node);
bh_assert(shared_memory_instance);
(void)ref_count;
return shared_memory_instance;
}
bh_assert(memory_idx == 0);
bh_assert(parent->memory_count > memory_idx);
shared_memory_instance = parent->memories[memory_idx];
shared_memory_inc_reference(shared_memory_instance);
return shared_memory_instance;
}
#endif
@ -427,7 +420,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
if (num_bytes_per_page < heap_size) {
set_error_buf(error_buf, error_buf_size,
"failed to insert app heap into linear memory, "
"try using `--heap_size=0` option");
"try using `--heap-size=0` option");
return NULL;
}
}
@ -485,7 +478,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
if (init_page_count > DEFAULT_MAX_PAGES) {
set_error_buf(error_buf, error_buf_size,
"failed to insert app heap into linear memory, "
"try using `--heap_size=0` option");
"try using `--heap-size=0` option");
return NULL;
}
else if (init_page_count == DEFAULT_MAX_PAGES) {
@ -604,23 +597,12 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
#if WASM_ENABLE_SHARED_MEMORY != 0
if (is_shared_memory) {
memory_inst->is_shared = true;
if (!shared_memory_set_memory_inst(
(WASMModuleCommon *)module,
(WASMMemoryInstanceCommon *)memory_inst)) {
set_error_buf(error_buf, error_buf_size, "allocate memory failed");
goto fail3;
}
memory_inst->ref_count = 1;
}
#endif
return memory_inst;
#if WASM_ENABLE_SHARED_MEMORY != 0
fail3:
if (heap_size > 0)
mem_allocator_destroy(memory_inst->heap_handle);
#endif
fail2:
if (heap_size > 0)
wasm_runtime_free(memory_inst->heap_handle);
@ -649,8 +631,9 @@ aot_get_default_memory(AOTModuleInstance *module_inst)
}
static bool
memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
uint32 heap_size, char *error_buf, uint32 error_buf_size)
memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
AOTModule *module, uint32 heap_size, char *error_buf,
uint32 error_buf_size)
{
uint32 global_index, global_data_offset, base_offset, length;
uint32 i, memory_count = module->memory_count;
@ -667,8 +650,8 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
memories = module_inst->global_table_data.memory_instances;
for (i = 0; i < memory_count; i++, memories++) {
memory_inst = memory_instantiate(module_inst, module, memories,
&module->memories[i], heap_size,
memory_inst = memory_instantiate(module_inst, parent, module, memories,
&module->memories[i], i, heap_size,
error_buf, error_buf_size);
if (!memory_inst) {
return false;
@ -1095,9 +1078,9 @@ check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size)
}
AOTModuleInstance *
aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
uint32 stack_size, uint32 heap_size, char *error_buf,
uint32 error_buf_size)
aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size)
{
AOTModuleInstance *module_inst;
const uint32 module_inst_struct_size =
@ -1107,6 +1090,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
uint64 total_size, table_size = 0;
uint8 *p;
uint32 i, extra_info_offset;
const bool is_sub_inst = parent != NULL;
/* Check heap size */
heap_size = align_uint(heap_size, 8);
@ -1166,7 +1150,7 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
goto fail;
/* Initialize memory space */
if (!memories_instantiate(module_inst, module, heap_size, error_buf,
if (!memories_instantiate(module_inst, parent, module, heap_size, error_buf,
error_buf_size))
goto fail;
@ -1201,17 +1185,6 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
}
#endif
#if WASM_ENABLE_WASI_NN != 0
if (!is_sub_inst) {
if (!(((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx =
wasi_nn_initialize())) {
set_error_buf(error_buf, error_buf_size,
"wasi nn initialization failed");
goto fail;
}
}
#endif
/* Initialize the thread related data */
if (stack_size == 0)
stack_size = DEFAULT_WASM_STACK_SIZE;
@ -1221,6 +1194,9 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
#endif
module_inst->default_wasm_stack_size = stack_size;
((AOTModuleInstanceExtra *)module_inst->e)->stack_sizes =
aot_get_data_section_addr(module, AOT_STACK_SIZES_SECTION_NAME, NULL);
#if WASM_ENABLE_PERF_PROFILING != 0
total_size = (uint64)sizeof(AOTFuncPerfProfInfo)
* (module->import_func_count + module->func_count);
@ -1267,16 +1243,6 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton);
}
#if WASM_ENABLE_LIBC_WASI != 0
/* Destroy wasi resource before freeing app heap, since some fields of
wasi contex are allocated from app heap, and if app heap is freed,
these fields will be set to NULL, we cannot free their internal data
which may allocated from global heap. */
/* Only destroy wasi ctx in the main module instance */
if (!is_sub_inst)
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
#endif
#if WASM_ENABLE_PERF_PROFILING != 0
if (module_inst->func_perf_profilings)
wasm_runtime_free(module_inst->func_perf_profilings);
@ -1305,18 +1271,16 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
if (module_inst->func_type_indexes)
wasm_runtime_free(module_inst->func_type_indexes);
if (((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports)
wasm_runtime_free(
((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports);
if (((AOTModuleInstanceExtra *)module_inst->e)->common.c_api_func_imports)
wasm_runtime_free(((AOTModuleInstanceExtra *)module_inst->e)
->common.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);
}
#if WASM_ENABLE_WASI_NN != 0
wasi_nn_destroy(module_inst);
#endif
wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
}
wasm_runtime_free(module_inst);
}
@ -1477,6 +1441,9 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
/* set thread handle and stack boundary */
wasm_exec_env_set_thread_info(exec_env);
/* set exec env so it can be later retrieved from instance */
((AOTModuleInstanceExtra *)module_inst->e)->common.cur_exec_env = exec_env;
if (ext_ret_count > 0) {
uint32 cell_num = 0, i;
uint8 *ext_ret_types = func_type->types + func_type->param_count + 1;
@ -1959,8 +1926,8 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
AOTModuleInstanceExtra *module_inst_extra =
(AOTModuleInstanceExtra *)module_inst->e;
CApiFuncImport *c_api_func_import =
module_inst_extra->c_api_func_imports
? module_inst_extra->c_api_func_imports + func_idx
module_inst_extra->common.c_api_func_imports
? module_inst_extra->common.c_api_func_imports + func_idx
: NULL;
uint32 *func_type_indexes = module_inst->func_type_indexes;
uint32 func_type_idx = func_type_indexes[func_idx];
@ -2496,13 +2463,13 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
tbl_seg = module->table_init_data_list[tbl_seg_idx];
bh_assert(tbl_seg);
if (!length) {
if (offset_len_out_of_bounds(src_offset, length, tbl_seg->func_index_count)
|| offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) {
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
return;
}
if (length + src_offset > tbl_seg->func_index_count
|| dst_offset + length > tbl_inst->cur_size) {
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
if (!length) {
return;
}
@ -2535,8 +2502,9 @@ aot_table_copy(AOTModuleInstance *module_inst, uint32 src_tbl_idx,
dst_tbl_inst = module_inst->tables[dst_tbl_idx];
bh_assert(dst_tbl_inst);
if ((uint64)dst_offset + length > dst_tbl_inst->cur_size
|| (uint64)src_offset + length > src_tbl_inst->cur_size) {
if (offset_len_out_of_bounds(dst_offset, length, dst_tbl_inst->cur_size)
|| offset_len_out_of_bounds(src_offset, length,
src_tbl_inst->cur_size)) {
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
return;
}
@ -2561,7 +2529,7 @@ aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length,
tbl_inst = module_inst->tables[tbl_idx];
bh_assert(tbl_inst);
if (data_offset + length > tbl_inst->cur_size) {
if (offset_len_out_of_bounds(data_offset, length, tbl_inst->cur_size)) {
aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
return;
}

View File

@ -88,36 +88,10 @@ typedef struct AOTFunctionInstance {
} AOTFunctionInstance;
typedef struct AOTModuleInstanceExtra {
CApiFuncImport *c_api_func_imports;
#if WASM_ENABLE_WASI_NN != 0
WASINNContext *wasi_nn_ctx;
#endif
DefPointer(const uint32 *, stack_sizes);
WASMModuleInstanceExtraCommon common;
} AOTModuleInstanceExtra;
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
/* clang-format off */
typedef struct AOTUnwindInfo {
uint8 Version : 3;
uint8 Flags : 5;
uint8 SizeOfProlog;
uint8 CountOfCodes;
uint8 FrameRegister : 4;
uint8 FrameOffset : 4;
struct {
struct {
uint8 CodeOffset;
uint8 UnwindOp : 4;
uint8 OpInfo : 4;
};
uint16 FrameOffset;
} UnwindCode[1];
} AOTUnwindInfo;
/* clang-format on */
/* size of mov instruction and jmp instruction */
#define PLT_ITEM_SIZE 12
#endif
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
typedef struct GOTItem {
uint32 func_idx;
@ -213,14 +187,6 @@ typedef struct AOTModule {
uint32 float_plt_count;
#endif
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
/* dynamic function table to be added by RtlAddFunctionTable(),
used to unwind the call stack and register exception handler
for AOT functions */
RUNTIME_FUNCTION *rtl_func_table;
bool rtl_func_table_registered;
#endif
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
uint32 got_item_count;
GOTItemList got_item_list;
@ -404,7 +370,7 @@ aot_unload(AOTModule *module);
* Instantiate a AOT module.
*
* @param module the AOT module to instantiate
* @param is_sub_inst the flag of sub instance
* @param parent the parent module instance
* @param heap_size the default heap size of the module instance, a heap will
* be created besides the app memory space. Both wasm app and native
* function can allocate memory from the heap. If heap_size is 0, the
@ -415,9 +381,9 @@ aot_unload(AOTModule *module);
* @return return the instantiated AOT module instance, NULL if failed
*/
AOTModuleInstance *
aot_instantiate(AOTModule *module, bool is_sub_inst, WASMExecEnv *exec_env_main,
uint32 stack_size, uint32 heap_size, char *error_buf,
uint32 error_buf_size);
aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
WASMExecEnv *exec_env_main, uint32 stack_size, uint32 heap_size,
char *error_buf, uint32 error_buf_size);
/**
* Deinstantiate a AOT module instance, destroy the resources.
@ -636,6 +602,10 @@ aot_dump_perf_profiling(const AOTModuleInstance *module_inst);
const uint8 *
aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len);
const void *
aot_get_data_section_addr(AOTModule *module, const char *section_name,
uint32 *p_data_size);
#if WASM_ENABLE_STATIC_PGO != 0
void
llvm_profile_instrument_target(uint64 target_value, void *data,

View File

@ -40,6 +40,7 @@ void __aeabi_ldivmod();
void __aeabi_memcpy();
void __aeabi_memmove();
void __aeabi_memset();
void __aeabi_memclr();
void __aeabi_uidiv();
void __aeabi_uidivmod();
void __aeabi_ul2d();
@ -126,6 +127,7 @@ static SymbolMap target_sym_map[] = {
REG_SYM(__aeabi_memcpy),
REG_SYM(__aeabi_memmove),
REG_SYM(__aeabi_memset),
REG_SYM(__aeabi_memclr),
REG_SYM(__aeabi_uidiv),
REG_SYM(__aeabi_uidivmod),
REG_SYM(__aeabi_ul2d),

View File

@ -9,6 +9,8 @@
#define R_RISCV_64 2
#define R_RISCV_CALL 18
#define R_RISCV_CALL_PLT 19
#define R_RISCV_PCREL_HI20 23
#define R_RISCV_PCREL_LO12_I 24
#define R_RISCV_HI20 26
#define R_RISCV_LO12_I 27
#define R_RISCV_LO12_S 28
@ -76,6 +78,13 @@ static SymbolMap target_sym_map[] = {
REG_SYM(__addsf3),
REG_SYM(__divdf3),
REG_SYM(__divsf3),
REG_SYM(__eqdf2),
REG_SYM(__eqsf2),
REG_SYM(__extendsfdf2),
REG_SYM(__fixunsdfdi),
REG_SYM(__fixunsdfsi),
REG_SYM(__fixunssfdi),
REG_SYM(__fixunssfsi),
REG_SYM(__gedf2),
REG_SYM(__gesf2),
REG_SYM(__gtdf2),
@ -87,44 +96,33 @@ static SymbolMap target_sym_map[] = {
REG_SYM(__muldf3),
REG_SYM(__nedf2),
REG_SYM(__nesf2),
REG_SYM(__eqsf2),
REG_SYM(__eqdf2),
REG_SYM(__extendsfdf2),
REG_SYM(__fixunsdfdi),
REG_SYM(__fixunsdfsi),
REG_SYM(__fixunssfsi),
REG_SYM(__subdf3),
REG_SYM(__subsf3),
REG_SYM(__truncdfsf2),
REG_SYM(__unorddf2),
REG_SYM(__unordsf2),
#endif
REG_SYM(__divdi3),
REG_SYM(__divsi3),
#if __riscv_xlen == 32
REG_SYM(__fixdfdi),
REG_SYM(__fixdfsi),
REG_SYM(__fixsfdi),
REG_SYM(__fixsfsi),
#endif
REG_SYM(__fixunssfdi),
#if __riscv_xlen == 32
REG_SYM(__floatdidf),
REG_SYM(__floatdisf),
REG_SYM(__floatsisf),
REG_SYM(__floatsidf),
REG_SYM(__floatsisf),
REG_SYM(__floatundidf),
REG_SYM(__floatundisf),
REG_SYM(__floatunsisf),
REG_SYM(__floatunsidf),
#endif
REG_SYM(__moddi3),
REG_SYM(__modsi3),
REG_SYM(__muldi3),
#if __riscv_xlen == 32
REG_SYM(__floatunsisf),
REG_SYM(__mulsf3),
REG_SYM(__mulsi3),
#endif
#endif
REG_SYM(__divdi3),
REG_SYM(__divsi3),
REG_SYM(__moddi3),
REG_SYM(__modsi3),
REG_SYM(__muldi3),
REG_SYM(__udivdi3),
REG_SYM(__udivsi3),
REG_SYM(__umoddi3),
@ -267,9 +265,10 @@ typedef struct RelocTypeStrMap {
}
static RelocTypeStrMap reloc_type_str_maps[] = {
RELOC_TYPE_MAP(R_RISCV_32), RELOC_TYPE_MAP(R_RISCV_CALL),
RELOC_TYPE_MAP(R_RISCV_CALL_PLT), RELOC_TYPE_MAP(R_RISCV_HI20),
RELOC_TYPE_MAP(R_RISCV_LO12_I), RELOC_TYPE_MAP(R_RISCV_LO12_S),
RELOC_TYPE_MAP(R_RISCV_32), RELOC_TYPE_MAP(R_RISCV_CALL),
RELOC_TYPE_MAP(R_RISCV_CALL_PLT), RELOC_TYPE_MAP(R_RISCV_PCREL_HI20),
RELOC_TYPE_MAP(R_RISCV_PCREL_LO12_I), RELOC_TYPE_MAP(R_RISCV_HI20),
RELOC_TYPE_MAP(R_RISCV_LO12_I), RELOC_TYPE_MAP(R_RISCV_LO12_S),
};
static const char *
@ -369,13 +368,29 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
break;
}
case R_RISCV_HI20:
case R_RISCV_HI20: /* S + A */
case R_RISCV_PCREL_HI20: /* S + A - P */
{
val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
if (reloc_type == R_RISCV_PCREL_HI20) {
val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend
- (intptr_t)addr);
}
else {
val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
}
CHECK_RELOC_OFFSET(sizeof(uint32));
if (val != ((intptr_t)symbol_addr + (intptr_t)reloc_addend)) {
goto fail_addr_out_of_range;
if (reloc_type == R_RISCV_PCREL_HI20) {
if (val
!= ((intptr_t)symbol_addr + (intptr_t)reloc_addend
- (intptr_t)addr)) {
goto fail_addr_out_of_range;
}
}
else {
if (val != ((intptr_t)symbol_addr + (intptr_t)reloc_addend)) {
goto fail_addr_out_of_range;
}
}
addr = target_section_addr + reloc_offset;
@ -386,13 +401,27 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
break;
}
case R_RISCV_LO12_I:
case R_RISCV_LO12_I: /* S + A */
case R_RISCV_PCREL_LO12_I: /* S - P */
{
val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
if (reloc_type == R_RISCV_PCREL_LO12_I) {
/* A = 0 */
val = (int32)((intptr_t)symbol_addr - (intptr_t)addr);
}
else {
val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend);
}
CHECK_RELOC_OFFSET(sizeof(uint32));
if (val != (intptr_t)symbol_addr + (intptr_t)reloc_addend) {
goto fail_addr_out_of_range;
if (reloc_type == R_RISCV_PCREL_LO12_I) {
if (val != (intptr_t)symbol_addr - (intptr_t)addr) {
goto fail_addr_out_of_range;
}
}
else {
if (val != (intptr_t)symbol_addr + (intptr_t)reloc_addend) {
goto fail_addr_out_of_range;
}
}
addr = target_section_addr + reloc_offset;

View File

@ -164,6 +164,9 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
(uint32)((uintptr_t)symbol_addr + (intptr_t)reloc_addend
- (uintptr_t)(target_section_addr
+ (uint32)reloc_offset)
#if defined(BH_PLATFORM_WINDOWS)
- sizeof(int32)
#endif
+ value); /* S + A - P */
break;
}

View File

@ -69,9 +69,6 @@ get_plt_table_size()
{
uint32 size =
get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
size += get_plt_item_size() + sizeof(AOTUnwindInfo);
#endif
return size;
}
@ -93,18 +90,6 @@ init_plt_table(uint8 *plt)
*p++ = 0xE0;
plt += get_plt_item_size();
}
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
p = plt;
/* mov exception_handler, rax */
*p++ = 0x48;
*p++ = 0xB8;
*(uint64 *)p = 0; /*(uint64)(uintptr_t)aot_exception_handler;*/
p += sizeof(uint64);
/* jmp rax */
*p++ = 0xFF;
*p++ = 0xE0;
#endif
}
static bool
@ -242,7 +227,7 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
- (uintptr_t)(target_section_addr + reloc_offset));
}
else {
target_addr = (intptr_t) /* L + A - P */
target_addr = (intptr_t) /* S + A - P */
((uintptr_t)symbol_addr + reloc_addend
- (uintptr_t)(target_section_addr + reloc_offset));
}

View File

@ -43,6 +43,11 @@ void __floatdidf();
void __divsf3();
void __fixdfdi();
void __floatundidf();
void __fixsfdi();
void __fixunssfdi();
void __fixunsdfdi();
void __floatdisf();
void __floatundisf();
static SymbolMap target_sym_map[] = {
@ -85,6 +90,11 @@ static SymbolMap target_sym_map[] = {
REG_SYM(__divsf3),
REG_SYM(__fixdfdi),
REG_SYM(__floatundidf),
REG_SYM(__fixsfdi),
REG_SYM(__fixunssfdi),
REG_SYM(__fixunsdfdi),
REG_SYM(__floatdisf),
REG_SYM(__floatundisf),
};
/* clang-format on */
@ -207,6 +217,10 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
case R_XTENSA_32:
{
uint8 *insn_addr = target_section_addr + reloc_offset;
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
insn_addr = os_get_dbus_mirror((void *)insn_addr);
bh_assert(insn_addr != NULL);
#endif
int32 initial_addend;
/* (S + A) */
if ((intptr_t)insn_addr & 3) {
@ -265,6 +279,11 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
return false;
}
#if (WASM_MEM_DUAL_BUS_MIRROR != 0)
insn_addr = os_get_dbus_mirror((void *)insn_addr);
bh_assert(insn_addr != NULL);
l32r_insn = (l32r_insn_t *)insn_addr;
#endif
imm16 = (int16)(relative_offset >> 2);
/* write back the imm16 to the l32r instruction */
@ -285,7 +304,6 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
#if __GNUC__ >= 9
#pragma GCC diagnostic pop
#endif
break;
}

View File

@ -36,5 +36,49 @@ if (WAMR_BUILD_DEBUG_AOT EQUAL 1)
file(GLOB debug_source ${IWASM_AOT_DIR}/debug/*.c)
endif()
set (IWASM_AOT_SOURCE ${c_source_all} ${arch_source} ${debug_source})
if ((WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
AND (WAMR_BUILD_PLATFORM STREQUAL "windows")
AND (NOT WAMR_DISABLE_HW_BOUND_CHECK EQUAL 1))
include(FetchContent)
FetchContent_Declare(
zycore
GIT_REPOSITORY https://github.com/zyantific/zycore-c.git
)
FetchContent_GetProperties(zycore)
if (NOT zycore_POPULATED)
message ("-- Fetching zycore ..")
FetchContent_Populate(zycore)
include_directories("${zycore_SOURCE_DIR}/include")
include_directories("${zycore_BINARY_DIR}")
add_definitions(-DZYCORE_STATIC_BUILD=1)
add_subdirectory(${zycore_SOURCE_DIR} ${zycore_BINARY_DIR} EXCLUDE_FROM_ALL)
file (GLOB_RECURSE c_source_zycore ${zycore_SOURCE_DIR}/src/*.c)
endif ()
FetchContent_Declare(
zydis
GIT_REPOSITORY https://github.com/zyantific/zydis.git
GIT_TAG e14a07895136182a5b53e181eec3b1c6e0b434de
)
FetchContent_GetProperties(zydis)
if (NOT zydis_POPULATED)
message ("-- Fetching zydis ..")
FetchContent_Populate(zydis)
option(ZYDIS_FEATURE_ENCODER "" OFF)
option(ZYDIS_BUILD_TOOLS "" OFF)
option(ZYDIS_BUILD_EXAMPLES "" OFF)
option(ZYDIS_BUILD_MAN "" OFF)
option(ZYDIS_BUILD_DOXYGEN "" OFF)
include_directories("${zydis_BINARY_DIR}")
include_directories("${zydis_SOURCE_DIR}/include")
include_directories("${zydis_SOURCE_DIR}/src")
add_definitions(-DZYDIS_STATIC_BUILD=1)
add_subdirectory(${zydis_SOURCE_DIR} ${zydis_BINARY_DIR} EXCLUDE_FROM_ALL)
file (GLOB_RECURSE c_source_zydis ${zydis_SOURCE_DIR}/src/*.c)
endif ()
endif ()
set (IWASM_AOT_SOURCE ${c_source_all} ${arch_source} ${debug_source}
${c_source_zycore} ${c_source_zydis})

View File

@ -107,7 +107,34 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
the actual main function. Directly calling main function
may cause exception thrown. */
if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) {
return wasm_runtime_call_wasm(exec_env, func, 0, NULL);
const char *wasi_proc_exit_exception = "wasi proc exit";
ret = wasm_runtime_call_wasm(exec_env, func, 0, NULL);
#if WASM_ENABLE_THREAD_MGR != 0
if (ret) {
/* On a successful return from the `_start` function,
we terminate other threads by mimicing wasi:proc_exit(0).
Note:
- A return from the `main` function is an equivalent of
exit(). (C standard)
- When exit code is 0, wasi-libc's `_start` function just
returns w/o calling `proc_exit`.
- A process termination should terminate threads in
the process. */
wasm_runtime_set_exception(module_inst, wasi_proc_exit_exception);
/* exit_code is zero-initialized */
ret = false;
}
#endif
/* report wasm proc exit as a success */
WASMModuleInstance *inst = (WASMModuleInstance *)module_inst;
if (!ret && strstr(inst->cur_exception, wasi_proc_exit_exception)) {
inst->cur_exception[0] = 0;
ret = true;
}
return ret;
}
#endif /* end of WASM_ENABLE_LIBC_WASI */

View File

@ -2290,8 +2290,10 @@ quit:
bool
wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary)
{
wasm_byte_vec_t local_binary = { 0 };
struct WASMModuleCommon *module_rt;
char error_buf[128] = { 0 };
bool ret;
bh_assert(singleton_engine);
@ -2300,15 +2302,25 @@ wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary)
return false;
}
if ((module_rt = wasm_runtime_load((uint8 *)binary->data,
(uint32)binary->size, error_buf, 128))) {
/* make a copy of binary */
wasm_byte_vec_copy(&local_binary, binary);
if (binary->size && !local_binary.data)
return false;
module_rt = wasm_runtime_load((uint8 *)local_binary.data,
(uint32)local_binary.size, error_buf, 128);
wasm_byte_vec_delete(&local_binary);
if (module_rt) {
wasm_runtime_unload(module_rt);
return true;
ret = true;
}
else {
ret = false;
LOG_VERBOSE(error_buf);
return false;
}
return ret;
}
static void
@ -4858,7 +4870,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
WASMModuleInstanceExtra *e =
((WASMModuleInstance *)instance->inst_comm_rt)->e;
p_func_imports = &(e->c_api_func_imports);
p_func_imports = &(e->common.c_api_func_imports);
import_func_count = MODULE_INTERP(module)->import_function_count;
}
#endif
@ -4868,7 +4880,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
(AOTModuleInstanceExtra *)((AOTModuleInstance *)
instance->inst_comm_rt)
->e;
p_func_imports = &(e->c_api_func_imports);
p_func_imports = &(e->common.c_api_func_imports);
import_func_count = MODULE_AOT(module)->import_func_count;
}
#endif

View File

@ -7,6 +7,7 @@
#define _WASM_EXEC_ENV_H
#include "bh_assert.h"
#include "wasm_suspend_flags.h"
#if WASM_ENABLE_INTERP != 0
#include "../interpreter/wasm.h"
#endif
@ -57,15 +58,8 @@ typedef struct WASMExecEnv {
exception. */
uint8 *native_stack_boundary;
/* Used to terminate or suspend current thread
bit 0: need to terminate
bit 1: need to suspend
bit 2: need to go into breakpoint
bit 3: return from pthread_exit */
union {
uint32 flags;
uintptr_t __padding__;
} suspend_flags;
/* Used to terminate or suspend current thread */
WASMSuspendFlags suspend_flags;
/* Auxiliary stack boundary */
union {

View File

@ -5,8 +5,10 @@
#include "wasm_runtime_common.h"
#include "../interpreter/wasm_runtime.h"
#include "../aot/aot_runtime.h"
#include "bh_platform.h"
#include "mem_alloc.h"
#include "wasm_memory.h"
#if WASM_ENABLE_SHARED_MEMORY != 0
#include "../common/wasm_shared_memory.h"
@ -23,6 +25,8 @@ static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN;
static mem_allocator_t pool_allocator = NULL;
static enlarge_memory_error_callback_t enlarge_memory_error_cb;
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
static void *allocator_user_data = NULL;
static void *(*malloc_func)(void *user_data, unsigned int size) = NULL;
@ -87,6 +91,16 @@ wasm_memory_init_with_allocator(void *_malloc_func, void *_realloc_func,
}
#endif
static inline bool
is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst)
{
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
return wasm_runtime_is_bounds_checks_enabled(module_inst);
#else
return true;
#endif
}
bool
wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
const MemAllocOption *alloc_option)
@ -269,6 +283,10 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
if (!is_bounds_checks_enabled(module_inst_comm)) {
return true;
}
memory_inst = wasm_get_default_memory(module_inst);
if (!memory_inst) {
goto fail;
@ -299,6 +317,10 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
if (!is_bounds_checks_enabled(module_inst_comm)) {
return true;
}
if (!wasm_runtime_get_app_addr_range(module_inst_comm, app_str_offset, NULL,
&app_end_offset))
goto fail;
@ -327,6 +349,10 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
if (!is_bounds_checks_enabled(module_inst_comm)) {
return true;
}
memory_inst = wasm_get_default_memory(module_inst);
if (!memory_inst) {
goto fail;
@ -354,10 +380,13 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
WASMMemoryInstance *memory_inst;
uint8 *addr;
bool bounds_checks;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
bounds_checks = is_bounds_checks_enabled(module_inst_comm);
memory_inst = wasm_get_default_memory(module_inst);
if (!memory_inst) {
return NULL;
@ -365,8 +394,17 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
addr = memory_inst->memory_data + app_offset;
if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end)
if (bounds_checks) {
if (memory_inst->memory_data <= addr
&& addr < memory_inst->memory_data_end) {
return addr;
}
}
/* If bounds checks is disabled, return the address directly */
else if (app_offset != 0) {
return addr;
}
return NULL;
}
@ -378,17 +416,27 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
WASMMemoryInstance *memory_inst;
uint8 *addr = (uint8 *)native_ptr;
bool bounds_checks;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
bounds_checks = is_bounds_checks_enabled(module_inst_comm);
memory_inst = wasm_get_default_memory(module_inst);
if (!memory_inst) {
return 0;
}
if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end)
if (bounds_checks) {
if (memory_inst->memory_data <= addr
&& addr < memory_inst->memory_data_end)
return (uint32)(addr - memory_inst->memory_data);
}
/* If bounds checks is disabled, return the offset directly */
else if (addr != NULL) {
return (uint32)(addr - memory_inst->memory_data);
}
return 0;
}
@ -460,6 +508,7 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
{
WASMMemoryInstance *memory_inst = wasm_get_default_memory(module_inst);
uint8 *native_addr;
bool bounds_checks;
if (!memory_inst) {
goto fail;
@ -467,6 +516,15 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
native_addr = memory_inst->memory_data + app_buf_addr;
bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst);
if (!bounds_checks) {
if (app_buf_addr == 0) {
native_addr = NULL;
}
goto success;
}
/* No need to check the app_offset and buf_size if memory access
boundary check with hardware trap is enabled */
#ifndef OS_ENABLE_HW_BOUND_CHECK
@ -492,6 +550,7 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
}
#endif
success:
*p_native_addr = (void *)native_addr;
return true;
fail:
@ -514,13 +573,16 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
{
WASMMemoryInstance *memory = wasm_get_default_memory(module);
uint8 *memory_data_old, *memory_data_new, *heap_data_old;
uint32 num_bytes_per_page, heap_size, total_size_old;
uint32 num_bytes_per_page, heap_size, total_size_old = 0;
uint32 cur_page_count, max_page_count, total_page_count;
uint64 total_size_new;
bool ret = true;
enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR;
if (!memory)
return false;
if (!memory) {
ret = false;
goto return_func;
}
heap_data_old = memory->heap_data;
heap_size = (uint32)(memory->heap_data_end - memory->heap_data);
@ -538,9 +600,15 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
/* No need to enlarge memory */
return true;
if (total_page_count < cur_page_count /* integer overflow */
|| total_page_count > max_page_count) {
return false;
if (total_page_count < cur_page_count) { /* integer overflow */
ret = false;
goto return_func;
}
if (total_page_count > max_page_count) {
failure_reason = MAX_SIZE_REACHED;
ret = false;
goto return_func;
}
bh_assert(total_size_new <= 4 * (uint64)BH_GB);
@ -552,7 +620,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
}
#if WASM_ENABLE_SHARED_MEMORY != 0
if (memory->is_shared) {
if (shared_memory_is_shared(memory)) {
memory->num_bytes_per_page = num_bytes_per_page;
memory->cur_page_count = total_page_count;
memory->max_page_count = max_page_count;
@ -566,14 +634,16 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
if (heap_size > 0) {
if (mem_allocator_is_heap_corrupted(memory->heap_handle)) {
wasm_runtime_show_app_heap_corrupted_prompt();
return false;
ret = false;
goto return_func;
}
}
if (!(memory_data_new =
wasm_runtime_realloc(memory_data_old, (uint32)total_size_new))) {
if (!(memory_data_new = wasm_runtime_malloc((uint32)total_size_new))) {
return false;
ret = false;
goto return_func;
}
if (memory_data_old) {
bh_memcpy_s(memory_data_new, (uint32)total_size_new,
@ -629,6 +699,26 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
os_writegsbase(memory_data_new);
#endif
return_func:
if (!ret && enlarge_memory_error_cb) {
WASMExecEnv *exec_env = NULL;
#if WASM_ENABLE_INTERP != 0
if (module->module_type == Wasm_Module_Bytecode)
exec_env =
((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env;
#endif
#if WASM_ENABLE_AOT != 0
if (module->module_type == Wasm_Module_AoT)
exec_env =
((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env;
#endif
enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
failure_reason,
(WASMModuleInstanceCommon *)module, exec_env);
}
return ret;
}
#else
@ -636,12 +726,16 @@ bool
wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
{
WASMMemoryInstance *memory = wasm_get_default_memory(module);
uint32 num_bytes_per_page, total_size_old;
uint32 num_bytes_per_page, total_size_old = 0;
uint32 cur_page_count, max_page_count, total_page_count;
uint64 total_size_new;
bool ret = true;
enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR;
if (!memory)
return false;
if (!memory) {
ret = false;
goto return_func;
}
num_bytes_per_page = memory->num_bytes_per_page;
cur_page_count = memory->cur_page_count;
@ -654,9 +748,15 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
/* No need to enlarge memory */
return true;
if (total_page_count < cur_page_count /* integer overflow */
|| total_page_count > max_page_count) {
return false;
if (total_page_count < cur_page_count) { /* integer overflow */
ret = false;
goto return_func;
}
if (total_page_count > max_page_count) {
failure_reason = MAX_SIZE_REACHED;
ret = false;
goto return_func;
}
bh_assert(total_size_new <= 4 * (uint64)BH_GB);
@ -671,7 +771,8 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
if (!os_mem_commit(memory->memory_data_end,
(uint32)total_size_new - total_size_old,
MMAP_PROT_READ | MMAP_PROT_WRITE)) {
return false;
ret = false;
goto return_func;
}
#endif
@ -683,7 +784,8 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
os_mem_decommit(memory->memory_data_end,
(uint32)total_size_new - total_size_old);
#endif
return false;
ret = false;
goto return_func;
}
/* The increased pages are filled with zero by the OS when os_mmap,
@ -703,62 +805,51 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
#endif
return true;
return_func:
if (!ret && enlarge_memory_error_cb) {
WASMExecEnv *exec_env = NULL;
#if WASM_ENABLE_INTERP != 0
if (module->module_type == Wasm_Module_Bytecode)
exec_env =
((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env;
#endif
#if WASM_ENABLE_AOT != 0
if (module->module_type == Wasm_Module_AoT)
exec_env =
((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env;
#endif
enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
failure_reason,
(WASMModuleInstanceCommon *)module, exec_env);
}
return ret;
}
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
void
wasm_runtime_set_enlarge_mem_error_callback(
const enlarge_memory_error_callback_t callback)
{
enlarge_memory_error_cb = callback;
}
bool
wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
{
bool ret = false;
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
if (node)
os_mutex_lock(&node->shared_mem_lock);
if (module->memory_count > 0)
shared_memory_lock(module->memories[0]);
#endif
ret = wasm_enlarge_memory_internal(module, inc_page_count);
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&node->shared_mem_lock);
if (module->memory_count > 0)
shared_memory_unlock(module->memories[0]);
#endif
return ret;
}
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|| WASM_ENABLE_BULK_MEMORY != 0
uint32
wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node)
{
uint32 num_bytes_per_page;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock);
#endif
num_bytes_per_page = memory->num_bytes_per_page;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock);
#endif
return num_bytes_per_page;
}
uint32
wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node)
{
uint32 linear_mem_size;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock);
#endif
linear_mem_size = memory->num_bytes_per_page * memory->cur_page_count;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock);
#endif
return linear_mem_size;
}
#endif

View File

@ -24,15 +24,9 @@ wasm_runtime_memory_destroy();
unsigned
wasm_runtime_memory_pool_size();
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|| WASM_ENABLE_BULK_MEMORY != 0
uint32
wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node);
uint32
wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node);
#endif
void
wasm_runtime_set_enlarge_mem_error_callback(
const enlarge_memory_error_callback_t callback);
#ifdef __cplusplus
}

View File

@ -6,6 +6,15 @@
#include "wasm_native.h"
#include "wasm_runtime_common.h"
#include "bh_log.h"
#if WASM_ENABLE_INTERP != 0
#include "../interpreter/wasm_runtime.h"
#endif
#if WASM_ENABLE_AOT != 0
#include "../aot/aot_runtime.h"
#endif
#if WASM_ENABLE_THREAD_MGR != 0
#include "../libraries/thread-mgr/thread_manager.h"
#endif
#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \
&& !defined(BH_PLATFORM_OPENRTOS) && !defined(BH_PLATFORM_ESP_IDF)
@ -22,6 +31,10 @@
static NativeSymbolsList g_native_symbols_list = NULL;
#if WASM_ENABLE_LIBC_WASI != 0
static void *g_wasi_context_key;
#endif /* WASM_ENABLE_LIBC_WASI */
uint32
get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
@ -394,6 +407,155 @@ wasm_native_unregister_natives(const char *module_name,
return false;
}
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
static uint32
context_key_to_idx(void *key)
{
bh_assert(key != NULL);
uint32 idx = (uint32)(uintptr_t)key;
bh_assert(idx > 0);
bh_assert(idx <= WASM_MAX_INSTANCE_CONTEXTS);
return idx - 1;
}
static void *
context_idx_to_key(uint32 idx)
{
bh_assert(idx < WASM_MAX_INSTANCE_CONTEXTS);
return (void *)(uintptr_t)(idx + 1);
}
typedef void (*dtor_t)(WASMModuleInstanceCommon *, void *);
static dtor_t g_context_dtors[WASM_MAX_INSTANCE_CONTEXTS];
static void
dtor_noop(WASMModuleInstanceCommon *inst, void *ctx)
{}
void *
wasm_native_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
void *ctx))
{
uint32 i;
for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) {
if (g_context_dtors[i] == NULL) {
if (dtor == NULL) {
dtor = dtor_noop;
}
g_context_dtors[i] = dtor;
return context_idx_to_key(i);
}
}
LOG_ERROR("failed to allocate instance context key");
return NULL;
}
void
wasm_native_destroy_context_key(void *key)
{
uint32 idx = context_key_to_idx(key);
bh_assert(g_context_dtors[idx] != NULL);
g_context_dtors[idx] = NULL;
}
static WASMModuleInstanceExtraCommon *
wasm_module_inst_extra_common(WASMModuleInstanceCommon *inst)
{
#if WASM_ENABLE_INTERP != 0
if (inst->module_type == Wasm_Module_Bytecode) {
return &((WASMModuleInstance *)inst)->e->common;
}
#endif
#if WASM_ENABLE_AOT != 0
if (inst->module_type == Wasm_Module_AoT) {
return &((AOTModuleInstanceExtra *)((AOTModuleInstance *)inst)->e)
->common;
}
#endif
bh_assert(false);
return NULL;
}
void
wasm_native_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx)
{
uint32 idx = context_key_to_idx(key);
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
common->contexts[idx] = ctx;
}
void
wasm_native_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
void *ctx)
{
#if WASM_ENABLE_THREAD_MGR != 0
wasm_cluster_set_context(inst, key, ctx);
#else
wasm_native_set_context(inst, key, ctx);
#endif
}
void *
wasm_native_get_context(WASMModuleInstanceCommon *inst, void *key)
{
uint32 idx = context_key_to_idx(key);
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
return common->contexts[idx];
}
void
wasm_native_call_context_dtors(WASMModuleInstanceCommon *inst)
{
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
uint32 i;
for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) {
dtor_t dtor = g_context_dtors[i];
if (dtor != NULL) {
dtor(inst, common->contexts[i]);
}
}
}
void
wasm_native_inherit_contexts(WASMModuleInstanceCommon *child,
WASMModuleInstanceCommon *parent)
{
WASMModuleInstanceExtraCommon *parent_common =
wasm_module_inst_extra_common(parent);
WASMModuleInstanceExtraCommon *child_common =
wasm_module_inst_extra_common(child);
bh_memcpy_s(child_common->contexts,
sizeof(*child_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS,
parent_common->contexts,
sizeof(*parent_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS);
}
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
#if WASM_ENABLE_LIBC_WASI != 0
WASIContext *
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
{
return wasm_native_get_context(module_inst_comm, g_wasi_context_key);
}
void
wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
WASIContext *wasi_ctx)
{
return wasm_native_set_context(module_inst_comm, g_wasi_context_key,
wasi_ctx);
}
static void
wasi_context_dtor(WASMModuleInstanceCommon *inst, void *ctx)
{
if (ctx == NULL) {
return;
}
wasm_runtime_destroy_wasi(inst);
}
#endif /* end of WASM_ENABLE_LIBC_WASI */
bool
wasm_native_init()
{
@ -420,6 +582,10 @@ wasm_native_init()
#endif /* WASM_ENABLE_SPEC_TEST */
#if WASM_ENABLE_LIBC_WASI != 0
g_wasi_context_key = wasm_native_create_context_key(wasi_context_dtor);
if (g_wasi_context_key == NULL) {
goto fail;
}
n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
if (!wasm_native_register_natives("wasi_unstable", native_symbols,
n_native_symbols))
@ -507,6 +673,12 @@ wasm_native_destroy()
{
NativeSymbolsNode *node, *node_next;
#if WASM_ENABLE_LIBC_WASI != 0
if (g_wasi_context_key != NULL) {
wasm_native_destroy_context_key(g_wasi_context_key);
g_wasi_context_key = NULL;
}
#endif
#if WASM_ENABLE_LIB_PTHREAD != 0
lib_pthread_destroy();
#endif

View File

@ -68,6 +68,36 @@ bool
wasm_native_unregister_natives(const char *module_name,
NativeSymbol *native_symbols);
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
struct WASMModuleInstanceCommon;
void *
wasm_native_create_context_key(
void (*dtor)(struct WASMModuleInstanceCommon *inst, void *ctx));
void
wasm_native_destroy_context_key(void *key);
void
wasm_native_set_context(struct WASMModuleInstanceCommon *inst, void *key,
void *ctx);
void
wasm_native_set_context_spread(struct WASMModuleInstanceCommon *inst, void *key,
void *ctx);
void *
wasm_native_get_context(struct WASMModuleInstanceCommon *inst, void *key);
void
wasm_native_call_context_dtors(struct WASMModuleInstanceCommon *inst);
void
wasm_native_inherit_contexts(struct WASMModuleInstanceCommon *child,
struct WASMModuleInstanceCommon *parent);
#else /* WASM_ENABLE_MODULE_INST_CONTEXT */
#define wasm_native_call_context_dtors(inst) (void)(inst)
#define wasm_native_inherit_contexts(child, parent) (void)(parent)
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT */
bool
wasm_native_init();

View File

@ -199,7 +199,90 @@ runtime_signal_handler(void *sig_addr)
}
}
}
#else
#else /* else of BH_PLATFORM_WINDOWS */
#if WASM_ENABLE_AOT != 0
#include <Zydis/Zydis.h>
static uint32
decode_insn(uint8 *insn)
{
uint8 *data = (uint8 *)insn;
uint32 length = 32; /* reserve enough size */
/* Initialize decoder context */
ZydisDecoder decoder;
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64,
ZYDIS_STACK_WIDTH_64);
/* Initialize formatter */
ZydisFormatter formatter;
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
/* Loop over the instructions in our buffer */
ZyanU64 runtime_address = (ZyanU64)(uintptr_t)data;
ZyanUSize offset = 0;
ZydisDecodedInstruction instruction;
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
char buffer[256];
if (ZYAN_SUCCESS(ZydisDecoderDecodeFull(
&decoder, data + offset, length - offset, &instruction, operands,
ZYDIS_MAX_OPERAND_COUNT_VISIBLE,
ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY))) {
/* Format & print the binary instruction structure to
human readable format */
ZydisFormatterFormatInstruction(&formatter, &instruction, operands,
instruction.operand_count_visible,
buffer, sizeof(buffer),
runtime_address);
/* Print current instruction */
/*
os_printf("%012" PRIX64 " ", runtime_address);
puts(buffer);
*/
return instruction.length;
}
/* Decode failed */
return 0;
}
#endif /* end of WASM_ENABLE_AOT != 0 */
static LONG
next_action(WASMModuleInstance *module_inst, EXCEPTION_POINTERS *exce_info)
{
#if WASM_ENABLE_AOT != 0
uint32 insn_size;
#endif
if (module_inst->module_type == Wasm_Module_Bytecode
&& module_inst->e->running_mode == Mode_Interp) {
/* Continue to search next exception handler for
interpreter mode as it can be caught by
`__try { .. } __except { .. }` sentences in
wasm_runtime.c */
return EXCEPTION_CONTINUE_SEARCH;
}
#if WASM_ENABLE_AOT != 0
/* Skip current instruction and continue to run for AOT/JIT mode.
TODO: implement unwind support for AOT/JIT code in Windows platform */
insn_size = decode_insn((uint8 *)exce_info->ContextRecord->Rip);
if (insn_size > 0) {
exce_info->ContextRecord->Rip += insn_size;
return EXCEPTION_CONTINUE_EXECUTION;
}
#endif
/* return different value from EXCEPTION_CONTINUE_SEARCH (= 0)
and EXCEPTION_CONTINUE_EXECUTION (= -1) */
return -2;
}
static LONG
runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
{
@ -211,6 +294,7 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
uint8 *mapped_mem_start_addr = NULL;
uint8 *mapped_mem_end_addr = NULL;
uint32 page_size = os_getpagesize();
LONG ret;
if (exec_env_tls && exec_env_tls->handle == os_self_thread()
&& (jmpbuf_node = exec_env_tls->jmpbuf_stack_top)) {
@ -232,32 +316,19 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
the wasm func returns, the caller will check whether the
exception is thrown and return to runtime. */
wasm_set_exception(module_inst, "out of bounds memory access");
if (module_inst->module_type == Wasm_Module_Bytecode) {
/* Continue to search next exception handler for
interpreter mode as it can be caught by
`__try { .. } __except { .. }` sentences in
wasm_runtime.c */
return EXCEPTION_CONTINUE_SEARCH;
}
else {
/* Skip current instruction and continue to run for
AOT mode. TODO: implement unwind support for AOT
code in Windows platform */
exce_info->ContextRecord->Rip++;
return EXCEPTION_CONTINUE_EXECUTION;
}
ret = next_action(module_inst, exce_info);
if (ret == EXCEPTION_CONTINUE_SEARCH
|| ret == EXCEPTION_CONTINUE_EXECUTION)
return ret;
}
else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr
&& (uint8 *)sig_addr
< exec_env_tls->exce_check_guard_page + page_size) {
bh_assert(wasm_copy_exception(module_inst, NULL));
if (module_inst->module_type == Wasm_Module_Bytecode) {
return EXCEPTION_CONTINUE_SEARCH;
}
else {
exce_info->ContextRecord->Rip++;
return EXCEPTION_CONTINUE_EXECUTION;
}
ret = next_action(module_inst, exce_info);
if (ret == EXCEPTION_CONTINUE_SEARCH
|| ret == EXCEPTION_CONTINUE_EXECUTION)
return ret;
}
}
#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
@ -267,12 +338,10 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
whether the exception is thrown and return to runtime, and
the damaged stack will be recovered by _resetstkoflw(). */
wasm_set_exception(module_inst, "native stack overflow");
if (module_inst->module_type == Wasm_Module_Bytecode) {
return EXCEPTION_CONTINUE_SEARCH;
}
else {
return EXCEPTION_CONTINUE_EXECUTION;
}
ret = next_action(module_inst, exce_info);
if (ret == EXCEPTION_CONTINUE_SEARCH
|| ret == EXCEPTION_CONTINUE_EXECUTION)
return ret;
}
#endif
}
@ -1196,7 +1265,8 @@ wasm_runtime_unload(WASMModuleCommon *module)
}
WASMModuleInstanceCommon *
wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
wasm_runtime_instantiate_internal(WASMModuleCommon *module,
WASMModuleInstanceCommon *parent,
WASMExecEnv *exec_env_main, uint32 stack_size,
uint32 heap_size, char *error_buf,
uint32 error_buf_size)
@ -1204,14 +1274,14 @@ wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
#if WASM_ENABLE_INTERP != 0
if (module->module_type == Wasm_Module_Bytecode)
return (WASMModuleInstanceCommon *)wasm_instantiate(
(WASMModule *)module, is_sub_inst, exec_env_main, stack_size,
heap_size, error_buf, error_buf_size);
(WASMModule *)module, (WASMModuleInstance *)parent, exec_env_main,
stack_size, heap_size, error_buf, error_buf_size);
#endif
#if WASM_ENABLE_AOT != 0
if (module->module_type == Wasm_Module_AoT)
return (WASMModuleInstanceCommon *)aot_instantiate(
(AOTModule *)module, is_sub_inst, exec_env_main, stack_size,
heap_size, error_buf, error_buf_size);
(AOTModule *)module, (AOTModuleInstance *)parent, exec_env_main,
stack_size, heap_size, error_buf, error_buf_size);
#endif
set_error_buf(error_buf, error_buf_size,
"Instantiate module failed, invalid module type");
@ -1224,7 +1294,7 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size,
uint32 error_buf_size)
{
return wasm_runtime_instantiate_internal(
module, false, NULL, stack_size, heap_size, error_buf, error_buf_size);
module, NULL, NULL, stack_size, heap_size, error_buf, error_buf_size);
}
void
@ -1868,33 +1938,6 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
}
#endif
static bool
clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm)
{
#if WASM_ENABLE_LIBC_WASI != 0
bool has_exception;
char exception[EXCEPTION_BUF_LEN];
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
has_exception = wasm_copy_exception(module_inst, exception);
if (has_exception && !strcmp(exception, "Exception: wasi proc exit")) {
/* The "wasi proc exit" exception is thrown by native lib to
let wasm app exit, which is a normal behavior, we clear
the exception here. And just clear the exception of current
thread, don't call `wasm_set_exception(module_inst, NULL)`
which will clear the exception of all threads. */
module_inst->cur_exception[0] = '\0';
return true;
}
return false;
#else
return false;
#endif
}
bool
wasm_runtime_call_wasm(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function, uint32 argc,
@ -1935,15 +1978,10 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
param_argc, new_argv);
#endif
if (!ret) {
if (clear_wasi_proc_exit_exception(exec_env->module_inst)) {
ret = true;
}
else {
if (new_argv != argv) {
wasm_runtime_free(new_argv);
}
return false;
if (new_argv != argv) {
wasm_runtime_free(new_argv);
}
return false;
}
#if WASM_ENABLE_REF_TYPES != 0
@ -2307,14 +2345,7 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm)
void
wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
{
WASMExecEnv *exec_env = NULL;
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module);
if (node)
os_mutex_lock(&node->shared_mem_lock);
#endif
exception_lock(module_inst);
if (exception) {
snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception),
"Exception: %s", exception);
@ -2322,19 +2353,14 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
else {
module_inst->cur_exception[0] = '\0';
}
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&node->shared_mem_lock);
#endif
exception_unlock(module_inst);
#if WASM_ENABLE_THREAD_MGR != 0
exec_env =
WASMExecEnv *exec_env =
wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst);
if (exec_env) {
wasm_cluster_spread_exception(exec_env, exception ? false : true);
wasm_cluster_spread_exception(exec_env, exception);
}
#else
(void)exec_env;
#endif
}
@ -2385,12 +2411,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
{
bool has_exception = false;
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module);
if (node)
os_mutex_lock(&node->shared_mem_lock);
#endif
exception_lock(module_inst);
if (module_inst->cur_exception[0] != '\0') {
/* NULL is passed if the caller is not interested in getting the
* exception content, but only in knowing if an exception has been
@ -2402,10 +2423,7 @@ wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
sizeof(module_inst->cur_exception));
has_exception = true;
}
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&node->shared_mem_lock);
#endif
exception_unlock(module_inst);
return has_exception;
}
@ -2482,6 +2500,54 @@ wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst_comm)
return module_inst->custom_data;
}
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
void
wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst,
bool enable)
{
/* Alwary disable bounds checks if hw bounds checks enabled */
#ifdef OS_ENABLE_HW_BOUND_CHECK
enable = false;
#endif
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e)
->common.disable_bounds_checks = enable ? false : true;
}
#endif
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e)
->common.disable_bounds_checks = enable ? false : true;
}
#endif
}
bool
wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst)
{
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
return !((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)
->e)
->common.disable_bounds_checks;
}
#endif
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
return !((AOTModuleInstanceExtra *)((WASMModuleInstance *)module_inst)
->e)
->common.disable_bounds_checks;
}
#endif
return true;
}
#endif
uint32
wasm_runtime_module_malloc_internal(WASMModuleInstanceCommon *module_inst,
WASMExecEnv *exec_env, uint32 size,
@ -3213,27 +3279,6 @@ wasm_runtime_get_wasi_exit_code(WASMModuleInstanceCommon *module_inst)
#endif
return wasi_ctx->exit_code;
}
WASIContext *
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
{
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
return module_inst->wasi_ctx;
}
void
wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
WASIContext *wasi_ctx)
{
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
module_inst->wasi_ctx = wasi_ctx;
}
#endif /* end of WASM_ENABLE_LIBC_WASI */
WASMModuleCommon *
@ -4496,10 +4541,6 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_index,
ret = aot_call_indirect(exec_env, 0, element_index, argc, argv);
#endif
if (!ret && clear_wasi_proc_exit_exception(exec_env->module_inst)) {
ret = true;
}
return ret;
}
@ -4636,6 +4677,8 @@ typedef struct ExternRefMapNode {
bool retained;
/* Whether it is marked by runtime */
bool marked;
/* cleanup function called when the externref is freed */
void (*cleanup)(void *);
} ExternRefMapNode;
static uint32
@ -4698,6 +4741,81 @@ lookup_extobj_callback(void *key, void *value, void *user_data)
}
}
static void
delete_externref(void *key, ExternRefMapNode *node)
{
bh_hash_map_remove(externref_map, key, NULL, NULL);
if (node->cleanup) {
(*node->cleanup)(node->extern_obj);
}
wasm_runtime_free(node);
}
static void
delete_extobj_callback(void *key, void *value, void *user_data)
{
ExternRefMapNode *node = (ExternRefMapNode *)value;
LookupExtObj_UserData *lookup_user_data =
(LookupExtObj_UserData *)user_data;
if (node->extern_obj == lookup_user_data->node.extern_obj
&& node->module_inst == lookup_user_data->node.module_inst) {
lookup_user_data->found = true;
delete_externref(key, node);
}
}
bool
wasm_externref_objdel(WASMModuleInstanceCommon *module_inst, void *extern_obj)
{
LookupExtObj_UserData lookup_user_data = { 0 };
bool ok = false;
/* in a wrapper, extern_obj could be any value */
lookup_user_data.node.extern_obj = extern_obj;
lookup_user_data.node.module_inst = module_inst;
lookup_user_data.found = false;
os_mutex_lock(&externref_lock);
/* Lookup hashmap firstly */
bh_hash_map_traverse(externref_map, delete_extobj_callback,
(void *)&lookup_user_data);
if (lookup_user_data.found) {
ok = true;
}
os_mutex_unlock(&externref_lock);
return ok;
}
bool
wasm_externref_set_cleanup(WASMModuleInstanceCommon *module_inst,
void *extern_obj, void (*extern_obj_cleanup)(void *))
{
LookupExtObj_UserData lookup_user_data = { 0 };
bool ok = false;
/* in a wrapper, extern_obj could be any value */
lookup_user_data.node.extern_obj = extern_obj;
lookup_user_data.node.module_inst = module_inst;
lookup_user_data.found = false;
os_mutex_lock(&externref_lock);
/* Lookup hashmap firstly */
bh_hash_map_traverse(externref_map, lookup_extobj_callback,
(void *)&lookup_user_data);
if (lookup_user_data.found) {
void *key = (void *)(uintptr_t)lookup_user_data.externref_idx;
ExternRefMapNode *node = bh_hash_map_find(externref_map, key);
node->cleanup = extern_obj_cleanup;
ok = true;
}
os_mutex_unlock(&externref_lock);
return ok;
}
bool
wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
uint32 *p_externref_idx)
@ -4747,6 +4865,7 @@ wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
memset(node, 0, sizeof(ExternRefMapNode));
node->extern_obj = extern_obj;
node->module_inst = module_inst;
node->cleanup = NULL;
externref_idx = externref_global_id;
@ -4797,8 +4916,7 @@ reclaim_extobj_callback(void *key, void *value, void *user_data)
if (node->module_inst == module_inst) {
if (!node->marked && !node->retained) {
bh_hash_map_remove(externref_map, key, NULL, NULL);
wasm_runtime_free(value);
delete_externref(key, node);
}
else {
node->marked = false;
@ -4913,8 +5031,7 @@ cleanup_extobj_callback(void *key, void *value, void *user_data)
(WASMModuleInstanceCommon *)user_data;
if (node->module_inst == module_inst) {
bh_hash_map_remove(externref_map, key, NULL, NULL);
wasm_runtime_free(value);
delete_externref(key, node);
}
}
@ -5507,3 +5624,37 @@ wasm_runtime_is_import_global_linked(const char *module_name,
return false;
#endif
}
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
void *
wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
void *ctx))
{
return wasm_native_create_context_key(dtor);
}
void
wasm_runtime_destroy_context_key(void *key)
{
wasm_native_destroy_context_key(key);
}
void
wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx)
{
wasm_native_set_context(inst, key, ctx);
}
void
wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
void *ctx)
{
wasm_native_set_context_spread(inst, key, ctx);
}
void *
wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key)
{
return wasm_native_get_context(inst, key);
}
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */

View File

@ -498,7 +498,8 @@ wasm_runtime_unload(WASMModuleCommon *module);
/* Internal API */
WASMModuleInstanceCommon *
wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
wasm_runtime_instantiate_internal(WASMModuleCommon *module,
WASMModuleInstanceCommon *parent,
WASMExecEnv *exec_env_main, uint32 stack_size,
uint32 heap_size, char *error_buf,
uint32 error_buf_size);
@ -593,6 +594,17 @@ wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data);
WASM_RUNTIME_API_EXTERN void *
wasm_runtime_get_user_data(WASMExecEnv *exec_env);
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst,
bool enable);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst);
#endif
#ifdef OS_ENABLE_HW_BOUND_CHECK
/* Access exception check guard page to trigger the signal handler */
void
@ -927,6 +939,26 @@ WASM_RUNTIME_API_EXTERN bool
wasm_runtime_unregister_natives(const char *module_name,
NativeSymbol *native_symbols);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void *
wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
void *ctx));
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void
wasm_runtime_destroy_context_key(void *key);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
void *ctx);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void *
wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key);
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
const WASMType *func_type, const char *signature,

View File

@ -9,9 +9,16 @@
#include "../libraries/thread-mgr/thread_manager.h"
#endif
static bh_list shared_memory_list_head;
static bh_list *const shared_memory_list = &shared_memory_list_head;
static korp_mutex shared_memory_list_lock;
/*
* Note: this lock can be per memory.
*
* For now, just use a global because:
* - it's a bit cumbersome to extend WASMMemoryInstance w/o breaking
* the AOT ABI.
* - If you care performance, it's better to make the interpreters
* use atomic ops.
*/
static korp_mutex _shared_memory_lock;
/* clang-format off */
enum {
@ -37,7 +44,7 @@ typedef struct AtomicWaitNode {
static HashMap *wait_map;
static uint32
wait_address_hash(void *address);
wait_address_hash(const void *address);
static bool
wait_address_equal(void *h1, void *h2);
@ -48,17 +55,15 @@ destroy_wait_info(void *wait_info);
bool
wasm_shared_memory_init()
{
if (os_mutex_init(&shared_memory_list_lock) != 0)
if (os_mutex_init(&_shared_memory_lock) != 0)
return false;
/* wait map not exists, create new map */
if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash,
(KeyEqualFunc)wait_address_equal, NULL,
destroy_wait_info))) {
os_mutex_destroy(&shared_memory_list_lock);
os_mutex_destroy(&_shared_memory_lock);
return false;
}
return true;
}
@ -66,115 +71,84 @@ void
wasm_shared_memory_destroy()
{
bh_hash_map_destroy(wait_map);
os_mutex_destroy(&shared_memory_list_lock);
os_mutex_destroy(&_shared_memory_lock);
}
static WASMSharedMemNode *
search_module(WASMModuleCommon *module)
uint32
shared_memory_inc_reference(WASMMemoryInstance *memory)
{
WASMSharedMemNode *node;
os_mutex_lock(&shared_memory_list_lock);
node = bh_list_first_elem(shared_memory_list);
while (node) {
if (module == node->module) {
os_mutex_unlock(&shared_memory_list_lock);
return node;
}
node = bh_list_elem_next(node);
}
os_mutex_unlock(&shared_memory_list_lock);
return NULL;
bh_assert(shared_memory_is_shared(memory));
uint32 old;
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_lock(&_shared_memory_lock);
#endif
old = BH_ATOMIC_32_FETCH_ADD(memory->ref_count, 1);
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_unlock(&_shared_memory_lock);
#endif
bh_assert(old >= 1);
bh_assert(old < UINT32_MAX);
return old + 1;
}
WASMSharedMemNode *
wasm_module_get_shared_memory(WASMModuleCommon *module)
uint32
shared_memory_dec_reference(WASMMemoryInstance *memory)
{
return search_module(module);
bh_assert(shared_memory_is_shared(memory));
uint32 old;
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_lock(&_shared_memory_lock);
#endif
old = BH_ATOMIC_32_FETCH_SUB(memory->ref_count, 1);
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_unlock(&_shared_memory_lock);
#endif
bh_assert(old > 0);
return old - 1;
}
int32
shared_memory_inc_reference(WASMModuleCommon *module)
bool
shared_memory_is_shared(WASMMemoryInstance *memory)
{
WASMSharedMemNode *node = search_module(module);
uint32 ref_count = -1;
if (node) {
os_mutex_lock(&node->lock);
ref_count = ++node->ref_count;
os_mutex_unlock(&node->lock);
}
return ref_count;
uint32 old;
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_lock(&_shared_memory_lock);
#endif
old = BH_ATOMIC_32_LOAD(memory->ref_count);
#if BH_ATOMIC_32_IS_ATOMIC == 0
os_mutex_unlock(&_shared_memory_lock);
#endif
return old > 0;
}
int32
shared_memory_dec_reference(WASMModuleCommon *module)
static korp_mutex *
shared_memory_get_lock_pointer(WASMMemoryInstance *memory)
{
WASMSharedMemNode *node = search_module(module);
uint32 ref_count = 0;
if (node) {
os_mutex_lock(&node->lock);
ref_count = --node->ref_count;
os_mutex_unlock(&node->lock);
if (ref_count == 0) {
os_mutex_lock(&shared_memory_list_lock);
bh_list_remove(shared_memory_list, node);
os_mutex_unlock(&shared_memory_list_lock);
os_mutex_destroy(&node->shared_mem_lock);
os_mutex_destroy(&node->lock);
wasm_runtime_free(node);
}
return ref_count;
}
return -1;
bh_assert(memory != NULL);
return &_shared_memory_lock;
}
WASMMemoryInstanceCommon *
shared_memory_get_memory_inst(WASMSharedMemNode *node)
void
shared_memory_lock(WASMMemoryInstance *memory)
{
return node->memory_inst;
/*
* Note: exception logic is currently abusing this lock.
* cf. https://github.com/bytecodealliance/wasm-micro-runtime/issues/2407
*/
bh_assert(memory != NULL);
os_mutex_lock(&_shared_memory_lock);
}
WASMSharedMemNode *
shared_memory_set_memory_inst(WASMModuleCommon *module,
WASMMemoryInstanceCommon *memory)
void
shared_memory_unlock(WASMMemoryInstance *memory)
{
WASMSharedMemNode *node;
bh_list_status ret;
if (!(node = wasm_runtime_malloc(sizeof(WASMSharedMemNode))))
return NULL;
node->module = module;
node->memory_inst = memory;
node->ref_count = 1;
if (os_mutex_init(&node->shared_mem_lock) != 0) {
wasm_runtime_free(node);
return NULL;
}
if (os_mutex_init(&node->lock) != 0) {
os_mutex_destroy(&node->shared_mem_lock);
wasm_runtime_free(node);
return NULL;
}
os_mutex_lock(&shared_memory_list_lock);
ret = bh_list_insert(shared_memory_list, node);
bh_assert(ret == BH_LIST_SUCCESS);
os_mutex_unlock(&shared_memory_list_lock);
(void)ret;
return node;
bh_assert(memory != NULL);
os_mutex_unlock(&_shared_memory_lock);
}
/* Atomics wait && notify APIs */
static uint32
wait_address_hash(void *address)
wait_address_hash(const void *address)
{
return (uint32)(uintptr_t)address;
}
@ -307,7 +281,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
AtomicWaitInfo *wait_info;
AtomicWaitNode *wait_node;
WASMSharedMemNode *node;
korp_mutex *lock;
#if WASM_ENABLE_THREAD_MGR != 0
WASMExecEnv *exec_env;
#endif
@ -322,7 +296,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
}
/* Currently we have only one memory instance */
if (!module_inst->memories[0]->is_shared) {
if (!shared_memory_is_shared(module_inst->memories[0])) {
wasm_runtime_set_exception(module, "expected shared memory");
return -1;
}
@ -340,30 +314,29 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
bh_assert(exec_env);
#endif
node = search_module((WASMModuleCommon *)module_inst->module);
bh_assert(node);
lock = shared_memory_get_lock_pointer(module_inst->memories[0]);
/* Lock the shared_mem_lock for the whole atomic wait process,
and use it to os_cond_reltimedwait */
os_mutex_lock(&node->shared_mem_lock);
os_mutex_lock(lock);
no_wait = (!wait64 && *(uint32 *)address != (uint32)expect)
|| (wait64 && *(uint64 *)address != expect);
if (no_wait) {
os_mutex_unlock(&node->shared_mem_lock);
os_mutex_unlock(lock);
return 1;
}
if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) {
os_mutex_unlock(&node->shared_mem_lock);
os_mutex_unlock(lock);
wasm_runtime_set_exception(module, "failed to create wait node");
return -1;
}
memset(wait_node, 0, sizeof(AtomicWaitNode));
if (0 != os_cond_init(&wait_node->wait_cond)) {
os_mutex_unlock(&node->shared_mem_lock);
os_mutex_unlock(lock);
wasm_runtime_free(wait_node);
wasm_runtime_set_exception(module, "failed to init wait cond");
return -1;
@ -375,7 +348,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
wait_info = acquire_wait_info(address, wait_node);
if (!wait_info) {
os_mutex_unlock(&node->shared_mem_lock);
os_mutex_unlock(lock);
os_cond_destroy(&wait_node->wait_cond);
wasm_runtime_free(wait_node);
wasm_runtime_set_exception(module, "failed to acquire wait_info");
@ -390,7 +363,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
if (timeout < 0) {
/* wait forever until it is notified or terminatied
here we keep waiting and checking every second */
os_cond_reltimedwait(&wait_node->wait_cond, &node->shared_mem_lock,
os_cond_reltimedwait(&wait_node->wait_cond, lock,
(uint64)timeout_1sec);
if (wait_node->status == S_NOTIFIED /* notified by atomic.notify */
#if WASM_ENABLE_THREAD_MGR != 0
@ -404,8 +377,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
else {
timeout_wait =
timeout_left < timeout_1sec ? timeout_left : timeout_1sec;
os_cond_reltimedwait(&wait_node->wait_cond, &node->shared_mem_lock,
timeout_wait);
os_cond_reltimedwait(&wait_node->wait_cond, lock, timeout_wait);
if (wait_node->status == S_NOTIFIED /* notified by atomic.notify */
|| timeout_left <= timeout_wait /* time out */
#if WASM_ENABLE_THREAD_MGR != 0
@ -433,7 +405,7 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
/* Release wait info if no wait nodes are attached */
map_try_release_wait_info(wait_map, wait_info, address);
os_mutex_unlock(&node->shared_mem_lock);
os_mutex_unlock(lock);
return is_timeout ? 2 : 0;
}
@ -445,7 +417,7 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
uint32 notify_result;
AtomicWaitInfo *wait_info;
WASMSharedMemNode *node;
korp_mutex *lock;
bool out_of_bounds;
bh_assert(module->module_type == Wasm_Module_Bytecode
@ -461,31 +433,30 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
}
/* Currently we have only one memory instance */
if (!module_inst->memories[0]->is_shared) {
if (!shared_memory_is_shared(module_inst->memories[0])) {
/* Always return 0 for ushared linear memory since there is
no way to create a waiter on it */
return 0;
}
node = search_module((WASMModuleCommon *)module_inst->module);
bh_assert(node);
lock = shared_memory_get_lock_pointer(module_inst->memories[0]);
/* Lock the shared_mem_lock for the whole atomic notify process,
and use it to os_cond_signal */
os_mutex_lock(&node->shared_mem_lock);
os_mutex_lock(lock);
wait_info = acquire_wait_info(address, NULL);
/* Nobody wait on this address */
if (!wait_info) {
os_mutex_unlock(&node->shared_mem_lock);
os_mutex_unlock(lock);
return 0;
}
/* Notify each wait node in the wait list */
notify_result = notify_wait_list(wait_info->wait_list, count);
os_mutex_unlock(&node->shared_mem_lock);
os_mutex_unlock(lock);
return notify_result;
}

View File

@ -7,53 +7,33 @@
#define _WASM_SHARED_MEMORY_H
#include "bh_common.h"
#if WASM_ENABLE_INTERP != 0
#include "wasm_runtime.h"
#endif
#if WASM_ENABLE_AOT != 0
#include "aot_runtime.h"
#endif
#include "../interpreter/wasm_runtime.h"
#include "wasm_runtime_common.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct WASMSharedMemNode {
bh_list_link l;
/* Lock */
korp_mutex lock;
/* The module reference */
WASMModuleCommon *module;
/* The memory information */
WASMMemoryInstanceCommon *memory_inst;
/* Lock used for atomic operations */
korp_mutex shared_mem_lock;
/* reference count */
uint32 ref_count;
} WASMSharedMemNode;
bool
wasm_shared_memory_init();
void
wasm_shared_memory_destroy();
WASMSharedMemNode *
wasm_module_get_shared_memory(WASMModuleCommon *module);
uint32
shared_memory_inc_reference(WASMMemoryInstance *memory);
int32
shared_memory_inc_reference(WASMModuleCommon *module);
uint32
shared_memory_dec_reference(WASMMemoryInstance *memory);
int32
shared_memory_dec_reference(WASMModuleCommon *module);
bool
shared_memory_is_shared(WASMMemoryInstance *memory);
WASMMemoryInstanceCommon *
shared_memory_get_memory_inst(WASMSharedMemNode *node);
void
shared_memory_lock(WASMMemoryInstance *memory);
WASMSharedMemNode *
shared_memory_set_memory_inst(WASMModuleCommon *module,
WASMMemoryInstanceCommon *memory);
void
shared_memory_unlock(WASMMemoryInstance *memory);
uint32
wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2023 Amazon Inc. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _WASM_SUSPEND_FLAGS_H
#define _WASM_SUSPEND_FLAGS_H
#include "bh_atomic.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Need to terminate */
#define WASM_SUSPEND_FLAG_TERMINATE 0x1
/* Need to suspend */
#define WASM_SUSPEND_FLAG_SUSPEND 0x2
/* Need to go into breakpoint */
#define WASM_SUSPEND_FLAG_BREAKPOINT 0x4
/* Return from pthread_exit */
#define WASM_SUSPEND_FLAG_EXIT 0x8
typedef union WASMSuspendFlags {
bh_atomic_32_t flags;
uintptr_t __padding__;
} WASMSuspendFlags;
#define WASM_SUSPEND_FLAGS_IS_ATOMIC BH_ATOMIC_32_IS_ATOMIC
#define WASM_SUSPEND_FLAGS_GET(s_flags) BH_ATOMIC_32_LOAD(s_flags.flags)
#define WASM_SUSPEND_FLAGS_FETCH_OR(s_flags, val) \
BH_ATOMIC_32_FETCH_OR(s_flags.flags, val)
#define WASM_SUSPEND_FLAGS_FETCH_AND(s_flags, val) \
BH_ATOMIC_32_FETCH_AND(s_flags.flags, val)
#if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0
#define WASM_SUSPEND_FLAGS_LOCK(lock) (void)0
#define WASM_SUSPEND_FLAGS_UNLOCK(lock) (void)0
#else /* else of WASM_SUSPEND_FLAGS_IS_ATOMIC */
#define WASM_SUSPEND_FLAGS_LOCK(lock) os_mutex_lock(&lock)
#define WASM_SUSPEND_FLAGS_UNLOCK(lock) os_mutex_unlock(&lock);
#endif /* WASM_SUSPEND_FLAGS_IS_ATOMIC */
#ifdef __cplusplus
}
#endif
#endif /* end of _WASM_SUSPEND_FLAGS_H */

View File

@ -28,12 +28,22 @@ extern "C" {
#endif
extern const char *aot_stack_sizes_name;
#ifndef AOT_STACK_SIZES_ALIAS_NAME
#define AOT_STACK_SIZES_ALIAS_NAME "aot_stack_sizes_alias"
#endif
extern const char *aot_stack_sizes_alias_name;
#ifndef AOT_STACK_SIZES_SECTION_NAME
#define AOT_STACK_SIZES_SECTION_NAME ".aot_stack_sizes"
#endif
extern const char *aot_stack_sizes_section_name;
typedef InitializerExpression AOTInitExpr;
typedef WASMType AOTFuncType;
typedef WASMExport AOTExport;
#if WASM_ENABLE_DEBUG_AOT != 0
typedef void *dwar_extractor_handle_t;
typedef void *dwarf_extractor_handle_t;
#endif
typedef enum AOTIntCond {
@ -275,7 +285,7 @@ typedef struct AOTCompData {
WASMModule *wasm_module;
#if WASM_ENABLE_DEBUG_AOT != 0
dwar_extractor_handle_t extractor;
dwarf_extractor_handle_t extractor;
#endif
} AOTCompData;

View File

@ -2617,64 +2617,6 @@ verify_module(AOTCompContext *comp_ctx)
return true;
}
/* Check whether the target supports hardware atomic instructions */
static bool
aot_require_lower_atomic_pass(AOTCompContext *comp_ctx)
{
bool ret = false;
if (!strncmp(comp_ctx->target_arch, "riscv", 5)) {
char *feature =
LLVMGetTargetMachineFeatureString(comp_ctx->target_machine);
if (feature) {
if (!strstr(feature, "+a")) {
ret = true;
}
LLVMDisposeMessage(feature);
}
}
return ret;
}
/* Check whether the target needs to expand switch to if/else */
static bool
aot_require_lower_switch_pass(AOTCompContext *comp_ctx)
{
bool ret = false;
/* IR switch/case will cause .rodata relocation on riscv/xtensa */
if (!strncmp(comp_ctx->target_arch, "riscv", 5)
|| !strncmp(comp_ctx->target_arch, "xtensa", 6)) {
ret = true;
}
return ret;
}
static bool
apply_passes_for_indirect_mode(AOTCompContext *comp_ctx)
{
LLVMPassManagerRef common_pass_mgr;
if (!(common_pass_mgr = LLVMCreatePassManager())) {
aot_set_last_error("create pass manager failed");
return false;
}
aot_add_expand_memory_op_pass(common_pass_mgr);
if (aot_require_lower_atomic_pass(comp_ctx))
LLVMAddLowerAtomicPass(common_pass_mgr);
if (aot_require_lower_switch_pass(comp_ctx))
LLVMAddLowerSwitchPass(common_pass_mgr);
LLVMRunPassManager(common_pass_mgr, comp_ctx->module);
LLVMDisposePassManager(common_pass_mgr);
return true;
}
bool
aot_compile_wasm(AOTCompContext *comp_ctx)
{
@ -2714,17 +2656,6 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
possible core dump. */
bh_print_time("Begin to run llvm optimization passes");
aot_apply_llvm_new_pass_manager(comp_ctx, comp_ctx->module);
/* Run specific passes for AOT indirect mode in last since general
optimization may create some intrinsic function calls like
llvm.memset, so let's remove these function calls here. */
if (!comp_ctx->is_jit_mode && comp_ctx->is_indirect_mode) {
bh_print_time("Begin to run optimization passes "
"for indirect mode");
if (!apply_passes_for_indirect_mode(comp_ctx)) {
return false;
}
}
bh_print_time("Finish llvm optimization passes");
}
@ -2765,7 +2696,7 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
if (comp_ctx->stack_sizes != NULL) {
LLVMOrcJITTargetAddress addr;
if ((err = LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &addr,
aot_stack_sizes_name))) {
aot_stack_sizes_alias_name))) {
aot_handle_llvm_errmsg("failed to look up stack_sizes", err);
return false;
}
@ -2804,6 +2735,33 @@ aot_generate_tempfile_name(const char *prefix, const char *extension,
snprintf(buffer + name_len, len - name_len, ".%s", extension);
return buffer;
}
#else
errno_t
_mktemp_s(char *nameTemplate, size_t sizeInChars);
char *
aot_generate_tempfile_name(const char *prefix, const char *extension,
char *buffer, uint32 len)
{
int name_len;
name_len = snprintf(buffer, len, "%s-XXXXXX", prefix);
if (_mktemp_s(buffer, name_len + 1) != 0) {
return NULL;
}
/* Check if buffer length is enough */
/* name_len + '.' + extension + '\0' */
if (name_len + 1 + strlen(extension) + 1 > len) {
aot_set_last_error("temp file name too long.");
return NULL;
}
snprintf(buffer + name_len, len - name_len, ".%s", extension);
return buffer;
}
#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */
bool

View File

@ -93,7 +93,10 @@ check_utf8_str(const uint8 *str, uint32 len)
/* Internal function in object file */
typedef struct AOTObjectFunc {
char *func_name;
/* text offset of aot_func#n */
uint64 text_offset;
/* text offset of aot_func_internal#n */
uint64 text_offset_of_aot_func_internal;
} AOTObjectFunc;
/* Symbol table list node */
@ -637,13 +640,33 @@ get_relocation_size(AOTRelocation *relocation, bool is_32bin)
}
static uint32
get_relocations_size(AOTRelocation *relocations, uint32 relocation_count,
get_relocations_size(AOTObjectData *obj_data,
AOTRelocationGroup *relocation_group,
AOTRelocation *relocations, uint32 relocation_count,
bool is_32bin)
{
AOTRelocation *relocation = relocations;
uint32 size = 0, i;
for (i = 0; i < relocation_count; i++, relocation++) {
/* ignore the relocations to aot_func_internal#n in text section
for windows platform since they will be applied in
aot_emit_text_section */
if (!strcmp(relocation_group->section_name, ".text")
&& !strncmp(relocation->symbol_name, AOT_FUNC_INTERNAL_PREFIX,
strlen(AOT_FUNC_INTERNAL_PREFIX))
&& ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6)
/* Windows AOT_COFF64_BIN_TYPE */
&& obj_data->target_info.bin_type == 6
/* IMAGE_REL_AMD64_REL32 in windows x86_64 */
&& relocation->relocation_type == 4)
|| (!strncmp(obj_data->comp_ctx->target_arch, "i386", 4)
/* Windows AOT_COFF32_BIN_TYPE */
&& obj_data->target_info.bin_type == 4
/* IMAGE_REL_I386_REL32 in windows x86_32 */
&& relocation->relocation_type == 20))) {
continue;
}
size = align_uint(size, 4);
size += get_relocation_size(relocation, is_32bin);
}
@ -651,19 +674,22 @@ get_relocations_size(AOTRelocation *relocations, uint32 relocation_count,
}
static uint32
get_relocation_group_size(AOTRelocationGroup *relocation_group, bool is_32bin)
get_relocation_group_size(AOTObjectData *obj_data,
AOTRelocationGroup *relocation_group, bool is_32bin)
{
uint32 size = 0;
/* section name index + relocation count + relocations */
size += (uint32)sizeof(uint32);
size += (uint32)sizeof(uint32);
size += get_relocations_size(relocation_group->relocations,
size += get_relocations_size(obj_data, relocation_group,
relocation_group->relocations,
relocation_group->relocation_count, is_32bin);
return size;
}
static uint32
get_relocation_groups_size(AOTRelocationGroup *relocation_groups,
get_relocation_groups_size(AOTObjectData *obj_data,
AOTRelocationGroup *relocation_groups,
uint32 relocation_group_count, bool is_32bin)
{
AOTRelocationGroup *relocation_group = relocation_groups;
@ -671,7 +697,7 @@ get_relocation_groups_size(AOTRelocationGroup *relocation_groups,
for (i = 0; i < relocation_group_count; i++, relocation_group++) {
size = align_uint(size, 4);
size += get_relocation_group_size(relocation_group, is_32bin);
size += get_relocation_group_size(obj_data, relocation_group, is_32bin);
}
return size;
}
@ -864,7 +890,7 @@ get_relocation_section_size(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
/* relocation group count + symbol_table + relocation groups */
return (uint32)sizeof(uint32) + symbol_table_size
+ get_relocation_groups_size(relocation_groups,
+ get_relocation_groups_size(obj_data, relocation_groups,
relocation_group_count,
is_32bit_binary(obj_data));
}
@ -1734,6 +1760,10 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
uint32 section_size = get_text_section_size(obj_data);
uint32 offset = *p_offset;
uint8 placeholder = 0;
AOTRelocationGroup *relocation_group;
AOTRelocation *relocation;
uint32 i, j, relocation_count;
uint8 *text;
*p_offset = offset = align_uint(offset, 4);
@ -1747,6 +1777,8 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
EMIT_BUF(&placeholder, 1);
}
text = buf + offset;
if (obj_data->text_size > 0) {
EMIT_BUF(obj_data->text, obj_data->text_size);
while (offset & 3)
@ -1768,6 +1800,67 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
return false;
}
/* apply relocations to aot_func_internal#n in text section for
windows platform */
if ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6)
/* Windows AOT_COFF64_BIN_TYPE */
&& obj_data->target_info.bin_type == 6)
|| (!strncmp(obj_data->comp_ctx->target_arch, "i386", 4)
/* Windows AOT_COFF32_BIN_TYPE */
&& obj_data->target_info.bin_type == 4)) {
relocation_group = obj_data->relocation_groups;
for (i = 0; i < obj_data->relocation_group_count;
i++, relocation_group++) {
/* relocation in text section */
if (!strcmp(relocation_group->section_name, ".text")) {
relocation = relocation_group->relocations;
relocation_count = relocation_group->relocation_count;
for (j = 0; j < relocation_count; j++) {
/* relocation to aot_func_internal#n */
if (str_starts_with(relocation->symbol_name,
AOT_FUNC_INTERNAL_PREFIX)
&& ((obj_data->target_info.bin_type
== 6 /* AOT_COFF64_BIN_TYPE */
&& relocation->relocation_type
== 4 /* IMAGE_REL_AMD64_REL32 */)
|| (obj_data->target_info.bin_type
== 4 /* AOT_COFF32_BIN_TYPE */
&& relocation->relocation_type
== 20 /* IMAGE_REL_I386_REL32 */))) {
uint32 func_idx =
atoi(relocation->symbol_name
+ strlen(AOT_FUNC_INTERNAL_PREFIX));
uint64 text_offset, reloc_offset, reloc_addend;
bh_assert(func_idx < obj_data->func_count);
text_offset = obj_data->funcs[func_idx]
.text_offset_of_aot_func_internal;
reloc_offset = relocation->relocation_offset;
reloc_addend = relocation->relocation_addend;
/* S + A - P */
*(uint32 *)(text + reloc_offset) =
(uint32)(text_offset + reloc_addend - reloc_offset
- 4);
/* remove current relocation as it has been applied */
if (j < relocation_count - 1) {
uint32 move_size =
(uint32)(sizeof(AOTRelocation)
* (relocation_count - 1 - j));
bh_memmove_s(relocation, move_size, relocation + 1,
move_size);
}
relocation_group->relocation_count--;
}
else {
relocation++;
}
}
}
}
}
*p_offset = offset;
return true;
@ -2333,6 +2426,7 @@ is_data_section(AOTObjectData *obj_data, LLVMSectionIteratorRef sec_itr,
|| (!strcmp(section_name, ".rdata")
&& get_relocations_count(sec_itr, &relocation_count)
&& relocation_count > 0)
|| !strcmp(section_name, aot_stack_sizes_section_name)
|| (obj_data->comp_ctx->enable_llvm_pgo
&& (!strncmp(section_name, "__llvm_prf_cnts", 15)
|| !strncmp(section_name, "__llvm_prf_data", 15)
@ -2402,7 +2496,7 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data)
&& !strcmp(name, "__llvm_prf_cnts")) {
snprintf(buf, sizeof(buf), "%s%u", name,
llvm_prf_cnts_idx++);
size = strlen(buf) + 1;
size = (uint32)(strlen(buf) + 1);
if (!(data_section->name = wasm_runtime_malloc(size))) {
aot_set_last_error(
"allocate memory for data section name failed.");
@ -2415,7 +2509,7 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data)
&& !strcmp(name, "__llvm_prf_data")) {
snprintf(buf, sizeof(buf), "%s%u", name,
llvm_prf_data_idx++);
size = strlen(buf) + 1;
size = (uint32)(strlen(buf) + 1);
if (!(data_section->name = wasm_runtime_malloc(size))) {
aot_set_last_error(
"allocate memory for data section name failed.");
@ -2519,15 +2613,15 @@ read_stack_usage_file(const AOTCompContext *comp_ctx, const char *filename,
}
if (prefix == aot_func_prefix) {
if (sz < precheck_stack_size_min) {
precheck_stack_size_min = sz;
precheck_stack_size_min = (uint32)sz;
}
if (sz > precheck_stack_size_max) {
precheck_stack_size_max = sz;
precheck_stack_size_max = (uint32)sz;
}
precheck_found++;
continue;
}
sizes[func_idx] = sz;
sizes[func_idx] = (uint32)sz;
found++;
}
fclose(fp);
@ -2604,9 +2698,16 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
while (!LLVMObjectFileIsSymbolIteratorAtEnd(obj_data->binary, sym_itr)) {
if ((name = LLVMGetSymbolName(sym_itr))
&& !strcmp(name, aot_stack_sizes_name)) {
&& (!strcmp(name, aot_stack_sizes_alias_name)
/* symbol of COFF32 starts with "_" */
|| (obj_data->target_info.bin_type == AOT_COFF32_BIN_TYPE
&& !strncmp(name, "_", 1)
&& !strcmp(name + 1, aot_stack_sizes_alias_name)))) {
uint64 sz = LLVMGetSymbolSize(sym_itr);
if (sz != sizeof(uint32) * obj_data->func_count) {
if (sz != sizeof(uint32) * obj_data->func_count
/* sz of COFF64/COFF32 is 0, ignore the check */
&& obj_data->target_info.bin_type != AOT_COFF64_BIN_TYPE
&& obj_data->target_info.bin_type != AOT_COFF32_BIN_TYPE) {
aot_set_last_error("stack_sizes had unexpected size.");
goto fail;
}
@ -2620,6 +2721,11 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
const char *sec_name = LLVMGetSectionName(sec_itr);
LOG_VERBOSE("stack_sizes found in section %s offset %" PRIu64 ".",
sec_name, addr);
if (strcmp(sec_name, aot_stack_sizes_section_name) || addr != 0) {
aot_set_last_error(
"stack_sizes found at an unexpected location.");
goto fail;
}
/*
* Note: We can't always modify stack_sizes in-place.
* Eg. When WAMRC_LLC_COMPILER is used, LLVM sometimes uses
@ -2636,16 +2742,12 @@ aot_resolve_stack_sizes(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
goto fail;
}
}
if (addr > UINT32_MAX) {
aot_set_last_error("too large stack_sizes offset.");
goto fail;
}
/*
* Record section/offset and construct a copy of stack_sizes.
* aot_emit_object_data_section_info will emit this copy.
*/
obj_data->stack_sizes_section_name = sec_name;
obj_data->stack_sizes_offset = addr;
obj_data->stack_sizes_offset = (uint32)addr;
obj_data->stack_sizes = wasm_runtime_malloc(
obj_data->func_count * sizeof(*obj_data->stack_sizes));
if (obj_data->stack_sizes == NULL) {
@ -2764,6 +2866,7 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
while (!LLVMObjectFileIsSymbolIteratorAtEnd(obj_data->binary, sym_itr)) {
if ((name = (char *)LLVMGetSymbolName(sym_itr))
&& str_starts_with(name, prefix)) {
/* symbol aot_func#n */
func_index = (uint32)atoi(name + strlen(prefix));
if (func_index < obj_data->func_count) {
LLVMSectionIteratorRef contain_section;
@ -2798,6 +2901,44 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
}
}
}
else if ((name = (char *)LLVMGetSymbolName(sym_itr))
&& str_starts_with(name, AOT_FUNC_INTERNAL_PREFIX)) {
/* symbol aot_func_internal#n */
func_index = (uint32)atoi(name + strlen(AOT_FUNC_INTERNAL_PREFIX));
if (func_index < obj_data->func_count) {
LLVMSectionIteratorRef contain_section;
char *contain_section_name;
func = obj_data->funcs + func_index;
if (!(contain_section = LLVMObjectFileCopySectionIterator(
obj_data->binary))) {
aot_set_last_error("llvm get section iterator failed.");
LLVMDisposeSymbolIterator(sym_itr);
return false;
}
LLVMMoveToContainingSection(contain_section, sym_itr);
contain_section_name =
(char *)LLVMGetSectionName(contain_section);
LLVMDisposeSectionIterator(contain_section);
if (!strcmp(contain_section_name, ".text.unlikely.")) {
func->text_offset_of_aot_func_internal =
align_uint(obj_data->text_size, 4)
+ LLVMGetSymbolAddress(sym_itr);
}
else if (!strcmp(contain_section_name, ".text.hot.")) {
func->text_offset_of_aot_func_internal =
align_uint(obj_data->text_size, 4)
+ align_uint(obj_data->text_unlikely_size, 4)
+ LLVMGetSymbolAddress(sym_itr);
}
else {
func->text_offset_of_aot_func_internal =
LLVMGetSymbolAddress(sym_itr);
}
}
}
LLVMMoveToNextSymbol(sym_itr);
}
LLVMDisposeSymbolIterator(sym_itr);
@ -2930,6 +3071,15 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data,
+ align_uint(obj_data->text_unlikely_size, 4);
}
/*
* Note: aot_stack_sizes_section_name section only contains
* stack_sizes table.
*/
if (!strcmp(relocation->symbol_name, aot_stack_sizes_name)) {
/* discard const */
relocation->symbol_name = (char *)aot_stack_sizes_section_name;
}
if (obj_data->comp_ctx->enable_llvm_pgo
&& (!strcmp(relocation->symbol_name, "__llvm_prf_cnts")
|| !strcmp(relocation->symbol_name, "__llvm_prf_data"))) {
@ -2960,7 +3110,7 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data,
|| !strcmp(group->section_name, ".rel.text")) {
snprintf(buf, sizeof(buf), "%s%u", relocation->symbol_name,
prof_section_idx);
size = strlen(buf) + 1;
size = (uint32)(strlen(buf) + 1);
if (!(relocation->symbol_name = wasm_runtime_malloc(size))) {
aot_set_last_error(
"allocate memory for relocation symbol name failed.");
@ -2975,7 +3125,7 @@ aot_resolve_object_relocation_group(AOTObjectData *obj_data,
19)) {
snprintf(buf, sizeof(buf), "%s%u", relocation->symbol_name,
prof_section_idx);
size = strlen(buf) + 1;
size = (uint32)(strlen(buf) + 1);
if (!(relocation->symbol_name = wasm_runtime_malloc(size))) {
aot_set_last_error(
"allocate memory for relocation symbol name failed.");
@ -3072,6 +3222,13 @@ is_relocation_section(AOTObjectData *obj_data, LLVMSectionIteratorRef sec_itr)
return false;
}
static bool
is_readonly_section(const char *name)
{
return !strcmp(name, ".rel.text") || !strcmp(name, ".rela.text")
|| !strcmp(name, ".rela.literal") || !strcmp(name, ".text");
}
static bool
get_relocation_groups_count(AOTObjectData *obj_data, uint32 *p_count)
{
@ -3134,7 +3291,7 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data)
|| !strcmp(name, ".rel__llvm_prf_data"))) {
char buf[32];
snprintf(buf, sizeof(buf), "%s%u", name, llvm_prf_data_idx);
size = strlen(buf) + 1;
size = (uint32)(strlen(buf) + 1);
if (!(relocation_group->section_name =
wasm_runtime_malloc(size))) {
aot_set_last_error(
@ -3169,6 +3326,19 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data)
relocation_group->section_name = ".rel.text";
}
/*
* Relocations in read-only sections are problematic,
* especially for XIP on platforms which don't have
* copy-on-write mappings.
*/
if (obj_data->comp_ctx->is_indirect_mode
&& is_readonly_section(relocation_group->section_name)) {
LOG_WARNING("%" PRIu32
" text relocations in %s section for indirect mode",
relocation_group->relocation_count,
relocation_group->section_name);
}
relocation_group++;
}
LLVMMoveToNextSection(sec_itr);

View File

@ -18,6 +18,17 @@
} \
} while (0)
static bool
is_win_platform(AOTCompContext *comp_ctx)
{
char *triple = LLVMGetTargetMachineTriple(comp_ctx->target_machine);
bh_assert(triple);
if (strstr(triple, "win32") || strstr(triple, "win"))
return true;
return false;
}
static bool
create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{
@ -458,7 +469,7 @@ check_app_addr_and_convert(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}
/* Check whether exception was thrown when executing the function */
if (comp_ctx->enable_bound_check
if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx))
&& !check_call_return(comp_ctx, func_ctx, res)) {
return false;
}
@ -696,7 +707,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
goto fail;
/* Check whether there was exception thrown when executing
the function */
if (comp_ctx->enable_bound_check
if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx))
&& !check_call_return(comp_ctx, func_ctx, res))
goto fail;
}
@ -849,7 +860,8 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* Check whether there was exception thrown when executing
the function */
if (!tail_call && comp_ctx->enable_bound_check
if (!tail_call
&& (comp_ctx->enable_bound_check || is_win_platform(comp_ctx))
&& !check_exception_thrown(comp_ctx, func_ctx))
goto fail;
}
@ -1431,7 +1443,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
goto fail;
/* Check whether exception was thrown when executing the function */
if (comp_ctx->enable_bound_check
if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx))
&& !check_call_return(comp_ctx, func_ctx, res))
goto fail;
@ -1483,7 +1495,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}
/* Check whether exception was thrown when executing the function */
if (comp_ctx->enable_bound_check
if ((comp_ctx->enable_bound_check || is_win_platform(comp_ctx))
&& !check_exception_thrown(comp_ctx, func_ctx))
goto fail;

View File

@ -7,6 +7,7 @@
#include "aot_llvm_extra2.h"
#include "aot_compiler.h"
#include "aot_emit_exception.h"
#include "aot_emit_table.h"
#include "../aot/aot_runtime.h"
#include "../aot/aot_intrinsic.h"
@ -145,6 +146,13 @@ aot_target_precheck_can_use_musttail(const AOTCompContext *comp_ctx)
*/
return false;
}
if (!strcmp(comp_ctx->target_arch, "mips")) {
/*
* cf.
* https://github.com/bytecodealliance/wasm-micro-runtime/issues/2412
*/
return false;
}
/*
* x86-64/i386: true
*
@ -230,6 +238,18 @@ aot_estimate_stack_usage_for_function_call(const AOTCompContext *comp_ctx,
return size;
}
static uint32
get_inst_extra_offset(AOTCompContext *comp_ctx)
{
const AOTCompData *comp_data = comp_ctx->comp_data;
uint32 table_count = comp_data->import_table_count + comp_data->table_count;
uint64 offset = get_tbl_inst_offset(comp_ctx, NULL, table_count);
uint32 offset_32 = (uint32)offset;
bh_assert(offset <= UINT32_MAX);
offset_32 = align_uint((uint32)offset_32, 8);
return offset_32;
}
/*
* a "precheck" function performs a few things before calling wrapped_func.
*
@ -297,8 +317,8 @@ aot_add_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module,
goto fail;
}
unsigned int param_count = LLVMCountParams(precheck_func);
uint64 sz = param_count * sizeof(LLVMValueRef);
uint32 param_count = LLVMCountParams(precheck_func);
uint32 sz = param_count * (uint32)sizeof(LLVMValueRef);
params = wasm_runtime_malloc(sz);
if (params == NULL) {
goto fail;
@ -327,9 +347,36 @@ aot_add_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module,
/*
* load the value for this wrapped function from the stack_sizes array
*/
LLVMValueRef stack_sizes;
if (comp_ctx->is_indirect_mode) {
uint32 offset_u32;
LLVMValueRef offset;
LLVMValueRef stack_sizes_p;
offset_u32 = get_inst_extra_offset(comp_ctx);
offset_u32 += offsetof(AOTModuleInstanceExtra, stack_sizes);
offset = I32_CONST(offset_u32);
if (!offset) {
goto fail;
}
stack_sizes_p =
LLVMBuildInBoundsGEP2(b, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
"aot_inst_stack_sizes_p");
if (!stack_sizes_p) {
goto fail;
}
stack_sizes =
LLVMBuildLoad2(b, INT32_PTR_TYPE, stack_sizes_p, "stack_sizes");
if (!stack_sizes) {
goto fail;
}
}
else {
stack_sizes = comp_ctx->stack_sizes;
}
LLVMValueRef func_index_const = I32_CONST(func_index);
LLVMValueRef sizes =
LLVMBuildBitCast(b, comp_ctx->stack_sizes, INT32_PTR_TYPE, "sizes");
LLVMBuildBitCast(b, stack_sizes, INT32_PTR_TYPE, "sizes");
if (!sizes) {
goto fail;
}
@ -584,6 +631,15 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module,
prefix)))
goto fail;
if (comp_ctx->is_indirect_mode) {
/* avoid LUT relocations ("switch-table") */
LLVMAttributeRef attr_no_jump_tables = LLVMCreateStringAttribute(
comp_ctx->context, "no-jump-tables",
(uint32)strlen("no-jump-tables"), "true", (uint32)strlen("true"));
LLVMAddAttributeAtIndex(func, LLVMAttributeFunctionIndex,
attr_no_jump_tables);
}
if (need_precheck) {
if (!comp_ctx->is_jit_mode)
LLVMSetLinkage(func, LLVMInternalLinkage);
@ -1373,11 +1429,12 @@ create_func_ptrs(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
}
const char *aot_stack_sizes_name = AOT_STACK_SIZES_NAME;
const char *aot_stack_sizes_alias_name = AOT_STACK_SIZES_ALIAS_NAME;
const char *aot_stack_sizes_section_name = AOT_STACK_SIZES_SECTION_NAME;
static bool
aot_create_stack_sizes(const AOTCompData *comp_data, AOTCompContext *comp_ctx)
{
const char *stack_sizes_name = "stack_sizes";
LLVMValueRef stack_sizes, *values, array, alias;
LLVMTypeRef stack_sizes_type;
#if LLVM_VERSION_MAJOR <= 13
@ -1393,7 +1450,7 @@ aot_create_stack_sizes(const AOTCompData *comp_data, AOTCompContext *comp_ctx)
}
stack_sizes =
LLVMAddGlobal(comp_ctx->module, stack_sizes_type, stack_sizes_name);
LLVMAddGlobal(comp_ctx->module, stack_sizes_type, aot_stack_sizes_name);
if (!stack_sizes) {
aot_set_last_error("failed to create stack_sizes global.");
return false;
@ -1429,7 +1486,7 @@ aot_create_stack_sizes(const AOTCompData *comp_data, AOTCompContext *comp_ctx)
*/
#if LLVM_VERSION_MAJOR > 13
alias = LLVMAddAlias2(comp_ctx->module, stack_sizes_type, 0, stack_sizes,
aot_stack_sizes_name);
aot_stack_sizes_alias_name);
#else
alias_type = LLVMPointerType(stack_sizes_type, 0);
if (!alias_type) {
@ -1437,7 +1494,7 @@ aot_create_stack_sizes(const AOTCompData *comp_data, AOTCompContext *comp_ctx)
return false;
}
alias = LLVMAddAlias(comp_ctx->module, alias_type, stack_sizes,
aot_stack_sizes_name);
aot_stack_sizes_alias_name);
#endif
if (!alias) {
aot_set_last_error("failed to create stack_sizes alias.");
@ -1449,6 +1506,7 @@ aot_create_stack_sizes(const AOTCompData *comp_data, AOTCompContext *comp_ctx)
* avoid creating extra relocations in the precheck functions.
*/
LLVMSetLinkage(stack_sizes, LLVMInternalLinkage);
LLVMSetSection(stack_sizes, aot_stack_sizes_section_name);
comp_ctx->stack_sizes_type = stack_sizes_type;
comp_ctx->stack_sizes = stack_sizes;
return true;
@ -2031,7 +2089,7 @@ jit_stack_size_callback(void *user_data, const char *name, size_t namelen,
return;
}
/* ensure NUL termination */
bh_memcpy_s(buf, sizeof(buf), name, namelen);
bh_memcpy_s(buf, (uint32)sizeof(buf), name, (uint32)namelen);
buf[namelen] = 0;
ret = sscanf(buf, AOT_FUNC_INTERNAL_PREFIX "%" SCNu32, &func_idx);
@ -2052,7 +2110,7 @@ jit_stack_size_callback(void *user_data, const char *name, size_t namelen,
/* Note: -1 == AOT_NEG_ONE from aot_create_stack_sizes */
bh_assert(comp_ctx->jit_stack_sizes[func_idx] == (uint32)-1);
comp_ctx->jit_stack_sizes[func_idx] = stack_size + call_size;
comp_ctx->jit_stack_sizes[func_idx] = (uint32)stack_size + call_size;
}
static bool
@ -2255,6 +2313,12 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
if (option->enable_stack_estimation)
comp_ctx->enable_stack_estimation = true;
if (option->llvm_passes)
comp_ctx->llvm_passes = option->llvm_passes;
if (option->builtin_intrinsics)
comp_ctx->builtin_intrinsics = option->builtin_intrinsics;
comp_ctx->opt_level = option->opt_level;
comp_ctx->size_level = option->size_level;
@ -2688,6 +2752,16 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
aot_set_last_error("create LLVM target machine failed.");
goto fail;
}
/* If only to create target machine for querying information, early stop
*/
if ((arch && !strcmp(arch, "help")) || (abi && !strcmp(abi, "help"))
|| (cpu && !strcmp(cpu, "help"))
|| (features && !strcmp(features, "+help"))) {
LOG_DEBUG(
"create LLVM target machine only for printing help info.");
goto fail;
}
}
triple = LLVMGetTargetMachineTriple(comp_ctx->target_machine);

View File

@ -417,6 +417,8 @@ typedef struct AOTCompContext {
const char *stack_usage_file;
char stack_usage_temp_file[64];
const char *llvm_passes;
const char *builtin_intrinsics;
} AOTCompContext;
enum {
@ -455,6 +457,8 @@ typedef struct AOTCompOption {
char **custom_sections;
uint32 custom_sections_count;
const char *stack_usage_file;
const char *llvm_passes;
const char *builtin_intrinsics;
} AOTCompOption, *aot_comp_option_t;
bool

View File

@ -27,7 +27,7 @@
#include <llvm/IR/Module.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/PassManager.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/ErrorHandling.h>
#include <llvm/Target/CodeGenCWrappers.h>
@ -73,115 +73,56 @@ LLVM_C_EXTERN_C_END
ExitOnError ExitOnErr;
class ExpandMemoryOpPass : public llvm::ModulePass
class ExpandMemoryOpPass : public PassInfoMixin<ExpandMemoryOpPass>
{
public:
static char ID;
ExpandMemoryOpPass()
: ModulePass(ID)
{}
bool runOnModule(Module &M) override;
bool expandMemIntrinsicUses(Function &F);
StringRef getPassName() const override
{
return "Expand memory operation intrinsics";
}
void getAnalysisUsage(AnalysisUsage &AU) const override
{
AU.addRequired<TargetTransformInfoWrapperPass>();
}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
char ExpandMemoryOpPass::ID = 0;
bool
ExpandMemoryOpPass::expandMemIntrinsicUses(Function &F)
PreservedAnalyses
ExpandMemoryOpPass::run(Function &F, FunctionAnalysisManager &AM)
{
Intrinsic::ID ID = F.getIntrinsicID();
bool Changed = false;
SmallVector<MemIntrinsic *, 16> MemCalls;
for (auto I = F.user_begin(), E = F.user_end(); I != E;) {
Instruction *Inst = cast<Instruction>(*I);
++I;
/* Iterate over all instructions in the function, looking for memcpy,
* memmove, and memset. When we find one, expand it into a loop. */
switch (ID) {
case Intrinsic::memcpy:
{
auto *Memcpy = cast<MemCpyInst>(Inst);
Function *ParentFunc = Memcpy->getParent()->getParent();
const TargetTransformInfo &TTI =
getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
*ParentFunc);
expandMemCpyAsLoop(Memcpy, TTI);
Changed = true;
Memcpy->eraseFromParent();
break;
for (auto &BB : F) {
for (auto &Inst : BB) {
if (auto *Memcpy = dyn_cast_or_null<MemCpyInst>(&Inst)) {
MemCalls.push_back(Memcpy);
}
case Intrinsic::memmove:
{
auto *Memmove = cast<MemMoveInst>(Inst);
expandMemMoveAsLoop(Memmove);
Changed = true;
Memmove->eraseFromParent();
break;
else if (auto *Memmove = dyn_cast_or_null<MemMoveInst>(&Inst)) {
MemCalls.push_back(Memmove);
}
case Intrinsic::memset:
{
auto *Memset = cast<MemSetInst>(Inst);
expandMemSetAsLoop(Memset);
Changed = true;
Memset->eraseFromParent();
break;
else if (auto *Memset = dyn_cast_or_null<MemSetInst>(&Inst)) {
MemCalls.push_back(Memset);
}
default:
break;
}
}
return Changed;
}
bool
ExpandMemoryOpPass::runOnModule(Module &M)
{
bool Changed = false;
for (Function &F : M) {
if (!F.isDeclaration())
continue;
switch (F.getIntrinsicID()) {
case Intrinsic::memcpy:
case Intrinsic::memmove:
case Intrinsic::memset:
if (expandMemIntrinsicUses(F))
Changed = true;
break;
default:
break;
for (MemIntrinsic *MemCall : MemCalls) {
if (MemCpyInst *Memcpy = dyn_cast<MemCpyInst>(MemCall)) {
Function *ParentFunc = Memcpy->getParent()->getParent();
const TargetTransformInfo &TTI =
AM.getResult<TargetIRAnalysis>(*ParentFunc);
expandMemCpyAsLoop(Memcpy, TTI);
Memcpy->eraseFromParent();
}
else if (MemMoveInst *Memmove = dyn_cast<MemMoveInst>(MemCall)) {
expandMemMoveAsLoop(Memmove);
Memmove->eraseFromParent();
}
else if (MemSetInst *Memset = dyn_cast<MemSetInst>(MemCall)) {
expandMemSetAsLoop(Memset);
Memset->eraseFromParent();
}
}
return Changed;
}
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
void
aot_add_expand_memory_op_pass(LLVMPassManagerRef pass)
{
reinterpret_cast<legacy::PassManager *>(pass)->add(
new ExpandMemoryOpPass());
}
void
aot_add_simple_loop_unswitch_pass(LLVMPassManagerRef pass)
{
reinterpret_cast<legacy::PassManager *>(pass)->add(
createSimpleLoopUnswitchLegacyPass());
return PA;
}
bool
@ -373,6 +314,10 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module)
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
if (comp_ctx->llvm_passes) {
ExitOnErr(PB.parsePassPipeline(MPM, comp_ctx->llvm_passes));
}
if (!disable_llvm_lto) {
/* Apply LTO for AOT mode */
if (comp_ctx->comp_data->func_count >= 10
@ -386,6 +331,15 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module)
else {
MPM.addPass(PB.buildPerModuleDefaultPipeline(OL));
}
/* Run specific passes for AOT indirect mode in last since general
optimization may create some intrinsic function calls like
llvm.memset, so let's remove these function calls here. */
if (comp_ctx->is_indirect_mode) {
FunctionPassManager FPM1;
FPM1.addPass(ExpandMemoryOpPass());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM1)));
}
}
MPM.run(*M, MAM);

View File

@ -28,25 +28,25 @@
using namespace lldb;
typedef struct dwar_extractor {
typedef struct dwarf_extractor {
SBDebugger debugger;
SBTarget target;
SBModule module;
} dwar_extractor;
} dwarf_extractor;
#define TO_HANDLE(extractor) (dwar_extractor_handle_t)(extractor)
#define TO_HANDLE(extractor) (dwarf_extractor_handle_t)(extractor)
#define TO_EXTACTOR(handle) (dwar_extractor *)(handle)
#define TO_EXTACTOR(handle) (dwarf_extractor *)(handle)
static bool is_debugger_initialized;
dwar_extractor_handle_t
dwarf_extractor_handle_t
create_dwarf_extractor(AOTCompData *comp_data, char *file_name)
{
char *arch = NULL;
char *platform = NULL;
dwar_extractor *extractor = NULL;
dwarf_extractor *extractor = NULL;
//__attribute__((constructor)) may be better?
if (!is_debugger_initialized) {
@ -61,7 +61,7 @@ create_dwarf_extractor(AOTCompData *comp_data, char *file_name)
SBError error;
SBFileSpec exe_file_spec(file_name, true);
if (!(extractor = new dwar_extractor())) {
if (!(extractor = new dwarf_extractor())) {
LOG_ERROR("Create Dwarf Extractor error: failed to allocate memory");
goto fail3;
}
@ -101,9 +101,9 @@ fail3:
}
void
destroy_dwarf_extractor(dwar_extractor_handle_t handle)
destroy_dwarf_extractor(dwarf_extractor_handle_t handle)
{
dwar_extractor *extractor = TO_EXTACTOR(handle);
dwarf_extractor *extractor = TO_EXTACTOR(handle);
if (!extractor)
return;
extractor->debugger.DeleteTarget(extractor->target);
@ -116,7 +116,7 @@ destroy_dwarf_extractor(dwar_extractor_handle_t handle)
LLVMMetadataRef
dwarf_gen_file_info(const AOTCompContext *comp_ctx)
{
dwar_extractor *extractor;
dwarf_extractor *extractor;
int units_number;
LLVMMetadataRef file_info = NULL;
const char *file_name;
@ -193,7 +193,7 @@ dwarf_gen_mock_vm_info(AOTCompContext *comp_ctx)
LLVMMetadataRef
dwarf_gen_comp_unit_info(const AOTCompContext *comp_ctx)
{
dwar_extractor *extractor;
dwarf_extractor *extractor;
int units_number;
LLVMMetadataRef comp_unit = NULL;
@ -292,7 +292,7 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx,
SBTypeList function_args = function.GetType().GetFunctionArgumentTypes();
SBType return_type = function.GetType().GetFunctionReturnType();
const size_t num_function_args = function_args.GetSize();
dwar_extractor *extractor;
dwarf_extractor *extractor;
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
return NULL;
@ -393,7 +393,7 @@ dwarf_gen_func_info(const AOTCompContext *comp_ctx,
const AOTFuncContext *func_ctx)
{
LLVMMetadataRef func_info = NULL;
dwar_extractor *extractor;
dwarf_extractor *extractor;
uint64_t vm_offset;
AOTFunc *func = func_ctx->aot_func;
@ -423,7 +423,7 @@ dwarf_get_func_name(const AOTCompContext *comp_ctx,
const AOTFuncContext *func_ctx, char *name, int len)
{
LLVMMetadataRef func_info = NULL;
dwar_extractor *extractor;
dwarf_extractor *extractor;
uint64_t vm_offset;
AOTFunc *func = func_ctx->aot_func;
@ -454,7 +454,7 @@ dwarf_gen_location(const AOTCompContext *comp_ctx,
const AOTFuncContext *func_ctx, uint64_t vm_offset)
{
LLVMMetadataRef location_info = NULL;
dwar_extractor *extractor;
dwarf_extractor *extractor;
AOTFunc *func = func_ctx->aot_func;
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
@ -493,7 +493,7 @@ dwarf_gen_func_ret_location(const AOTCompContext *comp_ctx,
const AOTFuncContext *func_ctx)
{
LLVMMetadataRef func_info = NULL;
dwar_extractor *extractor;
dwarf_extractor *extractor;
uint64_t vm_offset;
AOTFunc *func = func_ctx->aot_func;
LLVMMetadataRef location_info = NULL;

View File

@ -18,7 +18,7 @@ typedef unsigned int LLDBLangType;
struct AOTCompData;
typedef struct AOTCompData *aot_comp_data_t;
typedef void *dwar_extractor_handle_t;
typedef void *dwarf_extractor_handle_t;
struct AOTCompContext;
typedef struct AOTCompContext AOTCompContext;
@ -26,7 +26,7 @@ typedef struct AOTCompContext AOTCompContext;
struct AOTFuncContext;
typedef struct AOTFuncContext AOTFuncContext;
dwar_extractor_handle_t
dwarf_extractor_handle_t
create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name);
LLVMMetadataRef

View File

@ -88,27 +88,28 @@ fail:
static int
wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
uint32 dst, uint32 len, uint32 src)
uint32 dst_offset, uint32 len, uint32 src_offset)
{
WASMTableInstance *tbl;
uint32 tbl_sz;
WASMTableSeg *elem;
uint32 elem_len;
tbl = inst->tables[tbl_idx];
tbl_sz = tbl->cur_size;
if (dst > tbl_sz || tbl_sz - dst < len)
goto out_of_bounds;
elem = inst->module->table_segments + elem_idx;
elem_len = elem->function_count;
if (src > elem_len || elem_len - src < len)
if (offset_len_out_of_bounds(src_offset, len, elem_len))
goto out_of_bounds;
tbl = inst->tables[tbl_idx];
tbl_sz = tbl->cur_size;
if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
goto out_of_bounds;
bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
+ dst * sizeof(uint32),
(uint32)((tbl_sz - dst) * sizeof(uint32)),
elem->func_indexes + src, (uint32)(len * sizeof(uint32)));
+ dst_offset * sizeof(uint32),
(uint32)((tbl_sz - dst_offset) * sizeof(uint32)),
elem->func_indexes + src_offset,
(uint32)(len * sizeof(uint32)));
return 0;
out_of_bounds:
@ -157,14 +158,14 @@ wasm_copy_table(WASMModuleInstance *inst, uint32 src_tbl_idx,
WASMTableInstance *src_tbl, *dst_tbl;
uint32 src_tbl_sz, dst_tbl_sz;
src_tbl = inst->tables[src_tbl_idx];
src_tbl_sz = src_tbl->cur_size;
if (src_offset > src_tbl_sz || src_tbl_sz - src_offset < len)
goto out_of_bounds;
dst_tbl = inst->tables[dst_tbl_idx];
dst_tbl_sz = dst_tbl->cur_size;
if (dst_offset > dst_tbl_sz || dst_tbl_sz - dst_offset < len)
if (offset_len_out_of_bounds(dst_offset, len, dst_tbl_sz))
goto out_of_bounds;
src_tbl = inst->tables[src_tbl_idx];
src_tbl_sz = src_tbl->cur_size;
if (offset_len_out_of_bounds(src_offset, len, src_tbl_sz))
goto out_of_bounds;
bh_memmove_s((uint8 *)dst_tbl + offsetof(WASMTableInstance, elems)
@ -263,7 +264,7 @@ fail:
}
static int
wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst,
wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst_offset,
uint32 val, uint32 len)
{
WASMTableInstance *tbl;
@ -272,11 +273,11 @@ wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst,
tbl = inst->tables[tbl_idx];
tbl_sz = tbl->cur_size;
if (dst > tbl_sz || tbl_sz - dst < len)
if (offset_len_out_of_bounds(dst_offset, len, tbl_sz))
goto out_of_bounds;
for (; len != 0; dst++, len--) {
tbl->elems[dst] = val;
for (; len != 0; dst_offset++, len--) {
tbl->elems[dst_offset] = val;
}
return 0;

View File

@ -26,8 +26,8 @@ void
aot_destroy_comp_data(aot_comp_data_t comp_data);
#if WASM_ENABLE_DEBUG_AOT != 0
typedef void *dwar_extractor_handle_t;
dwar_extractor_handle_t
typedef void *dwarf_extractor_handle_t;
dwarf_extractor_handle_t
create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name);
#endif
@ -67,6 +67,8 @@ typedef struct AOTCompOption {
char **custom_sections;
uint32_t custom_sections_count;
const char *stack_usage_file;
const char *llvm_passes;
const char *builtin_intrinsics;
} AOTCompOption, *aot_comp_option_t;
bool

View File

@ -186,6 +186,7 @@ enum wasm_valkind_enum {
#ifndef WASM_VAL_T_DEFINED
#define WASM_VAL_T_DEFINED
struct wasm_ref_t;
typedef struct wasm_val_t {
wasm_valkind_t kind;
@ -197,6 +198,7 @@ typedef struct wasm_val_t {
double f64;
/* represent a foreign object, aka externref in .wat */
uintptr_t foreign;
struct wasm_ref_t *ref;
} of;
} wasm_val_t;
#endif
@ -914,6 +916,25 @@ wasm_runtime_set_custom_data(wasm_module_inst_t module_inst,
WASM_RUNTIME_API_EXTERN void *
wasm_runtime_get_custom_data(wasm_module_inst_t module_inst);
/**
* Set the memory bounds checks flag of a WASM module instance.
*
* @param module_inst the WASM module instance
* @param enable the flag to enable/disable the memory bounds checks
*/
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_bounds_checks(wasm_module_inst_t module_inst,
bool enable);
/**
* Check if the memory bounds checks flag is enabled for a WASM module instance.
*
* @param module_inst the WASM module instance
*
* @return true if the memory bounds checks flag is enabled, false otherwise
*/
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_bounds_checks_enabled(
wasm_module_inst_t module_inst);
/**
* Allocate memory from the heap of WASM module instance
*
@ -1271,6 +1292,32 @@ WASM_RUNTIME_API_EXTERN bool
wasm_externref_obj2ref(wasm_module_inst_t module_inst,
void *extern_obj, uint32_t *p_externref_idx);
/**
* Delete external object registered by `wasm_externref_obj2ref`.
*
* @param module_inst the WASM module instance that the extern object
* belongs to
* @param extern_obj the external object to be deleted
*
* @return true if success, false otherwise
*/
WASM_RUNTIME_API_EXTERN bool
wasm_externref_objdel(wasm_module_inst_t module_inst, void *extern_obj);
/**
* Set cleanup callback to release external object.
*
* @param module_inst the WASM module instance that the extern object
* belongs to
* @param extern_obj the external object to which to set the `extern_obj_cleanup` cleanup callback.
* @param extern_obj_cleanup a callback to release `extern_obj`
*
* @return true if success, false otherwise
*/
WASM_RUNTIME_API_EXTERN bool
wasm_externref_set_cleanup(wasm_module_inst_t module_inst, void *extern_obj,
void (*extern_obj_cleanup)(void *));
/**
* Retrieve the external object from an internal externref index
*
@ -1392,6 +1439,91 @@ WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_import_global_linked(const char *module_name,
const char *global_name);
typedef enum {
INTERNAL_ERROR,
MAX_SIZE_REACHED,
} enlarge_memory_error_reason_t;
typedef void (*enlarge_memory_error_callback_t)(
uint32_t inc_page_count, uint64_t current_memory_size,
uint32_t memory_index, enlarge_memory_error_reason_t failure_reason,
wasm_module_inst_t instance, wasm_exec_env_t exec_env);
/**
* Setup callback invoked when memory.grow fails
*/
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_enlarge_mem_error_callback(
const enlarge_memory_error_callback_t callback);
/*
* module instance context APIs
* wasm_runtime_create_context_key
* wasm_runtime_destroy_context_key
* wasm_runtime_set_context
* wasm_runtime_set_context_spread
* wasm_runtime_get_context
*
* This set of APIs is intended to be used by an embedder which provides
* extra sets of native functions, which need per module instance state
* and are maintained outside of the WAMR tree.
*
* It's modelled after the pthread specific API.
*
* wasm_runtime_set_context_spread is similar to
* wasm_runtime_set_context, except that
* wasm_runtime_set_context_spread applies the change
* to all threads in the cluster.
* It's an undefined behavior if multiple threads in a cluster call
* wasm_runtime_set_context_spread on the same key
* simultaneously. It's a caller's resposibility to perform necessary
* serialization if necessary. For example:
*
* if (wasm_runtime_get_context(inst, key) == NULL) {
* newctx = alloc_and_init(...);
* lock(some_lock);
* if (wasm_runtime_get_context(inst, key) == NULL) {
* // this thread won the race
* wasm_runtime_set_context_spread(inst, key, newctx);
* newctx = NULL;
* }
* unlock(some_lock);
* if (newctx != NULL) {
* // this thread lost the race, free it
* cleanup_and_free(newctx);
* }
* }
*
* Note: dynamic key create/destroy while instances are live is not
* implemented as of writing this.
* it's caller's resposibility to ensure destorying all module instances
* before calling wasm_runtime_create_context_key or
* wasm_runtime_destroy_context_key.
* otherwise, it's an undefined behavior.
*
* Note about threads:
* - When spawning a thread, the contexts (the pointers given to
* wasm_runtime_set_context) are copied from the parent
* instance.
* - The destructor is called only on the main instance.
*/
WASM_RUNTIME_API_EXTERN void *
wasm_runtime_create_context_key(
void (*dtor)(wasm_module_inst_t inst, void *ctx));
WASM_RUNTIME_API_EXTERN void
wasm_runtime_destroy_context_key(void *key);
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_context(wasm_module_inst_t inst, void *key,
void *ctx);
WASM_RUNTIME_API_EXTERN void
wasm_runtime_set_context_spread(wasm_module_inst_t inst, void *key,
void *ctx);
WASM_RUNTIME_API_EXTERN void *
wasm_runtime_get_context(wasm_module_inst_t inst, void *key);
/* clang-format on */
#ifdef __cplusplus

View File

@ -627,7 +627,6 @@ typedef struct WASMBranchBlock {
uint32 cell_num;
} WASMBranchBlock;
/* Execution environment, e.g. stack info */
/**
* Align an unsigned value on a alignment boundary.
*
@ -643,6 +642,24 @@ align_uint(unsigned v, unsigned b)
return (v + m) & ~m;
}
/**
* Check whether a piece of data is out of range
*
* @param offset the offset that the data starts
* @param len the length of the data
* @param max_size the maximum size of the data range
*
* @return true if out of range, false otherwise
*/
inline static bool
offset_len_out_of_bounds(uint32 offset, uint32 len, uint32 max_size)
{
if (offset + len < offset /* integer overflow */
|| offset + len > max_size)
return true;
return false;
}
/**
* Return the hash value of c string.
*/

View File

@ -41,26 +41,28 @@ typedef float64 CellType_F64;
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
#define CHECK_MEMORY_OVERFLOW(bytes) \
do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \
if (offset1 + bytes <= (uint64)get_linear_mem_size()) \
/* If offset1 is in valid range, maddr must also \
be in valid range, no need to check it again. */ \
maddr = memory->memory_data + offset1; \
else \
goto out_of_bounds; \
#define CHECK_MEMORY_OVERFLOW(bytes) \
do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \
if (disable_bounds_checks \
|| offset1 + bytes <= (uint64)get_linear_mem_size()) \
/* If offset1 is in valid range, maddr must also \
be in valid range, no need to check it again. */ \
maddr = memory->memory_data + offset1; \
else \
goto out_of_bounds; \
} while (0)
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
do { \
uint64 offset1 = (uint32)(start); \
if (offset1 + bytes <= (uint64)get_linear_mem_size()) \
/* App heap space is not valid space for \
bulk memory operation */ \
maddr = memory->memory_data + offset1; \
else \
goto out_of_bounds; \
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
do { \
uint64 offset1 = (uint32)(start); \
if (disable_bounds_checks \
|| offset1 + bytes <= (uint64)get_linear_mem_size()) \
/* App heap space is not valid space for \
bulk memory operation */ \
maddr = memory->memory_data + offset1; \
else \
goto out_of_bounds; \
} while (0)
#else
#define CHECK_MEMORY_OVERFLOW(bytes) \
@ -708,28 +710,28 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint32)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint32)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = LOAD_I32(maddr); \
STORE_U32(maddr, readv op sval); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
PUSH_I32(readv); \
break; \
@ -748,39 +750,39 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)LOAD_U32(maddr); \
STORE_U32(maddr, (uint32)(readv op sval)); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else { \
uint64 op_result; \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)LOAD_I64(maddr); \
op_result = readv op sval; \
STORE_I64(maddr, op_result); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
PUSH_I64(readv); \
break; \
@ -903,8 +905,9 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
if (!func_import->call_conv_wasm_c_api) {
native_func_pointer = module_inst->import_func_ptrs[cur_func_index];
}
else if (module_inst->e->c_api_func_imports) {
c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index;
else if (module_inst->e->common.c_api_func_imports) {
c_api_func_import =
module_inst->e->common.c_api_func_imports + cur_func_index;
native_func_pointer = c_api_func_import->func_ptr_linked;
}
@ -1060,21 +1063,33 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
os_mutex_unlock(&exec_env->wait_lock); \
} while (0)
#else
#define CHECK_SUSPEND_FLAGS() \
do { \
os_mutex_lock(&exec_env->wait_lock); \
if (exec_env->suspend_flags.flags != 0) { \
if (exec_env->suspend_flags.flags & 0x01) { \
/* terminate current thread */ \
os_mutex_unlock(&exec_env->wait_lock); \
return; \
} \
while (exec_env->suspend_flags.flags & 0x02) { \
/* suspend current thread */ \
os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \
} \
} \
os_mutex_unlock(&exec_env->wait_lock); \
#if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0
/* The lock is only needed when the suspend_flags is atomic; otherwise
the lock is already taken at the time when SUSPENSION_LOCK() is called. */
#define SUSPENSION_LOCK() os_mutex_lock(&exec_env->wait_lock);
#define SUSPENSION_UNLOCK() os_mutex_unlock(&exec_env->wait_lock);
#else
#define SUSPENSION_LOCK()
#define SUSPENSION_UNLOCK()
#endif
#define CHECK_SUSPEND_FLAGS() \
do { \
WASM_SUSPEND_FLAGS_LOCK(exec_env->wait_lock); \
if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \
& WASM_SUSPEND_FLAG_TERMINATE) { \
/* terminate current thread */ \
WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \
return; \
} \
while (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \
& WASM_SUSPEND_FLAG_SUSPEND) { \
/* suspend current thread */ \
SUSPENSION_LOCK() \
os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \
SUSPENSION_UNLOCK() \
} \
WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \
} while (0)
#endif /* WASM_ENABLE_DEBUG_INTERP */
#endif /* WASM_ENABLE_THREAD_MGR */
@ -1142,10 +1157,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMFunctionInstance *cur_func,
WASMInterpFrame *prev_frame)
{
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
#endif
WASMMemoryInstance *memory = wasm_get_default_memory(module);
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
@ -1174,6 +1185,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint8 local_type, *global_addr;
uint32 cache_index, type_index, param_cell_num, cell_num;
uint8 value_type;
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
bool disable_bounds_checks = !wasm_runtime_is_bounds_checks_enabled(
(WASMModuleInstanceCommon *)module);
#else
bool disable_bounds_checks = false;
#endif
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
uint8 *frame_ip_orig = NULL;
@ -3224,7 +3244,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
case WASM_OP_TABLE_INIT:
{
uint32 tbl_idx, elem_idx;
uint64 n, s, d;
uint32 n, s, d;
WASMTableInstance *tbl_inst;
read_leb_uint32(frame_ip, frame_ip_end, elem_idx);
@ -3239,20 +3259,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
s = (uint32)POP_I32();
d = (uint32)POP_I32();
/* TODO: what if the element is not passive? */
if (!n) {
break;
}
if (n + s > module->module->table_segments[elem_idx]
.function_count
|| d + n > tbl_inst->cur_size) {
if (offset_len_out_of_bounds(
s, n,
module->module->table_segments[elem_idx]
.function_count)
|| offset_len_out_of_bounds(d, n,
tbl_inst->cur_size)) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;
}
if (!n) {
break;
}
if (module->module->table_segments[elem_idx]
.is_dropped) {
wasm_set_exception(module,
@ -3293,7 +3314,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
case WASM_OP_TABLE_COPY:
{
uint32 src_tbl_idx, dst_tbl_idx;
uint64 n, s, d;
uint32 n, s, d;
WASMTableInstance *src_tbl_inst, *dst_tbl_inst;
read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx);
@ -3310,8 +3331,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
s = (uint32)POP_I32();
d = (uint32)POP_I32();
if (d + n > dst_tbl_inst->cur_size
|| s + n > src_tbl_inst->cur_size) {
if (offset_len_out_of_bounds(d, n,
dst_tbl_inst->cur_size)
|| offset_len_out_of_bounds(
s, n, src_tbl_inst->cur_size)) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;
@ -3381,11 +3404,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
fill_val = POP_I32();
i = POP_I32();
/* TODO: what if the element is not passive? */
/* TODO: what if the element is dropped? */
if (i + n > tbl_inst->cur_size) {
/* TODO: verify warning content */
if (offset_len_out_of_bounds(i, n,
tbl_inst->cur_size)) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;
@ -3503,23 +3523,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)(*(uint8 *)maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)LOAD_U16(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = LOAD_I32(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I32(readv);
@ -3538,30 +3558,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)(*(uint8 *)maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U16(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U32(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = LOAD_I64(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I64(readv);
@ -3580,23 +3600,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
*(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U32(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
break;
}
@ -3614,30 +3634,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
*(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U32(maddr, (uint32)sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
PUT_I64_TO_ADDR((uint32 *)maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
break;
}
@ -3657,32 +3677,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint8)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)(*(uint8 *)maddr);
if (readv == expect)
*(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint16)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)LOAD_U16(maddr);
if (readv == expect)
STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = LOAD_I32(maddr);
if (readv == expect)
STORE_U32(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I32(readv);
break;
@ -3703,43 +3723,43 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint8)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)(*(uint8 *)maddr);
if (readv == expect)
*(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint16)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U16(maddr);
if (readv == expect)
STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint32)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U32(maddr);
if (readv == expect)
STORE_U32(maddr, (uint32)(sval));
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_I64(maddr);
if (readv == expect)
STORE_I64(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I64(readv);
break;
@ -3772,7 +3792,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(DEBUG_OP_BREAK)
{
wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP);
exec_env->suspend_flags.flags |= 2;
WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags,
WASM_SUSPEND_FLAG_SUSPEND);
frame_ip--;
SYNC_ALL_TO_FRAME();
CHECK_SUSPEND_FLAGS();

View File

@ -35,7 +35,8 @@ typedef float64 CellType_F64;
#define CHECK_MEMORY_OVERFLOW(bytes) \
do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \
if (offset1 + bytes <= (uint64)get_linear_mem_size()) \
if (disable_bounds_checks \
|| offset1 + bytes <= (uint64)get_linear_mem_size()) \
/* If offset1 is in valid range, maddr must also \
be in valid range, no need to check it again. */ \
maddr = memory->memory_data + offset1; \
@ -43,15 +44,15 @@ typedef float64 CellType_F64;
goto out_of_bounds; \
} while (0)
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
do { \
uint64 offset1 = (uint32)(start); \
if (offset1 + bytes <= get_linear_mem_size()) \
/* App heap space is not valid space for \
bulk memory operation */ \
maddr = memory->memory_data + offset1; \
else \
goto out_of_bounds; \
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
do { \
uint64 offset1 = (uint32)(start); \
if (disable_bounds_checks || offset1 + bytes <= get_linear_mem_size()) \
/* App heap space is not valid space for \
bulk memory operation */ \
maddr = memory->memory_data + offset1; \
else \
goto out_of_bounds; \
} while (0)
#else
#define CHECK_MEMORY_OVERFLOW(bytes) \
@ -481,28 +482,28 @@ LOAD_PTR(void *addr)
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(1); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint32)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(2); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint32)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(4); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = LOAD_I32(maddr); \
STORE_U32(maddr, readv op sval); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
PUSH_I32(readv); \
break; \
@ -521,39 +522,39 @@ LOAD_PTR(void *addr)
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(1); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(2); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(4); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)LOAD_U32(maddr); \
STORE_U32(maddr, (uint32)(readv op sval)); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
else { \
uint64 op_result; \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(8); \
\
os_mutex_lock(&node->shared_mem_lock); \
shared_memory_lock(memory); \
readv = (uint64)LOAD_I64(maddr); \
op_result = readv op sval; \
STORE_I64(maddr, op_result); \
os_mutex_unlock(&node->shared_mem_lock); \
shared_memory_unlock(memory); \
} \
PUSH_I64(readv); \
break; \
@ -937,8 +938,9 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
if (!func_import->call_conv_wasm_c_api) {
native_func_pointer = module_inst->import_func_ptrs[cur_func_index];
}
else if (module_inst->e->c_api_func_imports) {
c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index;
else if (module_inst->e->common.c_api_func_imports) {
c_api_func_import =
module_inst->e->common.c_api_func_imports + cur_func_index;
native_func_pointer = c_api_func_import->func_ptr_linked;
}
@ -1064,18 +1066,17 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
#endif
#if WASM_ENABLE_THREAD_MGR != 0
#define CHECK_SUSPEND_FLAGS() \
do { \
os_mutex_lock(&exec_env->wait_lock); \
if (exec_env->suspend_flags.flags != 0) { \
if (exec_env->suspend_flags.flags & 0x01) { \
/* terminate current thread */ \
os_mutex_unlock(&exec_env->wait_lock); \
return; \
} \
/* TODO: support suspend and breakpoint */ \
} \
os_mutex_unlock(&exec_env->wait_lock); \
#define CHECK_SUSPEND_FLAGS() \
do { \
WASM_SUSPEND_FLAGS_LOCK(exec_env->wait_lock); \
if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) \
& WASM_SUSPEND_FLAG_TERMINATE) { \
/* terminate current thread */ \
WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \
return; \
} \
/* TODO: support suspend and breakpoint */ \
WASM_SUSPEND_FLAGS_UNLOCK(exec_env->wait_lock); \
} while (0)
#endif
@ -1166,10 +1167,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMFunctionInstance *cur_func,
WASMInterpFrame *prev_frame)
{
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
#endif
WASMMemoryInstance *memory = wasm_get_default_memory(module);
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
@ -1199,6 +1196,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint8 *maddr = NULL;
uint32 local_idx, local_offset, global_idx;
uint8 opcode, local_type, *global_addr;
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
bool disable_bounds_checks = !wasm_runtime_is_bounds_checks_enabled(
(WASMModuleInstanceCommon *)module);
#else
bool disable_bounds_checks = false;
#endif
#endif
#if WASM_ENABLE_LABELS_AS_VALUES != 0
#define HANDLE_OPCODE(op) &&HANDLE_##op
@ -3069,7 +3075,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
case WASM_OP_TABLE_INIT:
{
uint32 tbl_idx, elem_idx;
uint64 n, s, d;
uint32 n, s, d;
WASMTableInstance *tbl_inst;
elem_idx = read_uint32(frame_ip);
@ -3084,18 +3090,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
s = (uint32)POP_I32();
d = (uint32)POP_I32();
if (!n) {
break;
}
if (n + s > module->module->table_segments[elem_idx]
.function_count
|| d + n > tbl_inst->cur_size) {
if (offset_len_out_of_bounds(
s, n,
module->module->table_segments[elem_idx]
.function_count)
|| offset_len_out_of_bounds(d, n,
tbl_inst->cur_size)) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;
}
if (!n) {
break;
}
if (module->module->table_segments[elem_idx]
.is_dropped) {
wasm_set_exception(module,
@ -3134,7 +3143,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
case WASM_OP_TABLE_COPY:
{
uint32 src_tbl_idx, dst_tbl_idx;
uint64 n, s, d;
uint32 n, s, d;
WASMTableInstance *src_tbl_inst, *dst_tbl_inst;
dst_tbl_idx = read_uint32(frame_ip);
@ -3151,8 +3160,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
s = (uint32)POP_I32();
d = (uint32)POP_I32();
if (d + n > dst_tbl_inst->cur_size
|| s + n > src_tbl_inst->cur_size) {
if (offset_len_out_of_bounds(d, n,
dst_tbl_inst->cur_size)
|| offset_len_out_of_bounds(
s, n, src_tbl_inst->cur_size)) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;
@ -3223,7 +3234,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
fill_val = POP_I32();
i = POP_I32();
if (i + n > tbl_inst->cur_size) {
if (offset_len_out_of_bounds(i, n,
tbl_inst->cur_size)) {
wasm_set_exception(module,
"out of bounds table access");
goto got_exception;
@ -3338,23 +3350,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)(*(uint8 *)maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)LOAD_U16(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = LOAD_I32(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I32(readv);
@ -3373,30 +3385,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)(*(uint8 *)maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U16(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U32(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = LOAD_I64(maddr);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I64(readv);
@ -3414,23 +3426,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
*(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U32(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
break;
}
@ -3448,30 +3460,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
*(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_U32(maddr, (uint32)sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
STORE_I64(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
break;
}
@ -3491,32 +3503,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS(1);
expect = (uint8)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)(*(uint8 *)maddr);
if (readv == expect)
*(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
expect = (uint16)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint32)LOAD_U16(maddr);
if (readv == expect)
STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = LOAD_I32(maddr);
if (readv == expect)
STORE_U32(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I32(readv);
break;
@ -3537,43 +3549,43 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS(1);
expect = (uint8)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)(*(uint8 *)maddr);
if (readv == expect)
*(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2);
expect = (uint16)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U16(maddr);
if (readv == expect)
STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4);
expect = (uint32)expect;
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_U32(maddr);
if (readv == expect)
STORE_U32(maddr, (uint32)(sval));
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&node->shared_mem_lock);
shared_memory_lock(memory);
readv = (uint64)LOAD_I64(maddr);
if (readv == expect)
STORE_I64(maddr, sval);
os_mutex_unlock(&node->shared_mem_lock);
shared_memory_unlock(memory);
}
PUSH_I64(readv);
break;

View File

@ -7014,6 +7014,7 @@ static bool
copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
char *error_buf, uint32 error_buf_size)
{
bool ret = false;
int16 *frame_offset = NULL;
uint8 *cells = NULL, cell;
int16 *src_offsets = NULL;
@ -7084,13 +7085,13 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
if (is_if_block)
PUSH_OFFSET_TYPE(VALUE_TYPE_I32);
ret = true;
fail:
/* Free the emit data */
wasm_runtime_free(emit_data);
return true;
fail:
return false;
return ret;
}
#endif
@ -8063,9 +8064,13 @@ re_scan:
case WASM_OP_SELECT_T:
{
uint8 vec_len, ref_type;
#if WASM_ENABLE_FAST_INTERP != 0
uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled;
#endif
read_leb_uint32(p, p_end, vec_len);
if (!vec_len) {
if (vec_len != 1) {
/* typed select must have exactly one result */
set_error_buf(error_buf, error_buf_size,
"invalid result arity");
goto fail;
@ -8084,8 +8089,6 @@ re_scan:
#if WASM_ENABLE_FAST_INTERP != 0
if (loader_ctx->p_code_compiled) {
uint8 opcode_tmp = WASM_OP_SELECT;
uint8 *p_code_compiled_tmp =
loader_ctx->p_code_compiled - 2;
if (ref_type == VALUE_TYPE_V128) {
#if (WASM_ENABLE_SIMD == 0) \

View File

@ -6233,9 +6233,13 @@ re_scan:
case WASM_OP_SELECT_T:
{
uint8 vec_len, ref_type;
#if WASM_ENABLE_FAST_INTERP != 0
uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled;
#endif
read_leb_uint32(p, p_end, vec_len);
if (!vec_len) {
if (vec_len != 1) {
/* typed select must have exactly one result */
set_error_buf(error_buf, error_buf_size,
"invalid result arity");
goto fail;
@ -6254,8 +6258,6 @@ re_scan:
#if WASM_ENABLE_FAST_INTERP != 0
if (loader_ctx->p_code_compiled) {
uint8 opcode_tmp = WASM_OP_SELECT;
uint8 *p_code_compiled_tmp =
loader_ctx->p_code_compiled - 2;
if (ref_type == VALUE_TYPE_F64
|| ref_type == VALUE_TYPE_I64)

View File

@ -122,11 +122,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
}
#endif
#if WASM_ENABLE_SHARED_MEMORY != 0
if (memories[i]->is_shared) {
int32 ref_count = shared_memory_dec_reference(
(WASMModuleCommon *)module_inst->module);
bh_assert(ref_count >= 0);
if (shared_memory_is_shared(memories[i])) {
uint32 ref_count = shared_memory_dec_reference(memories[i]);
/* if the reference count is not zero,
don't free the memory */
if (ref_count > 0)
@ -159,7 +156,8 @@ memories_deinstantiate(WASMModuleInstance *module_inst,
}
static WASMMemoryInstance *
memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
WASMMemoryInstance *memory, uint32 memory_idx,
uint32 num_bytes_per_page, uint32 init_page_count,
uint32 max_page_count, uint32 heap_size, uint32 flags,
char *error_buf, uint32 error_buf_size)
@ -180,22 +178,11 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
bool is_shared_memory = flags & 0x02 ? true : false;
/* shared memory */
if (is_shared_memory) {
WASMSharedMemNode *node = wasm_module_get_shared_memory(
(WASMModuleCommon *)module_inst->module);
/* If the memory of this module has been instantiated,
return the memory instance directly */
if (node) {
uint32 ref_count;
ref_count = shared_memory_inc_reference(
(WASMModuleCommon *)module_inst->module);
bh_assert(ref_count > 0);
memory = (WASMMemoryInstance *)shared_memory_get_memory_inst(node);
bh_assert(memory);
(void)ref_count;
return memory;
}
if (is_shared_memory && parent != NULL) {
bh_assert(parent->memory_count > memory_idx);
memory = parent->memories[memory_idx];
shared_memory_inc_reference(memory);
return memory;
}
#endif /* end of WASM_ENABLE_SHARED_MEMORY */
@ -215,7 +202,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
if (num_bytes_per_page < heap_size) {
set_error_buf(error_buf, error_buf_size,
"failed to insert app heap into linear memory, "
"try using `--heap_size=0` option");
"try using `--heap-size=0` option");
return NULL;
}
}
@ -274,7 +261,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
if (init_page_count > DEFAULT_MAX_PAGES) {
set_error_buf(error_buf, error_buf_size,
"failed to insert app heap into linear memory, "
"try using `--heap_size=0` option");
"try using `--heap-size=0` option");
return NULL;
}
else if (init_page_count == DEFAULT_MAX_PAGES) {
@ -388,24 +375,13 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMMemoryInstance *memory,
#if WASM_ENABLE_SHARED_MEMORY != 0
if (is_shared_memory) {
memory->is_shared = true;
if (!shared_memory_set_memory_inst(
(WASMModuleCommon *)module_inst->module,
(WASMMemoryInstanceCommon *)memory)) {
set_error_buf(error_buf, error_buf_size, "allocate memory failed");
goto fail4;
}
memory->ref_count = 1;
}
#endif
LOG_VERBOSE("Memory instantiate success.");
return memory;
#if WASM_ENABLE_SHARED_MEMORY != 0
fail4:
if (heap_size > 0)
mem_allocator_destroy(memory->heap_handle);
#endif
fail3:
if (heap_size > 0)
wasm_runtime_free(memory->heap_handle);
@ -428,7 +404,8 @@ fail1:
*/
static WASMMemoryInstance **
memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
uint32 heap_size, char *error_buf, uint32 error_buf_size)
WASMModuleInstance *parent, uint32 heap_size,
char *error_buf, uint32 error_buf_size)
{
WASMImport *import;
uint32 mem_index = 0, i,
@ -474,26 +451,29 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
else
#endif
{
if (!(memories[mem_index++] = memory_instantiate(
module_inst, memory, num_bytes_per_page, init_page_count,
max_page_count, actual_heap_size, flags, error_buf,
error_buf_size))) {
if (!(memories[mem_index] = memory_instantiate(
module_inst, parent, memory, mem_index,
num_bytes_per_page, init_page_count, max_page_count,
actual_heap_size, flags, error_buf, error_buf_size))) {
memories_deinstantiate(module_inst, memories, memory_count);
return NULL;
}
mem_index++;
}
}
/* instantiate memories from memory section */
for (i = 0; i < module->memory_count; i++, memory++) {
if (!(memories[mem_index++] = memory_instantiate(
module_inst, memory, module->memories[i].num_bytes_per_page,
if (!(memories[mem_index] = memory_instantiate(
module_inst, parent, memory, mem_index,
module->memories[i].num_bytes_per_page,
module->memories[i].init_page_count,
module->memories[i].max_page_count, heap_size,
module->memories[i].flags, error_buf, error_buf_size))) {
memories_deinstantiate(module_inst, memories, memory_count);
return NULL;
}
mem_index++;
}
bh_assert(mem_index == memory_count);
@ -1104,10 +1084,14 @@ execute_post_instantiate_functions(WASMModuleInstance *module_inst,
goto fail;
}
#if WASM_ENABLE_LIBC_WASI != 0
if (initialize_func
&& !wasm_call_function(exec_env, initialize_func, 0, NULL)) {
goto fail;
}
#else
(void)initialize_func;
#endif
if (post_inst_func
&& !wasm_call_function(exec_env, post_inst_func, 0, NULL)) {
@ -1297,7 +1281,7 @@ sub_module_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
WASMModuleInstance *sub_module_inst = NULL;
sub_module_inst =
wasm_instantiate(sub_module, false, NULL, stack_size, heap_size,
wasm_instantiate(sub_module, NULL, NULL, stack_size, heap_size,
error_buf, error_buf_size);
if (!sub_module_inst) {
LOG_DEBUG("instantiate %s failed",
@ -1642,7 +1626,7 @@ wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode)
* Instantiate module
*/
WASMModuleInstance *
wasm_instantiate(WASMModule *module, bool is_sub_inst,
wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
WASMExecEnv *exec_env_main, uint32 stack_size,
uint32 heap_size, char *error_buf, uint32 error_buf_size)
{
@ -1659,6 +1643,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
#if WASM_ENABLE_MULTI_MODULE != 0
bool ret = false;
#endif
const bool is_sub_inst = parent != NULL;
if (!module)
return NULL;
@ -1777,8 +1762,9 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
/* Instantiate memories/tables/functions */
if ((module_inst->memory_count > 0
&& !(module_inst->memories = memories_instantiate(
module, module_inst, heap_size, error_buf, error_buf_size)))
&& !(module_inst->memories =
memories_instantiate(module, module_inst, parent, heap_size,
error_buf, error_buf_size)))
|| (module_inst->table_count > 0
&& !(module_inst->tables =
tables_instantiate(module, module_inst, first_table,
@ -1853,7 +1839,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
for (i = 0; i < module->data_seg_count; i++) {
WASMMemoryInstance *memory = NULL;
uint8 *memory_data = NULL;
uint32 memory_size = 0;
uint64 memory_size = 0;
WASMDataSeg *data_seg = module->data_segments[i];
#if WASM_ENABLE_BULK_MEMORY != 0
@ -1866,7 +1852,8 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
bh_assert(memory);
memory_data = memory->memory_data;
memory_size = memory->num_bytes_per_page * memory->cur_page_count;
memory_size =
(uint64)memory->num_bytes_per_page * memory->cur_page_count;
bh_assert(memory_data || memory_size == 0);
bh_assert(data_seg->base_offset.init_expr_type
@ -1912,7 +1899,7 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
/* check offset + length(could be zero) */
length = data_seg->data_length;
if (base_offset + length > memory_size) {
if ((uint64)base_offset + length > memory_size) {
LOG_DEBUG("base_offset(%d) + length(%d) > memory_size(%d)",
base_offset, length, memory_size);
#if WASM_ENABLE_REF_TYPES != 0
@ -1926,8 +1913,9 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
}
if (memory_data) {
bh_memcpy_s(memory_data + base_offset, memory_size - base_offset,
data_seg->data, length);
bh_memcpy_s(memory_data + base_offset,
(uint32)memory_size - base_offset, data_seg->data,
length);
}
}
@ -2097,16 +2085,6 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst,
}
#endif
#if WASM_ENABLE_WASI_NN != 0
if (!is_sub_inst) {
if (!(module_inst->e->wasi_nn_ctx = wasi_nn_initialize())) {
set_error_buf(error_buf, error_buf_size,
"wasi nn initialization failed");
goto fail;
}
}
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
if (!is_sub_inst) {
/* Add module instance into module's instance list */
@ -2222,16 +2200,6 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
sub_module_deinstantiate(module_inst);
#endif
#if WASM_ENABLE_LIBC_WASI != 0
/* Destroy wasi resource before freeing app heap, since some fields of
wasi contex are allocated from app heap, and if app heap is freed,
these fields will be set to NULL, we cannot free their internal data
which may allocated from global heap. */
/* Only destroy wasi ctx in the main module instance */
if (!is_sub_inst)
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
#endif
if (module_inst->memory_count > 0)
memories_deinstantiate(module_inst, module_inst->memories,
module_inst->memory_count);
@ -2261,16 +2229,15 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
}
#endif
if (module_inst->e->c_api_func_imports)
wasm_runtime_free(module_inst->e->c_api_func_imports);
if (module_inst->e->common.c_api_func_imports)
wasm_runtime_free(module_inst->e->common.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);
}
#if WASM_ENABLE_WASI_NN != 0
wasi_nn_destroy(module_inst);
#endif
wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
}
wasm_runtime_free(module_inst);
}
@ -2431,6 +2398,9 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
/* set thread handle and stack boundary */
wasm_exec_env_set_thread_info(exec_env);
/* set exec env so it can be later retrieved from instance */
module_inst->e->common.cur_exec_env = exec_env;
interp_call_wasm(module_inst, exec_env, function, argc, argv);
return !wasm_copy_exception(module_inst, NULL);
}
@ -3126,11 +3096,7 @@ llvm_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
{
bool ret;
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == exec_env->module_inst->module_type) {
return aot_call_indirect(exec_env, tbl_idx, elem_idx, argc, argv);
}
#endif
bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode);
ret = call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, false, 0);
#ifdef OS_ENABLE_HW_BOUND_CHECK
@ -3157,11 +3123,7 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
char buf[96];
bool ret = false;
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == exec_env->module_inst->module_type) {
return aot_invoke_native(exec_env, func_idx, argc, argv);
}
#endif
bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode);
module_inst = (WASMModuleInstance *)wasm_runtime_get_module_inst(exec_env);
module = module_inst->module;
@ -3174,8 +3136,9 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
import_func = &module->import_functions[func_idx].u.function;
if (import_func->call_conv_wasm_c_api) {
if (module_inst->e->c_api_func_imports) {
c_api_func_import = module_inst->e->c_api_func_imports + func_idx;
if (module_inst->e->common.c_api_func_imports) {
c_api_func_import =
module_inst->e->common.c_api_func_imports + func_idx;
func_ptr = c_api_func_import->func_ptr_linked;
}
else {
@ -3230,11 +3193,7 @@ llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index,
uint8 *maddr;
uint64 seg_len = 0;
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == module_inst->module_type) {
return aot_memory_init(module_inst, seg_index, offset, len, dst);
}
#endif
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
memory_inst = wasm_get_default_memory(module_inst);
module = module_inst->module;
@ -3260,11 +3219,7 @@ llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index,
bool
llvm_jit_data_drop(WASMModuleInstance *module_inst, uint32 seg_index)
{
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == module_inst->module_type) {
return aot_data_drop(module_inst, seg_index);
}
#endif
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
module_inst->module->data_segments[seg_index]->data_length = 0;
/* Currently we can't free the dropped data segment
@ -3279,11 +3234,7 @@ llvm_jit_drop_table_seg(WASMModuleInstance *module_inst, uint32 tbl_seg_idx)
{
WASMTableSeg *tbl_segs;
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == module_inst->module_type) {
return aot_drop_table_seg(module_inst, tbl_seg_idx);
}
#endif
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
tbl_segs = module_inst->module->table_segments;
tbl_segs[tbl_seg_idx].is_dropped = true;
@ -3297,12 +3248,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
WASMTableInstance *tbl_inst;
WASMTableSeg *tbl_seg;
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == module_inst->module_type) {
return aot_table_init(module_inst, tbl_idx, tbl_seg_idx, length,
src_offset, dst_offset);
}
#endif
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
tbl_inst = wasm_get_table_inst(module_inst, tbl_idx);
tbl_seg = module_inst->module->table_segments + tbl_seg_idx;
@ -3310,13 +3256,13 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
bh_assert(tbl_inst);
bh_assert(tbl_seg);
if (!length) {
if (offset_len_out_of_bounds(src_offset, length, tbl_seg->function_count)
|| offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) {
jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
return;
}
if (length + src_offset > tbl_seg->function_count
|| dst_offset + length > tbl_inst->cur_size) {
jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
if (!length) {
return;
}
@ -3345,21 +3291,16 @@ llvm_jit_table_copy(WASMModuleInstance *module_inst, uint32 src_tbl_idx,
WASMTableInstance *src_tbl_inst;
WASMTableInstance *dst_tbl_inst;
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == module_inst->module_type) {
aot_table_copy(module_inst, src_tbl_idx, dst_tbl_idx, length,
src_offset, dst_offset);
return;
}
#endif
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
src_tbl_inst = wasm_get_table_inst(module_inst, src_tbl_idx);
dst_tbl_inst = wasm_get_table_inst(module_inst, dst_tbl_idx);
bh_assert(src_tbl_inst);
bh_assert(dst_tbl_inst);
if ((uint64)dst_offset + length > dst_tbl_inst->cur_size
|| (uint64)src_offset + length > src_tbl_inst->cur_size) {
if (offset_len_out_of_bounds(dst_offset, length, dst_tbl_inst->cur_size)
|| offset_len_out_of_bounds(src_offset, length,
src_tbl_inst->cur_size)) {
jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
return;
}
@ -3381,17 +3322,12 @@ llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx,
{
WASMTableInstance *tbl_inst;
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == module_inst->module_type) {
aot_table_fill(module_inst, tbl_idx, length, val, data_offset);
return;
}
#endif
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
tbl_inst = wasm_get_table_inst(module_inst, tbl_idx);
bh_assert(tbl_inst);
if (data_offset + length > tbl_inst->cur_size) {
if (offset_len_out_of_bounds(data_offset, length, tbl_inst->cur_size)) {
jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS);
return;
}
@ -3408,11 +3344,7 @@ llvm_jit_table_grow(WASMModuleInstance *module_inst, uint32 tbl_idx,
WASMTableInstance *tbl_inst;
uint32 i, orig_size, total_size;
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == module_inst->module_type) {
return aot_table_grow(module_inst, tbl_idx, inc_size, init_val);
}
#endif
bh_assert(module_inst->module_type == Wasm_Module_Bytecode);
tbl_inst = wasm_get_table_inst(module_inst, tbl_idx);
if (!tbl_inst) {
@ -3452,11 +3384,7 @@ llvm_jit_alloc_frame(WASMExecEnv *exec_env, uint32 func_index)
WASMInterpFrame *frame;
uint32 size;
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == exec_env->module_inst->module_type) {
return aot_alloc_frame(exec_env, func_index);
}
#endif
bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode);
module_inst = (WASMModuleInstance *)exec_env->module_inst;
size = wasm_interp_interp_frame_size(0);
@ -3485,12 +3413,7 @@ llvm_jit_free_frame(WASMExecEnv *exec_env)
WASMInterpFrame *frame;
WASMInterpFrame *prev_frame;
#if WASM_ENABLE_JIT != 0
if (Wasm_Module_AoT == exec_env->module_inst->module_type) {
aot_free_frame(exec_env);
return;
}
#endif
bh_assert(exec_env->module_inst->module_type == Wasm_Module_Bytecode);
frame = wasm_exec_env_get_cur_frame(exec_env);
prev_frame = frame->prev_frame;

View File

@ -7,6 +7,7 @@
#define _WASM_RUNTIME_H
#include "wasm.h"
#include "bh_atomic.h"
#include "bh_hashmap.h"
#include "../common/wasm_runtime_common.h"
#include "../common/wasm_exec_env.h"
@ -79,7 +80,7 @@ struct WASMMemoryInstance {
/* Module type */
uint32 module_type;
/* Shared memory flag */
bool is_shared;
bh_atomic_32_t ref_count; /* 0: non-shared, > 0: reference count */
/* Number bytes per page */
uint32 num_bytes_per_page;
@ -209,8 +210,22 @@ typedef struct CApiFuncImport {
void *env_arg;
} CApiFuncImport;
/* The common part of WASMModuleInstanceExtra and AOTModuleInstanceExtra */
typedef struct WASMModuleInstanceExtraCommon {
void *contexts[WASM_MAX_INSTANCE_CONTEXTS];
CApiFuncImport *c_api_func_imports;
/* pointer to the exec env currently used */
WASMExecEnv *cur_exec_env;
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
/* Disable bounds checks or not */
bool disable_bounds_checks;
#endif
} WASMModuleInstanceExtraCommon;
/* Extra info of WASM module instance for interpreter/jit mode */
typedef struct WASMModuleInstanceExtra {
WASMModuleInstanceExtraCommon common;
WASMGlobalInstance *globals;
WASMFunctionInstance *functions;
@ -222,7 +237,6 @@ typedef struct WASMModuleInstanceExtra {
WASMFunctionInstance *free_function;
WASMFunctionInstance *retain_function;
CApiFuncImport *c_api_func_imports;
RunningMode running_mode;
#if WASM_ENABLE_MULTI_MODULE != 0
@ -241,10 +255,6 @@ typedef struct WASMModuleInstanceExtra {
&& WASM_ENABLE_LAZY_JIT != 0)
WASMModuleInstance *next;
#endif
#if WASM_ENABLE_WASI_NN != 0
WASINNContext *wasi_nn_ctx;
#endif
} WASMModuleInstanceExtra;
struct AOTFuncPerfProfInfo;
@ -290,12 +300,8 @@ struct WASMModuleInstance {
it denotes `AOTModule *` */
DefPointer(WASMModule *, module);
#if WASM_ENABLE_LIBC_WASI
/* WASI context */
DefPointer(WASIContext *, wasi_ctx);
#else
DefPointer(void *, wasi_ctx);
#endif
DefPointer(void *, used_to_be_wasi_ctx); /* unused */
DefPointer(WASMExecEnv *, exec_env_singleton);
/* Array of function pointers to import functions,
not available in AOTModuleInstance */
@ -400,7 +406,7 @@ void
wasm_unload(WASMModule *module);
WASMModuleInstance *
wasm_instantiate(WASMModule *module, bool is_sub_inst,
wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
WASMExecEnv *exec_env_main, uint32 stack_size,
uint32 heap_size, char *error_buf, uint32 error_buf_size);
@ -661,6 +667,16 @@ void
wasm_propagate_wasi_args(WASMModule *module);
#endif
#if WASM_ENABLE_THREAD_MGR != 0
void
exception_lock(WASMModuleInstance *module_inst);
void
exception_unlock(WASMModuleInstance *module_inst);
#else
#define exception_lock(module_inst) (void)(module_inst)
#define exception_unlock(module_inst) (void)(module_inst)
#endif
#ifdef __cplusplus
}
#endif

View File

@ -531,7 +531,8 @@ pthread_start_routine(void *arg)
else {
info_node->u.ret = (void *)(uintptr_t)argv[0];
#ifdef OS_ENABLE_HW_BOUND_CHECK
if (exec_env->suspend_flags.flags & 0x08)
if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags)
& WASM_SUSPEND_FLAG_EXIT)
/* argv[0] isn't set after longjmp(1) to
invoke_native_with_hw_bound_check */
info_node->u.ret = exec_env->thread_ret_value;
@ -558,9 +559,6 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
uint32 thread_handle;
uint32 stack_size = 8192;
int32 ret = -1;
#if WASM_ENABLE_LIBC_WASI != 0
WASIContext *wasi_ctx;
#endif
bh_assert(module);
bh_assert(module_inst);
@ -580,18 +578,14 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
#endif
if (!(new_module_inst = wasm_runtime_instantiate_internal(
module, true, exec_env, stack_size, 0, NULL, 0)))
module, module_inst, exec_env, stack_size, 0, NULL, 0)))
return -1;
/* Set custom_data to new module instance */
wasm_runtime_set_custom_data_internal(
new_module_inst, wasm_runtime_get_custom_data(module_inst));
#if WASM_ENABLE_LIBC_WASI != 0
wasi_ctx = get_wasi_ctx(module_inst);
if (wasi_ctx)
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
#endif
wasm_native_inherit_contexts(new_module_inst, module_inst);
if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst)))
goto fail;
@ -690,6 +684,14 @@ pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread,
bh_assert(node->joinable);
join_ret = 0;
ret = node->u.ret;
/* The target thread changes the node's status before calling
wasm_cluster_exit_thread to exit, so here its resources may
haven't been destroyed yet, we wait enough time to ensure that
they are actually destroyed to avoid unexpected behavior. */
os_mutex_lock(&exec_env->wait_lock);
os_cond_reltimedwait(&exec_env->wait_cond, &exec_env->wait_lock, 1000);
os_mutex_unlock(&exec_env->wait_lock);
}
if (retval_offset != 0)
@ -757,7 +759,6 @@ __pthread_self_wrapper(wasm_exec_env_t exec_env)
static void
pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
ThreadRoutineArgs *args = get_thread_arg(exec_env);
/* Currently exit main thread is not allowed */
if (!args)
@ -775,9 +776,6 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
/* destroy pthread key values */
call_key_destructor(exec_env);
/* routine exit, destroy instance */
wasm_runtime_deinstantiate_internal(module_inst, true);
if (!args->info_node->joinable) {
delete_thread_info_node(args->info_node);
}
@ -789,6 +787,8 @@ pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
wasm_runtime_free(args);
/* Don't destroy exec_env->module_inst in this functuntion since
it will be destroyed in wasm_cluster_exit_thread */
wasm_cluster_exit_thread(exec_env, (void *)(uintptr_t)retval_offset);
}

View File

@ -23,6 +23,7 @@ include(FetchContent)
set(RATS_BUILD_MODE "sgx"
CACHE INTERNAL "Select build mode for librats(host|occlum|sgxwasm)")
set(RATS_INSTALL_PATH "${CMAKE_BINARY_DIR}/librats" CACHE INTERNAL "")
set(BUILD_SAMPLES OFF CACHE BOOL "Disable de compilation of the librats samples" FORCE)
FetchContent_Declare(
librats
@ -34,8 +35,17 @@ if (NOT librats_POPULATED)
message("-- Fetching librats ..")
FetchContent_Populate(librats)
include_directories("${librats_SOURCE_DIR}/include")
# Prevent the propagation of the CMAKE_C_FLAGS of WAMR into librats
set(SAVED_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
set(CMAKE_C_FLAGS "")
# Import the building scripts of librats
add_subdirectory(${librats_SOURCE_DIR} ${librats_BINARY_DIR} EXCLUDE_FROM_ALL)
# Restore the CMAKE_C_FLAGS of WAMR
set(CMAKE_C_FLAGS ${SAVED_CMAKE_C_FLAGS})
endif()
file (GLOB source_all ${LIB_RATS_DIR}/*.c)

View File

@ -17,6 +17,8 @@ extern "C" {
#endif
typedef enum {
/* Used only for sock_addr_resolve hints */
SOCKET_ANY = -1,
SOCKET_DGRAM = 0,
SOCKET_STREAM,
} __wasi_sock_type_t;
@ -84,7 +86,7 @@ typedef struct __wasi_addr_t {
} addr;
} __wasi_addr_t;
typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
typedef enum { INET4 = 0, INET6, INET_UNSPEC } __wasi_address_family_t;
typedef struct __wasi_addr_info_t {
__wasi_addr_t addr;

View File

@ -430,6 +430,9 @@ addrinfo_hints_to_wasi_hints(const struct addrinfo *hints,
case AF_INET6:
wasi_hints->family = INET6;
break;
case AF_UNSPEC:
wasi_hints->family = INET_UNSPEC;
break;
default:
return __WASI_ERRNO_AFNOSUPPORT;
}
@ -440,6 +443,8 @@ addrinfo_hints_to_wasi_hints(const struct addrinfo *hints,
case SOCK_DGRAM:
wasi_hints->type = SOCKET_DGRAM;
break;
case 0:
wasi_hints->type = SOCKET_ANY;
default:
return __WASI_ERRNO_NOTSUP;
}

View File

@ -5,6 +5,8 @@
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#ifdef __wasi__
#include <wasi/api.h>
#include <sys/socket.h>
@ -39,11 +41,28 @@ test_nslookup(int af)
freeaddrinfo(res);
}
void *
test_nslookup_mt(void *params)
{
int *af = (int *)params;
test_nslookup(*af);
return NULL;
}
int
main()
{
test_nslookup(AF_INET); /* for ipv4 */
test_nslookup(AF_INET6); /* for ipv6 */
int afs[] = { AF_INET, AF_INET6 };
for (int i = 0; i < sizeof(afs) / sizeof(afs[0]); i++) {
pthread_t th;
printf("Testing %d in main thread...\n", afs[i]);
test_nslookup(afs[i]);
printf("Testing %d in a new thread...\n", afs[i]);
pthread_create(&th, NULL, test_nslookup_mt, &afs[i]);
pthread_join(th, NULL);
}
return 0;
}

View File

@ -5,6 +5,8 @@
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <time.h>
#ifdef __wasi__
#include <wasi/api.h>
#include <sys/socket.h>
@ -12,105 +14,123 @@
#endif
#include <arpa/inet.h>
#include <pthread.h>
#include <stdio.h>
#define SERVER_MSG "Message from server."
#define PORT 8989
pthread_mutex_t mut;
pthread_cond_t cond;
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int server_init_complete = 0;
char buffer[sizeof(SERVER_MSG) + 1];
struct socket_info {
union {
struct sockaddr_in addr_ipv4;
struct sockaddr_in6 addr_ipv6;
} addr;
typedef struct {
struct sockaddr_storage addr;
socklen_t addr_len;
int sock;
};
struct thread_args {
int family;
int protocol;
};
} socket_info_t;
struct socket_info
init_socket_addr(int family, int protocol)
void
wait_for_server(int wait_time_seconds)
{
int sock = socket(family, protocol, 0);
assert(sock != -1);
int res = 0;
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += wait_time_seconds;
struct socket_info info;
if (family == AF_INET) {
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
info.addr.addr_ipv4 = addr;
pthread_mutex_lock(&mut);
while (server_init_complete == 0) {
res = pthread_cond_timedwait(&cond, &mut, &ts);
if (res == ETIMEDOUT)
break;
}
else if (family == AF_INET6) {
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(PORT);
addr.sin6_addr = in6addr_loopback;
info.addr.addr_ipv6 = addr;
}
info.sock = sock;
return info;
pthread_mutex_unlock(&mut);
assert(res == 0);
}
void
assert_thread_args(struct thread_args *args)
notify_server_started()
{
assert(args->family == AF_INET || args->family == AF_INET6);
assert(args->protocol == SOCK_STREAM || args->protocol == SOCK_DGRAM);
pthread_mutex_lock(&mut);
server_init_complete = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mut);
}
socket_info_t
init_socket_addr(int family, int protocol)
{
socket_info_t info;
info.sock = socket(family, protocol, 0);
assert(info.sock != -1);
info.protocol = protocol;
memset(&info.addr, 0, sizeof(info.addr));
if (family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *)&info.addr;
addr->sin_family = AF_INET;
addr->sin_port = htons(PORT);
addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
info.addr_len = sizeof(struct sockaddr_in);
}
else if (family == AF_INET6) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&info.addr;
addr->sin6_family = AF_INET6;
addr->sin6_port = htons(PORT);
addr->sin6_addr = in6addr_loopback;
info.addr_len = sizeof(struct sockaddr_in6);
}
return info;
}
void *
server(void *arg)
{
server_init_complete = 0;
struct thread_args *args = (struct thread_args *)arg;
assert_thread_args(args);
struct socket_info init_server_sock =
init_socket_addr(args->family, args->protocol);
int server_sock = init_server_sock.sock;
socklen_t addr_size;
char buffer[sizeof(SERVER_MSG) + 1] = { 0 };
struct sockaddr_storage client_addr;
strcpy(buffer, SERVER_MSG);
socket_info_t *info = (socket_info_t *)arg;
struct sockaddr *server_addr = (struct sockaddr *)&info->addr;
int server_sock = info->sock;
struct sockaddr *server_addr = (struct sockaddr *)&init_server_sock.addr;
int ret = bind(server_sock, server_addr,
args->family == AF_INET ? sizeof(struct sockaddr_in)
: sizeof(struct sockaddr_in6));
assert(ret == 0);
int optval = 1;
assert(setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &optval,
sizeof(optval))
== 0);
(args->protocol == SOCK_STREAM) && listen(server_sock, 1);
pthread_mutex_lock(&mut);
server_init_complete = 1;
pthread_mutex_unlock(&mut);
pthread_cond_signal(&cond);
assert(bind(server_sock, server_addr, info->addr_len) == 0);
addr_size = sizeof(client_addr);
if (args->protocol == SOCK_STREAM) {
if (info->protocol == SOCK_STREAM)
listen(server_sock, 1);
notify_server_started();
socklen_t addr_size = info->addr_len;
if (info->protocol == SOCK_STREAM) {
int client_sock =
accept(server_sock, (struct sockaddr *)&client_addr, &addr_size);
assert(client_sock >= 0);
sendto(client_sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&client_addr, addr_size);
assert(close(client_sock) == 0);
assert(recv(client_sock, buffer, sizeof(buffer), 0) > 0);
strcpy(buffer, SERVER_MSG);
assert(send(client_sock, buffer, sizeof(buffer), 0) > 0);
assert(recv(client_sock, buffer, sizeof(buffer), 0) > 0);
}
else {
recvfrom(server_sock, buffer, sizeof(buffer), 0,
(struct sockaddr *)&client_addr, &addr_size);
sendto(server_sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&client_addr, addr_size);
assert(close(server_sock) == 0);
assert(recvfrom(server_sock, buffer, sizeof(buffer), 0,
(struct sockaddr *)&client_addr, &addr_size)
> 0);
strcpy(buffer, SERVER_MSG);
assert(sendto(server_sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&client_addr, addr_size)
> 0);
assert(recvfrom(server_sock, buffer, sizeof(buffer), 0,
(struct sockaddr *)&client_addr, &addr_size)
> 0);
}
assert(close(server_sock) == 0);
return NULL;
}
@ -118,46 +138,23 @@ server(void *arg)
void *
client(void *arg)
{
struct thread_args *args = (struct thread_args *)arg;
assert_thread_args(args);
char buffer[sizeof(SERVER_MSG) + 1];
socket_info_t *info = (socket_info_t *)arg;
int sock = info->sock;
struct sockaddr *addr = (struct sockaddr *)&info->addr;
pthread_mutex_lock(&mut);
wait_for_server(1);
while (server_init_complete == 0) {
pthread_cond_wait(&cond, &mut);
if (info->protocol == SOCK_STREAM) {
assert(connect(sock, addr, info->addr_len) != -1);
}
struct socket_info init_client_sock =
init_socket_addr(args->family, args->protocol);
int sock = init_client_sock.sock;
pthread_mutex_unlock(&mut);
if (args->family == AF_INET) {
struct sockaddr_in addr = init_client_sock.addr.addr_ipv4;
if (args->protocol == SOCK_STREAM) {
assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
}
else {
assert(sendto(sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&addr, sizeof(addr))
!= -1);
}
}
else {
struct sockaddr_in6 addr = init_client_sock.addr.addr_ipv6;
if (args->protocol == SOCK_STREAM) {
assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
}
else {
assert(sendto(sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&addr, sizeof(addr))
!= -1);
}
}
recv(sock, buffer, sizeof(buffer), 0);
assert(strcmp(buffer, SERVER_MSG) == 0);
assert(sendto(sock, "open", strlen("open"), 0, addr, info->addr_len) > 0);
assert(recv(sock, buffer, sizeof(buffer), 0) > 0);
assert(strncmp(buffer, SERVER_MSG, strlen(SERVER_MSG)) == 0);
assert(sendto(sock, "close", sizeof("close"), 0, addr, info->addr_len) > 0);
assert(close(sock) == 0);
return NULL;
}
@ -165,17 +162,19 @@ void
test_protocol(int family, int protocol)
{
pthread_t server_thread, client_thread;
assert(pthread_cond_init(&cond, NULL) == 0);
assert(pthread_mutex_init(&mut, NULL) == 0);
socket_info_t server_info = init_socket_addr(family, protocol);
socket_info_t client_info = init_socket_addr(family, protocol);
struct thread_args args = { family, protocol };
assert(pthread_create(&server_thread, NULL, server, (void *)&args) == 0);
assert(pthread_create(&client_thread, NULL, client, (void *)&args) == 0);
printf("Testing address family: %d protocol: %d\n", family, protocol);
server_init_complete = 0;
assert(pthread_create(&server_thread, NULL, server, (void *)&server_info)
== 0);
assert(pthread_create(&client_thread, NULL, client, (void *)&client_info)
== 0);
assert(pthread_join(server_thread, NULL) == 0);
assert(pthread_join(client_thread, NULL) == 0);
assert(pthread_mutex_destroy(&mut) == 0);
assert(pthread_cond_destroy(&cond) == 0);
}
int
@ -190,4 +189,4 @@ main(int argc, char **argv)
test_protocol(AF_INET6, SOCK_DGRAM);
return 0;
}
}

View File

@ -80,9 +80,6 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
int32 thread_id;
uint32 stack_size = 8192;
int32 ret = -1;
#if WASM_ENABLE_LIBC_WASI != 0
WASIContext *wasi_ctx;
#endif
bh_assert(module);
bh_assert(module_inst);
@ -90,7 +87,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
if (!(new_module_inst = wasm_runtime_instantiate_internal(
module, true, exec_env, stack_size, 0, NULL, 0)))
module, module_inst, exec_env, stack_size, 0, NULL, 0)))
return -1;
wasm_runtime_set_custom_data_internal(
@ -99,11 +96,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst)))
goto thread_preparation_fail;
#if WASM_ENABLE_LIBC_WASI != 0
wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
if (wasi_ctx)
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
#endif
wasm_native_inherit_contexts(new_module_inst, module_inst);
start_func = wasm_runtime_lookup_function(new_module_inst,
THREAD_START_FUNCTION, NULL);

View File

@ -0,0 +1,65 @@
#!/bin/bash
#
# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
set -eo pipefail
CC=${CC:=/opt/wasi-sdk/bin/clang}
WAMR_DIR=../../../../..
show_usage() {
echo "Usage: $0 [--sysroot PATH_TO_SYSROOT]"
echo "--sysroot PATH_TO_SYSROOT specify to build with custom sysroot for wasi-libc"
}
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
--sysroot)
sysroot_path="$2"
shift
shift
;;
--help)
show_usage
exit
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
rm -rf *.wasm
rm -rf *.aot
for test_c in *.c; do
test_wasm="$(basename $test_c .c).wasm"
if [[ -n "$sysroot_path" ]]; then
if [ ! -d "$sysroot_path" ]; then
echo "Directory $sysroot_path doesn't exist. Aborting"
exit 1
fi
sysroot_command="--sysroot $sysroot_path"
fi
echo "Compiling $test_c to $test_wasm"
$CC \
-target wasm32-wasi-threads \
-O2 \
-Wall \
-pthread \
-z stack-size=32768 \
-Wl,--export=__heap_base \
-Wl,--export=__data_end \
-Wl,--shared-memory,--max-memory=1966080 \
-Wl,--export=wasi_thread_start \
-Wl,--export=malloc \
-Wl,--export=free \
$sysroot_command \
$test_c -o $test_wasm
done

View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <pthread.h>
#include <errno.h>
#include "mutex_common.h"
int
main()
{
pthread_mutex_t mutex;
// Set mutex type to errorcheck. This type provides some additional checks
// (for example returns EDEADLK instead of deadlocking in some cases)
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init(&mutex_attr);
pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex, &mutex_attr);
pthread_mutexattr_destroy(&mutex_attr);
run_common_tests(&mutex);
fprintf(stderr, "Errorcheck mutex test is completed\n");
pthread_mutex_destroy(&mutex);
}

View File

@ -0,0 +1,3 @@
{
"name": "lib-wasi-threads stress tests"
}

View File

@ -0,0 +1,229 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef MUTEX_COMMON_H
#define MUTEX_COMMON_H
#include <pthread.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <stdbool.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
enum Constants {
NUM_ITER = 250000,
NUM_THREADS = 12,
NUM_RETRY = 8,
RETRY_SLEEP_TIME_US = 1000,
};
// We're counting how many times each thread was called using this array
// Main thread is also counted here so we need to make arrays bigger
typedef struct {
int tids[NUM_THREADS + 1];
int calls[NUM_THREADS + 1];
} StatCollector;
typedef struct {
pthread_mutex_t *mutex;
StatCollector stat;
int counter;
bool is_sleeping;
} MutexCounter;
// This enum defines whether thread should sleep to increase contention
enum SleepState {
NON_SLEEP = 0,
SLEEP = 1,
};
void
mutex_counter_init(MutexCounter *mutex_counter, pthread_mutex_t *mutex,
enum SleepState is_sleeping)
{
memset(mutex_counter, 0, sizeof(*mutex_counter));
mutex_counter->mutex = mutex;
mutex_counter->is_sleeping = is_sleeping;
}
// This function spawns the thread using exponential retries if it receives
// EAGAIN
static inline void
spawn_thread(pthread_t *tid, void *func, void *arg)
{
int status_code = -1;
int timeout_us = RETRY_SLEEP_TIME_US;
for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) {
status_code = pthread_create(tid, NULL, (void *(*)(void *))func, arg);
assert(status_code == 0 || status_code == EAGAIN);
if (status_code == EAGAIN) {
usleep(timeout_us);
timeout_us *= 2;
}
}
assert(status_code == 0 && "Thread creation should succeed");
}
// This function adds tid to our stat
static inline void
add_to_stat(StatCollector *stat, int tid)
{
int tid_num = 0;
for (; tid_num < NUM_THREADS + 1 && stat->tids[tid_num] != 0; ++tid_num) {
if (stat->tids[tid_num] == tid) {
stat->calls[tid_num]++;
return;
}
}
assert(tid_num < NUM_THREADS + 1);
stat->tids[tid_num] = tid;
stat->calls[tid_num] = 1;
}
// This function prints number of calls by TID
static inline void
print_stat(StatCollector *stat)
{
fprintf(stderr, "Thread calls count by TID\n");
for (int i = 0; i < NUM_THREADS + 1; ++i) {
if (stat->tids[i] != 0) {
fprintf(stderr, "TID: %d; Calls: %d\n", stat->tids[i],
stat->calls[i]);
}
}
}
// This function is run by the threads, it increases counter in a loop and then
// sleeps after unlocking the mutex to provide better contention
static inline void *
inc_shared_variable(void *arg)
{
MutexCounter *mutex_counter = (MutexCounter *)(arg);
int sleep_us = 0;
while (!pthread_mutex_lock(mutex_counter->mutex)
&& mutex_counter->counter < NUM_ITER) {
mutex_counter->counter++;
add_to_stat(&mutex_counter->stat, (int)(pthread_self()));
if (mutex_counter->is_sleeping) {
sleep_us = rand() % 1000;
}
assert(pthread_mutex_unlock(mutex_counter->mutex) == 0
&& "Should be able to unlock a mutex");
if (mutex_counter->is_sleeping) {
usleep(sleep_us);
}
}
assert(mutex_counter->counter == NUM_ITER);
assert(pthread_mutex_unlock(mutex_counter->mutex) == 0
&& "Should be able to unlock the mutex after test execution");
return NULL;
}
// Locking and unlocking a mutex in a single thread.
static inline void *
same_thread_lock_unlock_test(void *mutex)
{
for (int i = 0; i < NUM_ITER; ++i) {
assert(pthread_mutex_lock(mutex) == 0
&& "Main thread should be able to lock a mutex");
assert(pthread_mutex_unlock(mutex) == 0
&& "Main thread should be able to unlock a mutex");
}
return NULL;
}
// This function spawns a thread that locks and unlocks a mutex `NUM_ITER` times
// in a row
static inline void
same_non_main_thread_lock_unlock_test(pthread_mutex_t *mutex)
{
pthread_t tid = 0;
spawn_thread(&tid, same_thread_lock_unlock_test, mutex);
assert(tid != 0 && "TID can't be 0 after successful thread creation");
assert(pthread_join(tid, NULL) == 0
&& "Thread should be joined successfully");
}
// This function checks basic contention between main and non-main thread
// increasing the shared variable
static inline void
two_threads_inc_test(pthread_mutex_t *mutex)
{
MutexCounter mutex_counter;
mutex_counter_init(&mutex_counter, mutex, false);
pthread_t tid = 0;
spawn_thread(&tid, inc_shared_variable, &mutex_counter);
assert(tid != 0 && "TID can't be 0 after successful thread creation");
inc_shared_variable(&mutex_counter);
assert(pthread_join(tid, NULL) == 0
&& "Thread should be joined without errors");
assert(mutex_counter.counter == NUM_ITER);
}
// This function creates number of threads specified by NUM_THREADS and run
// concurrent increasing of shared variable
static inline void
max_threads_inc_test(pthread_mutex_t *mutex, int threads_num,
enum SleepState is_sleeping)
{
MutexCounter mutex_counter;
mutex_counter_init(&mutex_counter, mutex, is_sleeping);
pthread_t tids[threads_num];
for (int i = 0; i < threads_num; ++i) {
spawn_thread(&tids[i], inc_shared_variable, &mutex_counter);
}
inc_shared_variable(&mutex_counter);
for (int i = 0; i < threads_num; ++i) {
assert(pthread_join(tids[i], NULL) == 0
&& "Thread should be joined without errors");
}
print_stat(&mutex_counter.stat);
}
// This function just runs all the tests described above
static inline void
run_common_tests(pthread_mutex_t *mutex)
{
srand(time(NULL));
fprintf(stderr, "Starting same_thread_lock_unlock_test test\n");
same_thread_lock_unlock_test(mutex);
fprintf(stderr, "Finished same_thread_lock_unlock_test test\n");
fprintf(stderr, "Starting same_non_main_thread_lock_unlock_test test\n");
same_non_main_thread_lock_unlock_test(mutex);
fprintf(stderr, "Finished same_non_main_thread_lock_unlock_test test\n");
fprintf(stderr, "Starting two_threads_inc_test test\n");
two_threads_inc_test(mutex);
fprintf(stderr, "Finished two_threads_inc_test test\n");
fprintf(stderr, "Starting max_threads_inc_test_sleep test\n");
max_threads_inc_test(mutex, NUM_THREADS, SLEEP);
fprintf(stderr, "Finished concurrent_inc sleep test\n");
fprintf(stderr, "Starting max_threads_inc_test_non_sleep test\n");
max_threads_inc_test(mutex, NUM_THREADS, NON_SLEEP);
fprintf(stderr, "Finished max_threads_inc_test test\n");
}
#endif // MUTEX_COMMON_H

View File

@ -0,0 +1,20 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <pthread.h>
#include <errno.h>
#include "mutex_common.h"
int
main()
{
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
run_common_tests(&mutex);
fprintf(stderr, "Normal mutex test is completed\n");
pthread_mutex_destroy(&mutex);
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <pthread.h>
#include <errno.h>
#include "mutex_common.h"
void
multiple_same_thread_lock(void *mutex)
{
for (int i = 0; i < 100; ++i) {
assert(pthread_mutex_lock(mutex) == 0
&& "Recursive mutex should allow multiple locking");
}
for (int i = 0; i < 100; ++i) {
assert(pthread_mutex_unlock(mutex) == 0
&& "Recursive mutex should allow multiple unlocking");
}
}
void *
same_thread_multiple_rec_mutex_lock(void *mutex)
{
for (int i = 0; i < NUM_ITER; ++i) {
multiple_same_thread_lock(mutex);
}
return NULL;
}
int
main()
{
pthread_mutex_t mutex;
// Set mutex type to recursive. This type allows multiple locking and
// unlocking within the same thread
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init(&mutex_attr);
pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex, &mutex_attr);
pthread_mutexattr_destroy(&mutex_attr);
run_common_tests(&mutex);
fprintf(stderr, "Starting same_thread_multiple_rec_mutex_lock test\n");
same_thread_multiple_rec_mutex_lock(&mutex);
fprintf(stderr, "Finished same_thread_multiple_rec_mutex_lock test\n");
fprintf(stderr, "Starting same_thread_multiple_rec_mutex_lock test in "
"non-main thread\n");
pthread_t tid;
spawn_thread(&tid, same_thread_multiple_rec_mutex_lock, &mutex);
assert(pthread_join(tid, NULL) == 0
&& "Non-main thread should be joined successfully");
fprintf(stderr, "Finished same_thread_multiple_rec_mutex_lock test in "
"non-main thread\n");
fprintf(stderr, "Recursive mutex test is completed\n");
pthread_mutex_destroy(&mutex);
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include <assert.h>
#include <errno.h>
#include <math.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
enum CONSTANTS {
NUM_ITER = 100000,
NUM_RETRY = 8,
MAX_NUM_THREADS = 12,
RETRY_SLEEP_TIME_US = 2000,
};
unsigned prime_numbers_count = 0;
bool
is_prime(unsigned int num)
{
for (unsigned int i = 2; i <= (unsigned int)(sqrt(num)); ++i) {
if (num % i == 0) {
return false;
}
}
return true;
}
void *
check_if_prime(void *value)
{
unsigned int *num = (unsigned int *)(value);
usleep(10000);
if (is_prime(*num)) {
__atomic_fetch_add(&prime_numbers_count, 1, __ATOMIC_SEQ_CST);
}
return NULL;
}
unsigned int
validate()
{
unsigned int counter = 0;
for (unsigned int i = 2; i <= NUM_ITER; ++i) {
counter += is_prime(i);
}
return counter;
}
void
spawn_thread(pthread_t *thread, unsigned int *arg)
{
int status_code = -1;
int timeout_us = RETRY_SLEEP_TIME_US;
for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) {
status_code = pthread_create(thread, NULL, &check_if_prime, arg);
assert(status_code == 0 || status_code == EAGAIN);
if (status_code == EAGAIN) {
usleep(timeout_us);
timeout_us *= 2;
}
}
assert(status_code == 0 && "Thread creation should succeed");
}
int
main(int argc, char **argv)
{
pthread_t threads[MAX_NUM_THREADS];
unsigned int args[MAX_NUM_THREADS];
double percentage = 0.1;
for (unsigned int factorised_number = 2; factorised_number < NUM_ITER;
++factorised_number) {
if (factorised_number > NUM_ITER * percentage) {
fprintf(stderr, "Stress test is %d%% finished\n",
(unsigned int)(percentage * 100));
percentage += 0.1;
}
unsigned int thread_num = factorised_number % MAX_NUM_THREADS;
if (threads[thread_num] != 0) {
assert(pthread_join(threads[thread_num], NULL) == 0);
}
args[thread_num] = factorised_number;
usleep(RETRY_SLEEP_TIME_US);
spawn_thread(&threads[thread_num], &args[thread_num]);
assert(threads[thread_num] != 0);
}
for (int i = 0; i < MAX_NUM_THREADS; ++i) {
assert(threads[i] == 0 || pthread_join(threads[i], NULL) == 0);
}
// Check the test results
assert(
prime_numbers_count == validate()
&& "Answer mismatch between tested code and reference implementation");
fprintf(stderr, "Stress test finished successfully\n");
return 0;
}

View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
enum CONSTANTS {
NUM_ITER = 200000,
NUM_RETRY = 8,
MAX_NUM_THREADS = 12,
RETRY_SLEEP_TIME_US = 4000,
SECOND = 1000 * 1000 * 1000
};
int threads_executed = 0;
unsigned int threads_creation_tried = 0;
unsigned int threads_in_use = 0;
void *
thread_func(void *arg)
{
(void)(arg);
__atomic_fetch_add(&threads_executed, 1, __ATOMIC_RELAXED);
__atomic_fetch_sub(&threads_in_use, 1, __ATOMIC_SEQ_CST);
return NULL;
}
void
spawn_thread(pthread_t *thread)
{
int status_code = -1;
int timeout_us = RETRY_SLEEP_TIME_US;
for (int tries = 0; status_code != 0 && tries < NUM_RETRY; ++tries) {
status_code = pthread_create(thread, NULL, &thread_func, NULL);
__atomic_fetch_add(&threads_creation_tried, 1, __ATOMIC_RELAXED);
assert(status_code == 0 || status_code == EAGAIN);
if (status_code == EAGAIN) {
usleep(timeout_us);
timeout_us *= 2;
}
}
assert(status_code == 0 && "Thread creation should succeed");
}
int
main(int argc, char **argv)
{
double percentage = 0.1;
for (int iter = 0; iter < NUM_ITER; ++iter) {
if (iter > NUM_ITER * percentage) {
fprintf(stderr, "Spawning stress test is %d%% finished\n",
(unsigned int)(percentage * 100));
percentage += 0.1;
}
while (__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST)
== MAX_NUM_THREADS) {
usleep(100);
}
__atomic_fetch_add(&threads_in_use, 1, __ATOMIC_SEQ_CST);
pthread_t tmp;
spawn_thread(&tmp);
pthread_detach(tmp);
}
while ((__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) != 0)) {
// Casting to int* to supress compiler warning
__builtin_wasm_memory_atomic_wait32((int *)(&threads_in_use), 0,
SECOND);
}
assert(__atomic_load_n(&threads_in_use, __ATOMIC_SEQ_CST) == 0);
// Validation
assert(threads_creation_tried >= threads_executed
&& "Test executed more threads than were created");
assert((1. * threads_creation_tried) / threads_executed < 2.5
&& "Ensuring that we're retrying thread creation less than 2.5 "
"times on average ");
fprintf(stderr,
"Spawning stress test finished successfully executed %d threads "
"with retry ratio %f\n",
threads_creation_tried,
(1. * threads_creation_tried) / threads_executed);
return 0;
}

View File

@ -9,18 +9,57 @@ set -eo pipefail
CC=${CC:=/opt/wasi-sdk/bin/clang}
WAMR_DIR=../../../../..
show_usage() {
echo "Usage: $0 [--sysroot PATH_TO_SYSROOT]"
echo "--sysroot PATH_TO_SYSROOT specify to build with custom sysroot for wasi-libc"
}
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
--sysroot)
sysroot_path="$2"
shift
shift
;;
--help)
show_usage
exit
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
# Stress tests names
thread_start_file_exclusions=("linear_memory_size_update.wasm")
rm -rf *.wasm
rm -rf *.aot
for test_c in *.c; do
test_wasm="$(basename $test_c .c).wasm"
if [ $test_wasm = "linear_memory_size_update.wasm" ]; then
if [[ " ${thread_start_file_exclusions[@]} " =~ " ${test_wasm} " ]] ; then
thread_start_file=""
else
thread_start_file=$WAMR_DIR/samples/wasi-threads/wasm-apps/wasi_thread_start.S
fi
if [[ -n "$sysroot_path" ]]; then
if [ ! -d "$sysroot_path" ]; then
echo "Directory $sysroot_path doesn't exist. Aborting"
exit 1
fi
sysroot_command="--sysroot $sysroot_path"
fi
echo "Compiling $test_c to $test_wasm"
$CC \
-target wasm32-wasi-threads \
-O2 \
-pthread -ftls-model=local-exec \
-z stack-size=32768 \
-Wl,--export=__heap_base \
@ -30,6 +69,7 @@ for test_c in *.c; do
-Wl,--export=malloc \
-Wl,--export=free \
-I $WAMR_DIR/samples/wasi-threads/wasm-apps \
$sysroot_command \
$thread_start_file \
$test_c -o $test_wasm
done

View File

@ -65,7 +65,7 @@ main(int argc, char **argv)
assert(start_args_init(&data[i].base));
thread_ids[i] = __wasi_thread_spawn(&data[i]);
printf("Thread created with id=%d\n", thread_ids[i]);
assert(thread_ids[i] > 0 && "Thread creation failed");
ASSERT_VALID_TID(thread_ids[i]);
for (int j = 0; j < i; j++) {
assert(thread_ids[i] != thread_ids[j] && "Duplicated TIDs");

View File

@ -49,7 +49,7 @@ main(int argc, char **argv)
for (int i = 0; i < NUM_THREADS; i++) {
assert(start_args_init(&data[i].base));
thread_ids[i] = __wasi_thread_spawn(&data[i]);
assert(thread_ids[i] > 0 && "Thread creation failed");
ASSERT_VALID_TID(thread_ids[i]);
}
printf("Wait for threads to finish\n");

View File

@ -61,7 +61,7 @@ main(int argc, char **argv)
for (int i = 0; i < NUM_THREADS; i++) {
assert(start_args_init(&data[i].base));
thread_ids[i] = __wasi_thread_spawn(&data[i]);
assert(thread_ids[i] > 0 && "Thread creation failed");
ASSERT_VALID_TID(thread_ids[i]);
}
printf("Wait for threads to finish\n");

View File

@ -0,0 +1,3 @@
{
"name": "lib-wasi-threads tests"
}

View File

@ -38,7 +38,7 @@ main(int argc, char **argv)
assert(start_args_init(&data.base));
int thread_id = __wasi_thread_spawn(&data);
assert(thread_id > 0 && "Thread creation failed");
ASSERT_VALID_TID(thread_id);
return EXIT_SUCCESS;
}

View File

@ -69,7 +69,7 @@ main(int argc, char **argv)
data[i].iteration = i;
thread_ids[i] = __wasi_thread_spawn(&data[i]);
assert(thread_ids[i] > 0 && "Thread creation failed");
ASSERT_VALID_TID(thread_ids[i]);
}
printf("Wait for threads to finish\n");

View File

@ -21,7 +21,8 @@ tid_allocator_init(TidAllocator *tid_allocator)
return false;
for (int64 i = tid_allocator->pos - 1; i >= 0; i--)
tid_allocator->ids[i] = TID_MIN + (tid_allocator->pos - 1 - i);
tid_allocator->ids[i] =
(uint32)(TID_MIN + (tid_allocator->pos - 1 - i));
return true;
}
@ -54,7 +55,8 @@ tid_allocator_get_tid(TidAllocator *tid_allocator)
LOG_ERROR("Overflow detected during realloc");
return -1;
}
int32 *tmp = wasm_runtime_realloc(tid_allocator->ids, realloc_size);
int32 *tmp =
wasm_runtime_realloc(tid_allocator->ids, (uint32)realloc_size);
if (tmp == NULL) {
LOG_ERROR("Thread ID allocator realloc failed");
return -1;
@ -64,7 +66,8 @@ tid_allocator_get_tid(TidAllocator *tid_allocator)
tid_allocator->pos = new_size - old_size;
tid_allocator->ids = tmp;
for (int64 i = tid_allocator->pos - 1; i >= 0; i--)
tid_allocator->ids[i] = TID_MIN + (tid_allocator->size - 1 - i);
tid_allocator->ids[i] =
(uint32)(TID_MIN + (tid_allocator->size - 1 - i));
}
// Pop available thread identifier from the stack
@ -77,4 +80,4 @@ tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id)
// Release thread identifier by pushing it into the stack
bh_assert(tid_allocator->pos < tid_allocator->size);
tid_allocator->ids[tid_allocator->pos++] = thread_id;
}
}

View File

@ -8,8 +8,14 @@
#include "platform_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TID_ALLOCATOR_INIT_SIZE CLUSTER_MAX_THREAD_NUM
enum {
/* Keep it in sync with
https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids */
TID_MIN = 1,
TID_MAX = 0x1FFFFFFF
}; // Reserved TIDs (WASI specification)
@ -33,4 +39,8 @@ tid_allocator_get_tid(TidAllocator *tid_allocator);
void
tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id);
#ifdef __cplusplus
}
#endif
#endif /* _TID_ALLOCATOR_H */

View File

@ -0,0 +1,6 @@
# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
create_wamr_unit_test(wasi_threads
${CMAKE_CURRENT_LIST_DIR}/test_tid_allocator.cpp
)

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <gtest/gtest.h>
#include "tid_allocator.h"
#include <stdint.h>
class TidAllocatorTest : public ::testing::Test
{
protected:
void SetUp() override { ASSERT_TRUE(tid_allocator_init(&_allocator)); }
void TearDown() override { tid_allocator_deinit(&_allocator); }
TidAllocator _allocator;
};
static bool
is_tid_valid(int32 tid)
{
/* See: https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids
*/
return tid >= TID_MIN && tid <= TID_MAX;
}
TEST_F(TidAllocatorTest, BasicTest)
{
int32 tid = tid_allocator_get_tid(&_allocator);
ASSERT_TRUE(is_tid_valid(tid));
}
TEST_F(TidAllocatorTest, ShouldFailOnAllocatingMoreThanAllowedThreadIDs)
{
int32 last_tid = 0;
for (int32 i = 0; i < TID_MAX + 1; i++) {
last_tid = tid_allocator_get_tid(&_allocator);
if (last_tid < 0) {
break;
}
ASSERT_TRUE(is_tid_valid(last_tid));
}
ASSERT_LT(last_tid, 0);
}
TEST_F(TidAllocatorTest, ShouldAllocateMoreThanAllowedTIDsIfOldTIDsAreReleased)
{
int32 last_tid = 0;
for (int32 i = 0; i < TID_MAX + 1; i++) {
if (last_tid != 0) {
tid_allocator_release_tid(&_allocator, last_tid);
}
last_tid = tid_allocator_get_tid(&_allocator);
ASSERT_TRUE(is_tid_valid(last_tid));
}
}

View File

@ -3,7 +3,7 @@
set (LIBC_WASI_DIR ${CMAKE_CURRENT_LIST_DIR})
set (LIBUV_VERSION v1.44.2)
set (LIBUV_VERSION v1.46.0)
add_definitions (-DWASM_ENABLE_LIBC_WASI=1 -DWASM_ENABLE_UVWASI=1)

View File

@ -264,37 +264,6 @@ typedef uint8_t __wasi_sdflags_t;
typedef uint16_t __wasi_siflags_t;
typedef uint8_t __wasi_signal_t;
// 0 is reserved; POSIX has special semantics for kill(pid, 0).
#define __WASI_SIGHUP (1)
#define __WASI_SIGINT (2)
#define __WASI_SIGQUIT (3)
#define __WASI_SIGILL (4)
#define __WASI_SIGTRAP (5)
#define __WASI_SIGABRT (6)
#define __WASI_SIGBUS (7)
#define __WASI_SIGFPE (8)
#define __WASI_SIGKILL (9)
#define __WASI_SIGUSR1 (10)
#define __WASI_SIGSEGV (11)
#define __WASI_SIGUSR2 (12)
#define __WASI_SIGPIPE (13)
#define __WASI_SIGALRM (14)
#define __WASI_SIGTERM (15)
#define __WASI_SIGCHLD (16)
#define __WASI_SIGCONT (17)
#define __WASI_SIGSTOP (18)
#define __WASI_SIGTSTP (19)
#define __WASI_SIGTTIN (20)
#define __WASI_SIGTTOU (21)
#define __WASI_SIGURG (22)
#define __WASI_SIGXCPU (23)
#define __WASI_SIGXFSZ (24)
#define __WASI_SIGVTALRM (25)
#define __WASI_SIGPROF (26)
#define __WASI_SIGWINCH (27)
#define __WASI_SIGPOLL (28)
#define __WASI_SIGPWR (29)
#define __WASI_SIGSYS (30)
typedef uint16_t __wasi_subclockflags_t;
#define __WASI_SUBSCRIPTION_CLOCK_ABSTIME (0x0001)
@ -552,6 +521,8 @@ _Static_assert(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset"
/* keep syncing with wasi_socket_ext.h */
typedef enum {
/* Used only for sock_addr_resolve hints */
SOCKET_ANY = -1,
SOCKET_DGRAM = 0,
SOCKET_STREAM,
} __wasi_sock_type_t;
@ -605,7 +576,7 @@ typedef struct __wasi_addr_t {
} addr;
} __wasi_addr_t;
typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
typedef enum { INET4 = 0, INET6, INET_UNSPEC } __wasi_address_family_t;
typedef struct __wasi_addr_info_t {
__wasi_addr_t addr;
@ -627,17 +598,13 @@ typedef struct __wasi_addr_info_hints_t {
#endif
__wasi_errno_t wasmtime_ssp_args_get(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct argv_environ_values *arg_environ,
#endif
char **argv,
char *argv_buf
) WASMTIME_SSP_SYSCALL_NAME(args_get) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_args_sizes_get(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct argv_environ_values *arg_environ,
#endif
size_t *argc,
size_t *argv_buf_size
) WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) __attribute__((__warn_unused_result__));
@ -654,57 +621,43 @@ __wasi_errno_t wasmtime_ssp_clock_time_get(
) WASMTIME_SSP_SYSCALL_NAME(clock_time_get) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_environ_get(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct argv_environ_values *arg_environ,
#endif
char **environ,
char *environ_buf
) WASMTIME_SSP_SYSCALL_NAME(environ_get) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_environ_sizes_get(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct argv_environ_values *arg_environ,
#endif
size_t *environ_count,
size_t *environ_buf_size
) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_prestat_get(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_prestats *prestats,
#endif
__wasi_fd_t fd,
__wasi_prestat_t *buf
) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_prestat_dir_name(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_prestats *prestats,
#endif
__wasi_fd_t fd,
char *path,
size_t path_len
) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_close(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
struct fd_prestats *prestats,
#endif
__wasi_fd_t fd
) WASMTIME_SSP_SYSCALL_NAME(fd_close) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_datasync(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd
) WASMTIME_SSP_SYSCALL_NAME(fd_datasync) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_pread(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
const __wasi_iovec_t *iovs,
size_t iovs_len,
@ -713,9 +666,7 @@ __wasi_errno_t wasmtime_ssp_fd_pread(
) WASMTIME_SSP_SYSCALL_NAME(fd_pread) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_pwrite(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
const __wasi_ciovec_t *iovs,
size_t iovs_len,
@ -724,9 +675,7 @@ __wasi_errno_t wasmtime_ssp_fd_pwrite(
) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_read(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
const __wasi_iovec_t *iovs,
size_t iovs_len,
@ -734,18 +683,14 @@ __wasi_errno_t wasmtime_ssp_fd_read(
) WASMTIME_SSP_SYSCALL_NAME(fd_read) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_renumber(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
struct fd_prestats *prestats,
#endif
__wasi_fd_t from,
__wasi_fd_t to
) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_seek(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_filedelta_t offset,
__wasi_whence_t whence,
@ -753,49 +698,37 @@ __wasi_errno_t wasmtime_ssp_fd_seek(
) WASMTIME_SSP_SYSCALL_NAME(fd_seek) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_tell(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_filesize_t *newoffset
) WASMTIME_SSP_SYSCALL_NAME(fd_tell) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_fdstat_get(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_fdstat_t *buf
) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_fdflags_t flags
) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_rights_t fs_rights_base,
__wasi_rights_t fs_rights_inheriting
) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_sync(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd
) WASMTIME_SSP_SYSCALL_NAME(fd_sync) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_write(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
const __wasi_ciovec_t *iovs,
size_t iovs_len,
@ -803,9 +736,7 @@ __wasi_errno_t wasmtime_ssp_fd_write(
) WASMTIME_SSP_SYSCALL_NAME(fd_write) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_advise(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_filesize_t offset,
__wasi_filesize_t len,
@ -813,28 +744,22 @@ __wasi_errno_t wasmtime_ssp_fd_advise(
) WASMTIME_SSP_SYSCALL_NAME(fd_advise) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_allocate(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_filesize_t offset,
__wasi_filesize_t len
) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_path_create_directory(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
const char *path,
size_t path_len
) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_path_link(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
struct fd_prestats *prestats,
#endif
__wasi_fd_t old_fd,
__wasi_lookupflags_t old_flags,
const char *old_path,
@ -845,9 +770,7 @@ __wasi_errno_t wasmtime_ssp_path_link(
) WASMTIME_SSP_SYSCALL_NAME(path_link) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_path_open(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t dirfd,
__wasi_lookupflags_t dirflags,
const char *path,
@ -860,9 +783,7 @@ __wasi_errno_t wasmtime_ssp_path_open(
) WASMTIME_SSP_SYSCALL_NAME(path_open) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_readdir(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
void *buf,
size_t buf_len,
@ -871,9 +792,7 @@ __wasi_errno_t wasmtime_ssp_fd_readdir(
) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_path_readlink(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
const char *path,
size_t path_len,
@ -883,9 +802,7 @@ __wasi_errno_t wasmtime_ssp_path_readlink(
) WASMTIME_SSP_SYSCALL_NAME(path_readlink) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_path_rename(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t old_fd,
const char *old_path,
size_t old_path_len,
@ -895,17 +812,13 @@ __wasi_errno_t wasmtime_ssp_path_rename(
) WASMTIME_SSP_SYSCALL_NAME(path_rename) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_filestat_get(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_filestat_t *buf
) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_filestat_set_times(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_timestamp_t st_atim,
__wasi_timestamp_t st_mtim,
@ -913,17 +826,13 @@ __wasi_errno_t wasmtime_ssp_fd_filestat_set_times(
) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_filestat_set_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_filesize_t st_size
) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_path_filestat_get(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_lookupflags_t flags,
const char *path,
@ -932,9 +841,7 @@ __wasi_errno_t wasmtime_ssp_path_filestat_get(
) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_path_filestat_set_times(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
__wasi_lookupflags_t flags,
const char *path,
@ -945,10 +852,8 @@ __wasi_errno_t wasmtime_ssp_path_filestat_set_times(
) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_path_symlink(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
struct fd_prestats *prestats,
#endif
const char *old_path,
size_t old_path_len,
__wasi_fd_t fd,
@ -957,47 +862,27 @@ __wasi_errno_t wasmtime_ssp_path_symlink(
) WASMTIME_SSP_SYSCALL_NAME(path_symlink) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_path_unlink_file(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
const char *path,
size_t path_len
) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_path_remove_directory(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd,
const char *path,
size_t path_len
) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_poll_oneoff(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
const __wasi_subscription_t *in,
__wasi_event_t *out,
size_t nsubscriptions,
size_t *nevents
) WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) __attribute__((__warn_unused_result__));
#if 0
/**
* We throw exception in libc-wasi wrapper function wasi_proc_exit()
* but not call this function.
*/
_Noreturn void wasmtime_ssp_proc_exit(
__wasi_exitcode_t rval
) WASMTIME_SSP_SYSCALL_NAME(proc_exit);
#endif
__wasi_errno_t wasmtime_ssp_proc_raise(
__wasi_signal_t sig
) WASMTIME_SSP_SYSCALL_NAME(proc_raise) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_random_get(
void *buf,
size_t buf_len
@ -1005,50 +890,38 @@ __wasi_errno_t wasmtime_ssp_random_get(
__wasi_errno_t
wasi_ssp_sock_accept(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_addr_local(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_addr_t *addr
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_addr_remote(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_addr_t *addr
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_open(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype,
__wasi_fd_t *sockfd
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_bind(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t fd, __wasi_addr_t *addr
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_addr_resolve(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, char **ns_lookup_list,
#endif
const char *host, const char* service,
__wasi_addr_info_hints_t *hints, __wasi_addr_info_t *addr_info,
__wasi_size_t addr_info_size, __wasi_size_t *max_info_size
@ -1056,88 +929,66 @@ wasi_ssp_sock_addr_resolve(
__wasi_errno_t
wasi_ssp_sock_connect(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t fd, __wasi_addr_t *addr
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_get_recv_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_size_t *size
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_get_reuse_addr(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8_t *reuse
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_get_reuse_port(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8_t *reuse
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_get_send_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_size_t *size
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_set_recv_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_size_t size
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_set_reuse_addr(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8_t reuse
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_set_reuse_port(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, uint8_t reuse
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_set_send_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_size_t size
) __attribute__((__warn_unused_result__));
__wasi_errno_t
wasi_ssp_sock_listen(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t fd, __wasi_size_t backlog
) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_recv(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
void *buf,
size_t buf_len,
@ -1145,9 +996,7 @@ __wasi_errno_t wasmtime_ssp_sock_recv(
) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_recv_from(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
void *buf,
size_t buf_len,
@ -1157,9 +1006,7 @@ __wasi_errno_t wasmtime_ssp_sock_recv_from(
) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_send(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
const void *buf,
size_t buf_len,
@ -1167,9 +1014,7 @@ __wasi_errno_t wasmtime_ssp_sock_send(
) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_send_to(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds, struct addr_pool *addr_pool,
#endif
__wasi_fd_t sock,
const void *buf,
size_t buf_len,
@ -1179,317 +1024,239 @@ __wasi_errno_t wasmtime_ssp_sock_send_to(
) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_shutdown(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock
) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_recv_timeout(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint64_t timeout_us
) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_recv_timeout(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint64_t *timeout_us
) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_send_timeout(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint64_t timeout_us
) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_send_timeout(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint64_t *timeout_us
) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_send_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
size_t bufsiz
) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_send_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
size_t *bufsiz
) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
size_t bufsiz
) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
size_t *bufsiz
) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_keep_alive(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_keep_alive(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_reuse_addr(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_reuse_addr(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_reuse_port(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_reuse_port(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_linger(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled,
int linger_s
) WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_linger(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock, bool *is_enabled, int *linger_s
) WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_broadcast(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_broadcast(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint32_t time_s
) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint32_t *time_s
) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint32_t time_s
) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint32_t *time_s
) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool ipv6,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool ipv6,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
__wasi_addr_ip_t *imr_multiaddr,
uint32_t imr_interface
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
__wasi_addr_ip_t *imr_multiaddr,
uint32_t imr_interface
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ip_ttl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint8_t ttl_s
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_ip_ttl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint8_t *ttl_s
) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint8_t ttl_s
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
uint8_t *ttl_s
) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_set_ipv6_only(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_sock_get_ipv6_only(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_table *curfds,
#endif
__wasi_fd_t sock,
bool *is_enabled
) WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) __attribute__((__warn_unused_result__));

View File

@ -101,12 +101,6 @@
#define st_mtim st_mtimespec
#endif
#ifdef __APPLE__
#define CONFIG_TLS_USE_GSBASE 1
#else
#define CONFIG_TLS_USE_GSBASE 0
#endif
#if !defined(BH_PLATFORM_LINUX_SGX)
/* Clang's __GNUC_PREREQ macro has a different meaning than GCC one,
so we have to handle this case specially */

View File

@ -16,10 +16,6 @@
#include "debug_engine.h"
#endif
#if WASM_ENABLE_SHARED_MEMORY != 0
#include "wasm_shared_memory.h"
#endif
typedef struct {
bh_list_link l;
void (*destroy_cb)(WASMCluster *);
@ -32,6 +28,8 @@ static bh_list cluster_list_head;
static bh_list *const cluster_list = &cluster_list_head;
static korp_mutex cluster_list_lock;
static korp_mutex _exception_lock;
typedef void (*list_visitor)(void *, void *);
static uint32 cluster_max_thread_num = CLUSTER_MAX_THREAD_NUM;
@ -52,6 +50,10 @@ thread_manager_init()
return false;
if (os_mutex_init(&cluster_list_lock) != 0)
return false;
if (os_mutex_init(&_exception_lock) != 0) {
os_mutex_destroy(&cluster_list_lock);
return false;
}
return true;
}
@ -66,6 +68,7 @@ thread_manager_destroy()
cluster = next;
}
wasm_cluster_cancel_all_callbacks();
os_mutex_destroy(&_exception_lock);
os_mutex_destroy(&cluster_list_lock);
}
@ -477,9 +480,6 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasm_module_t module;
wasm_module_inst_t new_module_inst;
#if WASM_ENABLE_LIBC_WASI != 0
WASIContext *wasi_ctx;
#endif
WASMExecEnv *new_exec_env;
uint32 aux_stack_start, aux_stack_size;
uint32 stack_size = 8192;
@ -509,7 +509,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
#endif
if (!(new_module_inst = wasm_runtime_instantiate_internal(
module, true, exec_env, stack_size, 0, NULL, 0))) {
module, module_inst, exec_env, stack_size, 0, NULL, 0))) {
goto fail1;
}
@ -517,10 +517,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
wasm_runtime_set_custom_data_internal(
new_module_inst, wasm_runtime_get_custom_data(module_inst));
#if WASM_ENABLE_LIBC_WASI != 0
wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
#endif
wasm_native_inherit_contexts(new_module_inst, module_inst);
new_exec_env = wasm_exec_env_create_internal(new_module_inst,
exec_env->wasm_stack_size);
@ -606,7 +603,8 @@ thread_manager_start_routine(void *arg)
#ifdef OS_ENABLE_HW_BOUND_CHECK
os_mutex_lock(&exec_env->wait_lock);
if (exec_env->suspend_flags.flags & 0x08)
if (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags)
& WASM_SUSPEND_FLAG_EXIT)
ret = exec_env->thread_ret_value;
os_mutex_unlock(&exec_env->wait_lock);
#endif
@ -745,10 +743,10 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst,
#if WASM_ENABLE_INTERP != 0
if (module_inst_src->module_type == Wasm_Module_Bytecode) {
new_c_api_func_imports =
&(((WASMModuleInstance *)module_inst_dst)->e->c_api_func_imports);
new_c_api_func_imports = &(((WASMModuleInstance *)module_inst_dst)
->e->common.c_api_func_imports);
c_api_func_imports = ((const WASMModuleInstance *)module_inst_src)
->e->c_api_func_imports;
->e->common.c_api_func_imports;
import_func_count =
((WASMModule *)(((const WASMModuleInstance *)module_inst_src)
->module))
@ -759,10 +757,10 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst,
if (module_inst_src->module_type == Wasm_Module_AoT) {
AOTModuleInstanceExtra *e =
(AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_dst)->e;
new_c_api_func_imports = &(e->c_api_func_imports);
new_c_api_func_imports = &(e->common.c_api_func_imports);
e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_src)->e;
c_api_func_imports = e->c_api_func_imports;
c_api_func_imports = e->common.c_api_func_imports;
import_func_count =
((AOTModule *)(((AOTModuleInstance *)module_inst_src)->module))
@ -993,7 +991,9 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval)
if (exec_env->jmpbuf_stack_top) {
/* Store the return value in exec_env */
exec_env->thread_ret_value = retval;
exec_env->suspend_flags.flags |= 0x08;
WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags,
WASM_SUSPEND_FLAG_EXIT);
#ifndef BH_PLATFORM_WINDOWS
/* Pop all jmpbuf_node except the last one */
@ -1055,7 +1055,8 @@ set_thread_cancel_flags(WASMExecEnv *exec_env)
#if WASM_ENABLE_DEBUG_INTERP != 0
wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
#endif
exec_env->suspend_flags.flags |= 0x01;
WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags,
WASM_SUSPEND_FLAG_TERMINATE);
os_mutex_unlock(&exec_env->wait_lock);
}
@ -1178,7 +1179,8 @@ void
wasm_cluster_suspend_thread(WASMExecEnv *exec_env)
{
/* Set the suspend flag */
exec_env->suspend_flags.flags |= 0x02;
WASM_SUSPEND_FLAGS_FETCH_OR(exec_env->suspend_flags,
WASM_SUSPEND_FLAG_SUSPEND);
}
static void
@ -1214,7 +1216,8 @@ wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
void
wasm_cluster_resume_thread(WASMExecEnv *exec_env)
{
exec_env->suspend_flags.flags &= ~0x02;
WASM_SUSPEND_FLAGS_FETCH_AND(exec_env->suspend_flags,
~WASM_SUSPEND_FLAG_SUSPEND);
os_cond_signal(&exec_env->wait_cond);
}
@ -1234,76 +1237,52 @@ wasm_cluster_resume_all(WASMCluster *cluster)
os_mutex_unlock(&cluster->lock);
}
struct spread_exception_data {
WASMExecEnv *skip;
const char *exception;
};
static void
set_exception_visitor(void *node, void *user_data)
{
WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env);
WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst;
const struct spread_exception_data *data = user_data;
WASMExecEnv *exec_env = (WASMExecEnv *)node;
if (curr_exec_env != exec_env) {
WASMModuleInstance *curr_wasm_inst =
(WASMModuleInstance *)get_module_inst(curr_exec_env);
if (exec_env != data->skip) {
WASMModuleInstance *wasm_inst =
(WASMModuleInstance *)get_module_inst(exec_env);
/* Only spread non "wasi proc exit" exception */
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory(
(WASMModuleCommon *)curr_wasm_inst->module);
if (shared_mem_node)
os_mutex_lock(&shared_mem_node->shared_mem_lock);
#endif
if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) {
bh_memcpy_s(curr_wasm_inst->cur_exception,
sizeof(curr_wasm_inst->cur_exception),
wasm_inst->cur_exception,
sizeof(wasm_inst->cur_exception));
exception_lock(wasm_inst);
if (data->exception != NULL) {
snprintf(wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception),
"Exception: %s", data->exception);
}
#if WASM_ENABLE_SHARED_MEMORY != 0
if (shared_mem_node)
os_mutex_unlock(&shared_mem_node->shared_mem_lock);
#endif
else {
wasm_inst->cur_exception[0] = '\0';
}
exception_unlock(wasm_inst);
/* Terminate the thread so it can exit from dead loops */
set_thread_cancel_flags(curr_exec_env);
}
}
static void
clear_exception_visitor(void *node, void *user_data)
{
WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
if (curr_exec_env != exec_env) {
WASMModuleInstance *curr_wasm_inst =
(WASMModuleInstance *)get_module_inst(curr_exec_env);
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory(
(WASMModuleCommon *)curr_wasm_inst->module);
if (shared_mem_node)
os_mutex_lock(&shared_mem_node->shared_mem_lock);
#endif
curr_wasm_inst->cur_exception[0] = '\0';
#if WASM_ENABLE_SHARED_MEMORY != 0
if (shared_mem_node)
os_mutex_unlock(&shared_mem_node->shared_mem_lock);
#endif
if (data->exception != NULL) {
set_thread_cancel_flags(exec_env);
}
}
}
void
wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear)
wasm_cluster_spread_exception(WASMExecEnv *exec_env, const char *exception)
{
const bool has_exception = exception != NULL;
WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
bh_assert(cluster);
struct spread_exception_data data;
data.skip = exec_env;
data.exception = exception;
os_mutex_lock(&cluster->lock);
cluster->has_exception = !clear;
traverse_list(&cluster->exec_env_list,
clear ? clear_exception_visitor : set_exception_visitor,
exec_env);
cluster->has_exception = has_exception;
traverse_list(&cluster->exec_env_list, set_exception_visitor, &data);
os_mutex_unlock(&cluster->lock);
}
@ -1339,13 +1318,75 @@ wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
}
}
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
struct inst_set_context_data {
void *key;
void *ctx;
};
static void
set_context_visitor(void *node, void *user_data)
{
WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
WASMModuleInstanceCommon *module_inst = get_module_inst(curr_exec_env);
const struct inst_set_context_data *data = user_data;
wasm_runtime_set_context(module_inst, data->key, data->ctx);
}
void
wasm_cluster_set_context(WASMModuleInstanceCommon *module_inst, void *key,
void *ctx)
{
WASMExecEnv *exec_env = wasm_clusters_search_exec_env(module_inst);
if (exec_env == NULL) {
/* Maybe threads have not been started yet. */
wasm_runtime_set_context(module_inst, key, ctx);
}
else {
WASMCluster *cluster;
struct inst_set_context_data data;
data.key = key;
data.ctx = ctx;
cluster = wasm_exec_env_get_cluster(exec_env);
bh_assert(cluster);
os_mutex_lock(&cluster->lock);
traverse_list(&cluster->exec_env_list, set_context_visitor, &data);
os_mutex_unlock(&cluster->lock);
}
}
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
bool
wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
{
os_mutex_lock(&exec_env->wait_lock);
bool is_thread_terminated =
(exec_env->suspend_flags.flags & 0x01) ? true : false;
bool is_thread_terminated = (WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags)
& WASM_SUSPEND_FLAG_TERMINATE)
? true
: false;
os_mutex_unlock(&exec_env->wait_lock);
return is_thread_terminated;
}
void
exception_lock(WASMModuleInstance *module_inst)
{
/*
* Note: this lock could be per module instance if desirable.
* We can revisit on AOT version bump.
* It probably doesn't matter though because the exception handling
* logic should not be executed too frequently anyway.
*/
os_mutex_lock(&_exception_lock);
}
void
exception_unlock(WASMModuleInstance *module_inst)
{
os_mutex_unlock(&_exception_lock);
}

View File

@ -139,7 +139,7 @@ WASMExecEnv *
wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst);
void
wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear);
wasm_cluster_spread_exception(WASMExecEnv *exec_env, const char *exception);
WASMExecEnv *
wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env);
@ -151,6 +151,10 @@ void
wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
void *custom_data);
void
wasm_cluster_set_context(WASMModuleInstanceCommon *module_inst, void *key,
void *ctx);
bool
wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env);

View File

@ -0,0 +1,2 @@
**/*.wasm
**/*.tflite

View File

@ -25,6 +25,7 @@ Build the runtime image for your execution target type.
* `cpu`
* `nvidia-gpu`
* `vx-delegate`
* `tpu`
```
EXECUTION_TYPE=cpu
@ -64,6 +65,8 @@ docker run \
```
* (NVIDIA) GPU
* Requirements:
* [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker).
```
docker run \
@ -76,25 +79,36 @@ docker run \
/assets/test_tensorflow.wasm
```
* vx-delegate for NPU (x86 simulater)
* vx-delegate for NPU (x86 simulator)
```
docker run \
-v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-vx-delegate \
--dir=/assets \
-v $PWD/core/iwasm/libraries/wasi-nn/test:/assets \
wasi-nn-vx-delegate \
--dir=/ \
--env="TARGET=gpu" \
/assets/test_tensorflow.wasm
/assets/test_tensorflow_quantized.wasm
```
* (Coral) TPU
* Requirements:
* [Coral USB](https://coral.ai/products/accelerator/).
Requirements:
* [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker).
```
docker run \
--privileged \
--device=/dev/bus/usb:/dev/bus/usb \
-v $PWD/core/iwasm/libraries/wasi-nn/test:/assets \
wasi-nn-tpu \
--dir=/ \
--env="TARGET=tpu" \
/assets/test_tensorflow_quantized.wasm
```
## What is missing
Supported:
* Graph encoding: `tensorflowlite`.
* Execution target: `cpu` and `gpu`.
* Execution target: `cpu`, `gpu` and `tpu`.
* Tensor type: `fp32`.

View File

@ -18,12 +18,16 @@ if(NOT EXISTS ${TENSORFLOW_LITE})
set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
if(WASI_NN_ENABLE_GPU EQUAL 1)
if(WAMR_BUILD_WASI_NN_ENABLE_GPU EQUAL 1)
# Tensorflow specific:
# * https://www.tensorflow.org/lite/guide/build_cmake#available_options_to_build_tensorflow_lite
set (TFLITE_ENABLE_GPU ON)
endif()
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
set (TFLITE_ENABLE_XNNPACK OFF)
endif()
add_subdirectory(
"${TENSORFLOW_SOURCE_DIR}/tensorflow/lite"
"${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite"

View File

@ -0,0 +1,58 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
cmake_minimum_required(VERSION 3.16)
project(wasi-nn C CXX)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../..)
set(WASI_NN_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
#### libvmlib ####
# NOTE: we build vmlib as a shared library here so that it can be
# shared between iwasm and native libraries.
include(${WASI_NN_ROOT_DIR}/cmake/iwasm_helper.cmake)
include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
add_library(vmlib SHARED ${WAMR_RUNTIME_LIB_SOURCE})
# iwasm
include(${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
set(RUNTIME_SOURCE_ALL
${WAMR_ROOT_DIR}/product-mini/platforms/${WAMR_BUILD_PLATFORM}/main.c
${UNCOMMON_SHARED_SOURCE}
)
add_executable(iwasm ${RUNTIME_SOURCE_ALL})
target_link_libraries(iwasm vmlib -lpthread -lm -ldl)
#### TensorFlow ####
include(${WASI_NN_ROOT_DIR}/cmake/wasi_nn.cmake)
#### WASI-NN ####
include_directories(
${WAMR_ROOT_DIR}/core/iwasm/include
${WAMR_ROOT_DIR}/core/shared/utils
${WAMR_ROOT_DIR}/core/shared/platform/linux
)
add_library(wasi-nn SHARED
${WASI_NN_SOURCES}
)
# Add `get_native_lib` symbol
target_compile_definitions(wasi-nn PUBLIC
WASI_NN_SHARED
)
target_link_libraries(wasi-nn
${WASI_NN_LIBS}
vmlib
)

View File

@ -0,0 +1,13 @@
# wasi-nn as shared library
Example on how to create libwasi-nn (external library) instead of embedding wasi-nn inside iwasm
From folder `core/iwasm/libraries/wasi-nn/test`, build the test and run
```sh
../external/build/iwasm \
--dir=. \
--env="TARGET=cpu" \
--native-lib=../external/build/libwasi-nn.so \
test_tensorflow.wasm
```

View File

@ -9,16 +9,18 @@
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include "wasi_nn.h"
#include "wasi_nn_private.h"
#include "wasi_nn_app_native.h"
#include "logger.h"
#include "wasi_nn_tensorflowlite.hpp"
#include "logger.h"
#include "bh_platform.h"
#include "wasm_export.h"
#include "wasm_runtime.h"
#include "aot_runtime.h"
#define HASHMAP_INITIAL_SIZE 20
/* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */
@ -51,6 +53,119 @@ static api_function lookup[] = {
tensorflowlite_get_output }
};
static HashMap *hashmap;
static void
wasi_nn_ctx_destroy(WASINNContext *wasi_nn_ctx);
/* Get wasi-nn context from module instance */
static uint32
hash_func(const void *key)
{
// fnv1a_hash
const uint32 FNV_PRIME = 16777619;
const uint32 FNV_OFFSET_BASIS = 2166136261U;
uint32 hash = FNV_OFFSET_BASIS;
const unsigned char *bytes = (const unsigned char *)key;
for (size_t i = 0; i < sizeof(uintptr_t); ++i) {
hash ^= bytes[i];
hash *= FNV_PRIME;
}
return hash;
}
static bool
key_equal_func(void *key1, void *key2)
{
return key1 == key2;
}
static void
key_destroy_func(void *key1)
{}
static void
value_destroy_func(void *value)
{
wasi_nn_ctx_destroy((WASINNContext *)value);
}
static WASINNContext *
wasi_nn_initialize_context()
{
NN_DBG_PRINTF("Initializing wasi-nn context");
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_model_loaded = false;
tensorflowlite_initialize(&wasi_nn_ctx->tflite_ctx);
return wasi_nn_ctx;
}
static bool
wasi_nn_initialize()
{
NN_DBG_PRINTF("Initializing wasi-nn");
hashmap = bh_hash_map_create(HASHMAP_INITIAL_SIZE, true, hash_func,
key_equal_func, key_destroy_func,
value_destroy_func);
if (hashmap == NULL) {
NN_ERR_PRINTF("Error while initializing hashmap");
return false;
}
return true;
}
static WASINNContext *
wasm_runtime_get_wasi_nn_ctx(wasm_module_inst_t instance)
{
WASINNContext *wasi_nn_ctx =
(WASINNContext *)bh_hash_map_find(hashmap, (void *)instance);
if (wasi_nn_ctx == NULL) {
wasi_nn_ctx = wasi_nn_initialize_context();
if (wasi_nn_ctx == NULL)
return NULL;
bool ok =
bh_hash_map_insert(hashmap, (void *)instance, (void *)wasi_nn_ctx);
if (!ok) {
NN_ERR_PRINTF("Error while storing context");
wasi_nn_ctx_destroy(wasi_nn_ctx);
return NULL;
}
}
NN_DBG_PRINTF("Returning ctx");
return wasi_nn_ctx;
}
static void
wasi_nn_ctx_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_model_loaded: %d", wasi_nn_ctx->is_model_loaded);
NN_DBG_PRINTF("-> current_encoding: %d", wasi_nn_ctx->current_encoding);
tensorflowlite_destroy(wasi_nn_ctx->tflite_ctx);
wasm_runtime_free(wasi_nn_ctx);
}
void
wasi_nn_destroy(wasm_module_inst_t instance)
{
WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
wasi_nn_ctx_destroy(wasi_nn_ctx);
}
/* Utils */
static bool
@ -64,36 +179,13 @@ is_encoding_implemented(graph_encoding encoding)
static error
is_model_initialized(WASINNContext *wasi_nn_ctx)
{
if (!wasi_nn_ctx->is_initialized) {
if (!wasi_nn_ctx->is_model_loaded) {
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
@ -131,7 +223,7 @@ wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
NN_DBG_PRINTF("wasi_nn_load finished with status %d [graph=%d]", res, *g);
wasi_nn_ctx->current_encoding = encoding;
wasi_nn_ctx->is_initialized = true;
wasi_nn_ctx->is_model_loaded = true;
fail:
// XXX: Free intermediate structure pointers
@ -250,39 +342,6 @@ wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
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;
tensorflowlite_initialize(&wasi_nn_ctx->tflite_ctx);
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(wasi_nn_ctx->tflite_ctx);
wasm_runtime_free(wasi_nn_ctx);
}
/* Register WASI-NN in WAMR */
/* clang-format off */
@ -299,8 +358,19 @@ static NativeSymbol native_symbols_wasi_nn[] = {
};
uint32_t
get_wasi_nn_export_apis(NativeSymbol **p_libc_wasi_apis)
get_wasi_nn_export_apis(NativeSymbol **p_native_symbols)
{
*p_libc_wasi_apis = native_symbols_wasi_nn;
if (!wasi_nn_initialize())
return 0;
*p_native_symbols = native_symbols_wasi_nn;
return sizeof(native_symbols_wasi_nn) / sizeof(NativeSymbol);
}
#if defined(WASI_NN_SHARED)
uint32_t
get_native_lib(char **p_module_name, NativeSymbol **p_native_symbols)
{
*p_module_name = "wasi_nn";
return get_wasi_nn_export_apis(p_native_symbols);
}
#endif

View File

@ -7,25 +7,20 @@
#define WASI_NN_PRIVATE_H
#include "wasi_nn_types.h"
#include "wasm_export.h"
typedef struct {
bool is_initialized;
bool is_model_loaded;
graph_encoding current_encoding;
void *tflite_ctx;
} WASINNContext;
/**
* @brief Initialize wasi-nn
*
*/
WASINNContext *
wasi_nn_initialize();
/**
* @brief Destroy wasi-nn on app exists
*
*/
void
wasi_nn_destroy(WASINNContext *wasi_nn_ctx);
wasi_nn_destroy(wasm_module_inst_t instance);
#endif

View File

@ -7,9 +7,8 @@
#include "wasi_nn_tensorflowlite.hpp"
#include "logger.h"
#include "bh_common.h"
#include "bh_platform.h"
#include "platform_common.h"
#include "wasm_export.h"
#include <tensorflow/lite/interpreter.h>
#include <tensorflow/lite/kernels/register.h>
@ -17,11 +16,11 @@
#include <tensorflow/lite/optional_debug_tools.h>
#include <tensorflow/lite/error_reporter.h>
#if defined(WASI_NN_ENABLE_GPU)
#if WASM_ENABLE_WASI_NN_GPU != 0
#include <tensorflow/lite/delegates/gpu/delegate.h>
#endif
#if defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE)
#if WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE != 0
#include <tensorflow/lite/delegates/external/external_delegate.h>
#endif
@ -131,8 +130,8 @@ tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
return invalid_argument;
}
if (target != cpu && target != gpu) {
NN_ERR_PRINTF("Only CPU and GPU target is supported.");
if (target != cpu && target != gpu && target != tpu) {
NN_ERR_PRINTF("Only CPU, GPU and TPU target is supported.");
return invalid_argument;
}
@ -196,7 +195,7 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
switch (tfl_ctx->models[g].target) {
case gpu:
{
#if defined(WASI_NN_ENABLE_GPU)
#if WASM_ENABLE_WASI_NN_GPU != 0
NN_WARN_PRINTF("GPU enabled.");
// https://www.tensorflow.org/lite/performance/gpu
TfLiteGpuDelegateOptionsV2 options =
@ -217,10 +216,19 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
NN_ERR_PRINTF("Error when enabling GPU delegate.");
use_default = true;
}
#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE)
#else
NN_WARN_PRINTF("GPU not enabled.");
use_default = true;
#endif
break;
}
case tpu:
{
#if WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE != 0
NN_WARN_PRINTF("external delegation enabled.");
TfLiteExternalDelegateOptions options =
TfLiteExternalDelegateOptionsDefault(WASI_NN_EXT_DELEGATE_PATH);
TfLiteExternalDelegateOptionsDefault(
WASM_WASI_NN_EXTERNAL_DELEGATE_PATH);
tfl_ctx->delegate = TfLiteExternalDelegateCreate(&options);
if (tfl_ctx->delegate == NULL) {
NN_ERR_PRINTF("Error when generating External delegate.");
@ -234,7 +242,7 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
use_default = true;
}
#else
NN_WARN_PRINTF("GPU not enabled.");
NN_WARN_PRINTF("External delegate not enabled.");
use_default = true;
#endif
break;
@ -286,14 +294,37 @@ tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
return invalid_argument;
}
auto *input =
tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor<float>(
index);
if (input == NULL)
return missing_memory;
if (tensor->quantization.type == kTfLiteNoQuantization) {
NN_DBG_PRINTF("No quantization information. Using float as default");
float *it =
tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor<float>(
index);
int size = model_tensor_size * sizeof(float);
bh_memcpy_s(it, size, input_tensor->data, size);
}
else { // TODO: Assumming uint8 quantized networks.
TfLiteAffineQuantization *quant_info =
(TfLiteAffineQuantization *)tensor->quantization.params;
if (quant_info->scale->size != 1 || quant_info->zero_point->size != 1) {
NN_ERR_PRINTF("Quantization per channel is not supported");
return runtime_error;
}
uint8_t *it =
tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor<uint8_t>(
index);
float scale = quant_info->scale->data[0];
float zero_point = (float)quant_info->zero_point->data[0];
NN_DBG_PRINTF("input tensor: (scale, offset) = (%f, %f)", scale,
zero_point);
float *input_tensor_f = (float *)input_tensor->data;
for (uint32_t i = 0; i < model_tensor_size; ++i) {
it[i] = (uint8_t)(input_tensor_f[i] / scale + zero_point);
}
}
bh_memcpy_s(input, model_tensor_size * sizeof(float), input_tensor->data,
model_tensor_size * sizeof(float));
return success;
}
@ -326,6 +357,7 @@ tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
NN_DBG_PRINTF("Number of tensors (%d)", num_output_tensors);
if (index + 1 > num_output_tensors) {
NN_ERR_PRINTF("Index %d is invalid.", index);
return runtime_error;
}
@ -344,15 +376,37 @@ tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
return missing_memory;
}
float *tensor_f =
tfl_ctx->interpreters[ctx].interpreter->typed_output_tensor<float>(
index);
for (uint32_t i = 0; i < model_tensor_size; ++i)
NN_DBG_PRINTF("output: %f", tensor_f[i]);
if (tensor->quantization.type == kTfLiteNoQuantization) {
NN_DBG_PRINTF("No quantization information");
float *ot =
tfl_ctx->interpreters[ctx].interpreter->typed_output_tensor<float>(
index);
int size = model_tensor_size * sizeof(float);
bh_memcpy_s(output_tensor, size, ot, size);
}
else { // TODO: Assumming uint8 quantized networks.
TfLiteAffineQuantization *quant_info =
(TfLiteAffineQuantization *)tensor->quantization.params;
if (quant_info->scale->size != 1 || quant_info->zero_point->size != 1) {
NN_ERR_PRINTF("Quantization per channel is not supported");
return runtime_error;
}
uint8_t *ot = tfl_ctx->interpreters[ctx]
.interpreter->typed_output_tensor<uint8_t>(index);
float scale = quant_info->scale->data[0];
float zero_point = (float)quant_info->zero_point->data[0];
NN_DBG_PRINTF("output tensor: (scale, offset) = (%f, %f)", scale,
zero_point);
float *output_tensor_f = (float *)output_tensor;
for (uint32_t i = 0; i < model_tensor_size; ++i) {
output_tensor_f[i] = (ot[i] - zero_point) * scale;
}
}
*output_tensor_size = model_tensor_size;
bh_memcpy_s(output_tensor, model_tensor_size * sizeof(float), tensor_f,
model_tensor_size * sizeof(float));
return success;
}
@ -393,19 +447,35 @@ tensorflowlite_destroy(void *tflite_ctx)
*/
TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
if (tfl_ctx->delegate != NULL) {
#if defined(WASI_NN_ENABLE_GPU)
TfLiteGpuDelegateV2Delete(tfl_ctx->delegate);
#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE)
TfLiteExternalDelegateDelete(tfl_ctx->delegate);
#endif
}
NN_DBG_PRINTF("Freeing memory.");
for (int i = 0; i < MAX_GRAPHS_PER_INST; ++i) {
tfl_ctx->models[i].model.reset();
if (tfl_ctx->models[i].model_pointer)
if (tfl_ctx->models[i].model_pointer) {
if (tfl_ctx->delegate) {
switch (tfl_ctx->models[i].target) {
case gpu:
{
#if WASM_ENABLE_WASI_NN_GPU != 0
TfLiteGpuDelegateV2Delete(tfl_ctx->delegate);
#else
NN_ERR_PRINTF("GPU delegate delete but not enabled.");
#endif
break;
}
case tpu:
{
#if WASM_ENABLE_WASI_NN_EXTERNAL_DELEGATE != 0
TfLiteExternalDelegateDelete(tfl_ctx->delegate);
#else
NN_ERR_PRINTF(
"External delegate delete but not enabled.");
#endif
break;
}
}
}
wasm_runtime_free(tfl_ctx->models[i].model_pointer);
}
tfl_ctx->models[i].model_pointer = NULL;
}
for (int i = 0; i < MAX_GRAPH_EXEC_CONTEXTS_PER_INST; ++i) {

View File

@ -30,7 +30,6 @@ RUN make -j "$(grep -c ^processor /proc/cpuinfo)"
FROM ubuntu:22.04
COPY --from=base /home/wamr/product-mini/platforms/linux/build/libvmlib.so /libvmlib.so
COPY --from=base /home/wamr/product-mini/platforms/linux/build/iwasm /iwasm
ENTRYPOINT [ "/iwasm" ]

View File

@ -24,7 +24,7 @@ RUN apt-get install -y wget ca-certificates --no-install-recommends \
RUN cmake \
-DWAMR_BUILD_WASI_NN=1 \
-DWASI_NN_ENABLE_GPU=1 \
-DWAMR_BUILD_WASI_NN_ENABLE_GPU=1 \
..
RUN make -j "$(grep -c ^processor /proc/cpuinfo)"
@ -44,7 +44,6 @@ RUN mkdir -p /etc/OpenCL/vendors && \
ENV NVIDIA_VISIBLE_DEVICES=all
ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility
COPY --from=base /home/wamr/product-mini/platforms/linux/build/libvmlib.so /libvmlib.so
COPY --from=base /home/wamr/product-mini/platforms/linux/build/iwasm /iwasm
ENTRYPOINT [ "/iwasm" ]

Some files were not shown because too many files have changed in this diff Show More