mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-11 06:53:16 +00:00
Compare commits
106 Commits
abdc268d34
...
57131bd3c1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
57131bd3c1 | ||
![]() |
fbd27e5e03 | ||
![]() |
d3b0b5c066 | ||
![]() |
0eceed2ba9 | ||
![]() |
7d05dbc988 | ||
![]() |
be33a40ba7 | ||
![]() |
8a55a1e7a1 | ||
![]() |
915b00e980 | ||
![]() |
ee056d8076 | ||
![]() |
68d5ae10d4 | ||
![]() |
d598c0d0d3 | ||
![]() |
da6019f749 | ||
![]() |
ebf1404ad1 | ||
![]() |
c7148a6823 | ||
![]() |
8949797c84 | ||
![]() |
38fe056cc6 | ||
![]() |
430cc5e5ef | ||
![]() |
cb233ec042 | ||
![]() |
4fbb372f15 | ||
![]() |
0127eafbe5 | ||
![]() |
7a6a6a39e9 | ||
![]() |
18d4227ab6 | ||
![]() |
0641dd1506 | ||
![]() |
8ed89e2ab2 | ||
![]() |
d6876f1e9f | ||
![]() |
2372a472aa | ||
![]() |
23799a2cb6 | ||
![]() |
5b32130955 | ||
![]() |
a7aae9d2cc | ||
![]() |
535004dedc | ||
![]() |
1e41519977 | ||
![]() |
e414a327a0 | ||
![]() |
8289452abb | ||
![]() |
70c39bae77 | ||
![]() |
92e5f5f123 | ||
![]() |
7471d5a5d0 | ||
![]() |
f449b79a31 | ||
![]() |
64cafaff1e | ||
![]() |
ea408ab6c0 | ||
![]() |
71c07f3e4e | ||
![]() |
e5091e47ea | ||
![]() |
aa53d648fa | ||
![]() |
a29f3943ef | ||
![]() |
8414a20dfe | ||
![]() |
db7714f0f5 | ||
![]() |
4bf799c3af | ||
![]() |
cba9001749 | ||
![]() |
4ebd1bb597 | ||
![]() |
b3ce192e1a | ||
![]() |
c9b8c16088 | ||
![]() |
6dfb410869 | ||
![]() |
2f0750a6fe | ||
![]() |
20be1d33fe | ||
![]() |
965f2452c8 | ||
![]() |
05e3a09150 | ||
![]() |
745da82cd6 | ||
![]() |
7bbdbf5212 | ||
![]() |
d7e3e376a9 | ||
![]() |
0d001c4c38 | ||
![]() |
8e60feb181 | ||
![]() |
0343aaf8c3 | ||
![]() |
2fe7105e8d | ||
![]() |
9becf65d1e | ||
![]() |
78e68cec83 | ||
![]() |
75bf9797a2 | ||
![]() |
5478d267f4 | ||
![]() |
3a087c4244 | ||
![]() |
928598f1ce | ||
![]() |
c932597057 | ||
![]() |
d52f083ac0 | ||
![]() |
c4623e2cb5 | ||
![]() |
7f968f5926 | ||
![]() |
07c23cb98e | ||
![]() |
ea5757f1d7 | ||
![]() |
4d6b8dcd5d | ||
![]() |
99c75b53db | ||
![]() |
933f8124b0 | ||
![]() |
769d16eaab | ||
![]() |
350af77b03 | ||
![]() |
97e9502bb3 | ||
![]() |
48a97736b3 | ||
![]() |
602e86adc3 | ||
![]() |
79cb4366ae | ||
![]() |
b20ebc2724 | ||
![]() |
85efe08431 | ||
![]() |
93ef19b0ca | ||
![]() |
6a00874f2f | ||
![]() |
61cb97221e | ||
![]() |
ae6e490ad5 | ||
![]() |
16c46751ac | ||
![]() |
1c12a32066 | ||
![]() |
938503af38 | ||
![]() |
62bb6e8158 | ||
![]() |
aa1ff778b9 | ||
![]() |
2a303861cc | ||
![]() |
670aa83985 | ||
![]() |
207da7b22f | ||
![]() |
3580d1a386 | ||
![]() |
3ab9f84026 | ||
![]() |
7f9e49213e | ||
![]() |
782c69fe8a | ||
![]() |
21bcf5c75d | ||
![]() |
c018b8ab98 | ||
![]() |
6659a312cf | ||
![]() |
b7474b354f | ||
![]() |
76caabede5 |
53
.github/actions/install-wasi-sdk-wabt/action.yml
vendored
53
.github/actions/install-wasi-sdk-wabt/action.yml
vendored
|
@ -30,14 +30,23 @@ runs:
|
|||
if: ${{ startsWith(inputs.os, 'ubuntu') }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Downloading wasi-sdk for Ubuntu..."
|
||||
sudo wget -O wasi-sdk.tar.gz --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz
|
||||
|
||||
echo "Extracting wasi-sdk..."
|
||||
sudo tar -xf wasi-sdk.tar.gz
|
||||
sudo ln -sf wasi-sdk-25.0-x86_64-linux/ wasi-sdk
|
||||
|
||||
echo "Downloading wabt for Ubuntu..."
|
||||
sudo wget -O wabt.tar.gz --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/1.0.37/wabt-1.0.37-ubuntu-20.04.tar.gz
|
||||
|
||||
echo "Extracting wabt..."
|
||||
sudo tar -xf wabt.tar.gz
|
||||
sudo ln -sf wabt-1.0.37 wabt
|
||||
|
||||
/opt/wasi-sdk/bin/clang --version
|
||||
/opt/wabt/bin/wasm-interp --version
|
||||
|
||||
echo "::notice::wasi-sdk-25 and wabt-1.0.37 installed on ubuntu"
|
||||
working-directory: /opt
|
||||
|
||||
|
@ -45,14 +54,23 @@ runs:
|
|||
if: ${{ inputs.os == 'macos-13' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Downloading wasi-sdk for macOS-13..."
|
||||
sudo wget -O wasi-sdk.tar.gz --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-macos.tar.gz
|
||||
|
||||
echo "Extracting wasi-sdk..."
|
||||
sudo tar -xf wasi-sdk.tar.gz
|
||||
sudo ln -sf wasi-sdk-25.0-x86_64-macos wasi-sdk
|
||||
|
||||
echo "Downloading wabt for macOS-13..."
|
||||
sudo wget -O wabt.tar.gz --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/1.0.36/wabt-1.0.36-macos-12.tar.gz
|
||||
|
||||
echo "Extracting wabt..."
|
||||
sudo tar -xf wabt.tar.gz
|
||||
sudo ln -sf wabt-1.0.36 wabt
|
||||
|
||||
/opt/wasi-sdk/bin/clang --version
|
||||
/opt/wabt/bin/wasm-interp --version
|
||||
|
||||
echo "::notice::wasi-sdk-25 and wabt-1.0.36 installed on macos-13"
|
||||
working-directory: /opt
|
||||
|
||||
|
@ -60,21 +78,48 @@ runs:
|
|||
if: ${{ inputs.os == 'macos-14' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Downloading wasi-sdk for macOS-14..."
|
||||
sudo wget -O wasi-sdk.tar.gz --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-arm64-macos.tar.gz
|
||||
|
||||
echo "Extracting wasi-sdk..."
|
||||
sudo tar -xf wasi-sdk.tar.gz
|
||||
sudo ln -sf wasi-sdk-25.0-arm64-macos wasi-sdk
|
||||
|
||||
echo "Downloading wabt for macOS-14..."
|
||||
sudo wget -O wabt.tar.gz --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/1.0.37/wabt-1.0.37-macos-14.tar.gz
|
||||
|
||||
echo "Extracting wabt..."
|
||||
sudo tar -xf wabt.tar.gz
|
||||
sudo ln -sf wabt-1.0.37 wabt
|
||||
|
||||
/opt/wasi-sdk/bin/clang --version
|
||||
/opt/wabt/bin/wasm-interp --version
|
||||
|
||||
echo "::notice::wasi-sdk-25 and wabt-1.0.37 installed on macos-14"
|
||||
working-directory: /opt
|
||||
|
||||
#TODO: Add support for Windows
|
||||
- name: Set up wasi-sdk and wabt on Windows
|
||||
if: ${{ startsWith(inputs.os, 'windows') }}
|
||||
shell: powershell
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::notice::Support for Windows is not implemented yet"
|
||||
exit 1
|
||||
choco install -y wget
|
||||
|
||||
mkdir -p /opt/wasi-sdk
|
||||
mkdir -p /opt/wabt
|
||||
|
||||
echo "Downloading wasi-sdk for Windows..."
|
||||
wget -O wasi-sdk.tar.gz --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-windows.tar.gz
|
||||
|
||||
echo "Extracting wasi-sdk..."
|
||||
tar --strip-components=1 -xf wasi-sdk.tar.gz -C /opt/wasi-sdk
|
||||
|
||||
echo "Downloading wabt for Windows..."
|
||||
wget -O wabt.tar.gz --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/1.0.37/wabt-1.0.37-windows.tar.gz
|
||||
|
||||
echo "Extracting wabt..."
|
||||
tar --strip-components=1 -xf wabt.tar.gz -C /opt/wabt
|
||||
|
||||
/opt/wasi-sdk/bin/clang --version
|
||||
/opt/wabt/bin/wasm-interp --version
|
||||
|
||||
echo "::notice::wasi-sdk-25 and wabt-1.0.37 installed on Windows"
|
||||
|
|
46
.github/codeql/codeql_config.yml
vendored
Normal file
46
.github/codeql/codeql_config.yml
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
paths:
|
||||
- .github
|
||||
- core/iwasm
|
||||
- core/shared/platform/common/
|
||||
- core/shared/platform/include/
|
||||
- core/shared/platform/linux/
|
||||
- product-mini/platforms/common/
|
||||
- product-mini/platforms/linux/
|
||||
# TODO: add other platforms back if able to do cross-compilation
|
||||
# - product-mini/platforms/
|
||||
# TODO: add samples back after buildscript modification
|
||||
# - need to ignore workloads and wasm-apps
|
||||
# - samples
|
||||
- wamr-compiler/
|
||||
paths-ignore:
|
||||
# always ignore build
|
||||
- '**/build/**'
|
||||
- '**/test*/**'
|
||||
- '**/wasm-app*/**'
|
||||
- core/deps/
|
||||
# platform specific
|
||||
- core/iwasm/aot/arch/aot_reloc_aarch64.c
|
||||
- core/iwasm/aot/arch/aot_reloc_arc.c
|
||||
- core/iwasm/aot/arch/aot_reloc_arm.c
|
||||
- core/iwasm/aot/arch/aot_reloc_dummy.c
|
||||
- core/iwasm/aot/arch/aot_reloc_mips.c
|
||||
- core/iwasm/aot/arch/aot_reloc_riscv.c
|
||||
- core/iwasm/aot/arch/aot_reloc_thumb.c
|
||||
- core/iwasm/aot/arch/aot_reloc_xtensa.c
|
||||
- core/iwasm/libraries/lib-rats/
|
||||
- core/iwasm/libraries/lib-socket/
|
||||
- core/iwasm/libraries/lib-wasi-threads/*-test/
|
||||
- core/shared/platform/common/freertos/
|
||||
- core/shared/platform/common/math/
|
||||
#TODO: add me back if lldb libraries installed
|
||||
- core/iwasm/compilation/debug/
|
||||
# spend disk space and slow
|
||||
- core/iwasm/libraries/wasi-nn/src/wasi_nn_tflite*
|
||||
#TODO: add me back if openvino installed
|
||||
- core/iwasm/libraries/wasi-nn/src/wasi_nn_openvino*
|
||||
# for wasm
|
||||
- core/iwasm/libraries/wasi-nn/include/wasi_nn.h
|
||||
# reference
|
||||
- core/iwasm/common/arch/invokeNative_general.c
|
397
.github/scripts/codeql_buildscript.sh
vendored
397
.github/scripts/codeql_buildscript.sh
vendored
|
@ -5,308 +5,117 @@
|
|||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
sudo apt update
|
||||
# This script is used to build the WAMR project for CodeQL analysis.
|
||||
|
||||
sudo apt install -y build-essential cmake g++-multilib libgcc-12-dev lib32gcc-12-dev ccache ninja-build
|
||||
# Pre-requisites
|
||||
sudo apt -qq update
|
||||
sudo apt install -y -qq build-essential cmake g++-multilib libgcc-12-dev lib32gcc-12-dev ccache ninja-build
|
||||
|
||||
LLVM_VER=18.1.8
|
||||
pushd /opt
|
||||
sudo wget --progress=dot:giga -O clang+llvm-x86_64-linux-gnu.tar.xz https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VER}/clang+llvm-${LLVM_VER}-x86_64-linux-gnu-ubuntu-18.04.tar.xz \
|
||||
&& tar -xf clang+llvm-x86_64-linux-gnu.tar.xz \
|
||||
&& mv clang+llvm-${LLVM_VER}-x86_64-linux-gnu-ubuntu-18.04 llvm-${LLVM_VER}
|
||||
popd
|
||||
|
||||
# libtinfo.so.5 for /opt/llvm-18.1.8/lib/libomptarget.rtl.amdgpu.so.18.1
|
||||
sudo apt -qq update
|
||||
wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb
|
||||
sudo apt install -y -qq ./libtinfo5_6.3-2ubuntu0.1_amd64.deb
|
||||
|
||||
# Start the build process
|
||||
WAMR_DIR=${PWD}
|
||||
LLVM_DIR=/opt/llvm-${LLVM_VER}/lib/cmake/llvm
|
||||
|
||||
# TODO: use pre-built llvm binary to build wamrc to
|
||||
# avoid static code analysing for llvm
|
||||
: '
|
||||
# build wamrc
|
||||
cd ${WAMR_DIR}/wamr-compiler
|
||||
./build_llvm.sh
|
||||
rm -fr build && mkdir build && cd build
|
||||
cmake ..
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build wamrc!"
|
||||
exit 1;
|
||||
fi
|
||||
'
|
||||
# Function to build wamrc
|
||||
build_wamrc() {
|
||||
local options="$1"
|
||||
echo "Building wamrc with options: $options"
|
||||
|
||||
# build iwasm with default features enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -fr build && mkdir build && cd build
|
||||
cmake ..
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with default features enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
pushd ${WAMR_DIR}/wamr-compiler
|
||||
rm -rf build
|
||||
cmake -S . -B build \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DWAMR_BUILD_WITH_CUSTOM_LLVM=1 -DLLVM_DIR=${LLVM_DIR} \
|
||||
$options
|
||||
cmake --build build --target wamrc --parallel
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build wamrc with options: $options"
|
||||
exit 1
|
||||
fi
|
||||
popd
|
||||
}
|
||||
|
||||
# build iwasm with default features enabled on x86_32
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -fr build && mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_TARGET=X86_32
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with default features enabled on x86_32!"
|
||||
exit 1;
|
||||
fi
|
||||
# Function to build iwasm
|
||||
build_iwasm() {
|
||||
local options="$1"
|
||||
echo "Building iwasm with options: $options"
|
||||
|
||||
# build iwasm with classic interpreter enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_INTERP=0
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with classic interpreter enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
pushd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build
|
||||
cmake -S . -B build \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DLLVM_DIR=${LLVM_DIR} \
|
||||
$options
|
||||
cmake --build build --target iwasm --parallel
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with options: $options"
|
||||
exit 1
|
||||
fi
|
||||
popd
|
||||
}
|
||||
|
||||
# build iwasm with extra features enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -fr build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug \
|
||||
-DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1 \
|
||||
-DWAMR_BUILD_MULTI_MODULE=1 -DWAMR_BUILD_SIMD=1 \
|
||||
-DWAMR_BUILD_TAIL_CALL=1 -DWAMR_BUILD_REF_TYPES=1 \
|
||||
-DWAMR_BUILD_CUSTOM_NAME_SECTION=1 -DWAMR_BUILD_MEMORY_PROFILING=1 \
|
||||
-DWAMR_BUILD_PERF_PROFILING=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 \
|
||||
-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build wamrc iwasm with extra features enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
# List of compilation options for wamrc
|
||||
wamrc_options_list=(
|
||||
#default
|
||||
""
|
||||
)
|
||||
|
||||
# build iwasm with global heap pool enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -fr build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug \
|
||||
-DWAMR_BUILD_ALLOC_WITH_USER_DATA=1 \
|
||||
-DWAMR_DISABLE_STACK_HW_BOUND_CHECK=1 \
|
||||
-DWAMR_BUILD_GLOBAL_HEAP_POOL=1 \
|
||||
-DWAMR_BUILD_GLOBAL_HEAP_SIZE=131072
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with global heap pool enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
# List of compilation options for iwasm
|
||||
iwasm_options_list=(
|
||||
#default
|
||||
""
|
||||
# +classic interp
|
||||
"-DWAMR_BUILD_FAST_INTERP=0"
|
||||
# +llvm jit + fast jit
|
||||
"-DWAMR_BUILD_JIT=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_FAST_JIT_DUMP=1"
|
||||
#
|
||||
"-DWAMR_BUILD_TARGET=X86_32"
|
||||
#
|
||||
# libraries
|
||||
"-DWAMR_BUILD_LIBC_BUILTIN=0 -DWAMR_BUILD_LIBC_UVWASI=1 -DWAMR_BUILD_LIBC_EMCC=1"
|
||||
"-DWAMR_BUILD_THREAD_MGR=1 -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_SHARED_MEMORY=1 -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1"
|
||||
"-DWAMR_BUILD_THREAD_MGR=1 -DWAMR_BUILD_LIB_WASI_THREADS=1 -DWAMR_BUILD_SHARED_MEMORY=1 -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1"
|
||||
"-DWAMR_BUILD_WASI_NN=1 -DWAMR_BUILD_WASI_NN_LLAMACPP=1"
|
||||
#
|
||||
# Wasm specs
|
||||
"-DWAMR_BUILD_GC=1 -DWAMR_BUILD_EXCE_HANDLING=1 -DWAMR_BUILD_STRINGREF=1 -DWAMR_STRINGREF_IMPL_SOURCE=STUB"
|
||||
"-DWAMR_BUILD_MEMORY64=1 -DWAMR_BUILD_MULTI_MEMORY=1"
|
||||
#
|
||||
# WARM features
|
||||
"-DWAMR_BUILD_MULTI_MODULE=1 -DWAMR_BUILD_MINI_LOADER=1 -DWAMR_BUILD_SHARED_HEAP=1"
|
||||
"-DWAMR_DISABLE_HW_BOUND_CHECK=1"
|
||||
"-DWAMR_CONFIGURABLE_BOUNDS_CHECKS=1"
|
||||
# - Debug
|
||||
"-DWAMR_BUILD_DEBUG_INTERP=1 -DWAMR_BUILD_DEBUG_AOT=1 -DWAMR_BUILD_DYNAMIC_AOT_DEBUG=1"
|
||||
# - developer options
|
||||
"-DWAMR_BUILD_CUSTOM_NAME_SECTION=1 -DWAMR_BUILD_LOAD_CUSTOM_SECTION=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 -DWAMR_BUILD_LINUX_PERF=1 -DWAMR_BUILD_AOT_VALIDATOR=1 -DWAMR_BUILD_MEMORY_PROFILING=1 -DWAMR_BUILD_PERF_PROFILING=1"
|
||||
# - global heap
|
||||
"-DWAMR_BUILD_ALLOC_WITH_USER_DATA=1 -DWAMR_BUILD_GLOBAL_HEAP_POOL=1 -DWAMR_BUILD_GLOBAL_HEAP_SIZE=131072"
|
||||
"-DWAMR_BUILD_QUICK_AOT_ENTRY=0 -DWAMR_DISABLE_WAKEUP_BLOCKING_OP=1 -DWAMR_BUILD_MODULE_INST_CONTEXT=0"
|
||||
# - pgo
|
||||
"-DWAMR_BUILD_STATIC_PGO=1"
|
||||
# TODO: SGX specifics.
|
||||
)
|
||||
|
||||
# build iwasm with wasi-threads enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -fr build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_LIB_WASI_THREADS=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with wasi-threads enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
# Loop through all iwasm options and build
|
||||
for options in "${iwasm_options_list[@]}"; do
|
||||
build_iwasm "$options"
|
||||
done
|
||||
|
||||
# build iwasm with GC enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_GC=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with GC enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with exception handling enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_EXCE_HANDLING=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with exception handling enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with memory64 enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MEMORY64=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with memory64 enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with multi-memory enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MULTI_MEMORY=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with multi-memory enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with hardware boundary check disabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_DISABLE_HW_BOUND_CHECK=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with hardware boundary check disabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with quick AOT entry disabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_QUICK_AOT_ENTRY=0
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with quick AOT entry disabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with wakeup of blocking operations disabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_DISABLE_WAKEUP_BLOCKING_OP=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with wakeup of blocking operations disabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with module instance context disabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MODULE_INST_CONTEXT=0 \
|
||||
-DWAMR_BUILD_LIBC_BUILTIN=0 -DWAMR_BUILD_LIBC_WASI=0
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with module instance context disabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with libc-uvwasi enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -fr build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_LIBC_UVWASI=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with libc-uvwasi enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with fast jit lazy mode enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_FAST_JIT_DUMP=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with fast jit lazy mode enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with fast jit eager mode enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_FAST_JIT_DUMP=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with fast jit eager mode enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# TODO: use pre-built llvm binary to build llvm-jit and multi-tier-jit
|
||||
: '
|
||||
# build iwasm with llvm jit lazy mode enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_JIT=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build llvm jit lazy mode enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with llvm jit eager mode enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build llvm jit eager mode enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with multi-tier jit enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 \
|
||||
-DWAMR_BUILD_FAST_JIT_DUMP=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with multi-tier jit enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
'
|
||||
|
||||
# build iwasm with wasm mini-loader enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MINI_LOADER=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build with wasm mini-loader enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with source debugging enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_DEBUG_INTERP=1 -DWAMR_BUILD_DEBUG_AOT=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with source debugging enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with AOT static PGO enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_STATIC_PGO=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with AOT static PGO enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with configurable bounds checks enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_CONFIGURABLE_BOUNDS_CHECKS=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with configurable bounds checks enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with linux perf support enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux/
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_LINUX_PERF=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with linux perf support enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with shared heap enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_SHARED_HEAP=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm with shared heap enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# build iwasm with dynamic aot debug enabled
|
||||
cd ${WAMR_DIR}/product-mini/platforms/linux
|
||||
rm -rf build && mkdir build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_DYNAMIC_AOT_DEBUG=1
|
||||
make -j
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Failed to build iwasm dynamic aot debug enabled!"
|
||||
exit 1;
|
||||
fi
|
||||
# Loop through all wamrc options and build
|
||||
for options in "${wamrc_options_list[@]}"; do
|
||||
build_wamrc "$options"
|
||||
done
|
||||
|
|
5
.github/workflows/build_iwasm_release.yml
vendored
5
.github/workflows/build_iwasm_release.yml
vendored
|
@ -23,7 +23,7 @@ on:
|
|||
type: string
|
||||
required: true
|
||||
upload_url:
|
||||
description: a semantic version number. it is required when `release` is true.
|
||||
description: upload binary assets to the URL of release
|
||||
type: string
|
||||
required: false
|
||||
ver_num:
|
||||
|
@ -137,7 +137,8 @@ jobs:
|
|||
- name: compress the binary on non-Windows
|
||||
if: inputs.runner != 'windows-latest'
|
||||
run: |
|
||||
tar czf iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz iwasm
|
||||
# Follow the symlink to the actual binary file
|
||||
tar --dereference -czf iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz iwasm
|
||||
zip iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.runner }}.zip iwasm
|
||||
working-directory: ${{ inputs.cwd }}/build
|
||||
|
||||
|
|
57
.github/workflows/build_wamr_wasi_extensions.yml
vendored
Normal file
57
.github/workflows/build_wamr_wasi_extensions.yml
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
name: build wamr_wasi_extensions release
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
upload_url:
|
||||
description: upload binary assets to the URL of release
|
||||
type: string
|
||||
required: false
|
||||
ver_num:
|
||||
description: a semantic version number. it is required when `release` is true.
|
||||
type: string
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build_wamr_wasi_extensions:
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: write # for uploading release artifacts
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install-wasi-sdk-wabt
|
||||
uses: ./.github/actions/install-wasi-sdk-wabt
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
|
||||
- name: Build wamr-wasi-extensions
|
||||
run: |
|
||||
mkdir dist
|
||||
./build_libs.sh $(pwd)/dist/wamr-wasi-extensions
|
||||
working-directory: wamr-wasi-extensions
|
||||
|
||||
- name: Compress the binary
|
||||
run: |
|
||||
zip -r wamr-wasi-extensions-${{ inputs.ver_num }}.zip wamr-wasi-extensions
|
||||
working-directory: wamr-wasi-extensions/dist
|
||||
|
||||
- name: Upload release zip
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ inputs.upload_url }}
|
||||
asset_path: wamr-wasi-extensions/dist/wamr-wasi-extensions-${{ inputs.ver_num }}.zip
|
||||
asset_name: wamr-wasi-extensions-${{ inputs.ver_num }}.zip
|
||||
asset_content_type: application/zip
|
5
.github/workflows/build_wamrc.yml
vendored
5
.github/workflows/build_wamrc.yml
vendored
|
@ -23,7 +23,7 @@ on:
|
|||
type: string
|
||||
required: true
|
||||
upload_url:
|
||||
description: a semantic version number. it is required when `release` is true.
|
||||
description: upload binary assets to the URL of release
|
||||
type: string
|
||||
required: false
|
||||
ver_num:
|
||||
|
@ -73,7 +73,8 @@ jobs:
|
|||
- name: compress the binary on non-Windows
|
||||
if: inputs.runner != 'windows-latest' && inputs.release
|
||||
run: |
|
||||
tar czf wamrc-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz wamrc
|
||||
# Follow the symlink to the actual binary file
|
||||
tar --dereference -czf wamrc-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz wamrc
|
||||
zip wamrc-${{ inputs.ver_num }}-${{ inputs.runner }}.zip wamrc
|
||||
working-directory: wamr-compiler/build
|
||||
|
||||
|
|
189
.github/workflows/codeql.yml
vendored
189
.github/workflows/codeql.yml
vendored
|
@ -1,29 +1,24 @@
|
|||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
#pull_request:
|
||||
# types:
|
||||
# - opened
|
||||
# branches: '*'
|
||||
#push:
|
||||
# branches: [ "main" ]
|
||||
# midnight UTC
|
||||
# run on every push to the feature-development branch
|
||||
# the main branch is covered by below cron plan
|
||||
push:
|
||||
branches:
|
||||
- dev/**
|
||||
# midnight UTC on the latest commit on the main branch
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
- cron: "0 0 * * *"
|
||||
# allow to be triggered manually
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
# only run this job if the repository is not a fork
|
||||
# if want to run this job on a fork, please remove the if condition
|
||||
if: github.repository == 'bytecodealliance/wasm-micro-runtime'
|
||||
name: Analyze
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
|
@ -31,14 +26,15 @@ jobs:
|
|||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners
|
||||
# Consider using larger runners for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-13') || 'ubuntu-22.04' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
# But it is not free, so please be aware of the cost.
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 360
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
|
||||
#TODO: add actions
|
||||
language: ["cpp"]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -46,76 +42,95 @@ jobs:
|
|||
security-events: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3.28.17
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3.29.1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
queries: security-and-quality
|
||||
config-file: ./.github/codeql/codeql_config.yml
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
queries: security-and-quality
|
||||
- run: |
|
||||
./.github/scripts/codeql_buildscript.sh
|
||||
|
||||
# Command-line programs to run using the OS shell.
|
||||
# See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3.29.1
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
upload: false
|
||||
id: step1
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
# - cpp/alloca-in-loop is about touch_pages() which is intended to
|
||||
# - cpp/command-line-injection is about bh_system() which is used to
|
||||
# - cpp/path-injection is used in bh_read_file_to_buffer() to load a .wasm.
|
||||
# or operate a stack usage file which is not sensitive or generate a .aot
|
||||
# - cpp/suspicious-pointer-scaling
|
||||
# - wasm_runtime_invoke_native() used to trivial registers
|
||||
# - cpp/uncontrolled-process-operation is about dlopen() which is used by
|
||||
# native libraries registrations.
|
||||
# - cpp/world-writable-file-creation is about fopen() a temporary file
|
||||
# for perf-PID.map or .aot(wamrc). The permission isn't sensitive.
|
||||
# file.
|
||||
#
|
||||
# execute customized compiler
|
||||
- name: Filter out unwanted errors and warnings
|
||||
uses: advanced-security/filter-sarif@v1
|
||||
with:
|
||||
patterns: |
|
||||
## Exclude files and directories
|
||||
-**/build/**
|
||||
-**/core/deps/**
|
||||
-**/cmake*/Modules/**
|
||||
-**/test*/**
|
||||
-**/wasm-app*/**
|
||||
## Exclude rules 1. Related to formatting, style
|
||||
-**:cpp/commented-out-code
|
||||
-**:cpp/complex-condition
|
||||
-**:cpp/empty-if
|
||||
-**:cpp/fixme-comment
|
||||
-**:cpp/include-non-header
|
||||
-**:cpp/long-switch
|
||||
-**:cpp/poorly-documented-function
|
||||
-**:cpp/trivial-switch
|
||||
-**:cpp/unused-local-variable
|
||||
-**:cpp/unused-static-function
|
||||
-**:cpp/unused-static-variable
|
||||
-**:cpp/use-of-goto
|
||||
## Exclude rules 2. Related to special usage of APIs
|
||||
-**:cpp/alloca-in-loop
|
||||
-**:cpp/command-line-injection
|
||||
-**:cpp/path-injection
|
||||
-core/iwasm/common/wasm_runtime_common.c:cpp/suspicious-pointer-scaling
|
||||
-**:cpp/uncontrolled-process-operation
|
||||
-**:cpp/world-writable-file-creation
|
||||
input: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
|
||||
output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
|
||||
|
||||
- run: |
|
||||
./.github/scripts/codeql_buildscript.sh
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3.28.17
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
upload: false
|
||||
id: step1
|
||||
- name: Upload CodeQL results to code scanning
|
||||
uses: github/codeql-action/upload-sarif@v3.29.1
|
||||
with:
|
||||
sarif_file: ${{ steps.step1.outputs.sarif-output }}
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
# Filter out rules with low severity or high false positve rate
|
||||
# Also filter out warnings in third-party code
|
||||
- name: Filter out unwanted errors and warnings
|
||||
uses: advanced-security/filter-sarif@v1
|
||||
with:
|
||||
patterns: |
|
||||
-**:cpp/path-injection
|
||||
-**:cpp/world-writable-file-creation
|
||||
-**:cpp/poorly-documented-function
|
||||
-**:cpp/potentially-dangerous-function
|
||||
-**:cpp/use-of-goto
|
||||
-**:cpp/integer-multiplication-cast-to-long
|
||||
-**:cpp/comparison-with-wider-type
|
||||
-**:cpp/leap-year/*
|
||||
-**:cpp/ambiguously-signed-bit-field
|
||||
-**:cpp/suspicious-pointer-scaling
|
||||
-**:cpp/suspicious-pointer-scaling-void
|
||||
-**:cpp/unsigned-comparison-zero
|
||||
-**/cmake*/Modules/**
|
||||
input: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
|
||||
output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
|
||||
- name: Upload CodeQL results as an artifact
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v4.6.2
|
||||
with:
|
||||
name: codeql-results
|
||||
path: ${{ steps.step1.outputs.sarif-output }}
|
||||
retention-days: 10
|
||||
|
||||
- name: Upload CodeQL results to code scanning
|
||||
uses: github/codeql-action/upload-sarif@v3.28.17
|
||||
with:
|
||||
sarif_file: ${{ steps.step1.outputs.sarif-output }}
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
- name: Upload CodeQL results as an artifact
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v4.6.2
|
||||
with:
|
||||
name: codeql-results
|
||||
path: ${{ steps.step1.outputs.sarif-output }}
|
||||
retention-days: 10
|
||||
|
||||
- name: Fail if an error is found
|
||||
run: |
|
||||
./.github/scripts/codeql_fail_on_error.py \
|
||||
${{ steps.step1.outputs.sarif-output }}/cpp.sarif
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
- name: Fail if an error is found
|
||||
run: |
|
||||
./.github/scripts/codeql_fail_on_error.py \
|
||||
${{ steps.step1.outputs.sarif-output }}/cpp.sarif
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
|
|
182
.github/workflows/compilation_on_android_ubuntu.yml
vendored
182
.github/workflows/compilation_on_android_ubuntu.yml
vendored
|
@ -69,6 +69,7 @@ env:
|
|||
GC_TEST_OPTIONS: "-s spec -G -b -P"
|
||||
MEMORY64_TEST_OPTIONS: "-s spec -W -b -P"
|
||||
MULTI_MEMORY_TEST_OPTIONS: "-s spec -E -b -P"
|
||||
EXTENDED_CONST_EXPR_TEST_OPTIONS: "-s spec -N -b -P"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -164,6 +165,7 @@ jobs:
|
|||
"-DWAMR_BUILD_MEMORY64=1",
|
||||
"-DWAMR_BUILD_MULTI_MEMORY=1",
|
||||
"-DWAMR_BUILD_SHARED=1",
|
||||
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
|
||||
]
|
||||
os: [ubuntu-22.04]
|
||||
platform: [android, linux]
|
||||
|
@ -437,6 +439,11 @@ jobs:
|
|||
ctest --test-dir build --output-on-failure
|
||||
working-directory: samples/wasm-c-api
|
||||
|
||||
- name: Build Sample [printversion]
|
||||
run: |
|
||||
./test.sh
|
||||
working-directory: samples/printversion
|
||||
|
||||
build_samples_others:
|
||||
needs:
|
||||
[
|
||||
|
@ -604,6 +611,7 @@ jobs:
|
|||
$GC_TEST_OPTIONS,
|
||||
$MEMORY64_TEST_OPTIONS,
|
||||
$MULTI_MEMORY_TEST_OPTIONS,
|
||||
$EXTENDED_CONST_EXPR_TEST_OPTIONS,
|
||||
]
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
|
@ -613,49 +621,6 @@ jobs:
|
|||
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
|
||||
running_mode: aot
|
||||
test_option: $WAMR_COMPILER_TEST_OPTIONS
|
||||
exclude:
|
||||
# incompatible modes and features
|
||||
# classic-interp doesn't support simd
|
||||
- running_mode: "classic-interp"
|
||||
test_option: $SIMD_TEST_OPTIONS
|
||||
# llvm jit doesn't support multi module
|
||||
- running_mode: "jit"
|
||||
test_option: $MULTI_MODULES_TEST_OPTIONS
|
||||
# fast-jit doesn't support multi module, simd
|
||||
- running_mode: "fast-jit"
|
||||
test_option: $MULTI_MODULES_TEST_OPTIONS
|
||||
- running_mode: "fast-jit"
|
||||
test_option: $SIMD_TEST_OPTIONS
|
||||
# multi-tier-jit doesn't support multi module, simd
|
||||
- running_mode: "multi-tier-jit"
|
||||
test_option: $MULTI_MODULES_TEST_OPTIONS
|
||||
- running_mode: "multi-tier-jit"
|
||||
test_option: $SIMD_TEST_OPTIONS
|
||||
# fast-jit and multi-tier-jit don't support GC
|
||||
- running_mode: "fast-jit"
|
||||
test_option: $GC_TEST_OPTIONS
|
||||
- running_mode: "multi-tier-jit"
|
||||
test_option: $GC_TEST_OPTIONS
|
||||
# fast-interp, fast-jit, llvm-jit, multi-tier-jit don't support Memory64
|
||||
- running_mode: "fast-interp"
|
||||
test_option: $MEMORY64_TEST_OPTIONS
|
||||
- running_mode: "fast-jit"
|
||||
test_option: $MEMORY64_TEST_OPTIONS
|
||||
- running_mode: "jit"
|
||||
test_option: $MEMORY64_TEST_OPTIONS
|
||||
- running_mode: "multi-tier-jit"
|
||||
test_option: $MEMORY64_TEST_OPTIONS
|
||||
# aot, fast-interp, fast-jit, llvm-jit, multi-tier-jit don't support Multi Memory
|
||||
- running_mode: "aot"
|
||||
test_option: $MULTI_MEMORY_TEST_OPTIONS
|
||||
- running_mode: "fast-interp"
|
||||
test_option: $MULTI_MEMORY_TEST_OPTIONS
|
||||
- running_mode: "fast-jit"
|
||||
test_option: $MULTI_MEMORY_TEST_OPTIONS
|
||||
- running_mode: "jit"
|
||||
test_option: $MULTI_MEMORY_TEST_OPTIONS
|
||||
- running_mode: "multi-tier-jit"
|
||||
test_option: $MULTI_MEMORY_TEST_OPTIONS
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
|
@ -677,15 +642,6 @@ jobs:
|
|||
with:
|
||||
os: ${{ matrix.os }}
|
||||
|
||||
# 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
|
||||
|
@ -722,7 +678,7 @@ jobs:
|
|||
|
||||
- name: Build WASI thread tests
|
||||
if: matrix.test_option == '$WASI_TEST_OPTIONS'
|
||||
run: bash build.sh --sysroot "$SYSROOT_PATH"
|
||||
run: bash build.sh
|
||||
working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/
|
||||
|
||||
- name: build socket api tests
|
||||
|
@ -768,123 +724,3 @@ jobs:
|
|||
eval $(opam env)
|
||||
./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
|
||||
working-directory: ./tests/wamr-test-suites
|
||||
|
||||
test-wamr-ide:
|
||||
needs:
|
||||
[
|
||||
build_iwasm
|
||||
]
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
PYTHON_VERSION: '3.10'
|
||||
PYTHON_UBUNTU_STANDALONE_BUILD: https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-unknown-linux-gnu-install_only.tar.gz
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
rustup target add wasm32-wasip1
|
||||
sudo apt update && sudo apt-get install -y lld ninja-build
|
||||
npm install
|
||||
working-directory: test-tools/wamr-ide/VSCode-Extension
|
||||
|
||||
- name: code style check
|
||||
run: |
|
||||
npm install --save-dev prettier
|
||||
npm run prettier-format-check
|
||||
working-directory: test-tools/wamr-ide/VSCode-Extension
|
||||
|
||||
- name: build iwasm with source debugging feature
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DWAMR_BUILD_DEBUG_INTERP=1 -DWAMR_BUILD_REF_TYPES=1
|
||||
make
|
||||
working-directory: product-mini/platforms/linux
|
||||
|
||||
- name: Cache LLDB
|
||||
id: cache-lldb
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
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 }}
|
||||
|
||||
- if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }}
|
||||
name: get stand-alone python ubuntu
|
||||
run: |
|
||||
wget ${{ env.PYTHON_UBUNTU_STANDALONE_BUILD }} -O python.tar.gz
|
||||
tar -xvf python.tar.gz
|
||||
working-directory: core/deps
|
||||
|
||||
- if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }}
|
||||
name: download llvm
|
||||
run: |
|
||||
wget https://github.com/llvm/llvm-project/archive/1f27fe6128769f00197925c3b8f6abb9d0e5cd2e.zip
|
||||
unzip -q 1f27fe6128769f00197925c3b8f6abb9d0e5cd2e.zip
|
||||
mv llvm-project-1f27fe6128769f00197925c3b8f6abb9d0e5cd2e llvm-project
|
||||
working-directory: core/deps
|
||||
|
||||
- if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }}
|
||||
name: apply wamr patch
|
||||
run: |
|
||||
git init
|
||||
git config user.email "action@github.com"
|
||||
git config user.name "github action"
|
||||
git apply ../../../build-scripts/lldb_wasm.patch
|
||||
working-directory: core/deps/llvm-project
|
||||
|
||||
- if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }}
|
||||
name: build lldb ubuntu
|
||||
run: |
|
||||
echo "start to build lldb..."
|
||||
mkdir -p wamr-lldb
|
||||
cmake -S ./llvm -B build \
|
||||
-G Ninja \
|
||||
-DCMAKE_INSTALL_PREFIX=../wamr-lldb \
|
||||
-DCMAKE_BUILD_TYPE:STRING="Release" \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DLLVM_ENABLE_PROJECTS="clang;lldb" \
|
||||
-DLLVM_TARGETS_TO_BUILD:STRING="X86;WebAssembly" \
|
||||
-DLLVM_BUILD_BENCHMARKS:BOOL=OFF \
|
||||
-DLLVM_BUILD_DOCS:BOOL=OFF \
|
||||
-DLLVM_BUILD_EXAMPLES:BOOL=OFF \
|
||||
-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \
|
||||
-DLLVM_BUILD_TESTS:BOOL=OFF \
|
||||
-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \
|
||||
-DLLVM_INCLUDE_DOCS:BOOL=OFF \
|
||||
-DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \
|
||||
-DLLVM_INCLUDE_TESTS:BOOL=OFF \
|
||||
-DLLVM_ENABLE_BINDINGS:BOOL=OFF \
|
||||
-DLLVM_ENABLE_LIBXML2:BOOL=ON \
|
||||
-DLLVM_ENABLE_LLD:BOOL=ON \
|
||||
-DLLDB_ENABLE_PYTHON:BOOL=ON \
|
||||
-DLLDB_EMBED_PYTHON_HOME=ON \
|
||||
-DLLDB_PYTHON_HOME=.. \
|
||||
-DLLDB_PYTHON_RELATIVE_PATH=lib/lldb-python \
|
||||
-DPython3_EXECUTABLE="$(pwd)/../python/bin/python${{ env.PYTHON_VERSION }}"
|
||||
cmake --build build --target lldb install --parallel $(nproc)
|
||||
working-directory: core/deps/llvm-project
|
||||
|
||||
- if: ${{ steps.cache-lldb.outputs.cache-hit != 'true' }}
|
||||
name: copy lldb to extension folder
|
||||
run: |
|
||||
mkdir -p bin
|
||||
mkdir -p lib
|
||||
cp ../../../../../../core/deps/llvm-project/lldb/tools/lldb-vscode/package.json ./
|
||||
cp -r ../../../../../../core/deps/llvm-project/lldb/tools/lldb-vscode/syntaxes/ ./
|
||||
cp ../../../../../../core/deps/llvm-project/build/bin/lldb* bin
|
||||
cp ../../../../../../core/deps/llvm-project/build/lib/liblldb*.so lib
|
||||
cp ../../../../../../core/deps/llvm-project/build/lib/liblldb*.so.* lib
|
||||
cp -R ../../../../../../core/deps/llvm-project/build/lib/lldb-python lib
|
||||
cp -R ../../../../../../core/deps/python/lib/python* lib
|
||||
cp ../../../../../../core/deps/python/lib/libpython${{ env.PYTHON_VERSION }}.so.1.0 lib
|
||||
working-directory: test-tools/wamr-ide/VSCode-Extension/resource/debug/linux
|
||||
|
||||
- name: run tests
|
||||
timeout-minutes: 5
|
||||
run: xvfb-run npm run test
|
||||
working-directory: test-tools/wamr-ide/VSCode-Extension
|
||||
|
|
6
.github/workflows/compilation_on_macos.yml
vendored
6
.github/workflows/compilation_on_macos.yml
vendored
|
@ -142,6 +142,7 @@ jobs:
|
|||
"-DWAMR_BUILD_SIMD=1",
|
||||
"-DWAMR_BUILD_TAIL_CALL=1",
|
||||
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
|
||||
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
|
||||
]
|
||||
os: [macos-13]
|
||||
platform: [darwin]
|
||||
|
@ -282,6 +283,11 @@ jobs:
|
|||
ctest --test-dir build --output-on-failure
|
||||
working-directory: samples/wasm-c-api
|
||||
|
||||
- name: Build Sample [printversion]
|
||||
run: |
|
||||
./test.sh
|
||||
working-directory: samples/printversion
|
||||
|
||||
build_samples_others:
|
||||
needs: [build_iwasm, build_wamrc, build_llvm_libraries_on_intel_macos, build_llvm_libraries_on_arm_macos]
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
|
25
.github/workflows/compilation_on_sgx.yml
vendored
25
.github/workflows/compilation_on_sgx.yml
vendored
|
@ -100,6 +100,7 @@ jobs:
|
|||
"-DWAMR_BUILD_MULTI_MODULE=1",
|
||||
"-DWAMR_BUILD_PERF_PROFILING=1",
|
||||
"-DWAMR_BUILD_REF_TYPES=1",
|
||||
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
|
||||
# doesn't support
|
||||
"-DWAMR_BUILD_SIMD=0",
|
||||
"-DWAMR_BUILD_TAIL_CALL=1",
|
||||
|
@ -290,28 +291,6 @@ jobs:
|
|||
|
||||
- name: run spec tests
|
||||
run: |
|
||||
set +e
|
||||
source /opt/intel/sgxsdk/environment
|
||||
attempts=0
|
||||
max_attempts=3
|
||||
|
||||
while [ $attempts -lt $max_attempts ]; do
|
||||
./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
|
||||
exitcode="$?"
|
||||
|
||||
if [ $exitcode -eq 0 ]; then
|
||||
echo "Spec test passed"
|
||||
exit 0
|
||||
elif [ $exitcode -ne 143 ]; then
|
||||
echo "Spec test failed with error code $exitcode"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$exitcode is a known GitHub-hosted runner issue"
|
||||
echo "::notice::Re-running the spec test due to error code 143"
|
||||
attempts=$((attempts + 1))
|
||||
done
|
||||
|
||||
echo "::notice::Report an error with code 143 in SGX CI after $max_attempts attempts"
|
||||
exit 143
|
||||
./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
|
||||
working-directory: ./tests/wamr-test-suites
|
||||
|
|
86
.github/workflows/compilation_on_windows.yml
vendored
86
.github/workflows/compilation_on_windows.yml
vendored
|
@ -57,23 +57,33 @@ permissions:
|
|||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
build_llvm_libraries_on_windows:
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
uses: ./.github/workflows/build_llvm_libraries.yml
|
||||
with:
|
||||
os: "windows-latest"
|
||||
arch: "AArch64 ARM Mips RISCV X86"
|
||||
|
||||
build_iwasm:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
build_options: [
|
||||
"-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0",
|
||||
"-DWAMR_BUILD_AOT=0",
|
||||
"-DWAMR_BUILD_TAIL_CALL=1",
|
||||
"-DWAMR_BUILD_CUSTOM_NAME_SECTION=1",
|
||||
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
|
||||
"-DWAMR_BUILD_REF_TYPES=1",
|
||||
"-DWAMR_BUILD_SIMD=1",
|
||||
"-DWAMR_BUILD_DEBUG_INTERP=1",
|
||||
"-DWAMR_BUILD_LIB_PTHREAD=1",
|
||||
"-DWAMR_BUILD_LIB_WASI_THREADS=1",
|
||||
"-DWAMR_BUILD_LIBC_UVWASI=0 -DWAMR_BUILD_LIBC_WASI=1"
|
||||
]
|
||||
build_options:
|
||||
[
|
||||
"-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0",
|
||||
"-DWAMR_BUILD_AOT=0",
|
||||
"-DWAMR_BUILD_TAIL_CALL=1",
|
||||
"-DWAMR_BUILD_CUSTOM_NAME_SECTION=1",
|
||||
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
|
||||
"-DWAMR_BUILD_REF_TYPES=1",
|
||||
"-DWAMR_BUILD_SIMD=1",
|
||||
"-DWAMR_BUILD_DEBUG_INTERP=1",
|
||||
"-DWAMR_BUILD_LIB_PTHREAD=1",
|
||||
"-DWAMR_BUILD_LIB_WASI_THREADS=1",
|
||||
"-DWAMR_BUILD_LIBC_UVWASI=0 -DWAMR_BUILD_LIBC_WASI=1",
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
@ -89,17 +99,49 @@ jobs:
|
|||
cmake .. ${{ matrix.build_options }}
|
||||
cmake --build . --config Release --parallel 4
|
||||
|
||||
build_wamrc:
|
||||
needs: [build_llvm_libraries_on_windows]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-latest
|
||||
llvm_cache_key: ${{ needs.build_llvm_libraries_on_windows.outputs.cache_key }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# since jobs.id can't contain the dot character
|
||||
# it is hard to use `format` to assemble the cache key
|
||||
- name: Get LLVM libraries
|
||||
id: retrieve_llvm_libs
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.llvm_cache_key }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: Build wamrc
|
||||
run: |
|
||||
cmake -S . -B build
|
||||
cmake --build build --config Release --parallel 4
|
||||
working-directory: wamr-compiler
|
||||
|
||||
test:
|
||||
runs-on: windows-latest
|
||||
needs: [build]
|
||||
needs: [build_iwasm, build_wamrc]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
running_mode:
|
||||
[
|
||||
"classic-interp",
|
||||
"fast-interp",
|
||||
]
|
||||
running_mode: ["classic-interp", "fast-interp"]
|
||||
test_option:
|
||||
[
|
||||
$DEFAULT_TEST_OPTIONS,
|
||||
|
@ -130,6 +172,10 @@ jobs:
|
|||
run: ./build.sh
|
||||
working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/
|
||||
|
||||
- name: install wget
|
||||
shell: bash
|
||||
run: choco install wget
|
||||
|
||||
- name: run tests
|
||||
shell: bash
|
||||
timeout-minutes: 20
|
||||
|
|
49
.github/workflows/nightly_run.yml
vendored
49
.github/workflows/nightly_run.yml
vendored
|
@ -36,12 +36,12 @@ env:
|
|||
LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
MULTI_TIER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
|
||||
# For Spec Test
|
||||
# FIXME: use binary release(adding -b) instead of building from source after upgrading to 22.04
|
||||
DEFAULT_TEST_OPTIONS: "-s spec -P"
|
||||
MULTI_MODULES_TEST_OPTIONS: "-s spec -M -P"
|
||||
SIMD_TEST_OPTIONS: "-s spec -S -P"
|
||||
THREADS_TEST_OPTIONS: "-s spec -p -P"
|
||||
X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P"
|
||||
DEFAULT_TEST_OPTIONS: "-s spec -b -P"
|
||||
EXTENDED_CONST_EXPR_TEST_OPTIONS: "-s spec -b -P -N"
|
||||
MULTI_MODULES_TEST_OPTIONS: "-s spec -b -P -M"
|
||||
SIMD_TEST_OPTIONS: "-s spec -b -P -S"
|
||||
THREADS_TEST_OPTIONS: "-s spec -b -P -p"
|
||||
X86_32_TARGET_TEST_OPTIONS: "-m x86_32"
|
||||
WASI_TEST_OPTIONS: "-s wasi_certification -w"
|
||||
|
||||
permissions:
|
||||
|
@ -129,6 +129,7 @@ jobs:
|
|||
"-DWAMR_BUILD_MEMORY64=1",
|
||||
"-DWAMR_BUILD_MULTI_MEMORY=1",
|
||||
"-DWAMR_BUILD_SHARED=1",
|
||||
"-DWAMR_BUILD_EXTENDED_CONST_EXPR=1",
|
||||
]
|
||||
os: [ubuntu-22.04]
|
||||
platform: [android, linux]
|
||||
|
@ -589,6 +590,7 @@ jobs:
|
|||
$DEFAULT_TEST_OPTIONS,
|
||||
$MULTI_MODULES_TEST_OPTIONS,
|
||||
$SIMD_TEST_OPTIONS,
|
||||
$EXTENDED_CONST_EXPR_TEST_OPTIONS,
|
||||
$THREADS_TEST_OPTIONS,
|
||||
$WASI_TEST_OPTIONS,
|
||||
]
|
||||
|
@ -617,42 +619,21 @@ jobs:
|
|||
sanitizer: tsan
|
||||
- running_mode: "multi-tier-jit"
|
||||
sanitizer: tsan
|
||||
# classic-interp and fast-interp don't support simd
|
||||
- running_mode: "classic-interp"
|
||||
test_option: $SIMD_TEST_OPTIONS
|
||||
# simd128.h brings ubsan errors
|
||||
# like: negation of XXXcannot be represented in type 'long int';
|
||||
# cast to an unsigned type to negate this value to itself
|
||||
- running_mode: "fast-interp"
|
||||
test_option: $SIMD_TEST_OPTIONS
|
||||
# llvm jit doesn't support multi module
|
||||
- running_mode: "jit"
|
||||
test_option: $MULTI_MODULES_TEST_OPTIONS
|
||||
# fast-jit doesn't support multi module, simd
|
||||
- running_mode: "fast-jit"
|
||||
test_option: $MULTI_MODULES_TEST_OPTIONS
|
||||
- running_mode: "fast-jit"
|
||||
test_option: $SIMD_TEST_OPTIONS
|
||||
# multi-tier-jit doesn't support multi module, simd
|
||||
- running_mode: "multi-tier-jit"
|
||||
test_option: $MULTI_MODULES_TEST_OPTIONS
|
||||
- running_mode: "multi-tier-jit"
|
||||
test_option: $SIMD_TEST_OPTIONS
|
||||
sanitizer: ubsan
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install-wasi-sdk-wabt
|
||||
if: matrix.test_option == '$WASI_TEST_OPTIONS'
|
||||
uses: ./.github/actions/install-wasi-sdk-wabt
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
|
||||
# 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
|
||||
|
@ -697,12 +678,12 @@ jobs:
|
|||
|
||||
- name: Build WASI thread tests
|
||||
if: matrix.test_option == '$WASI_TEST_OPTIONS'
|
||||
run: bash build.sh --sysroot "$SYSROOT_PATH"
|
||||
run: bash build.sh
|
||||
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"
|
||||
run: bash build.sh
|
||||
working-directory: ./core/iwasm/libraries/lib-wasi-threads/stress-test/
|
||||
|
||||
- name: build socket api tests
|
||||
|
|
9
.github/workflows/release_process.yml
vendored
9
.github/workflows/release_process.yml
vendored
|
@ -239,3 +239,12 @@ jobs:
|
|||
arch: universal
|
||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
||||
ver_num: ${{ needs.create_tag.outputs.new_ver}}
|
||||
|
||||
release_wamr_wasi_extensions:
|
||||
permissions:
|
||||
contents: write # upload release artifact
|
||||
needs: [create_tag, create_release]
|
||||
uses: ./.github/workflows/build_wamr_wasi_extensions.yml
|
||||
with:
|
||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
||||
ver_num: ${{ needs.create_tag.outputs.new_ver }}
|
||||
|
|
4
.github/workflows/supply_chain.yml
vendored
4
.github/workflows/supply_chain.yml
vendored
|
@ -39,7 +39,7 @@ jobs:
|
|||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
||||
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
|
@ -60,6 +60,6 @@ jobs:
|
|||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@5eb3ed6614230b1931d5c08df9e096e4ba524f21
|
||||
uses: github/codeql-action/upload-sarif@4c57370d0304fbff638216539f81d9163f77712a
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
57
.github/workflows/wamr_wasi_extensions.yml
vendored
Normal file
57
.github/workflows/wamr_wasi_extensions.yml
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
name: wamr_wasi_extensions
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
paths:
|
||||
- ".github/workflows/wamr_wasi_extensions.yml"
|
||||
- "wamr_wasi_extensios/**"
|
||||
- "core/iwasm/libraries/wasi-nn/include/**"
|
||||
- "core/iwasm/libraries/lib-socket/**"
|
||||
# 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:
|
||||
build_wamr_wasi_extensions:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, macos-13, macos-14]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install-wasi-sdk-wabt
|
||||
uses: ./.github/actions/install-wasi-sdk-wabt
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
|
||||
- name: Build wamr-wasi-extensions
|
||||
run: |
|
||||
mkdir dist
|
||||
./build_libs.sh $(pwd)/dist/wamr-wasi-extensions
|
||||
working-directory: wamr-wasi-extensions
|
||||
|
||||
- name: Build wamr-wasi-extensions samples
|
||||
run: |
|
||||
./build_samples.sh $(pwd)/dist/wamr-wasi-extensions
|
||||
working-directory: wamr-wasi-extensions
|
||||
|
||||
- name: Upload artifacts
|
||||
if: matrix.os == 'macos-14'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: wamr-wasi-extensions
|
||||
path: wamr-wasi-extensions/dist
|
||||
retention-days: 10
|
|
@ -99,9 +99,9 @@ if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS)
|
|||
set (WAMR_BUILD_LIB_WASI_THREADS 0)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_ENABLE_COPY_CALLSTACK)
|
||||
if (NOT DEFINED WAMR_BUILD_COPY_CALL_STACK)
|
||||
# Disable copy callstack by default
|
||||
set (WAMR_ENABLE_COPY_CALLSTACK 0)
|
||||
set (WAMR_BUILD_COPY_CALL_STACK 0)
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
|
||||
|
@ -152,15 +152,11 @@ include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
|||
set (THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
if (MSVC)
|
||||
add_definitions(-DCOMPILING_WASM_RUNTIME_API=1)
|
||||
endif ()
|
||||
|
||||
add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
set_target_properties (vmlib PROPERTIES OUTPUT_NAME iwasm)
|
||||
target_include_directories(vmlib INTERFACE
|
||||
$<BUILD_INTERFACE:${WAMR_ROOT_DIR}/core/iwasm/include>
|
||||
$<INSTALL_INTERFACE:include/iwasm>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
target_link_libraries (vmlib PUBLIC ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
@ -189,7 +185,7 @@ set_version_info (vmlib)
|
|||
install (TARGETS vmlib
|
||||
EXPORT iwasmTargets
|
||||
LIBRARY DESTINATION lib
|
||||
PUBLIC_HEADER DESTINATION include/iwasm
|
||||
PUBLIC_HEADER DESTINATION include
|
||||
)
|
||||
|
||||
install_iwasm_package ()
|
||||
|
|
|
@ -21,7 +21,7 @@ WebAssembly Micro Runtime (WAMR) is a lightweight standalone WebAssembly (Wasm)
|
|||
|
||||
### Key features
|
||||
- Full compliant to the W3C Wasm MVP
|
||||
- Small runtime binary size (core vmlib on cortex-m4f with tail-call/bulk memroy/shared memroy support, text size from bloaty)
|
||||
- Small runtime binary size (core vmlib on cortex-m4f with tail-call/bulk memory/shared memory support, text size from bloaty)
|
||||
* ~58.9K for fast interpreter
|
||||
* ~56.3K for classic interpreter
|
||||
* ~29.4K for aot runtime
|
||||
|
|
|
@ -1,3 +1,35 @@
|
|||
## WAMR-2.3.1
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- Revert the location to install public headers (#4295). This restores compatibility (of installed headers) with WAMR-2.2.0 and earlier.
|
||||
|
||||
### New Features
|
||||
|
||||
- feat: Add instruction metering for interpreter (#4122)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- updating WASI stdio handle initialization and build options for UVWASI (#4260)
|
||||
- Fix SIMD load lane to avoid incompatible pointer types (#4278)
|
||||
- Fixed unit tests on X86_32 (#4279)
|
||||
- Improve Embedding WAMR guideline (#4284)
|
||||
- Fix Compiler Error C2491 (#4286)
|
||||
- Enhance type checking for function types in loader and improve error handling (#4294)
|
||||
- Dockerfile.vx-delegate build error fix (#4273)
|
||||
- Enable runtime API exposure for MSVC builds (#4287)
|
||||
|
||||
### Enhancements
|
||||
|
||||
- feat(yml): Add ESP32-P4 and ESP32-C5 support (#4270)
|
||||
- add a sample to use cmake package (#4291)
|
||||
|
||||
### Others
|
||||
|
||||
- build(deps): Bump github/codeql-action from 3.28.17 to 3.28.18 (#4285)
|
||||
|
||||
---
|
||||
|
||||
## WAMR-2.3.0
|
||||
|
||||
### Breaking changes
|
||||
|
@ -465,7 +497,7 @@
|
|||
- wasm loader: Fix handling if block without op else (#3404)
|
||||
- ref-types: Correct default value for function local variables (#3397)
|
||||
- aot compiler: Fix the length type passed to aot_memmove/aot_memset (#3378)
|
||||
- Fix loader and mini-loader select potiential error (#3374)
|
||||
- Fix loader and mini-loader select potential error (#3374)
|
||||
- Fix aot debugger compilation error on windows (#3370)
|
||||
- A few native stack detection fixes for macOS/arm64 (#3368)
|
||||
- Fix ESP32-S3 compiling error (#3359)
|
||||
|
|
|
@ -211,6 +211,10 @@ if (NOT DEFINED WAMR_BUILD_TAIL_CALL)
|
|||
set (WAMR_BUILD_TAIL_CALL 0)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_EXTENDED_CONST_EXPR)
|
||||
set (WAMR_BUILD_EXTENDED_CONST_EXPR 0)
|
||||
endif ()
|
||||
|
||||
########################################
|
||||
# Compilation options to marco
|
||||
########################################
|
||||
|
@ -334,15 +338,10 @@ if (WAMR_BUILD_SHARED_HEAP EQUAL 1)
|
|||
add_definitions (-DWASM_ENABLE_SHARED_HEAP=1)
|
||||
message (" Shared heap enabled")
|
||||
endif()
|
||||
|
||||
if (WAMR_ENABLE_COPY_CALLSTACK EQUAL 1)
|
||||
add_definitions (-DWAMR_ENABLE_COPY_CALLSTACK=1)
|
||||
if (WAMR_BUILD_COPY_CALL_STACK EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_COPY_CALL_STACK=1)
|
||||
message(" Copy callstack enabled")
|
||||
else ()
|
||||
add_definitions (-DWAMR_ENABLE_COPY_CALLSTACK=0)
|
||||
message(" Copy callstack disabled")
|
||||
endif()
|
||||
|
||||
if (WAMR_BUILD_MEMORY64 EQUAL 1)
|
||||
# if native is 32-bit or cross-compiled to 32-bit
|
||||
if (NOT WAMR_BUILD_TARGET MATCHES ".*64.*")
|
||||
|
@ -539,6 +538,9 @@ if (WAMR_BUILD_WASI_NN EQUAL 1)
|
|||
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 ()
|
||||
if (NOT DEFINED WAMR_BUILD_WASI_EPHEMERAL_NN)
|
||||
set(WAMR_BUILD_WASI_EPHEMERAL_NN 1)
|
||||
endif()
|
||||
if (WAMR_BUILD_WASI_EPHEMERAL_NN EQUAL 1)
|
||||
message (" WASI-NN: use 'wasi_ephemeral_nn' instead of 'wasi-nn'")
|
||||
add_definitions (-DWASM_ENABLE_WASI_EPHEMERAL_NN=1)
|
||||
|
@ -671,7 +673,17 @@ if (WAMR_BUILD_AOT_VALIDATOR EQUAL 1)
|
|||
message (" AOT validator enabled")
|
||||
add_definitions (-DWASM_ENABLE_AOT_VALIDATOR=1)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_INSTRUCTION_METERING EQUAL 1)
|
||||
message (" Instruction metering enabled")
|
||||
add_definitions (-DWASM_ENABLE_INSTRUCTION_METERING=1)
|
||||
endif ()
|
||||
if (WAMR_BUILD_EXTENDED_CONST_EXPR EQUAL 1)
|
||||
message (" Extended constant expression enabled")
|
||||
add_definitions(-DWASM_ENABLE_EXTENDED_CONST_EXPR=1)
|
||||
else()
|
||||
message (" Extended constant expression disabled")
|
||||
add_definitions(-DWASM_ENABLE_EXTENDED_CONST_EXPR=0)
|
||||
endif ()
|
||||
########################################
|
||||
# Show Phase4 Wasm proposals status.
|
||||
########################################
|
||||
|
@ -685,6 +697,7 @@ message (
|
|||
" \"WebAssembly C and C++ API\"\n"
|
||||
" Configurable. 0 is OFF. 1 is ON:\n"
|
||||
" \"Bulk Memory Operation\" via WAMR_BUILD_BULK_MEMORY: ${WAMR_BUILD_BULK_MEMORY}\n"
|
||||
" \"Extended Constant Expressions\" via WAMR_BUILD_EXTENDED_CONST_EXPR: ${WAMR_BUILD_EXTENDED_CONST_EXPR}\n"
|
||||
" \"Fixed-width SIMD\" via WAMR_BUILD_SIMD: ${WAMR_BUILD_SIMD}\n"
|
||||
" \"Garbage collection\" via WAMR_BUILD_GC: ${WAMR_BUILD_GC}\n"
|
||||
" \"Legacy Exception handling\" via WAMR_BUILD_EXCE_HANDLING: ${WAMR_BUILD_EXCE_HANDLING}\n"
|
||||
|
@ -699,7 +712,6 @@ message (
|
|||
" \"Branch Hinting\"\n"
|
||||
" \"Custom Annotation Syntax in the Text Format\"\n"
|
||||
" \"Exception handling\"\n"
|
||||
" \"Extended Constant Expressions\"\n"
|
||||
" \"Import/Export of Mutable Globals\"\n"
|
||||
" \"JS String Builtins\"\n"
|
||||
" \"Relaxed SIMD\"\n"
|
||||
|
|
|
@ -1 +1 @@
|
|||
requests==2.32.3
|
||||
requests==2.32.4
|
|
@ -106,6 +106,7 @@ endif ()
|
|||
|
||||
if (WAMR_BUILD_WASI_NN EQUAL 1)
|
||||
include (${IWASM_DIR}/libraries/wasi-nn/cmake/wasi_nn.cmake)
|
||||
set (WAMR_BUILD_MODULE_INST_CONTEXT 1)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
|
||||
|
@ -193,6 +194,13 @@ else()
|
|||
enable_language (ASM)
|
||||
endif()
|
||||
|
||||
# it will expose the runtime APIs.
|
||||
# you'll use the following command to check the exported APIs
|
||||
# dumpbin.exe /EXPORTS xxx
|
||||
if (MSVC)
|
||||
add_compile_definitions(COMPILING_WASM_RUNTIME_API=1)
|
||||
endif ()
|
||||
|
||||
include (${SHARED_PLATFORM_CONFIG})
|
||||
include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake)
|
||||
include (${IWASM_DIR}/common/iwasm_common.cmake)
|
||||
|
|
|
@ -8,7 +8,7 @@ endif()
|
|||
|
||||
set(WAMR_VERSION_MAJOR 2)
|
||||
set(WAMR_VERSION_MINOR 3)
|
||||
set(WAMR_VERSION_PATCH 0)
|
||||
set(WAMR_VERSION_PATCH 1)
|
||||
|
||||
message("-- WAMR version: ${WAMR_VERSION_MAJOR}.${WAMR_VERSION_MINOR}.${WAMR_VERSION_PATCH}")
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
import argparse
|
||||
import re
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shlex
|
||||
|
@ -39,7 +38,7 @@ INVALID_FILE_NAME_SEGMENT = r"([a-zA-Z0-9]+\-[a-zA-Z0-9]+)"
|
|||
|
||||
def locate_command(command: str) -> bool:
|
||||
if not shutil.which(command):
|
||||
print(f"Command '{command}'' not found")
|
||||
print(f"Command '{command}' not found")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
|
@ -193,8 +193,8 @@
|
|||
#error "Heap aux stack allocation must be enabled for WASI threads"
|
||||
#endif
|
||||
|
||||
#ifndef WAMR_ENABLE_COPY_CALLSTACK
|
||||
#define WAMR_ENABLE_COPY_CALLSTACK 0
|
||||
#ifndef WASM_ENABLE_COPY_CALL_STACK
|
||||
#define WASM_ENABLE_COPY_CALL_STACK 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_BASE_LIB
|
||||
|
@ -716,4 +716,12 @@ unless used elsewhere */
|
|||
#define WASM_ENABLE_AOT_VALIDATOR 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_INSTRUCTION_METERING
|
||||
#define WASM_ENABLE_INSTRUCTION_METERING 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_EXTENDED_CONST_EXPR
|
||||
#define WASM_ENABLE_EXTENDED_CONST_EXPR 0
|
||||
#endif
|
||||
|
||||
#endif /* end of _CONFIG_H_ */
|
||||
|
|
|
@ -968,6 +968,35 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
static void
|
||||
destroy_init_expr(InitializerExpression *expr)
|
||||
{
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (expr->init_expr_type == INIT_EXPR_TYPE_STRUCT_NEW
|
||||
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW
|
||||
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) {
|
||||
wasm_runtime_free(expr->u.unary.v.data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
// free left expr and right expr for binary oprand
|
||||
if (!is_expr_binary_op(expr->init_expr_type)) {
|
||||
return;
|
||||
}
|
||||
if (expr->u.binary.l_expr) {
|
||||
destroy_init_expr_recursive(expr->u.binary.l_expr);
|
||||
}
|
||||
if (expr->u.binary.r_expr) {
|
||||
destroy_init_expr_recursive(expr->u.binary.r_expr);
|
||||
}
|
||||
expr->u.binary.l_expr = expr->u.binary.r_expr = NULL;
|
||||
#endif
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0 \
|
||||
*/
|
||||
|
||||
static void
|
||||
destroy_import_memories(AOTImportMemory *import_memories)
|
||||
{
|
||||
|
@ -993,6 +1022,10 @@ destroy_mem_init_data_list(AOTModule *module, AOTMemInitData **data_list,
|
|||
/* If the module owns the binary data, free the bytes buffer */
|
||||
if (module->is_binary_freeable && data_list[i]->bytes)
|
||||
wasm_runtime_free(data_list[i]->bytes);
|
||||
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
destroy_init_expr(&data_list[i]->offset);
|
||||
#endif
|
||||
/* Free the data segment structure itself */
|
||||
wasm_runtime_free(data_list[i]);
|
||||
}
|
||||
|
@ -1043,11 +1076,11 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
|
|||
uint32 byte_count;
|
||||
uint32 is_passive;
|
||||
uint32 memory_index;
|
||||
InitializerExpression init_value;
|
||||
InitializerExpression offset_expr;
|
||||
|
||||
read_uint32(buf, buf_end, is_passive);
|
||||
read_uint32(buf, buf_end, memory_index);
|
||||
if (!load_init_expr(&buf, buf_end, module, &init_value, error_buf,
|
||||
if (!load_init_expr(&buf, buf_end, module, &offset_expr, error_buf,
|
||||
error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1062,8 +1095,7 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
|
|||
data_list[i]->is_passive = (bool)is_passive;
|
||||
data_list[i]->memory_index = memory_index;
|
||||
#endif
|
||||
data_list[i]->offset.init_expr_type = init_value.init_expr_type;
|
||||
data_list[i]->offset.u = init_value.u;
|
||||
data_list[i]->offset = offset_expr;
|
||||
data_list[i]->byte_count = byte_count;
|
||||
data_list[i]->bytes = NULL;
|
||||
/* If the module owns the binary data, clone the bytes buffer */
|
||||
|
@ -1148,18 +1180,6 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
static void
|
||||
destroy_init_expr(InitializerExpression *expr)
|
||||
{
|
||||
if (expr->init_expr_type == INIT_EXPR_TYPE_STRUCT_NEW
|
||||
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW
|
||||
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) {
|
||||
wasm_runtime_free(expr->u.data);
|
||||
}
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
|
||||
static void
|
||||
destroy_import_tables(AOTImportTable *import_tables)
|
||||
{
|
||||
|
@ -1183,6 +1203,9 @@ destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count)
|
|||
for (j = 0; j < data_list[i]->value_count; j++) {
|
||||
destroy_init_expr(&data_list[i]->init_values[j]);
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
destroy_init_expr(&data_list[i]->offset);
|
||||
#endif
|
||||
wasm_runtime_free(data_list[i]);
|
||||
}
|
||||
|
@ -1208,34 +1231,34 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
break;
|
||||
case INIT_EXPR_TYPE_I32_CONST:
|
||||
case INIT_EXPR_TYPE_F32_CONST:
|
||||
read_uint32(buf, buf_end, expr->u.i32);
|
||||
read_uint32(buf, buf_end, expr->u.unary.v.i32);
|
||||
break;
|
||||
case INIT_EXPR_TYPE_I64_CONST:
|
||||
case INIT_EXPR_TYPE_F64_CONST:
|
||||
read_uint64(buf, buf_end, expr->u.i64);
|
||||
read_uint64(buf, buf_end, expr->u.unary.v.i64);
|
||||
break;
|
||||
case INIT_EXPR_TYPE_V128_CONST:
|
||||
i64x2 = (uint64 *)expr->u.v128.i64x2;
|
||||
i64x2 = (uint64 *)expr->u.unary.v.v128.i64x2;
|
||||
CHECK_BUF(buf, buf_end, sizeof(uint64) * 2);
|
||||
wasm_runtime_read_v128(buf, &i64x2[0], &i64x2[1]);
|
||||
buf += sizeof(uint64) * 2;
|
||||
break;
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
read_uint32(buf, buf_end, expr->u.global_index);
|
||||
read_uint32(buf, buf_end, expr->u.unary.v.global_index);
|
||||
break;
|
||||
/* INIT_EXPR_TYPE_FUNCREF_CONST can be used when
|
||||
both reference types and GC are disabled */
|
||||
case INIT_EXPR_TYPE_FUNCREF_CONST:
|
||||
read_uint32(buf, buf_end, expr->u.ref_index);
|
||||
read_uint32(buf, buf_end, expr->u.unary.v.ref_index);
|
||||
break;
|
||||
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_REF_TYPES != 0
|
||||
case INIT_EXPR_TYPE_REFNULL_CONST:
|
||||
read_uint32(buf, buf_end, expr->u.ref_index);
|
||||
read_uint32(buf, buf_end, expr->u.unary.v.ref_index);
|
||||
break;
|
||||
#endif /* end of WASM_ENABLE_GC != 0 || WASM_ENABLE_REF_TYPES != 0 */
|
||||
#if WASM_ENABLE_GC != 0
|
||||
case INIT_EXPR_TYPE_I31_NEW:
|
||||
read_uint32(buf, buf_end, expr->u.i32);
|
||||
read_uint32(buf, buf_end, expr->u.unary.v.i32);
|
||||
break;
|
||||
case INIT_EXPR_TYPE_STRUCT_NEW:
|
||||
{
|
||||
|
@ -1256,7 +1279,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
free_if_fail = true;
|
||||
init_values->count = field_count;
|
||||
init_values->type_idx = type_idx;
|
||||
expr->u.data = init_values;
|
||||
expr->u.unary.v.data = init_values;
|
||||
|
||||
if (type_idx >= module->type_count) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
|
@ -1294,7 +1317,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
break;
|
||||
}
|
||||
case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
|
||||
read_uint32(buf, buf_end, expr->u.type_index);
|
||||
read_uint32(buf, buf_end, expr->u.unary.v.type_index);
|
||||
break;
|
||||
case INIT_EXPR_TYPE_ARRAY_NEW:
|
||||
case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
|
||||
|
@ -1309,9 +1332,16 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
read_uint32(buf, buf_end, type_idx);
|
||||
read_uint32(buf, buf_end, length);
|
||||
|
||||
if (type_idx >= module->type_count
|
||||
|| !wasm_type_is_array_type(module->types[type_idx])) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"invalid or non-array type index.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
|
||||
expr->u.array_new_default.type_index = type_idx;
|
||||
expr->u.array_new_default.length = length;
|
||||
expr->u.unary.v.array_new_default.type_index = type_idx;
|
||||
expr->u.unary.v.array_new_default.length = length;
|
||||
}
|
||||
else {
|
||||
uint32 i, elem_size, elem_data_count;
|
||||
|
@ -1322,7 +1352,7 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
return false;
|
||||
}
|
||||
free_if_fail = true;
|
||||
expr->u.data = init_values;
|
||||
expr->u.unary.v.data = init_values;
|
||||
|
||||
init_values->type_idx = type_idx;
|
||||
init_values->length = length;
|
||||
|
@ -1350,6 +1380,34 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
break;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
case INIT_EXPR_TYPE_I32_ADD:
|
||||
case INIT_EXPR_TYPE_I32_SUB:
|
||||
case INIT_EXPR_TYPE_I32_MUL:
|
||||
case INIT_EXPR_TYPE_I64_ADD:
|
||||
case INIT_EXPR_TYPE_I64_SUB:
|
||||
case INIT_EXPR_TYPE_I64_MUL:
|
||||
{
|
||||
expr->u.binary.l_expr = expr->u.binary.r_expr = NULL;
|
||||
if (!(expr->u.binary.l_expr =
|
||||
loader_malloc(sizeof(InitializerExpression), error_buf,
|
||||
error_buf_size))) {
|
||||
goto fail;
|
||||
}
|
||||
if (!load_init_expr(&buf, buf_end, module, expr->u.binary.l_expr,
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
if (!(expr->u.binary.r_expr =
|
||||
loader_malloc(sizeof(InitializerExpression), error_buf,
|
||||
error_buf_size))) {
|
||||
goto fail;
|
||||
}
|
||||
if (!load_init_expr(&buf, buf_end, module, expr->u.binary.r_expr,
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
|
||||
default:
|
||||
set_error_buf(error_buf, error_buf_size, "invalid init expr type.");
|
||||
return false;
|
||||
|
@ -1362,10 +1420,13 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
fail:
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (free_if_fail) {
|
||||
wasm_runtime_free(expr->u.data);
|
||||
wasm_runtime_free(expr->u.unary.v.data);
|
||||
}
|
||||
#else
|
||||
(void)free_if_fail;
|
||||
#endif
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
destroy_init_expr(expr);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
@ -1528,14 +1589,16 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
|
|||
/* Create each table data segment */
|
||||
for (i = 0; i < module->table_init_data_count; i++) {
|
||||
uint32 mode, elem_type;
|
||||
uint32 table_index, init_expr_type, value_count;
|
||||
uint64 init_expr_value, size1;
|
||||
uint32 table_index, value_count;
|
||||
uint64 size1;
|
||||
InitializerExpression offset_expr;
|
||||
|
||||
read_uint32(buf, buf_end, mode);
|
||||
read_uint32(buf, buf_end, elem_type);
|
||||
read_uint32(buf, buf_end, table_index);
|
||||
read_uint32(buf, buf_end, init_expr_type);
|
||||
read_uint64(buf, buf_end, init_expr_value);
|
||||
if (!load_init_expr(&buf, buf_end, module, &offset_expr, error_buf,
|
||||
error_buf_size))
|
||||
return false;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (wasm_is_type_multi_byte_type(elem_type)) {
|
||||
uint16 ref_type, nullable;
|
||||
|
@ -1581,8 +1644,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
|
|||
}
|
||||
}
|
||||
#endif
|
||||
data_list[i]->offset.init_expr_type = (uint8)init_expr_type;
|
||||
data_list[i]->offset.u.i64 = (int64)init_expr_value;
|
||||
data_list[i]->offset = offset_expr;
|
||||
data_list[i]->value_count = value_count;
|
||||
for (j = 0; j < data_list[i]->value_count; j++) {
|
||||
if (!load_init_expr(&buf, buf_end, module,
|
||||
|
@ -1723,6 +1785,12 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
(void)u8;
|
||||
|
||||
read_uint32(buf, buf_end, j);
|
||||
#if WASM_ENABLE_AOT_VALIDATOR != 0
|
||||
if (j >= module->type_count) {
|
||||
set_error_buf(error_buf, error_buf_size, "invalid type index");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
if (module->types[j]->ref_count == UINT16_MAX) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"wasm type's ref count too large");
|
||||
|
@ -1986,6 +2054,13 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
AOTType *cur_type = module->types[j];
|
||||
parent_type_idx = cur_type->parent_type_idx;
|
||||
if (parent_type_idx != (uint32)-1) { /* has parent */
|
||||
#if WASM_ENABLE_AOT_VALIDATOR != 0
|
||||
if (parent_type_idx >= module->type_count) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"invalid parent type index");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
AOTType *parent_type = module->types[parent_type_idx];
|
||||
|
||||
module->types[j]->parent_type = parent_type;
|
||||
|
@ -2009,6 +2084,13 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
|||
AOTType *cur_type = module->types[j];
|
||||
parent_type_idx = cur_type->parent_type_idx;
|
||||
if (parent_type_idx != (uint32)-1) { /* has parent */
|
||||
#if WASM_ENABLE_AOT_VALIDATOR != 0
|
||||
if (parent_type_idx >= module->type_count) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"invalid parent type index");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
AOTType *parent_type = module->types[parent_type_idx];
|
||||
/* subtyping has been checked during compilation */
|
||||
bh_assert(wasm_type_is_subtype_of(
|
||||
|
@ -3323,7 +3405,7 @@ do_data_relocation(AOTModule *module, AOTRelocationGroup *group,
|
|||
uint8 *data_addr;
|
||||
uint32 data_size = 0, i;
|
||||
AOTRelocation *relocation = group->relocations;
|
||||
void *symbol_addr;
|
||||
void *symbol_addr = NULL;
|
||||
char *symbol, *data_section_name;
|
||||
|
||||
if (!strncmp(group->section_name, ".rela.", 6)) {
|
||||
|
@ -4128,10 +4210,16 @@ create_module(char *name, char *error_buf, uint32 error_buf_size)
|
|||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
#if WASM_ENABLE_UVWASI == 0
|
||||
module->wasi_args.stdio[0] = os_invalid_raw_handle();
|
||||
module->wasi_args.stdio[1] = os_invalid_raw_handle();
|
||||
module->wasi_args.stdio[2] = os_invalid_raw_handle();
|
||||
#endif
|
||||
#else
|
||||
module->wasi_args.stdio[0] = os_get_invalid_handle();
|
||||
module->wasi_args.stdio[1] = os_get_invalid_handle();
|
||||
module->wasi_args.stdio[2] = os_get_invalid_handle();
|
||||
#endif /* WASM_ENABLE_UVWASI == 0 */
|
||||
#endif /* WASM_ENABLE_LIBC_WASI != 0 */
|
||||
|
||||
return module;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
|
@ -4467,7 +4555,7 @@ aot_unload(AOTModule *module)
|
|||
destroy_import_globals(module->import_globals);
|
||||
|
||||
if (module->globals) {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
uint32 i;
|
||||
for (i = 0; i < module->global_count; i++) {
|
||||
destroy_init_expr(&module->globals[i].init_expr);
|
||||
|
|
|
@ -185,6 +185,13 @@ typedef struct {
|
|||
#define REG_STRINGREF_SYM()
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
#define REG_SHARED_HEAP_SYM() \
|
||||
REG_SYM(wasm_runtime_check_and_update_last_used_shared_heap),
|
||||
#else
|
||||
#define REG_SHARED_HEAP_SYM()
|
||||
#endif
|
||||
|
||||
#define REG_COMMON_SYMBOLS \
|
||||
REG_SYM(aot_set_exception_with_id), \
|
||||
REG_SYM(aot_invoke_native), \
|
||||
|
@ -218,6 +225,7 @@ typedef struct {
|
|||
REG_LLVM_PGO_SYM() \
|
||||
REG_GC_SYM() \
|
||||
REG_STRINGREF_SYM() \
|
||||
REG_SHARED_HEAP_SYM() \
|
||||
|
||||
#define CHECK_RELOC_OFFSET(data_size) do { \
|
||||
if (!check_reloc_offset(target_section_size, \
|
||||
|
|
|
@ -60,6 +60,16 @@ bh_static_assert(offsetof(AOTModuleInstanceExtra, stack_sizes) == 0);
|
|||
bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_base_addr_adj)
|
||||
== 8);
|
||||
bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_start_off) == 16);
|
||||
bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_end_off) == 24);
|
||||
bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap) == 32);
|
||||
|
||||
bh_static_assert(offsetof(WASMSharedHeap, next) == 0);
|
||||
bh_static_assert(offsetof(WASMSharedHeap, chain_next) == 8);
|
||||
bh_static_assert(offsetof(WASMSharedHeap, heap_handle) == 16);
|
||||
bh_static_assert(offsetof(WASMSharedHeap, base_addr) == 24);
|
||||
bh_static_assert(offsetof(WASMSharedHeap, size) == 32);
|
||||
bh_static_assert(offsetof(WASMSharedHeap, start_off_mem64) == 40);
|
||||
bh_static_assert(offsetof(WASMSharedHeap, start_off_mem32) == 48);
|
||||
|
||||
bh_static_assert(sizeof(CApiFuncImport) == sizeof(uintptr_t) * 3);
|
||||
|
||||
|
@ -279,18 +289,21 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
switch (flag) {
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
{
|
||||
if (!check_global_init_expr(module, init_expr->u.global_index,
|
||||
if (!check_global_init_expr(module,
|
||||
init_expr->u.unary.v.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
if (init_expr->u.global_index < module->import_global_count) {
|
||||
if (init_expr->u.unary.v.global_index
|
||||
< module->import_global_count) {
|
||||
PUT_REF_TO_ADDR(
|
||||
addr, module->import_globals[init_expr->u.global_index]
|
||||
.global_data_linked.gc_obj);
|
||||
addr,
|
||||
module->import_globals[init_expr->u.unary.v.global_index]
|
||||
.global_data_linked.gc_obj);
|
||||
}
|
||||
else {
|
||||
uint32 global_idx =
|
||||
init_expr->u.global_index - module->import_global_count;
|
||||
uint32 global_idx = init_expr->u.unary.v.global_index
|
||||
- module->import_global_count;
|
||||
return assign_table_init_value(
|
||||
module_inst, module, &module->globals[global_idx].init_expr,
|
||||
addr, error_buf, error_buf_size);
|
||||
|
@ -306,7 +319,7 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
case INIT_EXPR_TYPE_FUNCREF_CONST:
|
||||
{
|
||||
WASMFuncObjectRef func_obj = NULL;
|
||||
uint32 func_idx = init_expr->u.u32;
|
||||
uint32 func_idx = init_expr->u.unary.v.u32;
|
||||
|
||||
if (func_idx != UINT32_MAX) {
|
||||
if (!(func_obj =
|
||||
|
@ -321,7 +334,8 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
}
|
||||
case INIT_EXPR_TYPE_I31_NEW:
|
||||
{
|
||||
WASMI31ObjectRef i31_obj = wasm_i31_obj_new(init_expr->u.i32);
|
||||
WASMI31ObjectRef i31_obj =
|
||||
wasm_i31_obj_new(init_expr->u.unary.v.i32);
|
||||
PUT_REF_TO_ADDR(addr, i31_obj);
|
||||
break;
|
||||
}
|
||||
|
@ -335,11 +349,12 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
uint32 type_idx;
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
|
||||
init_values = (WASMStructNewInitValues *)init_expr->u.data;
|
||||
init_values =
|
||||
(WASMStructNewInitValues *)init_expr->u.unary.v.data;
|
||||
type_idx = init_values->type_idx;
|
||||
}
|
||||
else {
|
||||
type_idx = init_expr->u.type_index;
|
||||
type_idx = init_expr->u.unary.v.type_index;
|
||||
}
|
||||
|
||||
struct_type = (WASMStructType *)module->types[type_idx];
|
||||
|
@ -388,12 +403,13 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
uint32 type_idx, len;
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
|
||||
type_idx = init_expr->u.array_new_default.type_index;
|
||||
len = init_expr->u.array_new_default.length;
|
||||
type_idx = init_expr->u.unary.v.array_new_default.type_index;
|
||||
len = init_expr->u.unary.v.array_new_default.length;
|
||||
arr_init_val = &empty_val;
|
||||
}
|
||||
else {
|
||||
init_values = (WASMArrayNewInitValues *)init_expr->u.data;
|
||||
init_values =
|
||||
(WASMArrayNewInitValues *)init_expr->u.unary.v.data;
|
||||
type_idx = init_values->type_idx;
|
||||
len = init_values->length;
|
||||
|
||||
|
@ -444,6 +460,90 @@ assign_table_init_value(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
|
||||
static bool
|
||||
get_init_value_recursive(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
InitializerExpression *expr, WASMValue *value,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
uint8 flag = expr->init_expr_type;
|
||||
switch (flag) {
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
{
|
||||
if (!check_global_init_expr(module, expr->u.unary.v.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
#if WASM_ENABLE_GC == 0
|
||||
*value = module->import_globals[expr->u.unary.v.global_index]
|
||||
.global_data_linked;
|
||||
#else
|
||||
if (expr->u.unary.v.global_index < module->import_global_count) {
|
||||
*value = module->import_globals[expr->u.unary.v.global_index]
|
||||
.global_data_linked;
|
||||
}
|
||||
else {
|
||||
*value = module
|
||||
->globals[expr->u.unary.v.global_index
|
||||
- module->import_global_count]
|
||||
.init_expr.u.unary.v;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case INIT_EXPR_TYPE_I32_CONST:
|
||||
case INIT_EXPR_TYPE_I64_CONST:
|
||||
{
|
||||
*value = expr->u.unary.v;
|
||||
break;
|
||||
}
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
case INIT_EXPR_TYPE_I32_ADD:
|
||||
case INIT_EXPR_TYPE_I32_SUB:
|
||||
case INIT_EXPR_TYPE_I32_MUL:
|
||||
case INIT_EXPR_TYPE_I64_ADD:
|
||||
case INIT_EXPR_TYPE_I64_SUB:
|
||||
case INIT_EXPR_TYPE_I64_MUL:
|
||||
{
|
||||
WASMValue l_value, r_value;
|
||||
if (!get_init_value_recursive(module_inst, module,
|
||||
expr->u.binary.l_expr, &l_value,
|
||||
error_buf, error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
if (!get_init_value_recursive(module_inst, module,
|
||||
expr->u.binary.r_expr, &r_value,
|
||||
error_buf, error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_I32_ADD) {
|
||||
value->i32 = l_value.i32 + r_value.i32;
|
||||
}
|
||||
else if (flag == INIT_EXPR_TYPE_I32_SUB) {
|
||||
value->i32 = l_value.i32 - r_value.i32;
|
||||
}
|
||||
else if (flag == INIT_EXPR_TYPE_I32_MUL) {
|
||||
value->i32 = l_value.i32 * r_value.i32;
|
||||
}
|
||||
else if (flag == INIT_EXPR_TYPE_I64_ADD) {
|
||||
value->i64 = l_value.i64 + r_value.i64;
|
||||
}
|
||||
else if (flag == INIT_EXPR_TYPE_I64_SUB) {
|
||||
value->i64 = l_value.i64 - r_value.i64;
|
||||
}
|
||||
else if (flag == INIT_EXPR_TYPE_I64_MUL) {
|
||||
value->i64 = l_value.i64 * r_value.i64;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
|
@ -472,30 +572,24 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
flag = init_expr->init_expr_type;
|
||||
switch (flag) {
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
case INIT_EXPR_TYPE_I32_CONST:
|
||||
case INIT_EXPR_TYPE_I64_CONST:
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
case INIT_EXPR_TYPE_I32_ADD:
|
||||
case INIT_EXPR_TYPE_I32_SUB:
|
||||
case INIT_EXPR_TYPE_I32_MUL:
|
||||
case INIT_EXPR_TYPE_I64_ADD:
|
||||
case INIT_EXPR_TYPE_I64_SUB:
|
||||
case INIT_EXPR_TYPE_I64_MUL:
|
||||
#endif
|
||||
{
|
||||
if (!check_global_init_expr(module, init_expr->u.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
WASMValue value;
|
||||
if (!get_init_value_recursive(module_inst, module, init_expr,
|
||||
&value, error_buf,
|
||||
error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
#if WASM_ENABLE_GC == 0
|
||||
init_global_data(
|
||||
p, global->type.val_type,
|
||||
&module->import_globals[init_expr->u.global_index]
|
||||
.global_data_linked);
|
||||
#else
|
||||
if (init_expr->u.global_index < module->import_global_count) {
|
||||
init_global_data(
|
||||
p, global->type.val_type,
|
||||
&module->import_globals[init_expr->u.global_index]
|
||||
.global_data_linked);
|
||||
}
|
||||
else {
|
||||
uint32 global_idx =
|
||||
init_expr->u.global_index - module->import_global_count;
|
||||
init_global_data(p, global->type.val_type,
|
||||
&module->globals[global_idx].init_expr.u);
|
||||
}
|
||||
#endif
|
||||
init_global_data(p, global->type.val_type, &value);
|
||||
break;
|
||||
}
|
||||
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
|
||||
|
@ -516,7 +610,7 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
case INIT_EXPR_TYPE_FUNCREF_CONST:
|
||||
{
|
||||
WASMFuncObjectRef func_obj = NULL;
|
||||
uint32 func_idx = init_expr->u.u32;
|
||||
uint32 func_idx = init_expr->u.unary.v.ref_index;
|
||||
|
||||
if (func_idx != UINT32_MAX) {
|
||||
if (!(func_obj =
|
||||
|
@ -531,7 +625,8 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
}
|
||||
case INIT_EXPR_TYPE_I31_NEW:
|
||||
{
|
||||
WASMI31ObjectRef i31_obj = wasm_i31_obj_new(init_expr->u.i32);
|
||||
WASMI31ObjectRef i31_obj =
|
||||
wasm_i31_obj_new(init_expr->u.unary.v.i32);
|
||||
PUT_REF_TO_ADDR(p, i31_obj);
|
||||
break;
|
||||
}
|
||||
|
@ -545,11 +640,12 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
uint32 type_idx;
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
|
||||
init_values = (WASMStructNewInitValues *)init_expr->u.data;
|
||||
init_values =
|
||||
(WASMStructNewInitValues *)init_expr->u.unary.v.data;
|
||||
type_idx = init_values->type_idx;
|
||||
}
|
||||
else {
|
||||
type_idx = init_expr->u.type_index;
|
||||
type_idx = init_expr->u.unary.v.type_index;
|
||||
}
|
||||
|
||||
struct_type = (WASMStructType *)module->types[type_idx];
|
||||
|
@ -599,12 +695,14 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
uint32 type_idx, len;
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
|
||||
type_idx = init_expr->u.array_new_default.type_index;
|
||||
len = init_expr->u.array_new_default.length;
|
||||
type_idx =
|
||||
init_expr->u.unary.v.array_new_default.type_index;
|
||||
len = init_expr->u.unary.v.array_new_default.length;
|
||||
arr_init_val = &empty_val;
|
||||
}
|
||||
else {
|
||||
init_values = (WASMArrayNewInitValues *)init_expr->u.data;
|
||||
init_values =
|
||||
(WASMArrayNewInitValues *)init_expr->u.unary.v.data;
|
||||
type_idx = init_values->type_idx;
|
||||
len = init_values->length;
|
||||
|
||||
|
@ -650,7 +748,8 @@ global_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
default:
|
||||
{
|
||||
init_global_data(p, global->type.val_type, &init_expr->u);
|
||||
init_global_data(p, global->type.val_type,
|
||||
&init_expr->u.unary.v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -671,6 +770,7 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
uint64 total_size;
|
||||
AOTTableInitData *table_seg;
|
||||
AOTTableInstance *tbl_inst = first_tbl_inst;
|
||||
uint8 offset_flag;
|
||||
|
||||
total_size = (uint64)sizeof(AOTTableInstance *) * module_inst->table_count;
|
||||
if (total_size > 0
|
||||
|
@ -743,28 +843,25 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
tbl_inst = module_inst->tables[table_seg->table_index];
|
||||
bh_assert(tbl_inst);
|
||||
|
||||
offset_flag = table_seg->offset.init_expr_type;
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
bh_assert(
|
||||
table_seg->offset.init_expr_type
|
||||
== (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST
|
||||
: INIT_EXPR_TYPE_I32_CONST)
|
||||
|| table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| table_seg->offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST
|
||||
|| table_seg->offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_REFNULL_CONST);
|
||||
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| offset_flag == INIT_EXPR_TYPE_FUNCREF_CONST
|
||||
|| offset_flag == INIT_EXPR_TYPE_REFNULL_CONST
|
||||
|| (tbl_inst->is_table64 ? is_valid_i64_offset(offset_flag)
|
||||
: is_valid_i32_offset(offset_flag)));
|
||||
#else
|
||||
bh_assert(table_seg->offset.init_expr_type
|
||||
== (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST
|
||||
: INIT_EXPR_TYPE_I32_CONST)
|
||||
|| table_seg->offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_GET_GLOBAL);
|
||||
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| (tbl_inst->is_table64 ? is_valid_i64_offset(offset_flag)
|
||||
: is_valid_i32_offset(offset_flag)));
|
||||
#endif
|
||||
|
||||
/* Resolve table data base offset */
|
||||
/* TODO: The table64 current implementation assumes table max size
|
||||
* UINT32_MAX, so the offset conversion here is safe */
|
||||
if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
global_index = table_seg->offset.u.global_index;
|
||||
if (offset_flag == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
global_index = table_seg->offset.u.unary.v.global_index;
|
||||
|
||||
if (!check_global_init_expr(module, global_index, error_buf,
|
||||
error_buf_size)) {
|
||||
|
@ -782,8 +879,15 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
base_offset =
|
||||
*(uint32 *)(module_inst->global_data + global_data_offset);
|
||||
}
|
||||
else
|
||||
base_offset = (uint32)table_seg->offset.u.i32;
|
||||
else {
|
||||
WASMValue offset_value;
|
||||
if (!get_init_value_recursive(module_inst, module,
|
||||
&table_seg->offset, &offset_value,
|
||||
error_buf, error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
base_offset = (uint32)offset_value.i32;
|
||||
}
|
||||
|
||||
/* Copy table data */
|
||||
/* base_offset only since length might negative */
|
||||
|
@ -818,7 +922,7 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
|
|||
#if WASM_ENABLE_GC == 0
|
||||
for (j = 0; j < length; j++) {
|
||||
tbl_inst->elems[base_offset + j] =
|
||||
table_seg->init_values[j].u.ref_index;
|
||||
table_seg->init_values[j].u.unary.v.ref_index;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1118,6 +1222,7 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
|
|||
AOTMemInitData *data_seg;
|
||||
uint64 total_size;
|
||||
mem_offset_t base_offset;
|
||||
uint8 offset_flag;
|
||||
|
||||
module_inst->memory_count = memory_count;
|
||||
total_size = sizeof(AOTMemoryInstance *) * (uint64)memory_count;
|
||||
|
@ -1156,15 +1261,15 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
|
|||
initialized */
|
||||
continue;
|
||||
|
||||
bh_assert(data_seg->offset.init_expr_type
|
||||
== (memory_inst->is_memory64 ? INIT_EXPR_TYPE_I64_CONST
|
||||
: INIT_EXPR_TYPE_I32_CONST)
|
||||
|| data_seg->offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_GET_GLOBAL);
|
||||
offset_flag = data_seg->offset.init_expr_type;
|
||||
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| (memory_inst->is_memory64
|
||||
? is_valid_i64_offset(offset_flag)
|
||||
: is_valid_i32_offset(offset_flag)));
|
||||
|
||||
/* Resolve memory data base offset */
|
||||
if (data_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
global_index = data_seg->offset.u.global_index;
|
||||
if (offset_flag == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
global_index = data_seg->offset.u.unary.v.global_index;
|
||||
|
||||
if (!check_global_init_expr(module, global_index, error_buf,
|
||||
error_buf_size)) {
|
||||
|
@ -1192,14 +1297,20 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
|
|||
}
|
||||
}
|
||||
else {
|
||||
WASMValue offset_value;
|
||||
if (!get_init_value_recursive(module_inst, module,
|
||||
&data_seg->offset, &offset_value,
|
||||
error_buf, error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
if (memory_inst->is_memory64) {
|
||||
base_offset = data_seg->offset.u.i64;
|
||||
base_offset = offset_value.i64;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
base_offset = data_seg->offset.u.u32;
|
||||
base_offset = offset_value.u32;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1989,6 +2100,8 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
|
|||
#else
|
||||
extra->shared_heap_start_off.u32[0] = UINT32_MAX;
|
||||
#endif
|
||||
/* After shared heap chain, will early stop if shared heap is NULL */
|
||||
extra->shared_heap = NULL;
|
||||
|
||||
#if WASM_ENABLE_PERF_PROFILING != 0
|
||||
total_size = sizeof(AOTFuncPerfProfInfo)
|
||||
|
@ -2043,6 +2156,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
|
|||
uint8 tbl_elem_type;
|
||||
uint32 tbl_init_size, tbl_max_size, j;
|
||||
WASMRefType *tbl_elem_ref_type;
|
||||
WASMValue offset_value;
|
||||
|
||||
bh_assert(table_init_data);
|
||||
|
||||
|
@ -2074,69 +2188,73 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
|
|||
if (!wasm_elem_is_active(table_init_data->mode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bh_assert(table_init_data->offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_I32_CONST
|
||||
|| table_init_data->offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| table_init_data->offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_FUNCREF_CONST
|
||||
|| table_init_data->offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_REFNULL_CONST);
|
||||
uint8 offset_flag = table_init_data->offset.init_expr_type;
|
||||
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| offset_flag == INIT_EXPR_TYPE_FUNCREF_CONST
|
||||
|| offset_flag == INIT_EXPR_TYPE_REFNULL_CONST
|
||||
|| offset_flag == INIT_EXPR_TYPE_I32_CONST
|
||||
|| offset_flag == INIT_EXPR_TYPE_I32_ADD
|
||||
|| offset_flag == INIT_EXPR_TYPE_I32_SUB
|
||||
|| offset_flag == INIT_EXPR_TYPE_I32_MUL);
|
||||
|
||||
/* init vec(funcidx) or vec(expr) */
|
||||
if (table_init_data->offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
if (offset_flag == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
uint32 data_offset;
|
||||
if (!check_global_init_expr(module,
|
||||
table_init_data->offset.u.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
if (!check_global_init_expr(
|
||||
module, table_init_data->offset.u.unary.v.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (table_init_data->offset.u.global_index
|
||||
if (table_init_data->offset.u.unary.v.global_index
|
||||
< module->import_global_count) {
|
||||
data_offset =
|
||||
module
|
||||
->import_globals[table_init_data->offset.u.global_index]
|
||||
.data_offset;
|
||||
data_offset = module
|
||||
->import_globals[table_init_data->offset.u
|
||||
.unary.v.global_index]
|
||||
.data_offset;
|
||||
}
|
||||
else {
|
||||
data_offset =
|
||||
module
|
||||
->globals[table_init_data->offset.u.global_index
|
||||
->globals[table_init_data->offset.u.unary.v.global_index
|
||||
- module->import_global_count]
|
||||
.data_offset;
|
||||
}
|
||||
|
||||
table_init_data->offset.u.i32 =
|
||||
offset_value.i32 =
|
||||
*(uint32 *)(module_inst->global_data + data_offset);
|
||||
}
|
||||
else {
|
||||
if (!get_init_value_recursive(
|
||||
module_inst, module, &table_init_data->offset,
|
||||
&offset_value, error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* check offset since length might negative */
|
||||
if ((uint32)table_init_data->offset.u.i32 > table->cur_size) {
|
||||
LOG_DEBUG("base_offset(%d) > table->cur_size(%d)",
|
||||
table_init_data->offset.u.i32, table->cur_size);
|
||||
if ((uint32)offset_value.i32 > table->cur_size) {
|
||||
LOG_DEBUG("base_offset(%d) > table->cur_size(%d)", offset_value.i32,
|
||||
table->cur_size);
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"out of bounds table access");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((uint32)table_init_data->offset.u.i32 + table_init_data->value_count
|
||||
if ((uint32)offset_value.i32 + table_init_data->value_count
|
||||
> table->cur_size) {
|
||||
LOG_DEBUG("base_offset(%d) + length(%d) > table->cur_size(%d)",
|
||||
table_init_data->offset.u.i32,
|
||||
table_init_data->value_count, table->cur_size);
|
||||
offset_value.i32, table_init_data->value_count,
|
||||
table->cur_size);
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"out of bounds table access");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (j = 0; j < module->table_init_data_list[i]->value_count; j++) {
|
||||
if (!assign_table_init_value(
|
||||
module_inst, module, &table_init_data->init_values[j],
|
||||
table_data + table_init_data->offset.u.i32 + j, error_buf,
|
||||
error_buf_size)) {
|
||||
if (!assign_table_init_value(module_inst, module,
|
||||
&table_init_data->init_values[j],
|
||||
table_data + offset_value.i32 + j,
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -3639,7 +3757,7 @@ aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst,
|
|||
for (i = 0; i < module_inst->memory_count; i++) {
|
||||
AOTMemoryInstance *mem_inst = module_inst->memories[i];
|
||||
mem_conspn->memories_size +=
|
||||
mem_inst->num_bytes_per_page * mem_inst->cur_page_count;
|
||||
(uint64)mem_inst->num_bytes_per_page * mem_inst->cur_page_count;
|
||||
mem_conspn->app_heap_size =
|
||||
mem_inst->heap_data_end - mem_inst->heap_data;
|
||||
/* size of app heap structure */
|
||||
|
@ -3729,10 +3847,10 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
|
|||
for (i = 0; i < length; i++) {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/* UINT32_MAX indicates that it is a null ref */
|
||||
if (init_values[i].u.ref_index != UINT32_MAX) {
|
||||
if (!(func_obj = aot_create_func_obj(module_inst,
|
||||
init_values[i].u.ref_index,
|
||||
true, NULL, 0))) {
|
||||
if (init_values[i].u.unary.v.ref_index != UINT32_MAX) {
|
||||
if (!(func_obj = aot_create_func_obj(
|
||||
module_inst, init_values[i].u.unary.v.ref_index, true,
|
||||
NULL, 0))) {
|
||||
aot_set_exception_with_id(module_inst, EXCE_NULL_FUNC_OBJ);
|
||||
return;
|
||||
}
|
||||
|
@ -3742,7 +3860,7 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx,
|
|||
table_elems[i] = NULL_REF;
|
||||
}
|
||||
#else
|
||||
table_elems[i] = init_values[i].u.ref_index;
|
||||
table_elems[i] = init_values[i].u.unary.v.ref_index;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -4137,9 +4255,9 @@ aot_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame)
|
|||
}
|
||||
#endif /* end of WASM_ENABLE_AOT_STACK_FRAME != 0 */
|
||||
|
||||
#if WAMR_ENABLE_COPY_CALLSTACK != 0
|
||||
#if WASM_ENABLE_COPY_CALL_STACK != 0
|
||||
uint32
|
||||
aot_copy_callstack_tiny_frame(WASMExecEnv *exec_env, wasm_frame_t *buffer,
|
||||
aot_copy_callstack_tiny_frame(WASMExecEnv *exec_env, WASMCApiFrame *buffer,
|
||||
const uint32 length, const uint32 skip_n,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
|
@ -4193,7 +4311,7 @@ aot_copy_callstack_tiny_frame(WASMExecEnv *exec_env, wasm_frame_t *buffer,
|
|||
}
|
||||
|
||||
uint32
|
||||
aot_copy_callstack_standard_frame(WASMExecEnv *exec_env, wasm_frame_t *buffer,
|
||||
aot_copy_callstack_standard_frame(WASMExecEnv *exec_env, WASMCApiFrame *buffer,
|
||||
const uint32 length, const uint32 skip_n,
|
||||
char *error_buf, uint32_t error_buf_size)
|
||||
{
|
||||
|
@ -4243,7 +4361,7 @@ aot_copy_callstack_standard_frame(WASMExecEnv *exec_env, wasm_frame_t *buffer,
|
|||
}
|
||||
|
||||
uint32
|
||||
aot_copy_callstack(WASMExecEnv *exec_env, wasm_frame_t *buffer,
|
||||
aot_copy_callstack(WASMExecEnv *exec_env, WASMCApiFrame *buffer,
|
||||
const uint32 length, const uint32 skip_n, char *error_buf,
|
||||
uint32_t error_buf_size)
|
||||
{
|
||||
|
@ -4265,7 +4383,7 @@ aot_copy_callstack(WASMExecEnv *exec_env, wasm_frame_t *buffer,
|
|||
error_buf, error_buf_size);
|
||||
}
|
||||
}
|
||||
#endif // WAMR_ENABLE_COPY_CALLSTACK
|
||||
#endif // WASM_ENABLE_COPY_CALL_STACK
|
||||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||
bool
|
||||
|
@ -4877,8 +4995,8 @@ aot_dump_pgo_prof_data_to_buf(AOTModuleInstance *module_inst, char *buf,
|
|||
}
|
||||
|
||||
prof_header.magic = 0xFF6C70726F667281LL;
|
||||
/* Version 8 */
|
||||
prof_header.version = 0x0000000000000008LL;
|
||||
/* Version 9 */
|
||||
prof_header.version = 0x0000000000000009LL;
|
||||
/* with VARIANT_MASK_IR_PROF (IR Instrumentation) */
|
||||
prof_header.version |= 0x1ULL << 56;
|
||||
/* with VARIANT_MASK_MEMPROF (Memory Profile) */
|
||||
|
@ -4887,14 +5005,19 @@ aot_dump_pgo_prof_data_to_buf(AOTModuleInstance *module_inst, char *buf,
|
|||
prof_header.num_prof_counters = num_prof_counters;
|
||||
prof_header.names_size = prof_names_size;
|
||||
prof_header.value_kind_last = 1;
|
||||
/* __llvm_prf_bits won't be used in PGO, set dummy value here */
|
||||
prof_header.num_prof_bitmaps = 0;
|
||||
prof_header.bitmap_delta = 0;
|
||||
|
||||
if (!is_little_endian()) {
|
||||
aot_exchange_uint64((uint8 *)&prof_header.magic);
|
||||
aot_exchange_uint64((uint8 *)&prof_header.version);
|
||||
aot_exchange_uint64((uint8 *)&prof_header.num_prof_data);
|
||||
aot_exchange_uint64((uint8 *)&prof_header.num_prof_counters);
|
||||
aot_exchange_uint64((uint8 *)&prof_header.num_prof_bitmaps);
|
||||
aot_exchange_uint64((uint8 *)&prof_header.names_size);
|
||||
aot_exchange_uint64((uint8 *)&prof_header.counters_delta);
|
||||
aot_exchange_uint64((uint8 *)&prof_header.bitmap_delta);
|
||||
aot_exchange_uint64((uint8 *)&prof_header.value_kind_last);
|
||||
}
|
||||
|
||||
|
@ -4912,19 +5035,23 @@ aot_dump_pgo_prof_data_to_buf(AOTModuleInstance *module_inst, char *buf,
|
|||
prof_data_64->func_md5 = prof_data->func_md5;
|
||||
prof_data_64->func_hash = prof_data->func_hash;
|
||||
prof_data_64->offset_counters = prof_data->offset_counters;
|
||||
prof_data_64->offset_bitmaps = prof_data->offset_bitmaps;
|
||||
prof_data_64->func_ptr = prof_data->func_ptr;
|
||||
prof_data_64->values = (uint64)(uintptr_t)prof_data->values;
|
||||
prof_data_64->num_counters = prof_data->num_counters;
|
||||
/* __llvm_prf_bits won't be used in PGO, set dummy value here */
|
||||
prof_data_64->num_bitmaps = 0;
|
||||
prof_data_64->num_value_sites[0] = prof_data->num_value_sites[0];
|
||||
prof_data_64->num_value_sites[1] = prof_data->num_value_sites[1];
|
||||
|
||||
if (!is_little_endian()) {
|
||||
aot_exchange_uint64((uint8 *)&prof_data_64->func_hash);
|
||||
aot_exchange_uint64((uint8 *)&prof_data_64->offset_counters);
|
||||
aot_exchange_uint64((uint8 *)&prof_data_64->offset_counters);
|
||||
aot_exchange_uint64((uint8 *)&prof_data_64->offset_bitmaps);
|
||||
aot_exchange_uint64((uint8 *)&prof_data_64->func_ptr);
|
||||
aot_exchange_uint64((uint8 *)&prof_data_64->values);
|
||||
aot_exchange_uint32((uint8 *)&prof_data_64->num_counters);
|
||||
aot_exchange_uint32((uint8 *)&prof_data_64->num_bitmaps);
|
||||
aot_exchange_uint16((uint8 *)&prof_data_64->num_value_sites[0]);
|
||||
aot_exchange_uint16((uint8 *)&prof_data_64->num_value_sites[1]);
|
||||
}
|
||||
|
|
|
@ -125,6 +125,8 @@ typedef struct AOTModuleInstanceExtra {
|
|||
*/
|
||||
DefPointer(uint8 *, shared_heap_base_addr_adj);
|
||||
MemBound shared_heap_start_off;
|
||||
MemBound shared_heap_end_off;
|
||||
DefPointer(WASMSharedHeap *, shared_heap);
|
||||
|
||||
WASMModuleInstanceExtraCommon common;
|
||||
|
||||
|
@ -142,9 +144,6 @@ typedef struct AOTModuleInstanceExtra {
|
|||
WASMModuleInstanceCommon **import_func_module_insts;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
WASMSharedHeap *shared_heap;
|
||||
#endif
|
||||
} AOTModuleInstanceExtra;
|
||||
|
||||
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
|
||||
|
@ -437,6 +436,9 @@ typedef struct AOTFrame {
|
|||
} AOTFrame;
|
||||
|
||||
#if WASM_ENABLE_STATIC_PGO != 0
|
||||
/* The bitmaps fields in LLVMProfileRawHeader, LLVMProfileData,
|
||||
* LLVMProfileData_64 all dummy fields, it's used in MC/DC code coverage
|
||||
* instead of PGO. See https://llvm.org/docs/InstrProfileFormat.html#bitmap */
|
||||
typedef struct LLVMProfileRawHeader {
|
||||
uint64 magic;
|
||||
uint64 version;
|
||||
|
@ -445,8 +447,11 @@ typedef struct LLVMProfileRawHeader {
|
|||
uint64 padding_bytes_before_counters;
|
||||
uint64 num_prof_counters;
|
||||
uint64 padding_bytes_after_counters;
|
||||
uint64 num_prof_bitmaps;
|
||||
uint64 padding_bytes_after_bitmaps;
|
||||
uint64 names_size;
|
||||
uint64 counters_delta;
|
||||
uint64 bitmap_delta;
|
||||
uint64 names_delta;
|
||||
uint64 value_kind_last;
|
||||
} LLVMProfileRawHeader;
|
||||
|
@ -464,10 +469,12 @@ typedef struct LLVMProfileData {
|
|||
uint64 func_md5;
|
||||
uint64 func_hash;
|
||||
uint64 offset_counters;
|
||||
uint64 offset_bitmaps;
|
||||
uintptr_t func_ptr;
|
||||
ValueProfNode **values;
|
||||
uint32 num_counters;
|
||||
uint16 num_value_sites[2];
|
||||
uint32 num_bitmaps;
|
||||
} LLVMProfileData;
|
||||
|
||||
/* The profiling data for writing to the output file, the width of
|
||||
|
@ -477,10 +484,12 @@ typedef struct LLVMProfileData_64 {
|
|||
uint64 func_md5;
|
||||
uint64 func_hash;
|
||||
uint64 offset_counters;
|
||||
uint64 offset_bitmaps;
|
||||
uint64 func_ptr;
|
||||
uint64 values;
|
||||
uint32 num_counters;
|
||||
uint16 num_value_sites[2];
|
||||
uint32 num_bitmaps;
|
||||
} LLVMProfileData_64;
|
||||
#endif /* end of WASM_ENABLE_STATIC_PGO != 0 */
|
||||
|
||||
|
@ -777,12 +786,12 @@ aot_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame);
|
|||
bool
|
||||
aot_create_call_stack(struct WASMExecEnv *exec_env);
|
||||
|
||||
#if WAMR_ENABLE_COPY_CALLSTACK != 0
|
||||
#if WASM_ENABLE_COPY_CALL_STACK != 0
|
||||
uint32
|
||||
aot_copy_callstack(WASMExecEnv *exec_env, wasm_frame_t *buffer,
|
||||
aot_copy_callstack(WASMExecEnv *exec_env, WASMCApiFrame *buffer,
|
||||
const uint32 length, const uint32 skip_n, char *error_buf,
|
||||
uint32_t error_buf_size);
|
||||
#endif // WAMR_ENABLE_COPY_CALLSTACK
|
||||
#endif // WASM_ENABLE_COPY_CALL_STACK
|
||||
|
||||
/**
|
||||
* @brief Dump wasm call stack or get the size
|
||||
|
|
|
@ -1145,7 +1145,7 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
|
|||
return true;
|
||||
else {
|
||||
int32 heap_type = ref_type1->ref_ht_common.heap_type;
|
||||
// We dont care whether type2 is nullable or not. So
|
||||
// We don't care whether type2 is nullable or not. So
|
||||
// we normalize it into its related one-byte type.
|
||||
if (type2 == REF_TYPE_HT_NULLABLE
|
||||
|| type2 == REF_TYPE_HT_NON_NULLABLE) {
|
||||
|
|
|
@ -85,6 +85,10 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
|
|||
wasm_runtime_dump_exec_env_mem_consumption(exec_env);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_INSTRUCTION_METERING != 0
|
||||
exec_env->instructions_to_execute = -1;
|
||||
#endif
|
||||
|
||||
return exec_env;
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
|
|
|
@ -87,6 +87,11 @@ typedef struct WASMExecEnv {
|
|||
uint8 *bottom;
|
||||
} wasm_stack;
|
||||
|
||||
#if WASM_ENABLE_INSTRUCTION_METERING != 0
|
||||
/* instructions to execute */
|
||||
int instructions_to_execute;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
/**
|
||||
* Cache for
|
||||
|
|
|
@ -225,3 +225,18 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
void
|
||||
destroy_init_expr_recursive(InitializerExpression *expr)
|
||||
{
|
||||
if (expr == NULL) {
|
||||
return;
|
||||
}
|
||||
if (is_expr_binary_op(expr->init_expr_type)) {
|
||||
destroy_init_expr_recursive(expr->u.binary.l_expr);
|
||||
destroy_init_expr_recursive(expr->u.binary.r_expr);
|
||||
}
|
||||
wasm_runtime_free(expr);
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
|
||||
|
|
|
@ -50,6 +50,11 @@ void
|
|||
wasm_loader_set_error_buf(char *error_buf, uint32 error_buf_size,
|
||||
const char *string, bool is_aot);
|
||||
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
void
|
||||
destroy_init_expr_recursive(InitializerExpression *expr);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -143,7 +143,7 @@ is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst)
|
|||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
static void *
|
||||
wasm_mmap_linear_memory(uint64_t map_size, uint64 commit_size);
|
||||
wasm_mmap_linear_memory(uint64 map_size, uint64 commit_size);
|
||||
static void
|
||||
wasm_munmap_linear_memory(void *mapped_mem, uint64 commit_size,
|
||||
uint64 map_size);
|
||||
|
@ -177,39 +177,54 @@ wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args)
|
|||
goto fail1;
|
||||
}
|
||||
|
||||
if (!(heap->heap_handle =
|
||||
runtime_malloc(mem_allocator_get_heap_struct_size()))) {
|
||||
size = align_uint(size, os_getpagesize());
|
||||
if (size > APP_HEAP_SIZE_MAX || size < APP_HEAP_SIZE_MIN) {
|
||||
LOG_WARNING("Invalid size of shared heap");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
size = align_uint(size, os_getpagesize());
|
||||
heap->size = size;
|
||||
heap->start_off_mem64 = UINT64_MAX - heap->size + 1;
|
||||
heap->start_off_mem32 = UINT32_MAX - heap->size + 1;
|
||||
heap->attached_count = 0;
|
||||
|
||||
if (size > APP_HEAP_SIZE_MAX || size < APP_HEAP_SIZE_MIN) {
|
||||
LOG_WARNING("Invalid size of shared heap");
|
||||
goto fail3;
|
||||
if (init_args->pre_allocated_addr != NULL) {
|
||||
/* Create shared heap from a pre allocated buffer, its size need to
|
||||
* align with system page */
|
||||
if (size != init_args->size) {
|
||||
LOG_WARNING("Pre allocated size need to be aligned with system "
|
||||
"page size to create shared heap");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
heap->heap_handle = NULL;
|
||||
heap->base_addr = init_args->pre_allocated_addr;
|
||||
}
|
||||
else {
|
||||
if (!(heap->heap_handle =
|
||||
runtime_malloc(mem_allocator_get_heap_struct_size()))) {
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
map_size = size;
|
||||
map_size = size;
|
||||
#else
|
||||
/* Totally 8G is mapped, the opcode load/store address range is 0 to 8G:
|
||||
* ea = i + memarg.offset
|
||||
* both i and memarg.offset are u32 in range 0 to 4G
|
||||
* so the range of ea is 0 to 8G
|
||||
*/
|
||||
map_size = 8 * (uint64)BH_GB;
|
||||
/* Totally 8G is mapped, the opcode load/store address range is 0 to 8G:
|
||||
* ea = i + memarg.offset
|
||||
* both i and memarg.offset are u32 in range 0 to 4G
|
||||
* so the range of ea is 0 to 8G
|
||||
*/
|
||||
map_size = 8 * (uint64)BH_GB;
|
||||
#endif
|
||||
|
||||
if (!(heap->base_addr = wasm_mmap_linear_memory(map_size, size))) {
|
||||
goto fail3;
|
||||
}
|
||||
if (!mem_allocator_create_with_struct_and_pool(
|
||||
heap->heap_handle, heap_struct_size, heap->base_addr, size)) {
|
||||
LOG_WARNING("init share heap failed");
|
||||
goto fail4;
|
||||
if (!(heap->base_addr = wasm_mmap_linear_memory(map_size, size))) {
|
||||
goto fail3;
|
||||
}
|
||||
if (!mem_allocator_create_with_struct_and_pool(
|
||||
heap->heap_handle, heap_struct_size, heap->base_addr, size)) {
|
||||
LOG_WARNING("init share heap failed");
|
||||
goto fail4;
|
||||
}
|
||||
}
|
||||
|
||||
os_mutex_lock(&shared_heap_list_lock);
|
||||
|
@ -233,6 +248,219 @@ fail1:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
WASMSharedHeap *
|
||||
wasm_runtime_chain_shared_heaps(WASMSharedHeap *head, WASMSharedHeap *body)
|
||||
{
|
||||
WASMSharedHeap *cur;
|
||||
bool heap_handle_exist = false;
|
||||
|
||||
if (!head || !body) {
|
||||
LOG_WARNING("Invalid shared heap to chain.");
|
||||
return NULL;
|
||||
}
|
||||
heap_handle_exist = head->heap_handle != NULL;
|
||||
|
||||
os_mutex_lock(&shared_heap_list_lock);
|
||||
if (head->attached_count != 0 || body->attached_count != 0) {
|
||||
LOG_WARNING("To create shared heap chain, all shared heap need to be "
|
||||
"detached first.");
|
||||
os_mutex_unlock(&shared_heap_list_lock);
|
||||
return NULL;
|
||||
}
|
||||
for (cur = shared_heap_list; cur; cur = cur->next) {
|
||||
if (cur->chain_next == body || cur->chain_next == head) {
|
||||
LOG_WARNING(
|
||||
"To create shared heap chain, both the 'head' and 'body' "
|
||||
"shared heap can't already be the 'body' in another a chain");
|
||||
os_mutex_unlock(&shared_heap_list_lock);
|
||||
return NULL;
|
||||
}
|
||||
if (cur == head && cur->chain_next) {
|
||||
LOG_WARNING(
|
||||
"To create shared heap chain, the 'head' shared heap can't "
|
||||
"already be the 'head' in another a chain");
|
||||
os_mutex_unlock(&shared_heap_list_lock);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
for (cur = body; cur; cur = cur->chain_next) {
|
||||
if (cur->heap_handle && heap_handle_exist) {
|
||||
LOG_WARNING(
|
||||
"To create shared heap chain, only one of shared heap can "
|
||||
"dynamically shared_heap_malloc and shared_heap_free, the rest "
|
||||
"can only be pre-allocated shared heap");
|
||||
os_mutex_unlock(&shared_heap_list_lock);
|
||||
return NULL;
|
||||
}
|
||||
if (cur->heap_handle)
|
||||
heap_handle_exist = true;
|
||||
}
|
||||
|
||||
head->start_off_mem64 = body->start_off_mem64 - head->size;
|
||||
head->start_off_mem32 = body->start_off_mem32 - head->size;
|
||||
head->chain_next = body;
|
||||
os_mutex_unlock(&shared_heap_list_lock);
|
||||
return head;
|
||||
}
|
||||
|
||||
WASMSharedHeap *
|
||||
wasm_runtime_unchain_shared_heaps(WASMSharedHeap *head, bool entire_chain)
|
||||
{
|
||||
WASMSharedHeap *cur, *tmp;
|
||||
|
||||
if (!head || !head->chain_next) {
|
||||
LOG_WARNING("Invalid shared heap chain to disconnect the head from.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_mutex_lock(&shared_heap_list_lock);
|
||||
if (head->attached_count != 0) {
|
||||
LOG_WARNING("To disconnect the shared heap head from the shared heap "
|
||||
"chain, the shared heap chain needs to be detached first.");
|
||||
os_mutex_unlock(&shared_heap_list_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cur = head;
|
||||
while (cur && cur->chain_next) {
|
||||
cur->start_off_mem64 = UINT64_MAX - cur->size + 1;
|
||||
cur->start_off_mem32 = UINT32_MAX - cur->size + 1;
|
||||
tmp = cur;
|
||||
cur = cur->chain_next;
|
||||
tmp->chain_next = NULL;
|
||||
if (!entire_chain)
|
||||
break;
|
||||
}
|
||||
os_mutex_unlock(&shared_heap_list_lock);
|
||||
return cur;
|
||||
}
|
||||
|
||||
static uint8 *
|
||||
get_last_used_shared_heap_base_addr_adj(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstanceExtra *e =
|
||||
(WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e;
|
||||
return e->shared_heap_base_addr_adj;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_INTERP != 0 */
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstanceExtra *e =
|
||||
(AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
|
||||
return e->shared_heap_base_addr_adj;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_AOT != 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uintptr_t
|
||||
get_last_used_shared_heap_start_offset(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstanceExtra *e =
|
||||
(WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e;
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
return e->shared_heap_start_off.u64;
|
||||
#else
|
||||
return e->shared_heap_start_off.u32[0];
|
||||
#endif
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_INTERP != 0 */
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstanceExtra *e =
|
||||
(AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
return e->shared_heap_start_off.u64;
|
||||
#else
|
||||
return e->shared_heap_start_off.u32[0];
|
||||
#endif
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_AOT != 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uintptr_t
|
||||
get_last_used_shared_heap_end_offset(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstanceExtra *e =
|
||||
(WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e;
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
return e->shared_heap_end_off.u64;
|
||||
#else
|
||||
return e->shared_heap_end_off.u32[0];
|
||||
#endif
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_INTERP != 0 */
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstanceExtra *e =
|
||||
(AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
return e->shared_heap_end_off.u64;
|
||||
#else
|
||||
return e->shared_heap_end_off.u32[0];
|
||||
#endif
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_AOT != 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
update_last_used_shared_heap(WASMModuleInstanceCommon *module_inst,
|
||||
WASMSharedHeap *shared_heap, bool is_memory64)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstanceExtra *e =
|
||||
(WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e;
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
if (is_memory64)
|
||||
e->shared_heap_start_off.u64 = shared_heap->start_off_mem64;
|
||||
else
|
||||
e->shared_heap_start_off.u64 = shared_heap->start_off_mem32;
|
||||
e->shared_heap_end_off.u64 =
|
||||
e->shared_heap_start_off.u64 - 1 + shared_heap->size;
|
||||
e->shared_heap_base_addr_adj =
|
||||
shared_heap->base_addr - e->shared_heap_start_off.u64;
|
||||
#else
|
||||
e->shared_heap_start_off.u32[0] = (uint32)shared_heap->start_off_mem32;
|
||||
e->shared_heap_end_off.u32[0] =
|
||||
e->shared_heap_start_off.u32[0] - 1 + shared_heap->size;
|
||||
e->shared_heap_base_addr_adj =
|
||||
shared_heap->base_addr - e->shared_heap_start_off.u32[0];
|
||||
#endif
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_INTERP != 0 */
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstanceExtra *e =
|
||||
(AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
if (is_memory64)
|
||||
e->shared_heap_start_off.u64 = shared_heap->start_off_mem64;
|
||||
else
|
||||
e->shared_heap_start_off.u64 = shared_heap->start_off_mem32;
|
||||
e->shared_heap_end_off.u64 =
|
||||
e->shared_heap_start_off.u64 - 1 + shared_heap->size;
|
||||
e->shared_heap_base_addr_adj =
|
||||
shared_heap->base_addr - e->shared_heap_start_off.u64;
|
||||
#else
|
||||
e->shared_heap_start_off.u32[0] = (uint32)shared_heap->start_off_mem32;
|
||||
e->shared_heap_end_off.u32[0] =
|
||||
e->shared_heap_start_off.u32[0] - 1 + shared_heap->size;
|
||||
e->shared_heap_base_addr_adj =
|
||||
shared_heap->base_addr - e->shared_heap_start_off.u32[0];
|
||||
#endif
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_AOT != 0 */
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_attach_shared_heap_internal(WASMModuleInstanceCommon *module_inst,
|
||||
WASMSharedHeap *shared_heap)
|
||||
|
@ -263,20 +491,6 @@ wasm_runtime_attach_shared_heap_internal(WASMModuleInstanceCommon *module_inst,
|
|||
return false;
|
||||
}
|
||||
e->shared_heap = shared_heap;
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
if (memory->is_memory64)
|
||||
e->shared_heap_start_off.u64 = shared_heap->start_off_mem64;
|
||||
else
|
||||
e->shared_heap_start_off.u64 = shared_heap->start_off_mem32;
|
||||
e->shared_heap_base_addr_adj =
|
||||
shared_heap->base_addr - e->shared_heap_start_off.u64;
|
||||
#else
|
||||
e->shared_heap_start_off.u32[0] = (uint32)shared_heap->start_off_mem32;
|
||||
e->shared_heap_base_addr_adj =
|
||||
shared_heap->base_addr - e->shared_heap_start_off.u32[0];
|
||||
#endif
|
||||
#endif /* end of WASM_ENABLE_JIT != 0 */
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_INTERP != 0 */
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
|
@ -288,21 +502,13 @@ wasm_runtime_attach_shared_heap_internal(WASMModuleInstanceCommon *module_inst,
|
|||
return false;
|
||||
}
|
||||
e->shared_heap = shared_heap;
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
if (memory->is_memory64)
|
||||
e->shared_heap_start_off.u64 = shared_heap->start_off_mem64;
|
||||
else
|
||||
e->shared_heap_start_off.u64 = shared_heap->start_off_mem32;
|
||||
e->shared_heap_base_addr_adj =
|
||||
shared_heap->base_addr - e->shared_heap_start_off.u64;
|
||||
#else
|
||||
e->shared_heap_start_off.u32[0] = (uint32)shared_heap->start_off_mem32;
|
||||
e->shared_heap_base_addr_adj =
|
||||
shared_heap->base_addr - e->shared_heap_start_off.u32[0];
|
||||
#endif
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_AOT != 0 */
|
||||
update_last_used_shared_heap(module_inst, shared_heap, memory->is_memory64);
|
||||
|
||||
os_mutex_lock(&shared_heap_list_lock);
|
||||
shared_heap->attached_count++;
|
||||
os_mutex_unlock(&shared_heap_list_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -320,30 +526,46 @@ wasm_runtime_attach_shared_heap(WASMModuleInstanceCommon *module_inst,
|
|||
void
|
||||
wasm_runtime_detach_shared_heap_internal(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
/* Reset shared_heap_end_off = UINT64/32_MAX - 1 to handling a corner case,
|
||||
app_offset >= shared_heap_start && app_offset <= shared_heap_end-bytes+1
|
||||
when bytes=1 and both e->shared_heap_start_off and e->shared_heap_end_off
|
||||
is 0xffffffff */
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstanceExtra *e =
|
||||
(WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e;
|
||||
if (e->shared_heap != NULL) {
|
||||
os_mutex_lock(&shared_heap_list_lock);
|
||||
e->shared_heap->attached_count--;
|
||||
os_mutex_unlock(&shared_heap_list_lock);
|
||||
}
|
||||
e->shared_heap = NULL;
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
e->shared_heap_start_off.u64 = UINT64_MAX;
|
||||
e->shared_heap_end_off.u64 = UINT64_MAX - 1;
|
||||
#else
|
||||
e->shared_heap_start_off.u32[0] = UINT32_MAX;
|
||||
e->shared_heap_end_off.u32[0] = UINT32_MAX - 1;
|
||||
#endif
|
||||
e->shared_heap_base_addr_adj = NULL;
|
||||
#endif
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_INTERP != 0 */
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstanceExtra *e =
|
||||
(AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
|
||||
if (e->shared_heap != NULL) {
|
||||
os_mutex_lock(&shared_heap_list_lock);
|
||||
e->shared_heap->attached_count--;
|
||||
os_mutex_unlock(&shared_heap_list_lock);
|
||||
}
|
||||
e->shared_heap = NULL;
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
e->shared_heap_start_off.u64 = UINT64_MAX;
|
||||
e->shared_heap_end_off.u64 = UINT64_MAX - 1;
|
||||
#else
|
||||
e->shared_heap_start_off.u32[0] = UINT32_MAX;
|
||||
e->shared_heap_end_off.u32[0] = UINT32_MAX - 1;
|
||||
#endif
|
||||
e->shared_heap_base_addr_adj = NULL;
|
||||
}
|
||||
|
@ -385,71 +607,93 @@ wasm_runtime_get_shared_heap(WASMModuleInstanceCommon *module_inst_comm)
|
|||
return get_shared_heap(module_inst_comm);
|
||||
}
|
||||
|
||||
static bool
|
||||
bool
|
||||
is_app_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
|
||||
bool is_memory64, uint64 app_offset, uint32 bytes)
|
||||
{
|
||||
WASMSharedHeap *heap = get_shared_heap(module_inst);
|
||||
WASMSharedHeap *heap = get_shared_heap(module_inst), *cur;
|
||||
uint64 shared_heap_start, shared_heap_end;
|
||||
|
||||
if (!heap) {
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (bytes == 0) {
|
||||
bytes = 1;
|
||||
}
|
||||
|
||||
if (!is_memory64) {
|
||||
if (app_offset >= heap->start_off_mem32
|
||||
&& app_offset <= UINT32_MAX - bytes + 1) {
|
||||
return true;
|
||||
}
|
||||
shared_heap_start =
|
||||
(uint64)get_last_used_shared_heap_start_offset(module_inst);
|
||||
shared_heap_end = (uint64)get_last_used_shared_heap_end_offset(module_inst);
|
||||
if (bytes - 1 <= shared_heap_end && app_offset >= shared_heap_start
|
||||
&& app_offset <= shared_heap_end - bytes + 1) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (app_offset >= heap->start_off_mem64
|
||||
&& app_offset <= UINT64_MAX - bytes + 1) {
|
||||
|
||||
/* Early stop for app start address not in the shared heap(chain) at all */
|
||||
shared_heap_start =
|
||||
is_memory64 ? heap->start_off_mem64 : heap->start_off_mem32;
|
||||
shared_heap_end = is_memory64 ? UINT64_MAX : UINT32_MAX;
|
||||
if (bytes - 1 > shared_heap_end || app_offset < shared_heap_start
|
||||
|| app_offset > shared_heap_end - bytes + 1) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Find the exact shared heap that app addr is in, and update last used
|
||||
* shared heap info in module inst extra */
|
||||
for (cur = heap; cur; cur = cur->chain_next) {
|
||||
shared_heap_start =
|
||||
is_memory64 ? cur->start_off_mem64 : cur->start_off_mem32;
|
||||
shared_heap_end = shared_heap_start - 1 + cur->size;
|
||||
if (bytes - 1 <= shared_heap_end && app_offset >= shared_heap_start
|
||||
&& app_offset <= shared_heap_end - bytes + 1) {
|
||||
update_last_used_shared_heap(module_inst, cur, is_memory64);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_native_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
|
||||
uint8 *addr, uint32 bytes)
|
||||
bool is_memory64, uint8 *addr, uint32 bytes)
|
||||
{
|
||||
WASMSharedHeap *heap = get_shared_heap(module_inst);
|
||||
uintptr_t base_addr;
|
||||
uintptr_t addr_int;
|
||||
uintptr_t end_addr;
|
||||
WASMSharedHeap *cur, *heap = get_shared_heap(module_inst);
|
||||
uintptr_t base_addr, addr_int, end_addr;
|
||||
|
||||
if (!heap) {
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
base_addr = (uintptr_t)heap->base_addr;
|
||||
addr_int = (uintptr_t)addr;
|
||||
if (addr_int < base_addr) {
|
||||
return false;
|
||||
/* Iterate through shared heap chain to find whether native addr in one of
|
||||
* shared heap */
|
||||
for (cur = heap; cur != NULL; cur = cur->chain_next) {
|
||||
base_addr = (uintptr_t)cur->base_addr;
|
||||
addr_int = (uintptr_t)addr;
|
||||
if (addr_int < base_addr)
|
||||
continue;
|
||||
|
||||
end_addr = addr_int + bytes;
|
||||
/* Check for overflow */
|
||||
if (end_addr <= addr_int)
|
||||
continue;
|
||||
|
||||
if (end_addr > base_addr + cur->size)
|
||||
continue;
|
||||
|
||||
update_last_used_shared_heap(module_inst, cur, is_memory64);
|
||||
return true;
|
||||
}
|
||||
|
||||
end_addr = addr_int + bytes;
|
||||
/* Check for overflow */
|
||||
if (end_addr <= addr_int) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (end_addr > base_addr + heap->size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64
|
||||
wasm_runtime_shared_heap_malloc(WASMModuleInstanceCommon *module_inst,
|
||||
uint64_t size, void **p_native_addr)
|
||||
uint64 size, void **p_native_addr)
|
||||
{
|
||||
WASMMemoryInstance *memory =
|
||||
wasm_get_default_memory((WASMModuleInstance *)module_inst);
|
||||
|
@ -459,6 +703,14 @@ wasm_runtime_shared_heap_malloc(WASMModuleInstanceCommon *module_inst,
|
|||
if (!memory || !shared_heap)
|
||||
return 0;
|
||||
|
||||
while (shared_heap && !shared_heap->heap_handle) {
|
||||
shared_heap = shared_heap->chain_next;
|
||||
}
|
||||
if (!shared_heap) {
|
||||
LOG_WARNING("Can't allocate from pre allocated shared heap");
|
||||
return 0;
|
||||
}
|
||||
|
||||
native_addr = mem_allocator_malloc(shared_heap->heap_handle, size);
|
||||
if (!native_addr)
|
||||
return 0;
|
||||
|
@ -467,12 +719,10 @@ wasm_runtime_shared_heap_malloc(WASMModuleInstanceCommon *module_inst,
|
|||
*p_native_addr = native_addr;
|
||||
}
|
||||
|
||||
if (memory->is_memory64)
|
||||
return shared_heap->start_off_mem64
|
||||
+ ((uint8 *)native_addr - shared_heap->base_addr);
|
||||
else
|
||||
return shared_heap->start_off_mem32
|
||||
+ ((uint8 *)native_addr - shared_heap->base_addr);
|
||||
return memory->is_memory64
|
||||
? shared_heap->start_off_mem64
|
||||
: shared_heap->start_off_mem32
|
||||
+ ((uint8 *)native_addr - shared_heap->base_addr);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -487,6 +737,14 @@ wasm_runtime_shared_heap_free(WASMModuleInstanceCommon *module_inst, uint64 ptr)
|
|||
return;
|
||||
}
|
||||
|
||||
while (shared_heap && !shared_heap->heap_handle) {
|
||||
shared_heap = shared_heap->chain_next;
|
||||
}
|
||||
if (!shared_heap) {
|
||||
LOG_WARNING("The address to free is from pre allocated shared heap");
|
||||
return;
|
||||
}
|
||||
|
||||
if (memory->is_memory64) {
|
||||
if (ptr < shared_heap->start_off_mem64) { /* ptr can not > UINT64_MAX */
|
||||
LOG_WARNING("The address to free isn't in shared heap");
|
||||
|
@ -564,14 +822,16 @@ destroy_shared_heaps()
|
|||
while (heap) {
|
||||
cur = heap;
|
||||
heap = heap->next;
|
||||
mem_allocator_destroy(cur->heap_handle);
|
||||
wasm_runtime_free(cur->heap_handle);
|
||||
if (cur->heap_handle) {
|
||||
mem_allocator_destroy(cur->heap_handle);
|
||||
wasm_runtime_free(cur->heap_handle);
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
map_size = cur->size;
|
||||
map_size = cur->size;
|
||||
#else
|
||||
map_size = 8 * (uint64)BH_GB;
|
||||
map_size = 8 * (uint64)BH_GB;
|
||||
#endif
|
||||
wasm_munmap_linear_memory(cur->base_addr, cur->size, map_size);
|
||||
wasm_munmap_linear_memory(cur->base_addr, cur->size, map_size);
|
||||
}
|
||||
wasm_runtime_free(cur);
|
||||
}
|
||||
os_mutex_destroy(&shared_heap_list_lock);
|
||||
|
@ -798,6 +1058,10 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
|
|||
WASMMemoryInstance *memory_inst;
|
||||
uint64 app_end_offset, max_linear_memory_size = MAX_LINEAR_MEMORY_SIZE;
|
||||
char *str, *str_end;
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
uintptr_t shared_heap_end_off;
|
||||
char *shared_heap_base_addr_adj;
|
||||
#endif
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
@ -814,12 +1078,12 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
|
|||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (is_app_addr_in_shared_heap(module_inst_comm, memory_inst->is_memory64,
|
||||
app_str_offset, 1)) {
|
||||
WASMSharedHeap *shared_heap = get_shared_heap(module_inst_comm);
|
||||
str = (char *)shared_heap->base_addr
|
||||
+ (memory_inst->is_memory64
|
||||
? (app_str_offset - shared_heap->start_off_mem64)
|
||||
: (app_str_offset - shared_heap->start_off_mem32));
|
||||
str_end = (char *)shared_heap->base_addr + shared_heap->size;
|
||||
shared_heap_end_off =
|
||||
get_last_used_shared_heap_end_offset(module_inst_comm);
|
||||
shared_heap_base_addr_adj =
|
||||
(char *)get_last_used_shared_heap_base_addr_adj(module_inst_comm);
|
||||
str = shared_heap_base_addr_adj + app_str_offset;
|
||||
str_end = shared_heap_base_addr_adj + shared_heap_end_off + 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -884,7 +1148,8 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
|
|||
}
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (is_native_addr_in_shared_heap(module_inst_comm, native_ptr, size)) {
|
||||
if (is_native_addr_in_shared_heap(
|
||||
module_inst_comm, memory_inst->is_memory64, native_ptr, size)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -926,17 +1191,8 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
|
|||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (is_app_addr_in_shared_heap(module_inst_comm, memory_inst->is_memory64,
|
||||
app_offset, 1)) {
|
||||
WASMSharedHeap *shared_heap = get_shared_heap(module_inst_comm);
|
||||
uint64 shared_heap_start = 0;
|
||||
|
||||
if (memory_inst && !memory_inst->is_memory64) {
|
||||
shared_heap_start = shared_heap->start_off_mem32;
|
||||
}
|
||||
else if (memory_inst && memory_inst->is_memory64) {
|
||||
shared_heap_start = shared_heap->start_off_mem64;
|
||||
}
|
||||
|
||||
return shared_heap->base_addr + app_offset - shared_heap_start;
|
||||
return get_last_used_shared_heap_base_addr_adj(module_inst_comm)
|
||||
+ app_offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -974,29 +1230,17 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
|
|||
|
||||
bounds_checks = is_bounds_checks_enabled(module_inst_comm);
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
/* If shared heap is enabled, bounds check is always needed */
|
||||
bounds_checks = true;
|
||||
#endif
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (is_native_addr_in_shared_heap(module_inst_comm, addr, 1)) {
|
||||
WASMSharedHeap *shared_heap = get_shared_heap(module_inst_comm);
|
||||
uint64 shared_heap_start = 0;
|
||||
|
||||
if (memory_inst && !memory_inst->is_memory64) {
|
||||
shared_heap_start = shared_heap->start_off_mem32;
|
||||
}
|
||||
else if (memory_inst && memory_inst->is_memory64) {
|
||||
shared_heap_start = shared_heap->start_off_mem64;
|
||||
}
|
||||
|
||||
return shared_heap_start + (addr - shared_heap->base_addr);
|
||||
if (is_native_addr_in_shared_heap(module_inst_comm,
|
||||
memory_inst->is_memory64, addr, 1)) {
|
||||
return (uint64)(uintptr_t)(addr
|
||||
- get_last_used_shared_heap_base_addr_adj(
|
||||
module_inst_comm));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1098,8 +1342,8 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
|||
uint8 *native_addr;
|
||||
bool bounds_checks;
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
WASMSharedHeap *shared_heap;
|
||||
bool is_in_shared_heap = false;
|
||||
uint8 *shared_heap_base_addr_adj = NULL;
|
||||
uintptr_t shared_heap_end_off = 0;
|
||||
#endif
|
||||
|
||||
bh_assert(app_buf_addr <= UINTPTR_MAX && app_buf_size <= UINTPTR_MAX);
|
||||
|
@ -1113,36 +1357,17 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
|||
if (is_app_addr_in_shared_heap((WASMModuleInstanceCommon *)module_inst,
|
||||
memory_inst->is_memory64, app_buf_addr,
|
||||
app_buf_size)) {
|
||||
shared_heap = get_shared_heap((WASMModuleInstanceCommon *)module_inst);
|
||||
native_addr = shared_heap->base_addr
|
||||
+ (memory_inst->is_memory64
|
||||
? (app_buf_addr - shared_heap->start_off_mem64)
|
||||
: (app_buf_addr - shared_heap->start_off_mem32));
|
||||
is_in_shared_heap = true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
native_addr = memory_inst->memory_data + (uintptr_t)app_buf_addr;
|
||||
}
|
||||
|
||||
bounds_checks =
|
||||
is_bounds_checks_enabled((WASMModuleInstanceCommon *)module_inst);
|
||||
|
||||
if (!bounds_checks) {
|
||||
if (app_buf_addr == 0) {
|
||||
native_addr = NULL;
|
||||
}
|
||||
goto success;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (is_in_shared_heap) {
|
||||
const char *str, *str_end;
|
||||
shared_heap_base_addr_adj = get_last_used_shared_heap_base_addr_adj(
|
||||
(WASMModuleInstanceCommon *)module_inst);
|
||||
shared_heap_end_off = get_last_used_shared_heap_end_offset(
|
||||
(WASMModuleInstanceCommon *)module_inst);
|
||||
native_addr = shared_heap_base_addr_adj + (uintptr_t)app_buf_addr;
|
||||
|
||||
/* The whole string must be in the linear memory */
|
||||
/* The whole string must be in the shared heap */
|
||||
str = (const char *)native_addr;
|
||||
str_end = (const char *)shared_heap->base_addr + shared_heap->size;
|
||||
str_end =
|
||||
(const char *)shared_heap_base_addr_adj + shared_heap_end_off + 1;
|
||||
while (str < str_end && *str != '\0')
|
||||
str++;
|
||||
if (str == str_end) {
|
||||
|
@ -1154,6 +1379,17 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
|||
}
|
||||
#endif
|
||||
|
||||
native_addr = memory_inst->memory_data + (uintptr_t)app_buf_addr;
|
||||
bounds_checks =
|
||||
is_bounds_checks_enabled((WASMModuleInstanceCommon *)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
|
||||
|
|
|
@ -41,10 +41,60 @@ SET_LINEAR_MEMORY_SIZE(WASMMemoryInstance *memory, uint64 size)
|
|||
#define SET_LINEAR_MEMORY_SIZE(memory, size) memory->memory_data_size = size
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
/* Only enable shared heap for the default memory */
|
||||
#define is_default_memory (memidx == 0)
|
||||
#else
|
||||
#define is_default_memory true
|
||||
#endif
|
||||
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
#define get_shared_heap_end_off() module->e->shared_heap_end_off.u64
|
||||
#else
|
||||
#define get_shared_heap_end_off() \
|
||||
(uint64)(module->e->shared_heap_end_off.u32[0])
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
#define shared_heap_is_memory64 is_memory64
|
||||
#else
|
||||
#define shared_heap_is_memory64 false
|
||||
#endif
|
||||
|
||||
#define app_addr_in_shared_heap(app_addr, bytes) \
|
||||
(is_default_memory \
|
||||
&& is_app_addr_in_shared_heap((WASMModuleInstanceCommon *)module, \
|
||||
shared_heap_is_memory64, (uint64)app_addr, \
|
||||
bytes))
|
||||
#define shared_heap_addr_app_to_native(app_addr, native_addr) \
|
||||
native_addr = module->e->shared_heap_base_addr_adj + app_addr
|
||||
#define CHECK_SHARED_HEAP_OVERFLOW(app_addr, bytes, native_addr) \
|
||||
if (app_addr_in_shared_heap(app_addr, bytes)) \
|
||||
shared_heap_addr_app_to_native(app_addr, native_addr); \
|
||||
else
|
||||
|
||||
#else /* else of WASM_ENABLE_SHARED_HEAP != 0 */
|
||||
#define CHECK_SHARED_HEAP_OVERFLOW(app_addr, bytes, native_addr)
|
||||
#endif /* end of WASM_ENABLE_SHARED_HEAP != 0 */
|
||||
#endif /* end of WASM_ENABLE_INTERP != 0 */
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
bool
|
||||
is_app_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
|
||||
bool is_memory64, uint64 app_offset, uint32 bytes);
|
||||
|
||||
WASMSharedHeap *
|
||||
wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args);
|
||||
|
||||
WASMSharedHeap *
|
||||
wasm_runtime_chain_shared_heaps(WASMSharedHeap *head, WASMSharedHeap *body);
|
||||
|
||||
WASMSharedHeap *
|
||||
wasm_runtime_unchain_shared_heaps(WASMSharedHeap *head, bool entire_chain);
|
||||
|
||||
bool
|
||||
wasm_runtime_attach_shared_heap(WASMModuleInstanceCommon *module_inst,
|
||||
WASMSharedHeap *shared_heap);
|
||||
|
@ -68,7 +118,7 @@ wasm_runtime_shared_heap_malloc(WASMModuleInstanceCommon *module_inst,
|
|||
void
|
||||
wasm_runtime_shared_heap_free(WASMModuleInstanceCommon *module_inst,
|
||||
uint64 ptr);
|
||||
#endif
|
||||
#endif /* end of WASM_ENABLE_SHARED_HEAP != 0 */
|
||||
|
||||
bool
|
||||
wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
|
||||
|
|
|
@ -1504,7 +1504,7 @@ wasm_runtime_load_ex(uint8 *buf, uint32 size, const LoadArgs *args,
|
|||
error_buf_size);
|
||||
}
|
||||
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
bool
|
||||
wasm_runtime_resolve_symbols(WASMModuleCommon *module)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
|
@ -1743,9 +1743,9 @@ wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env)
|
|||
wasm_exec_env_destroy(exec_env);
|
||||
}
|
||||
|
||||
#if WAMR_ENABLE_COPY_CALLSTACK != 0
|
||||
#if WASM_ENABLE_COPY_CALL_STACK != 0
|
||||
uint32
|
||||
wasm_copy_callstack(const wasm_exec_env_t exec_env, wasm_frame_t *buffer,
|
||||
wasm_copy_callstack(const wasm_exec_env_t exec_env, WASMCApiFrame *buffer,
|
||||
const uint32 length, const uint32 skip_n, char *error_buf,
|
||||
uint32_t error_buf_size)
|
||||
{
|
||||
|
@ -1780,7 +1780,7 @@ wasm_copy_callstack(const wasm_exec_env_t exec_env, wasm_frame_t *buffer,
|
|||
strncpy(error_buf, err_msg, error_buf_size);
|
||||
return 0;
|
||||
}
|
||||
#endif // WAMR_ENABLE_COPY_CALLSTACK
|
||||
#endif // WASM_ENABLE_COPY_CALL_STACK
|
||||
|
||||
bool
|
||||
wasm_runtime_init_thread_env(void)
|
||||
|
@ -2285,6 +2285,15 @@ wasm_runtime_access_exce_check_guard_page()
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_INSTRUCTION_METERING != 0
|
||||
void
|
||||
wasm_runtime_set_instruction_count_limit(WASMExecEnv *exec_env,
|
||||
int instructions_to_execute)
|
||||
{
|
||||
exec_env->instructions_to_execute = instructions_to_execute;
|
||||
}
|
||||
#endif
|
||||
|
||||
WASMFuncType *
|
||||
wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function,
|
||||
uint32 module_type)
|
||||
|
@ -3877,11 +3886,15 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
|
|||
init_options.allocator = &uvwasi_allocator;
|
||||
init_options.argc = argc;
|
||||
init_options.argv = (const char **)argv;
|
||||
init_options.in = (stdinfd != -1) ? (uvwasi_fd_t)stdinfd : init_options.in;
|
||||
init_options.out =
|
||||
(stdoutfd != -1) ? (uvwasi_fd_t)stdoutfd : init_options.out;
|
||||
init_options.err =
|
||||
(stderrfd != -1) ? (uvwasi_fd_t)stderrfd : init_options.err;
|
||||
init_options.in = (stdinfd != os_get_invalid_handle())
|
||||
? (uvwasi_fd_t)stdinfd
|
||||
: init_options.in;
|
||||
init_options.out = (stdoutfd != os_get_invalid_handle())
|
||||
? (uvwasi_fd_t)stdoutfd
|
||||
: init_options.out;
|
||||
init_options.err = (stderrfd != os_get_invalid_handle())
|
||||
? (uvwasi_fd_t)stderrfd
|
||||
: init_options.err;
|
||||
|
||||
if (dir_count > 0) {
|
||||
init_options.preopenc = dir_count;
|
||||
|
@ -7836,7 +7849,7 @@ wasm_runtime_detect_native_stack_overflow_size(WASMExecEnv *exec_env,
|
|||
return true;
|
||||
}
|
||||
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
bool
|
||||
wasm_runtime_is_underlying_binary_freeable(WASMModuleCommon *const module)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
|
@ -7870,3 +7883,37 @@ wasm_runtime_is_underlying_binary_freeable(WASMModuleCommon *const module)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
bool
|
||||
wasm_runtime_check_and_update_last_used_shared_heap(
|
||||
WASMModuleInstanceCommon *module_inst, uintptr_t app_offset, size_t bytes,
|
||||
uintptr_t *shared_heap_start_off_p, uintptr_t *shared_heap_end_off_p,
|
||||
uint8 **shared_heap_base_addr_adj_p, bool is_memory64)
|
||||
{
|
||||
WASMSharedHeap *heap = wasm_runtime_get_shared_heap(module_inst), *cur;
|
||||
uint64 shared_heap_start, shared_heap_end;
|
||||
|
||||
if (bytes == 0) {
|
||||
bytes = 1;
|
||||
}
|
||||
|
||||
/* Find the exact shared heap that app addr is in, and update last used
|
||||
* shared heap info in func context */
|
||||
for (cur = heap; cur; cur = cur->chain_next) {
|
||||
shared_heap_start =
|
||||
is_memory64 ? cur->start_off_mem64 : cur->start_off_mem32;
|
||||
shared_heap_end = shared_heap_start - 1 + cur->size;
|
||||
if (bytes - 1 <= shared_heap_end && app_offset >= shared_heap_start
|
||||
&& app_offset <= shared_heap_end - bytes + 1) {
|
||||
*shared_heap_start_off_p = (uintptr_t)shared_heap_start;
|
||||
*shared_heap_end_off_p = (uintptr_t)shared_heap_end;
|
||||
*shared_heap_base_addr_adj_p =
|
||||
cur->base_addr - (uintptr_t)shared_heap_start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -758,12 +758,12 @@ wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst,
|
|||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env);
|
||||
|
||||
#if WAMR_ENABLE_COPY_CALLSTACK != 0
|
||||
#if WASM_ENABLE_COPY_CALL_STACK != 0
|
||||
WASM_RUNTIME_API_EXTERN uint32_t
|
||||
wasm_copy_callstack(const wasm_exec_env_t exec_env, wasm_frame_t *buffer,
|
||||
wasm_copy_callstack(const wasm_exec_env_t exec_env, WASMCApiFrame *buffer,
|
||||
const uint32 length, const uint32 skip_n, char *error_buf,
|
||||
uint32 error_buf_size);
|
||||
#endif // WAMR_ENABLE_COPY_CALLSTACK
|
||||
#endif // WASM_ENABLE_COPY_CALL_STACK
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon *
|
||||
|
@ -791,9 +791,17 @@ WASM_RUNTIME_API_EXTERN void
|
|||
wasm_runtime_set_native_stack_boundary(WASMExecEnv *exec_env,
|
||||
uint8 *native_stack_boundary);
|
||||
|
||||
#if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0
|
||||
#if WASM_ENABLE_INSTRUCTION_METERING != 0
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_instruction_count_limit(WASMExecEnv *exec_env,
|
||||
int instructions_to_execute);
|
||||
#endif
|
||||
|
||||
#if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN
|
||||
void
|
||||
wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst,
|
||||
bool enable);
|
||||
|
||||
|
@ -1328,6 +1336,14 @@ void
|
|||
wasm_runtime_set_linux_perf(bool flag);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
bool
|
||||
wasm_runtime_check_and_update_last_used_shared_heap(
|
||||
WASMModuleInstanceCommon *module_inst, uintptr_t app_offset, size_t bytes,
|
||||
uintptr_t *shared_heap_start_off_p, uintptr_t *shared_heap_end_off_p,
|
||||
uint8 **shared_heap_base_addr_adj_p, bool is_memory64);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -48,7 +48,7 @@ typedef struct AOTSymbolList {
|
|||
} AOTSymbolList;
|
||||
|
||||
/* AOT object data */
|
||||
typedef struct AOTObjectData {
|
||||
struct AOTObjectData {
|
||||
AOTCompContext *comp_ctx;
|
||||
|
||||
LLVMMemoryBufferRef mem_buf;
|
||||
|
@ -82,7 +82,7 @@ typedef struct AOTObjectData {
|
|||
const char *stack_sizes_section_name;
|
||||
uint32 stack_sizes_offset;
|
||||
uint32 *stack_sizes;
|
||||
} AOTObjectData;
|
||||
};
|
||||
|
||||
#if 0
|
||||
static void dump_buf(uint8 *buf, uint32 size, char *title)
|
||||
|
@ -216,7 +216,7 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
|
|||
#if WASM_ENABLE_GC != 0
|
||||
WASMModule *module = comp_data->wasm_module;
|
||||
#endif
|
||||
|
||||
bh_assert(expr != NULL);
|
||||
/* + init value size */
|
||||
switch (expr->init_expr_type) {
|
||||
case INIT_EXPR_NONE:
|
||||
|
@ -248,7 +248,7 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
|
|||
{
|
||||
uint32 i;
|
||||
WASMStructNewInitValues *struct_new_init_values =
|
||||
(WASMStructNewInitValues *)expr->u.data;
|
||||
(WASMStructNewInitValues *)expr->u.unary.v.data;
|
||||
|
||||
/* type_index + field_count + fields */
|
||||
size += sizeof(uint32) + sizeof(uint32);
|
||||
|
@ -285,7 +285,7 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
|
|||
case INIT_EXPR_TYPE_ARRAY_NEW_FIXED:
|
||||
{
|
||||
WASMArrayNewInitValues *array_new_init_values =
|
||||
(WASMArrayNewInitValues *)expr->u.data;
|
||||
(WASMArrayNewInitValues *)expr->u.unary.v.data;
|
||||
WASMArrayType *array_type = NULL;
|
||||
uint32 value_count;
|
||||
|
||||
|
@ -302,12 +302,27 @@ get_init_expr_size(const AOTCompContext *comp_ctx, const AOTCompData *comp_data,
|
|||
|
||||
/* array_elem_type + type_index + len + elems */
|
||||
size += sizeof(uint32) * 3
|
||||
+ wasm_value_type_size_internal(array_type->elem_type,
|
||||
comp_ctx->pointer_size)
|
||||
+ (uint64)wasm_value_type_size_internal(
|
||||
array_type->elem_type, comp_ctx->pointer_size)
|
||||
* value_count;
|
||||
break;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
case INIT_EXPR_TYPE_I32_ADD:
|
||||
case INIT_EXPR_TYPE_I32_SUB:
|
||||
case INIT_EXPR_TYPE_I32_MUL:
|
||||
case INIT_EXPR_TYPE_I64_ADD:
|
||||
case INIT_EXPR_TYPE_I64_SUB:
|
||||
case INIT_EXPR_TYPE_I64_MUL:
|
||||
{
|
||||
size +=
|
||||
get_init_expr_size(comp_ctx, comp_data, expr->u.binary.l_expr);
|
||||
size +=
|
||||
get_init_expr_size(comp_ctx, comp_data, expr->u.binary.r_expr);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
bh_assert(0);
|
||||
}
|
||||
|
@ -324,15 +339,16 @@ get_table_init_data_size(AOTCompContext *comp_ctx,
|
|||
/*
|
||||
* mode (4 bytes), elem_type (4 bytes)
|
||||
*
|
||||
* table_index(4 bytes) + init expr type (4 bytes) + init expr value (8
|
||||
* bytes)
|
||||
* table_index(4 bytes)
|
||||
*/
|
||||
size = (uint32)(sizeof(uint32) * 2 + sizeof(uint32) + sizeof(uint32)
|
||||
+ sizeof(uint64))
|
||||
size = (uint32)(sizeof(uint32) * 2 + sizeof(uint32))
|
||||
/* Size of WasmRefType - inner padding (ref type + nullable +
|
||||
heap_type) */
|
||||
+ 8;
|
||||
|
||||
size += get_init_expr_size(comp_ctx, comp_ctx->comp_data,
|
||||
&table_init_data->offset);
|
||||
|
||||
/* + value count/func index count (4 bytes) + init_values */
|
||||
size += sizeof(uint32);
|
||||
for (i = 0; i < table_init_data->value_count; i++) {
|
||||
|
@ -1811,6 +1827,10 @@ static bool
|
|||
aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||
AOTCompContext *comp_ctx, InitializerExpression *expr)
|
||||
{
|
||||
if (expr == NULL) {
|
||||
aot_set_last_error("invalid init expr.");
|
||||
return false;
|
||||
}
|
||||
uint32 offset = *p_offset;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
WASMModule *module = comp_ctx->comp_data->wasm_module;
|
||||
|
@ -1824,31 +1844,31 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
break;
|
||||
case INIT_EXPR_TYPE_I32_CONST:
|
||||
case INIT_EXPR_TYPE_F32_CONST:
|
||||
EMIT_U32(expr->u.i32);
|
||||
EMIT_U32(expr->u.unary.v.i32);
|
||||
break;
|
||||
case INIT_EXPR_TYPE_I64_CONST:
|
||||
case INIT_EXPR_TYPE_F64_CONST:
|
||||
EMIT_U64(expr->u.i64);
|
||||
EMIT_U64(expr->u.unary.v.i64);
|
||||
break;
|
||||
case INIT_EXPR_TYPE_V128_CONST:
|
||||
EMIT_V128(expr->u.v128);
|
||||
EMIT_V128(expr->u.unary.v.v128);
|
||||
break;
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
EMIT_U32(expr->u.global_index);
|
||||
EMIT_U32(expr->u.unary.v.global_index);
|
||||
break;
|
||||
case INIT_EXPR_TYPE_FUNCREF_CONST:
|
||||
case INIT_EXPR_TYPE_REFNULL_CONST:
|
||||
EMIT_U32(expr->u.ref_index);
|
||||
EMIT_U32(expr->u.unary.v.ref_index);
|
||||
break;
|
||||
#if WASM_ENABLE_GC != 0
|
||||
case INIT_EXPR_TYPE_I31_NEW:
|
||||
EMIT_U32(expr->u.i32);
|
||||
EMIT_U32(expr->u.unary.v.i32);
|
||||
break;
|
||||
case INIT_EXPR_TYPE_STRUCT_NEW:
|
||||
{
|
||||
uint32 i;
|
||||
WASMStructNewInitValues *init_values =
|
||||
(WASMStructNewInitValues *)expr->u.data;
|
||||
(WASMStructNewInitValues *)expr->u.unary.v.data;
|
||||
WASMStructType *struct_type = NULL;
|
||||
|
||||
EMIT_U32(init_values->type_idx);
|
||||
|
@ -1879,7 +1899,7 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
break;
|
||||
}
|
||||
case INIT_EXPR_TYPE_STRUCT_NEW_DEFAULT:
|
||||
EMIT_U32(expr->u.type_index);
|
||||
EMIT_U32(expr->u.unary.v.type_index);
|
||||
break;
|
||||
case INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT:
|
||||
{
|
||||
|
@ -1889,11 +1909,11 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
< module->type_count);
|
||||
array_type =
|
||||
(WASMArrayType *)
|
||||
module->types[expr->u.array_new_default.type_index];
|
||||
module->types[expr->u.unary.v.array_new_default.type_index];
|
||||
|
||||
EMIT_U32(array_type->elem_type);
|
||||
EMIT_U32(expr->u.array_new_default.type_index);
|
||||
EMIT_U32(expr->u.array_new_default.length);
|
||||
EMIT_U32(expr->u.unary.v.array_new_default.type_index);
|
||||
EMIT_U32(expr->u.unary.v.array_new_default.length);
|
||||
break;
|
||||
}
|
||||
case INIT_EXPR_TYPE_ARRAY_NEW:
|
||||
|
@ -1901,7 +1921,7 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
{
|
||||
uint32 value_count, i, field_size;
|
||||
WASMArrayNewInitValues *init_values =
|
||||
(WASMArrayNewInitValues *)expr->u.data;
|
||||
(WASMArrayNewInitValues *)expr->u.unary.v.data;
|
||||
WASMArrayType *array_type = NULL;
|
||||
|
||||
bh_assert(init_values->type_idx < module->type_count);
|
||||
|
@ -1933,6 +1953,25 @@ aot_emit_init_expr(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
break;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
case INIT_EXPR_TYPE_I32_ADD:
|
||||
case INIT_EXPR_TYPE_I32_SUB:
|
||||
case INIT_EXPR_TYPE_I32_MUL:
|
||||
case INIT_EXPR_TYPE_I64_ADD:
|
||||
case INIT_EXPR_TYPE_I64_SUB:
|
||||
case INIT_EXPR_TYPE_I64_MUL:
|
||||
if (comp_ctx->enable_extended_const) {
|
||||
if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
|
||||
expr->u.binary.l_expr)) {
|
||||
return false;
|
||||
}
|
||||
if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
|
||||
expr->u.binary.r_expr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
aot_set_last_error("invalid init expr type.");
|
||||
return false;
|
||||
|
@ -2034,8 +2073,10 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
EMIT_U32(init_datas[i]->mode);
|
||||
EMIT_U32(init_datas[i]->elem_type);
|
||||
EMIT_U32(init_datas[i]->table_index);
|
||||
EMIT_U32(init_datas[i]->offset.init_expr_type);
|
||||
EMIT_U64(init_datas[i]->offset.u.i64);
|
||||
if (!aot_emit_init_expr(buf, buf_end, &offset, comp_ctx,
|
||||
&init_datas[i]->offset))
|
||||
return false;
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (comp_ctx->enable_gc && init_datas[i]->elem_ref_type) {
|
||||
EMIT_U16(init_datas[i]->elem_ref_type->ref_ht_common.ref_type);
|
||||
|
@ -3378,6 +3419,12 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data)
|
|||
bh_memcpy_s(data_section->name, size, buf, size);
|
||||
data_section->is_name_allocated = true;
|
||||
}
|
||||
else if (obj_data->comp_ctx->enable_llvm_pgo
|
||||
&& !strcmp(name, "__llvm_prf_bits")) {
|
||||
LOG_WARNING("__llvm_prf_bits section is not supported and "
|
||||
"shouldn't be used in PGO.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj_data->comp_ctx->enable_llvm_pgo
|
||||
&& !strcmp(name, "__llvm_prf_names")) {
|
||||
|
|
|
@ -347,7 +347,8 @@ call_aot_invoke_c_api_native(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* Get &c_api_func_imports[func_idx], note size of CApiFuncImport
|
||||
is pointer_size * 3 */
|
||||
offset = I32_CONST((comp_ctx->pointer_size * 3) * import_func_idx);
|
||||
offset = I32_CONST((unsigned long long)comp_ctx->pointer_size * 3
|
||||
* import_func_idx);
|
||||
CHECK_LLVM_CONST(offset);
|
||||
c_api_func_import =
|
||||
LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, c_api_func_imports,
|
||||
|
|
|
@ -10,6 +10,40 @@
|
|||
#include "aot_intrinsic.h"
|
||||
#include "aot_emit_control.h"
|
||||
|
||||
#define BUILD_IS_NOT_NULL(value, res, name) \
|
||||
do { \
|
||||
if (!(res = LLVMBuildIsNotNull(comp_ctx->builder, value, name))) { \
|
||||
aot_set_last_error("llvm build is not null failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_BR(llvm_block) \
|
||||
do { \
|
||||
if (!LLVMBuildBr(comp_ctx->builder, llvm_block)) { \
|
||||
aot_set_last_error("llvm build br failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_COND_BR(value_if, block_then, block_else) \
|
||||
do { \
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, value_if, block_then, \
|
||||
block_else)) { \
|
||||
aot_set_last_error("llvm build cond br failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_TRUNC(value, data_type) \
|
||||
do { \
|
||||
if (!(value = LLVMBuildTrunc(comp_ctx->builder, value, data_type, \
|
||||
"val_trunc"))) { \
|
||||
aot_set_last_error("llvm build trunc failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_ICMP(op, left, right, res, name) \
|
||||
do { \
|
||||
if (!(res = \
|
||||
|
@ -111,6 +145,418 @@ ffs(int n)
|
|||
static LLVMValueRef
|
||||
get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
uint32
|
||||
get_module_inst_extra_offset(AOTCompContext *comp_ctx);
|
||||
|
||||
#define BUILD_LOAD_PTR(ptr, data_type, res) \
|
||||
do { \
|
||||
if (!(res = LLVMBuildLoad2(comp_ctx->builder, data_type, ptr, \
|
||||
"load_value"))) { \
|
||||
aot_set_last_error("llvm build load failed"); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Update last used shared heap info(alloc ptr) in function ctx:
|
||||
* 1. shared_heap_start_off 2. shared_heap_end_off 3. shared_heap_base_addr_adj
|
||||
*/
|
||||
bool
|
||||
aot_check_shared_heap_chain_and_update(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMBasicBlockRef check_succ,
|
||||
LLVMValueRef start_offset,
|
||||
LLVMValueRef bytes, bool is_memory64)
|
||||
{
|
||||
LLVMValueRef param_values[7], ret_value, func, value, cmp;
|
||||
LLVMTypeRef param_types[7], ret_type, func_type, func_ptr_type;
|
||||
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = INTPTR_T_TYPE;
|
||||
param_types[2] = SIZE_T_TYPE;
|
||||
param_types[3] = INTPTR_T_PTR_TYPE;
|
||||
param_types[4] = INTPTR_T_PTR_TYPE;
|
||||
param_types[5] = INT8_PTR_TYPE;
|
||||
param_types[6] = INT8_TYPE;
|
||||
ret_type = INT8_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(wasm_runtime_check_and_update_last_used_shared_heap, 7);
|
||||
|
||||
/* Call function */
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
param_values[1] = start_offset;
|
||||
param_values[2] = bytes;
|
||||
/* pass alloc ptr */
|
||||
param_values[3] = func_ctx->shared_heap_start_off;
|
||||
param_values[4] = func_ctx->shared_heap_end_off;
|
||||
param_values[5] = func_ctx->shared_heap_base_addr_adj;
|
||||
param_values[6] = is_memory64 ? I8_ONE : I8_ZERO;
|
||||
|
||||
if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
|
||||
param_values, 7, "call"))) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
BUILD_ICMP(LLVMIntEQ, ret_value, I8_ZERO, cmp, "shared_heap_oob");
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp,
|
||||
check_succ)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the basic blocks for shared heap and shared chain memory checks.
|
||||
*
|
||||
* Arguments:
|
||||
* block_curr: The current basic block.
|
||||
* app_addr_in_cache_shared_heap: Output, block for cache shared heap.
|
||||
* app_addr_in_linear_mem: Output, block for linear memory.
|
||||
* app_addr_in_shared_heap_chain: Output, block for shared heap chain
|
||||
* (only for shared heap chain).
|
||||
* check_shared_heap_chain: Output, block for checking shared heap chain
|
||||
* (only for shared heap chain).
|
||||
*
|
||||
* Topology:
|
||||
* If enable_shared_heap:
|
||||
* block_curr -> app_addr_in_cache_shared_heap
|
||||
* -> app_addr_in_linear_mem
|
||||
* If enable_shared_chain:
|
||||
* block_curr -> app_addr_in_shared_heap_chain
|
||||
* -> app_addr_in_cache_shared_heap
|
||||
* -> check_shared_heap_chain
|
||||
* -> app_addr_in_linear_mem
|
||||
*/
|
||||
static bool
|
||||
setup_shared_heap_blocks(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMBasicBlockRef block_curr,
|
||||
LLVMBasicBlockRef *app_addr_in_cache_shared_heap,
|
||||
LLVMBasicBlockRef *app_addr_in_linear_mem,
|
||||
LLVMBasicBlockRef *app_addr_in_shared_heap_chain,
|
||||
LLVMBasicBlockRef *check_shared_heap_chain)
|
||||
{
|
||||
ADD_BASIC_BLOCK(*app_addr_in_cache_shared_heap,
|
||||
"app_addr_in_cache_shared_heap");
|
||||
ADD_BASIC_BLOCK(*app_addr_in_linear_mem, "app_addr_in_linear_mem");
|
||||
|
||||
if (comp_ctx->enable_shared_heap) {
|
||||
LLVMMoveBasicBlockAfter(*app_addr_in_cache_shared_heap, block_curr);
|
||||
LLVMMoveBasicBlockAfter(*app_addr_in_linear_mem,
|
||||
*app_addr_in_cache_shared_heap);
|
||||
}
|
||||
else if (comp_ctx->enable_shared_chain) {
|
||||
ADD_BASIC_BLOCK(*app_addr_in_shared_heap_chain,
|
||||
"app_addr_in_shared_heap_chain");
|
||||
ADD_BASIC_BLOCK(*check_shared_heap_chain, "check_shared_heap_chain");
|
||||
LLVMMoveBasicBlockAfter(*app_addr_in_shared_heap_chain, block_curr);
|
||||
LLVMMoveBasicBlockAfter(*app_addr_in_cache_shared_heap,
|
||||
*app_addr_in_shared_heap_chain);
|
||||
LLVMMoveBasicBlockAfter(*check_shared_heap_chain,
|
||||
*app_addr_in_cache_shared_heap);
|
||||
LLVMMoveBasicBlockAfter(*app_addr_in_linear_mem,
|
||||
*app_addr_in_cache_shared_heap);
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a branch to check if start_offset is in the shared heap chain region.
|
||||
*
|
||||
* Arguments:
|
||||
* start_offset: The offset to check.
|
||||
* app_addr_in_shared_heap_chain: Block to branch if in shared heap chain.
|
||||
* app_addr_in_linear_mem: Block to branch if not in shared heap chain.
|
||||
*/
|
||||
static bool
|
||||
build_check_app_addr_in_shared_heap_chain(
|
||||
AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMValueRef start_offset, LLVMBasicBlockRef app_addr_in_shared_heap_chain,
|
||||
LLVMBasicBlockRef app_addr_in_linear_mem)
|
||||
{
|
||||
LLVMValueRef is_in_shared_heap = NULL;
|
||||
|
||||
/* Use start_offset > func_ctx->shared_heap_head_start_off to test
|
||||
* start_off falls in shared heap chain memory region. The shared heap
|
||||
* chain oob will be detected in app_addr_in_shared_heap block or
|
||||
* aot_check_shared_heap_chain_and_update function
|
||||
*/
|
||||
BUILD_ICMP(LLVMIntUGT, start_offset, func_ctx->shared_heap_head_start_off,
|
||||
is_in_shared_heap, "shared_heap_lb_cmp");
|
||||
BUILD_COND_BR(is_in_shared_heap, app_addr_in_shared_heap_chain,
|
||||
app_addr_in_linear_mem);
|
||||
|
||||
SET_BUILD_POS(app_addr_in_shared_heap_chain);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the conditional branch for cache shared heap or shared heap chain.
|
||||
*
|
||||
* Arguments:
|
||||
* cmp: The condition for being in cache shared heap.
|
||||
* app_addr_in_cache_shared_heap: Block for cache shared heap.
|
||||
* app_addr_in_linear_mem: Block for linear memory.
|
||||
* check_shared_heap_chain: Block for checking shared heap chain.
|
||||
* bytes: The access size in bytes.
|
||||
* start_offset: The offset to check.
|
||||
* is_memory64: Whether memory is 64-bit.
|
||||
*/
|
||||
static bool
|
||||
build_shared_heap_conditional_branching(
|
||||
AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef cmp,
|
||||
LLVMBasicBlockRef app_addr_in_cache_shared_heap,
|
||||
LLVMBasicBlockRef app_addr_in_linear_mem,
|
||||
LLVMBasicBlockRef check_shared_heap_chain, LLVMValueRef bytes,
|
||||
LLVMValueRef start_offset, bool is_memory64)
|
||||
{
|
||||
if (comp_ctx->enable_shared_heap) {
|
||||
BUILD_COND_BR(cmp, app_addr_in_cache_shared_heap,
|
||||
app_addr_in_linear_mem);
|
||||
}
|
||||
else if (comp_ctx->enable_shared_chain) {
|
||||
BUILD_COND_BR(cmp, app_addr_in_cache_shared_heap,
|
||||
check_shared_heap_chain);
|
||||
SET_BUILD_POS(check_shared_heap_chain);
|
||||
if (!aot_check_shared_heap_chain_and_update(
|
||||
comp_ctx, func_ctx, app_addr_in_cache_shared_heap, start_offset,
|
||||
bytes, is_memory64))
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the native address in the cache shared heap.
|
||||
*
|
||||
* Arguments:
|
||||
* start_offset: The offset to use for address calculation.
|
||||
* maddr: Output, the native address that in the cache shared heap.
|
||||
*/
|
||||
static bool
|
||||
build_get_maddr_in_cache_shared_heap(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMValueRef start_offset,
|
||||
LLVMValueRef *maddr)
|
||||
{
|
||||
LLVMValueRef shared_heap_base_addr_adj;
|
||||
/* load the local variable */
|
||||
BUILD_LOAD_PTR(func_ctx->shared_heap_base_addr_adj, INT8_PTR_TYPE,
|
||||
shared_heap_base_addr_adj);
|
||||
if (!(*maddr = LLVMBuildInBoundsGEP2(
|
||||
comp_ctx->builder, INT8_TYPE, shared_heap_base_addr_adj,
|
||||
&start_offset, 1, "maddr_cache_shared_heap"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for memory overflow in shared heap for normal memory access.
|
||||
*
|
||||
* Arguments:
|
||||
* block_curr: The current basic block.
|
||||
* block_maddr_phi: The phi block for memory address.
|
||||
* maddr_phi: The phi node for memory address.
|
||||
* start_offset: The first offset to check.
|
||||
* mem_base_addr: The base address of memory. Only used with segue.
|
||||
* bytes_u32: The access size in bytes.
|
||||
* is_memory64: Whether memory is wasm64 memory.
|
||||
* is_target_64bit: Whether target is 64-bit.
|
||||
* enable_segue: Whether to use segment register addressing.
|
||||
*/
|
||||
static bool
|
||||
aot_check_shared_heap_memory_overflow(
|
||||
AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMBasicBlockRef block_curr, LLVMBasicBlockRef block_maddr_phi,
|
||||
LLVMValueRef maddr_phi, LLVMValueRef start_offset,
|
||||
LLVMValueRef mem_base_addr, uint32 bytes_u32, bool is_memory64,
|
||||
bool is_target_64bit, bool enable_segue)
|
||||
{
|
||||
LLVMBasicBlockRef app_addr_in_cache_shared_heap, app_addr_in_linear_mem;
|
||||
LLVMBasicBlockRef app_addr_in_shared_heap_chain = NULL,
|
||||
check_shared_heap_chain = NULL;
|
||||
LLVMValueRef cmp, cmp1, cmp2, shared_heap_start_off, shared_heap_end_off,
|
||||
shared_heap_check_bound, maddr = NULL;
|
||||
/* On 64/32-bit target, the offset is 64/32-bit */
|
||||
LLVMTypeRef offset_type = is_target_64bit ? I64_TYPE : I32_TYPE;
|
||||
LLVMValueRef length, bytes;
|
||||
|
||||
if (!setup_shared_heap_blocks(
|
||||
comp_ctx, func_ctx, block_curr, &app_addr_in_cache_shared_heap,
|
||||
&app_addr_in_linear_mem, &app_addr_in_shared_heap_chain,
|
||||
&check_shared_heap_chain))
|
||||
goto fail;
|
||||
LLVMMoveBasicBlockAfter(block_maddr_phi, app_addr_in_linear_mem);
|
||||
|
||||
/* Early branching when it's not in shared heap chain at all */
|
||||
if (comp_ctx->enable_shared_chain
|
||||
&& !build_check_app_addr_in_shared_heap_chain(
|
||||
comp_ctx, func_ctx, start_offset, app_addr_in_shared_heap_chain,
|
||||
app_addr_in_linear_mem))
|
||||
goto fail;
|
||||
|
||||
/* Load the local variable of the function */
|
||||
BUILD_LOAD_PTR(func_ctx->shared_heap_start_off, offset_type,
|
||||
shared_heap_start_off);
|
||||
BUILD_LOAD_PTR(func_ctx->shared_heap_end_off, offset_type,
|
||||
shared_heap_end_off);
|
||||
/* Check if the app address is in the cache shared heap range.
|
||||
* If yes, branch to the cache branch; if not, check the shared heap chain
|
||||
*/
|
||||
BUILD_ICMP(LLVMIntUGE, start_offset, shared_heap_start_off, cmp,
|
||||
"cmp_cache_shared_heap_start");
|
||||
length =
|
||||
is_target_64bit ? I64_CONST(bytes_u32 - 1) : I32_CONST(bytes_u32 - 1);
|
||||
CHECK_LLVM_CONST(length);
|
||||
BUILD_OP(Sub, shared_heap_end_off, length, shared_heap_check_bound,
|
||||
"cache_shared_heap_end_bound");
|
||||
BUILD_ICMP(LLVMIntULE, start_offset, shared_heap_check_bound, cmp1,
|
||||
"cmp_cache_shared_heap_end");
|
||||
BUILD_OP(And, cmp, cmp1, cmp2, "is_in_cache_shared_heap");
|
||||
/* Conditional branching based on whether in cached shared heap */
|
||||
bytes = is_target_64bit ? I64_CONST(bytes_u32) : I32_CONST(bytes_u32);
|
||||
if (!build_shared_heap_conditional_branching(
|
||||
comp_ctx, func_ctx, cmp2, app_addr_in_cache_shared_heap,
|
||||
app_addr_in_linear_mem, check_shared_heap_chain, bytes,
|
||||
start_offset, is_memory64))
|
||||
goto fail;
|
||||
|
||||
SET_BUILD_POS(app_addr_in_cache_shared_heap);
|
||||
if (!build_get_maddr_in_cache_shared_heap(comp_ctx, func_ctx, start_offset,
|
||||
&maddr))
|
||||
goto fail;
|
||||
|
||||
if (enable_segue) {
|
||||
LLVMValueRef mem_base_addr_u64, maddr_u64, offset_to_mem_base;
|
||||
if (!(maddr_u64 = LLVMBuildPtrToInt(comp_ctx->builder, maddr, I64_TYPE,
|
||||
"maddr_u64"))
|
||||
|| !(mem_base_addr_u64 =
|
||||
LLVMBuildPtrToInt(comp_ctx->builder, mem_base_addr,
|
||||
I64_TYPE, "mem_base_addr_u64"))) {
|
||||
aot_set_last_error("llvm build ptr to int failed");
|
||||
goto fail;
|
||||
}
|
||||
if (!(offset_to_mem_base =
|
||||
LLVMBuildSub(comp_ctx->builder, maddr_u64, mem_base_addr_u64,
|
||||
"offset_to_mem_base"))) {
|
||||
aot_set_last_error("llvm build sub failed");
|
||||
goto fail;
|
||||
}
|
||||
if (!(maddr = LLVMBuildIntToPtr(comp_ctx->builder, offset_to_mem_base,
|
||||
INT8_PTR_TYPE_GS,
|
||||
"maddr_shared_heap_segue"))) {
|
||||
aot_set_last_error("llvm build int to ptr failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
LLVMAddIncoming(maddr_phi, &maddr, &app_addr_in_cache_shared_heap, 1);
|
||||
BUILD_BR(block_maddr_phi);
|
||||
SET_BUILD_POS(app_addr_in_linear_mem);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for memory overflow in shared heap for bulk memory access.
|
||||
*
|
||||
* Arguments:
|
||||
* block_curr: The current basic block.
|
||||
* block_maddr_phi: The phi block for memory address.
|
||||
* check_succ: The block to branch to on success.
|
||||
* maddr_phi: The phi node for memory address.
|
||||
* start_offset: The offset to check.
|
||||
* max_addr: The maximum address to check.
|
||||
* bytes: The access size in bytes (LLVMValueRef).
|
||||
* is_memory64: Whether memory is wasm64 memory.
|
||||
* is_target_64bit: Whether target is 64-bit.
|
||||
*/
|
||||
static bool
|
||||
aot_check_bulk_memory_shared_heap_memory_overflow(
|
||||
AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMBasicBlockRef block_curr, LLVMBasicBlockRef block_maddr_phi,
|
||||
LLVMBasicBlockRef check_succ, LLVMValueRef maddr_phi,
|
||||
LLVMValueRef start_offset, LLVMValueRef max_addr, LLVMValueRef bytes,
|
||||
bool is_memory64, bool is_target_64bit)
|
||||
{
|
||||
LLVMBasicBlockRef app_addr_in_cache_shared_heap, app_addr_in_linear_mem;
|
||||
LLVMBasicBlockRef app_addr_in_shared_heap_chain = NULL,
|
||||
check_shared_heap_chain = NULL;
|
||||
LLVMValueRef cmp, cmp1, cmp2, shared_heap_start_off, shared_heap_end_off,
|
||||
maddr = NULL, max_offset;
|
||||
/* On 64/32-bit target, the offset is 64/32-bit */
|
||||
LLVMTypeRef offset_type = is_target_64bit ? I64_TYPE : I32_TYPE;
|
||||
|
||||
if (!setup_shared_heap_blocks(
|
||||
comp_ctx, func_ctx, block_curr, &app_addr_in_cache_shared_heap,
|
||||
&app_addr_in_linear_mem, &app_addr_in_shared_heap_chain,
|
||||
&check_shared_heap_chain))
|
||||
goto fail;
|
||||
LLVMMoveBasicBlockAfter(block_maddr_phi, check_succ);
|
||||
|
||||
/* Early branching when it's not in shared heap chain at all */
|
||||
if (comp_ctx->enable_shared_chain
|
||||
&& !build_check_app_addr_in_shared_heap_chain(
|
||||
comp_ctx, func_ctx, start_offset, app_addr_in_shared_heap_chain,
|
||||
app_addr_in_linear_mem))
|
||||
goto fail;
|
||||
|
||||
/* Load the local variable of the function */
|
||||
BUILD_LOAD_PTR(func_ctx->shared_heap_start_off, offset_type,
|
||||
shared_heap_start_off);
|
||||
BUILD_LOAD_PTR(func_ctx->shared_heap_end_off, offset_type,
|
||||
shared_heap_end_off);
|
||||
/* Check if the app address is in the cache shared heap range.
|
||||
* If yes, branch to the cache branch; if not, check the shared heap chain
|
||||
*/
|
||||
BUILD_ICMP(LLVMIntUGE, start_offset, shared_heap_start_off, cmp,
|
||||
"cmp_cache_shared_heap_start");
|
||||
BUILD_OP(Add, max_addr, is_target_64bit ? I64_NEG_ONE : I32_NEG_ONE,
|
||||
max_offset, "max_offset");
|
||||
BUILD_ICMP(LLVMIntULE, max_offset, shared_heap_end_off, cmp1,
|
||||
"cmp_cache_shared_heap_end");
|
||||
BUILD_OP(And, cmp, cmp1, cmp2, "is_in_cache_shared_heap");
|
||||
/* Conditional branching based on whether in cached shared heap */
|
||||
if (!build_shared_heap_conditional_branching(
|
||||
comp_ctx, func_ctx, cmp2, app_addr_in_cache_shared_heap,
|
||||
app_addr_in_linear_mem, check_shared_heap_chain, bytes,
|
||||
start_offset, is_memory64))
|
||||
goto fail;
|
||||
|
||||
SET_BUILD_POS(app_addr_in_cache_shared_heap);
|
||||
if (!build_get_maddr_in_cache_shared_heap(comp_ctx, func_ctx, start_offset,
|
||||
&maddr))
|
||||
goto fail;
|
||||
|
||||
LLVMAddIncoming(maddr_phi, &maddr, &app_addr_in_cache_shared_heap, 1);
|
||||
BUILD_BR(block_maddr_phi);
|
||||
SET_BUILD_POS(app_addr_in_linear_mem);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
LLVMValueRef
|
||||
aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
mem_offset_t offset, uint32 bytes, bool enable_segue,
|
||||
|
@ -118,10 +564,10 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
{
|
||||
LLVMValueRef offset_const =
|
||||
MEMORY64_COND_VALUE(I64_CONST(offset), I32_CONST(offset));
|
||||
LLVMValueRef addr, maddr, maddr_phi = NULL, offset1, cmp1, cmp2, cmp;
|
||||
LLVMValueRef addr, maddr, offset1, cmp1, cmp;
|
||||
LLVMValueRef mem_base_addr, mem_check_bound;
|
||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMBasicBlockRef check_succ, block_maddr_phi = NULL;
|
||||
LLVMBasicBlockRef check_succ;
|
||||
AOTValue *aot_value_top;
|
||||
uint32 local_idx_of_aot_value = 0;
|
||||
uint64 const_value;
|
||||
|
@ -136,6 +582,10 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
#else
|
||||
bool is_memory64 = IS_MEMORY64;
|
||||
#endif
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
LLVMValueRef maddr_phi = NULL;
|
||||
LLVMBasicBlockRef block_maddr_phi = NULL;
|
||||
#endif
|
||||
|
||||
is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false;
|
||||
|
||||
|
@ -262,6 +712,13 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
*alignp = 1;
|
||||
}
|
||||
|
||||
/* The overflow check needs to be done under following conditions:
|
||||
* 1. In 64-bit target, offset and addr will be extended to 64-bit
|
||||
* 1.1 offset + addr can overflow when it's memory64
|
||||
* 1.2 no overflow when it's memory32
|
||||
* 2. In 32-bit target, offset and addr will be 32-bit
|
||||
* 2.1 offset + addr can overflow when it's memory32
|
||||
*/
|
||||
if (is_target_64bit) {
|
||||
if (!(offset_const = LLVMBuildZExt(comp_ctx->builder, offset_const,
|
||||
I64_TYPE, "offset_i64"))
|
||||
|
@ -275,7 +732,9 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
/* offset1 = offset + addr; */
|
||||
BUILD_OP(Add, offset_const, addr, offset1, "offset1");
|
||||
|
||||
if (is_memory64 && comp_ctx->enable_bound_check) {
|
||||
/* 1.1 offset + addr can overflow when it's memory64
|
||||
* 2.1 Or when it's on 32-bit platform */
|
||||
if (is_memory64 || !is_target_64bit) {
|
||||
/* Check whether integer overflow occurs in offset + addr */
|
||||
LLVMBasicBlockRef check_integer_overflow_end;
|
||||
ADD_BASIC_BLOCK(check_integer_overflow_end,
|
||||
|
@ -289,23 +748,14 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
goto fail;
|
||||
}
|
||||
SET_BUILD_POS(check_integer_overflow_end);
|
||||
block_curr = check_integer_overflow_end;
|
||||
}
|
||||
|
||||
if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
|
||||
LLVMBasicBlockRef app_addr_in_shared_heap, app_addr_in_linear_mem;
|
||||
LLVMValueRef is_in_shared_heap, shared_heap_check_bound = NULL;
|
||||
|
||||
/* Add basic blocks */
|
||||
ADD_BASIC_BLOCK(app_addr_in_shared_heap, "app_addr_in_shared_heap");
|
||||
ADD_BASIC_BLOCK(app_addr_in_linear_mem, "app_addr_in_linear_mem");
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (comp_ctx->enable_shared_heap
|
||||
|| comp_ctx->enable_shared_chain /* TODO: && mem_idx == 0 */) {
|
||||
ADD_BASIC_BLOCK(block_maddr_phi, "maddr_phi");
|
||||
|
||||
LLVMMoveBasicBlockAfter(app_addr_in_shared_heap, block_curr);
|
||||
LLVMMoveBasicBlockAfter(app_addr_in_linear_mem,
|
||||
app_addr_in_shared_heap);
|
||||
LLVMMoveBasicBlockAfter(block_maddr_phi, app_addr_in_linear_mem);
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_maddr_phi);
|
||||
SET_BUILD_POS(block_maddr_phi);
|
||||
if (!(maddr_phi =
|
||||
LLVMBuildPhi(comp_ctx->builder,
|
||||
enable_segue ? INT8_PTR_TYPE_GS : INT8_PTR_TYPE,
|
||||
|
@ -313,110 +763,16 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
aot_set_last_error("llvm build phi failed");
|
||||
goto fail;
|
||||
}
|
||||
SET_BUILD_POS(block_curr);
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
|
||||
|
||||
if (!is_target_64bit) {
|
||||
/* Check whether integer overflow occurs in addr + offset */
|
||||
LLVMBasicBlockRef check_integer_overflow_end;
|
||||
ADD_BASIC_BLOCK(check_integer_overflow_end,
|
||||
"check_integer_overflow_end");
|
||||
LLVMMoveBasicBlockAfter(check_integer_overflow_end, block_curr);
|
||||
|
||||
BUILD_ICMP(LLVMIntULT, offset1, addr, cmp1, "cmp1");
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true,
|
||||
cmp1, check_integer_overflow_end)) {
|
||||
goto fail;
|
||||
}
|
||||
SET_BUILD_POS(check_integer_overflow_end);
|
||||
}
|
||||
|
||||
shared_heap_check_bound =
|
||||
is_memory64 ? I64_CONST(UINT64_MAX - bytes + 1)
|
||||
: (comp_ctx->pointer_size == sizeof(uint64)
|
||||
? I64_CONST(UINT32_MAX - bytes + 1)
|
||||
: I32_CONST(UINT32_MAX - bytes + 1));
|
||||
CHECK_LLVM_CONST(shared_heap_check_bound);
|
||||
|
||||
/* Check whether the bytes to access are in shared heap */
|
||||
if (!comp_ctx->enable_bound_check) {
|
||||
/* Use IntUGT but not IntUGE to compare, since (1) in the ems
|
||||
memory allocator, the hmu node includes hmu header and hmu
|
||||
memory, only the latter is returned to the caller as the
|
||||
allocated memory, the hmu header isn't returned so the
|
||||
first byte of the shared heap won't be accessed, (2) using
|
||||
IntUGT gets better performance than IntUGE in some cases */
|
||||
BUILD_ICMP(LLVMIntUGT, offset1, func_ctx->shared_heap_start_off,
|
||||
is_in_shared_heap, "is_in_shared_heap");
|
||||
/* We don't check the shared heap's upper boundary if boundary
|
||||
check isn't enabled, the runtime may also use the guard pages
|
||||
of shared heap to check the boundary if hardware boundary
|
||||
check feature is enabled. */
|
||||
}
|
||||
else {
|
||||
/* Use IntUGT but not IntUGE to compare, same as above */
|
||||
BUILD_ICMP(LLVMIntUGT, offset1, func_ctx->shared_heap_start_off,
|
||||
cmp1, "cmp1");
|
||||
/* Check the shared heap's upper boundary if boundary check is
|
||||
enabled */
|
||||
BUILD_ICMP(LLVMIntULE, offset1, shared_heap_check_bound, cmp2,
|
||||
"cmp2");
|
||||
BUILD_OP(And, cmp1, cmp2, is_in_shared_heap, "is_in_shared_heap");
|
||||
}
|
||||
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, is_in_shared_heap,
|
||||
app_addr_in_shared_heap, app_addr_in_linear_mem)) {
|
||||
aot_set_last_error("llvm build cond br failed");
|
||||
if (!aot_check_shared_heap_memory_overflow(
|
||||
comp_ctx, func_ctx, block_curr, block_maddr_phi, maddr_phi,
|
||||
offset1, mem_base_addr, bytes, is_memory64, is_target_64bit,
|
||||
enable_segue)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, app_addr_in_shared_heap);
|
||||
|
||||
/* Get native address inside shared heap */
|
||||
if (!(maddr =
|
||||
LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
||||
func_ctx->shared_heap_base_addr_adj,
|
||||
&offset1, 1, "maddr_shared_heap"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (enable_segue) {
|
||||
LLVMValueRef mem_base_addr_u64, maddr_u64, offset_to_mem_base;
|
||||
|
||||
if (!(maddr_u64 = LLVMBuildPtrToInt(comp_ctx->builder, maddr,
|
||||
I64_TYPE, "maddr_u64"))
|
||||
|| !(mem_base_addr_u64 =
|
||||
LLVMBuildPtrToInt(comp_ctx->builder, mem_base_addr,
|
||||
I64_TYPE, "mem_base_addr_u64"))) {
|
||||
aot_set_last_error("llvm build ptr to int failed");
|
||||
goto fail;
|
||||
}
|
||||
if (!(offset_to_mem_base =
|
||||
LLVMBuildSub(comp_ctx->builder, maddr_u64,
|
||||
mem_base_addr_u64, "offset_to_mem_base"))) {
|
||||
aot_set_last_error("llvm build sub failed");
|
||||
goto fail;
|
||||
}
|
||||
if (!(maddr = LLVMBuildIntToPtr(
|
||||
comp_ctx->builder, offset_to_mem_base, INT8_PTR_TYPE_GS,
|
||||
"maddr_shared_heap_segue"))) {
|
||||
aot_set_last_error("llvm build int to ptr failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
LLVMAddIncoming(maddr_phi, &maddr, &app_addr_in_shared_heap, 1);
|
||||
|
||||
if (!LLVMBuildBr(comp_ctx->builder, block_maddr_phi)) {
|
||||
aot_set_last_error("llvm build br failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, app_addr_in_linear_mem);
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (comp_ctx->enable_bound_check
|
||||
&& !(is_local_of_aot_value
|
||||
|
@ -449,21 +805,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (is_target_64bit) {
|
||||
BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp, "cmp");
|
||||
}
|
||||
else {
|
||||
if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
|
||||
/* Check integer overflow has been checked above */
|
||||
BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp, "cmp");
|
||||
}
|
||||
else {
|
||||
/* Check integer overflow */
|
||||
BUILD_ICMP(LLVMIntULT, offset1, addr, cmp1, "cmp1");
|
||||
BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp2, "cmp2");
|
||||
BUILD_OP(Or, cmp1, cmp2, cmp, "cmp");
|
||||
}
|
||||
}
|
||||
BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp, "cmp");
|
||||
|
||||
/* Add basic blocks */
|
||||
ADD_BASIC_BLOCK(check_succ, "check_succ");
|
||||
|
@ -509,17 +851,20 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
}
|
||||
|
||||
if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (comp_ctx->enable_shared_heap
|
||||
|| comp_ctx->enable_shared_chain /* TODO: && mem_idx == 0 */) {
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMAddIncoming(maddr_phi, &maddr, &block_curr, 1);
|
||||
if (!LLVMBuildBr(comp_ctx->builder, block_maddr_phi)) {
|
||||
aot_set_last_error("llvm build br failed");
|
||||
goto fail;
|
||||
}
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_maddr_phi);
|
||||
SET_BUILD_POS(block_maddr_phi);
|
||||
return maddr_phi;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return maddr;
|
||||
fail:
|
||||
return NULL;
|
||||
|
@ -544,15 +889,6 @@ fail:
|
|||
LLVMSetAlignment(value, known_align); \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_TRUNC(value, data_type) \
|
||||
do { \
|
||||
if (!(value = LLVMBuildTrunc(comp_ctx->builder, value, data_type, \
|
||||
"val_trunc"))) { \
|
||||
aot_set_last_error("llvm build trunc failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_STORE() \
|
||||
do { \
|
||||
LLVMValueRef res; \
|
||||
|
@ -1150,16 +1486,23 @@ LLVMValueRef
|
|||
check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMValueRef offset, LLVMValueRef bytes)
|
||||
{
|
||||
LLVMValueRef maddr, max_addr, cmp;
|
||||
LLVMValueRef mem_base_addr, maddr_phi = NULL;
|
||||
LLVMValueRef maddr, max_addr, cmp, cmp1;
|
||||
LLVMValueRef mem_base_addr;
|
||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMBasicBlockRef check_succ, block_maddr_phi = NULL;
|
||||
LLVMBasicBlockRef check_succ;
|
||||
LLVMValueRef mem_size;
|
||||
bool is_target_64bit;
|
||||
#if WASM_ENABLE_MEMORY64 == 0
|
||||
bool is_memory64 = false;
|
||||
#else
|
||||
bool is_memory64 = IS_MEMORY64;
|
||||
#endif
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
LLVMValueRef maddr_phi = NULL;
|
||||
LLVMBasicBlockRef block_maddr_phi = NULL;
|
||||
#endif
|
||||
|
||||
is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false;
|
||||
|
||||
/* Get memory base address and memory data size */
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
|
@ -1221,111 +1564,71 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
ADD_BASIC_BLOCK(check_succ, "check_succ");
|
||||
LLVMMoveBasicBlockAfter(check_succ, block_curr);
|
||||
|
||||
offset =
|
||||
LLVMBuildZExt(comp_ctx->builder, offset, I64_TYPE, "extend_offset");
|
||||
bytes = LLVMBuildZExt(comp_ctx->builder, bytes, I64_TYPE, "extend_len");
|
||||
if (!offset || !bytes) {
|
||||
aot_set_last_error("llvm build zext failed.");
|
||||
goto fail;
|
||||
/* Same logic with aot_check_memory_overflow, offset and bytes are 32/64
|
||||
* bits on 32/64 bits platform */
|
||||
if (is_target_64bit) {
|
||||
offset =
|
||||
LLVMBuildZExt(comp_ctx->builder, offset, I64_TYPE, "extend_offset");
|
||||
bytes = LLVMBuildZExt(comp_ctx->builder, bytes, I64_TYPE, "extend_len");
|
||||
if (!offset || !bytes) {
|
||||
aot_set_last_error("llvm build zext failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
BUILD_OP(Add, offset, bytes, max_addr, "max_addr");
|
||||
|
||||
if (is_memory64 && comp_ctx->enable_bound_check) {
|
||||
/* Check whether integer overflow occurs in offset + addr */
|
||||
/* Check overflow when it's memory64 or it's on 32 bits platform */
|
||||
if (is_memory64 || !is_target_64bit) {
|
||||
/* Check whether integer overflow occurs in offset + bytes */
|
||||
LLVMBasicBlockRef check_integer_overflow_end;
|
||||
ADD_BASIC_BLOCK(check_integer_overflow_end,
|
||||
"check_integer_overflow_end");
|
||||
LLVMMoveBasicBlockAfter(check_integer_overflow_end, block_curr);
|
||||
|
||||
/* offset + bytes can overflow yet is valid(for example, 0xffffffff, 1),
|
||||
* allow it to be 0(either 0, 0 or overflow and valid) */
|
||||
BUILD_ICMP(LLVMIntULT, max_addr, offset, cmp, "cmp");
|
||||
BUILD_ICMP(LLVMIntNE, max_addr, is_target_64bit ? I64_ZERO : I32_ZERO,
|
||||
cmp1, "cmp1");
|
||||
BUILD_OP(And, cmp, cmp1, cmp, "overflow");
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp,
|
||||
check_integer_overflow_end)) {
|
||||
goto fail;
|
||||
}
|
||||
SET_BUILD_POS(check_integer_overflow_end);
|
||||
block_curr = check_integer_overflow_end;
|
||||
}
|
||||
|
||||
if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
|
||||
LLVMBasicBlockRef app_addr_in_shared_heap, app_addr_in_linear_mem;
|
||||
LLVMValueRef shared_heap_start_off, shared_heap_check_bound;
|
||||
LLVMValueRef max_offset, cmp1, cmp2, is_in_shared_heap;
|
||||
|
||||
/* Add basic blocks */
|
||||
ADD_BASIC_BLOCK(app_addr_in_shared_heap, "app_addr_in_shared_heap");
|
||||
ADD_BASIC_BLOCK(app_addr_in_linear_mem, "app_addr_in_linear_mem");
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (comp_ctx->enable_shared_heap
|
||||
|| comp_ctx->enable_shared_chain /* TODO: && mem_idx == 0 */) {
|
||||
ADD_BASIC_BLOCK(block_maddr_phi, "maddr_phi");
|
||||
|
||||
LLVMMoveBasicBlockAfter(app_addr_in_shared_heap, block_curr);
|
||||
LLVMMoveBasicBlockAfter(app_addr_in_linear_mem,
|
||||
app_addr_in_shared_heap);
|
||||
LLVMMoveBasicBlockAfter(block_maddr_phi, check_succ);
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_maddr_phi);
|
||||
SET_BUILD_POS(block_maddr_phi);
|
||||
if (!(maddr_phi = LLVMBuildPhi(comp_ctx->builder, INT8_PTR_TYPE,
|
||||
"maddr_phi"))) {
|
||||
aot_set_last_error("llvm build phi failed");
|
||||
goto fail;
|
||||
}
|
||||
SET_BUILD_POS(block_curr);
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
|
||||
|
||||
shared_heap_start_off = func_ctx->shared_heap_start_off;
|
||||
if (comp_ctx->pointer_size == sizeof(uint32)) {
|
||||
if (!(shared_heap_start_off =
|
||||
LLVMBuildZExt(comp_ctx->builder, shared_heap_start_off,
|
||||
I64_TYPE, "shared_heap_start_off_u64"))) {
|
||||
aot_set_last_error("llvm build zext failed");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
shared_heap_check_bound =
|
||||
is_memory64 ? I64_CONST(UINT64_MAX) : I64_CONST(UINT32_MAX);
|
||||
CHECK_LLVM_CONST(shared_heap_check_bound);
|
||||
|
||||
/* Check whether the bytes to access are in shared heap */
|
||||
if (!comp_ctx->enable_bound_check) {
|
||||
/* Use IntUGT but not IntUGE to compare, same as the check
|
||||
in aot_check_memory_overflow */
|
||||
BUILD_ICMP(LLVMIntUGT, offset, func_ctx->shared_heap_start_off,
|
||||
is_in_shared_heap, "is_in_shared_heap");
|
||||
}
|
||||
else {
|
||||
BUILD_ICMP(LLVMIntUGT, offset, func_ctx->shared_heap_start_off,
|
||||
cmp1, "cmp1");
|
||||
BUILD_OP(Add, max_addr, I64_NEG_ONE, max_offset, "max_offset");
|
||||
BUILD_ICMP(LLVMIntULE, max_offset, shared_heap_check_bound, cmp2,
|
||||
"cmp2");
|
||||
BUILD_OP(And, cmp1, cmp2, is_in_shared_heap, "is_in_shared_heap");
|
||||
}
|
||||
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, is_in_shared_heap,
|
||||
app_addr_in_shared_heap, app_addr_in_linear_mem)) {
|
||||
aot_set_last_error("llvm build cond br failed");
|
||||
if (!aot_check_bulk_memory_shared_heap_memory_overflow(
|
||||
comp_ctx, func_ctx, block_curr, block_maddr_phi, check_succ,
|
||||
maddr_phi, offset, max_addr, bytes, is_memory64,
|
||||
is_target_64bit)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, app_addr_in_shared_heap);
|
||||
|
||||
/* Get native address inside shared heap */
|
||||
if (!(maddr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
||||
func_ctx->shared_heap_base_addr_adj,
|
||||
&offset, 1, "maddr_shared_heap"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed");
|
||||
goto fail;
|
||||
}
|
||||
LLVMAddIncoming(maddr_phi, &maddr, &app_addr_in_shared_heap, 1);
|
||||
|
||||
if (!LLVMBuildBr(comp_ctx->builder, block_maddr_phi)) {
|
||||
aot_set_last_error("llvm build br failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, app_addr_in_linear_mem);
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* mem_size is always 64-bit, extend max_addr on 32 bits platform */
|
||||
if (!is_target_64bit
|
||||
&& !(max_addr = LLVMBuildZExt(comp_ctx->builder, max_addr, I64_TYPE,
|
||||
"extend_max_addr"))) {
|
||||
aot_set_last_error("llvm build zext failed.");
|
||||
goto fail;
|
||||
}
|
||||
BUILD_ICMP(LLVMIntUGT, max_addr, mem_size, cmp, "cmp_max_mem_addr");
|
||||
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
|
@ -1341,7 +1644,9 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (comp_ctx->enable_shared_heap
|
||||
|| comp_ctx->enable_shared_chain /* TODO: && mem_idx == 0 */) {
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMAddIncoming(maddr_phi, &maddr, &block_curr, 1);
|
||||
if (!LLVMBuildBr(comp_ctx->builder, block_maddr_phi)) {
|
||||
|
@ -1352,6 +1657,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
return maddr_phi;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return maddr;
|
||||
fail:
|
||||
return NULL;
|
||||
|
|
|
@ -1517,73 +1517,154 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
return true;
|
||||
}
|
||||
|
||||
#define BUILD_IS_NOT_NULL(value, res, name) \
|
||||
do { \
|
||||
if (!(res = LLVMBuildIsNotNull(comp_ctx->builder, value, name))) { \
|
||||
aot_set_last_error("llvm build is not null failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define get_module_extra_field_offset(field) \
|
||||
do { \
|
||||
offset_u32 = get_module_inst_extra_offset(comp_ctx); \
|
||||
if (comp_ctx->is_jit_mode) \
|
||||
offset_u32 += offsetof(WASMModuleInstanceExtra, field); \
|
||||
else \
|
||||
offset_u32 += offsetof(AOTModuleInstanceExtra, field); \
|
||||
} while (0)
|
||||
|
||||
#define LOAD_MODULE_EXTRA_FIELD_AND_ALLOCA(field, type) \
|
||||
do { \
|
||||
get_module_extra_field_offset(field); \
|
||||
offset = I32_CONST(offset_u32); \
|
||||
CHECK_LLVM_CONST(offset); \
|
||||
if (!(field_p = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, \
|
||||
func_ctx->aot_inst, &offset, 1, \
|
||||
#field "_p"))) { \
|
||||
aot_set_last_error("llvm build inbounds gep failed"); \
|
||||
goto fail; \
|
||||
} \
|
||||
if (!(load_val = \
|
||||
LLVMBuildLoad2(comp_ctx->builder, type, field_p, #field))) { \
|
||||
aot_set_last_error("llvm build load failed"); \
|
||||
goto fail; \
|
||||
} \
|
||||
if (!(func_ctx->field = \
|
||||
LLVMBuildAlloca(comp_ctx->builder, type, #field))) { \
|
||||
aot_set_last_error("llvm build alloca failed"); \
|
||||
goto fail; \
|
||||
} \
|
||||
if (!LLVMBuildStore(comp_ctx->builder, load_val, func_ctx->field)) { \
|
||||
aot_set_last_error("llvm build store failed"); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static bool
|
||||
create_shared_heap_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef offset, base_addr_p, start_off_p, cmp;
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
LLVMValueRef offset, field_p, load_val, shared_heap_head_p,
|
||||
shared_heap_head, cmp, field_p_or_default, shared_heap_head_start_off,
|
||||
shared_heap_head_start_off_minus_one;
|
||||
LLVMTypeRef shared_heap_offset_type;
|
||||
uint32 offset_u32;
|
||||
|
||||
/* Load aot_inst->e->shared_heap_base_addr_adj */
|
||||
offset_u32 = get_module_inst_extra_offset(comp_ctx);
|
||||
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (comp_ctx->is_jit_mode)
|
||||
offset_u32 +=
|
||||
offsetof(WASMModuleInstanceExtra, shared_heap_base_addr_adj);
|
||||
else
|
||||
#if WASM_ENABLE_MEMORY64 == 0
|
||||
bool is_memory64 = false;
|
||||
#else
|
||||
bool is_memory64 = IS_MEMORY64;
|
||||
#endif
|
||||
offset_u32 +=
|
||||
offsetof(AOTModuleInstanceExtra, shared_heap_base_addr_adj);
|
||||
|
||||
shared_heap_offset_type =
|
||||
comp_ctx->pointer_size == sizeof(uint64) ? I64_TYPE : I32_TYPE;
|
||||
|
||||
/* shared_heap_base_addr_adj, shared_heap_start_off, and
|
||||
* shared_heap_end_off can be updated later, use local variable to
|
||||
* represent them */
|
||||
LOAD_MODULE_EXTRA_FIELD_AND_ALLOCA(shared_heap_base_addr_adj,
|
||||
INT8_PTR_TYPE);
|
||||
LOAD_MODULE_EXTRA_FIELD_AND_ALLOCA(shared_heap_start_off,
|
||||
shared_heap_offset_type);
|
||||
LOAD_MODULE_EXTRA_FIELD_AND_ALLOCA(shared_heap_end_off,
|
||||
shared_heap_offset_type);
|
||||
|
||||
/* Shared Heap head start off won't be updated, no need to alloca */
|
||||
get_module_extra_field_offset(shared_heap);
|
||||
offset = I32_CONST(offset_u32);
|
||||
CHECK_LLVM_CONST(offset);
|
||||
|
||||
if (!(base_addr_p = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
||||
func_ctx->aot_inst, &offset, 1,
|
||||
"shared_heap_base_addr_adj_p"))) {
|
||||
if (!(shared_heap_head_p = LLVMBuildInBoundsGEP2(
|
||||
comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
|
||||
"shared_heap_head_p"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed");
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
if (!(func_ctx->shared_heap_base_addr_adj =
|
||||
LLVMBuildLoad2(comp_ctx->builder, INT8_PTR_TYPE, base_addr_p,
|
||||
"shared_heap_base_addr_adj"))) {
|
||||
if (!(shared_heap_head =
|
||||
LLVMBuildLoad2(comp_ctx->builder, INT8_PTR_TYPE,
|
||||
shared_heap_head_p, "shared_heap_head"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
BUILD_IS_NOT_NULL(shared_heap_head, cmp, "has_shared_heap");
|
||||
|
||||
/* Load aot_inst->e->shared_heap_start_off */
|
||||
offset_u32 = get_module_inst_extra_offset(comp_ctx);
|
||||
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_SHARED_HEAP != 0
|
||||
if (comp_ctx->is_jit_mode)
|
||||
offset_u32 += offsetof(WASMModuleInstanceExtra, shared_heap_start_off);
|
||||
else
|
||||
#endif
|
||||
offset_u32 += offsetof(AOTModuleInstanceExtra, shared_heap_start_off);
|
||||
if (is_memory64) {
|
||||
offset_u32 = offsetof(WASMSharedHeap, start_off_mem64);
|
||||
}
|
||||
else {
|
||||
offset_u32 = offsetof(WASMSharedHeap, start_off_mem32);
|
||||
}
|
||||
offset = I32_CONST(offset_u32);
|
||||
CHECK_LLVM_CONST(offset);
|
||||
|
||||
if (!(start_off_p = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
||||
func_ctx->aot_inst, &offset, 1,
|
||||
"shared_heap_start_off_p"))) {
|
||||
if (!(field_p = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
||||
shared_heap_head, &offset, 1,
|
||||
"head_start_off_p"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed");
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
if (!(func_ctx->shared_heap_start_off = LLVMBuildLoad2(
|
||||
comp_ctx->builder,
|
||||
comp_ctx->pointer_size == sizeof(uint64) ? I64_TYPE : I32_TYPE,
|
||||
start_off_p, "shared_heap_start_off"))) {
|
||||
|
||||
/* Select a valid shared heap head ptr or safe alloca ptr stores
|
||||
* shared_heap_start_off(UINT32_MAX/UINT64_MAX) */
|
||||
if (!(field_p_or_default = LLVMBuildSelect(comp_ctx->builder, cmp, field_p,
|
||||
func_ctx->shared_heap_start_off,
|
||||
"ptr_or_default"))) {
|
||||
aot_set_last_error("llvm build select failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(shared_heap_head_start_off = LLVMBuildLoad2(
|
||||
comp_ctx->builder, shared_heap_offset_type, field_p_or_default,
|
||||
"shared_heap_head_start_off"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
if (!(shared_heap_head_start_off_minus_one = LLVMBuildAdd(
|
||||
comp_ctx->builder, shared_heap_head_start_off,
|
||||
comp_ctx->pointer_size == sizeof(uint64) ? I64_NEG_ONE
|
||||
: I32_NEG_ONE,
|
||||
"head_start_off_minus_one"))) {
|
||||
aot_set_last_error("llvm build load failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(cmp = LLVMBuildIsNotNull(comp_ctx->builder,
|
||||
func_ctx->shared_heap_base_addr_adj,
|
||||
"has_shared_heap"))) {
|
||||
aot_set_last_error("llvm build is not null failed");
|
||||
return false;
|
||||
/* if there is attached shared heap(s), the value will be valid start_off-1,
|
||||
* otherwise it will be UINT32_MAX/UINT64_MAX, so during the bounds checks,
|
||||
* when has attached shared heap:
|
||||
* offset > start_off - 1 => offset >= start_off
|
||||
* when no attached shared heap:
|
||||
* offset > UINT32_MAX/UINT64_MAX is always false
|
||||
* */
|
||||
if (!(func_ctx->shared_heap_head_start_off = LLVMBuildSelect(
|
||||
comp_ctx->builder, cmp, shared_heap_head_start_off_minus_one,
|
||||
shared_heap_head_start_off, "head_start_off"))) {
|
||||
aot_set_last_error("llvm build select failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
#else /* else of WASM_ENABLE_SHARED_HEAP != 0 */
|
||||
return true;
|
||||
#endif /* end of WASM_ENABLE_SHARED_HEAP != 0 */
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1877,7 +1958,7 @@ aot_create_func_context(const AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
}
|
||||
|
||||
/* Load shared heap, shared heap start off mem32 or mem64 */
|
||||
if (comp_ctx->enable_shared_heap
|
||||
if ((comp_ctx->enable_shared_heap || comp_ctx->enable_shared_chain)
|
||||
&& !create_shared_heap_info(comp_ctx, func_ctx)) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -2703,6 +2784,12 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
|
|||
if (option->enable_shared_heap)
|
||||
comp_ctx->enable_shared_heap = true;
|
||||
|
||||
if (option->enable_shared_chain)
|
||||
comp_ctx->enable_shared_chain = true;
|
||||
|
||||
if (option->enable_extended_const)
|
||||
comp_ctx->enable_extended_const = true;
|
||||
|
||||
comp_ctx->opt_level = option->opt_level;
|
||||
comp_ctx->size_level = option->size_level;
|
||||
|
||||
|
@ -3204,6 +3291,21 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
|
|||
|
||||
#if WASM_ENABLE_WAMR_COMPILER != 0
|
||||
WASMModule *wasm_module = (WASMModule *)comp_data->wasm_module;
|
||||
bool is_memory64 = false;
|
||||
|
||||
/* TODO: multi-memories for now assuming the memory64 flag of a memory is
|
||||
* consistent across multi-memories */
|
||||
if (wasm_module->import_memory_count > 0)
|
||||
is_memory64 = !!(wasm_module->import_memories[0].u.memory.mem_type.flags
|
||||
& MEMORY64_FLAG);
|
||||
else if (wasm_module->memory_count > 0)
|
||||
is_memory64 = !!(wasm_module->memories[0].flags & MEMORY64_FLAG);
|
||||
|
||||
if (!(option->bounds_checks == 1 || option->bounds_checks == 0)
|
||||
&& is_memory64) {
|
||||
/* For memory64, the boundary check default value is true */
|
||||
comp_ctx->enable_bound_check = true;
|
||||
}
|
||||
|
||||
/* Return error if SIMD is disabled by command line but SIMD instructions
|
||||
* are used */
|
||||
|
@ -3984,7 +4086,7 @@ aot_get_func_from_table(const AOTCompContext *comp_ctx, LLVMValueRef base,
|
|||
|
||||
if (!(func =
|
||||
LLVMBuildBitCast(comp_ctx->builder, func, func_type, "func"))) {
|
||||
aot_set_last_error("cast function fialed.");
|
||||
aot_set_last_error("cast function failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -4053,7 +4155,7 @@ aot_load_const_from_table(AOTCompContext *comp_ctx, LLVMValueRef base,
|
|||
|
||||
if (!(const_addr = LLVMBuildBitCast(comp_ctx->builder, const_addr,
|
||||
const_ptr_type, "const_addr"))) {
|
||||
aot_set_last_error("cast const fialed.");
|
||||
aot_set_last_error("cast const failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -254,8 +254,12 @@ typedef struct AOTFuncContext {
|
|||
bool mem_space_unchanged;
|
||||
AOTCheckedAddrList checked_addr_list;
|
||||
|
||||
/* The last accessed shared heap info */
|
||||
LLVMValueRef shared_heap_base_addr_adj;
|
||||
LLVMValueRef shared_heap_start_off;
|
||||
LLVMValueRef shared_heap_end_off;
|
||||
/* The start offset of the head of shared heap chain */
|
||||
LLVMValueRef shared_heap_head_start_off;
|
||||
|
||||
LLVMBasicBlockRef got_exception_block;
|
||||
LLVMBasicBlockRef func_return_block;
|
||||
|
@ -457,6 +461,9 @@ typedef struct AOTCompContext {
|
|||
/* Enable LLVM PGO (Profile-Guided Optimization) */
|
||||
bool enable_llvm_pgo;
|
||||
|
||||
/* Enable extended constant expression */
|
||||
bool enable_extended_const;
|
||||
|
||||
/* Treat unknown import function as wasm-c-api import function
|
||||
and allow to directly invoke it from AOT/JIT code */
|
||||
bool quick_invoke_c_api_import;
|
||||
|
@ -486,6 +493,7 @@ typedef struct AOTCompContext {
|
|||
bool enable_gc;
|
||||
|
||||
bool enable_shared_heap;
|
||||
bool enable_shared_chain;
|
||||
|
||||
uint32 opt_level;
|
||||
uint32 size_level;
|
||||
|
|
|
@ -121,7 +121,8 @@ wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 seg_idx,
|
|||
+ dst_offset * sizeof(table_elem_type_t));
|
||||
init_values = tbl_seg_init_values + src_offset;
|
||||
for (i = 0; i < len; i++) {
|
||||
addr[i] = (table_elem_type_t)(uintptr_t)init_values[+i].u.ref_index;
|
||||
addr[i] =
|
||||
(table_elem_type_t)(uintptr_t)init_values[+i].u.unary.v.ref_index;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -68,6 +68,7 @@ typedef struct AOTCompOption {
|
|||
bool enable_ref_types;
|
||||
bool enable_gc;
|
||||
bool enable_aux_stack_check;
|
||||
bool enable_extended_const;
|
||||
AOTStackFrameType aux_stack_frame_type;
|
||||
AOTCallStackFeatures call_stack_features;
|
||||
bool enable_perf_profiling;
|
||||
|
@ -79,6 +80,7 @@ typedef struct AOTCompOption {
|
|||
bool enable_stack_estimation;
|
||||
bool quick_invoke_c_api_import;
|
||||
bool enable_shared_heap;
|
||||
bool enable_shared_chain;
|
||||
char *use_prof_file;
|
||||
uint32_t opt_level;
|
||||
uint32_t size_level;
|
||||
|
|
|
@ -139,8 +139,6 @@ typedef struct wasm_frame_t {
|
|||
uint32_t *lp;
|
||||
} WASMCApiFrame;
|
||||
|
||||
typedef WASMCApiFrame wasm_frame_t;
|
||||
|
||||
/* WASM section */
|
||||
typedef struct wasm_section_t {
|
||||
struct wasm_section_t *next;
|
||||
|
@ -351,6 +349,7 @@ typedef enum {
|
|||
|
||||
typedef struct SharedHeapInitArgs {
|
||||
uint32_t size;
|
||||
void *pre_allocated_addr;
|
||||
} SharedHeapInitArgs;
|
||||
|
||||
/**
|
||||
|
@ -904,7 +903,7 @@ wasm_runtime_destroy_exec_env(wasm_exec_env_t exec_env);
|
|||
* @return number of copied frames
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN uint32_t
|
||||
wasm_copy_callstack(const wasm_exec_env_t exec_env, wasm_frame_t *buffer,
|
||||
wasm_copy_callstack(const wasm_exec_env_t exec_env, WASMCApiFrame *buffer,
|
||||
const uint32_t length, const uint32_t skip_n,
|
||||
char *error_buf, uint32_t error_buf_size);
|
||||
|
||||
|
@ -1821,6 +1820,20 @@ WASM_RUNTIME_API_EXTERN void
|
|||
wasm_runtime_set_native_stack_boundary(wasm_exec_env_t exec_env,
|
||||
uint8_t *native_stack_boundary);
|
||||
|
||||
/**
|
||||
* Set the instruction count limit to the execution environment.
|
||||
* By default the instruction count limit is -1, which means no limit.
|
||||
* However, if the instruction count limit is set to a positive value,
|
||||
* the execution will be terminated when the instruction count reaches
|
||||
* the limit.
|
||||
*
|
||||
* @param exec_env the execution environment
|
||||
* @param instruction_count the instruction count limit
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_instruction_count_limit(wasm_exec_env_t exec_env,
|
||||
int instruction_count);
|
||||
|
||||
/**
|
||||
* Dump runtime memory consumption, including:
|
||||
* Exec env memory consumption
|
||||
|
@ -2302,7 +2315,37 @@ WASM_RUNTIME_API_EXTERN wasm_shared_heap_t
|
|||
wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args);
|
||||
|
||||
/**
|
||||
* Attach a shared heap to a module instance
|
||||
* This function links two shared heap(lists), `head` and `body` in to a single
|
||||
* shared heap list, where `head` becomes the new shared heap list head. The
|
||||
* shared heap list remains one continuous shared heap in wasm app's point of
|
||||
* view. At most one shared heap in shared heap list can be dynamically
|
||||
* allocated, the rest have to be the pre-allocated shared heap. *
|
||||
*
|
||||
* @param head The head of the shared heap chain.
|
||||
* @param body The body of the shared heap chain to be appended.
|
||||
* @return The new head of the shared heap chain. NULL if failed.
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN wasm_shared_heap_t
|
||||
wasm_runtime_chain_shared_heaps(wasm_shared_heap_t head,
|
||||
wasm_shared_heap_t body);
|
||||
|
||||
/**
|
||||
* This function unchains the shared heaps from the given head. If
|
||||
* `entire_chain` is true, it will unchain the entire chain of shared heaps.
|
||||
* Otherwise, it will unchain only the first shared heap in the chain.
|
||||
*
|
||||
* @param head The head of the shared heap chain.
|
||||
* @param entire_chain A boolean flag indicating whether to unchain the entire
|
||||
* chain.
|
||||
* @return The new head of the shared heap chain. Or the last shared heap in the
|
||||
* chain if `entire_chain` is true.
|
||||
*/
|
||||
wasm_shared_heap_t
|
||||
wasm_runtime_unchain_shared_heaps(wasm_shared_heap_t head, bool entire_chain);
|
||||
|
||||
/**
|
||||
* Attach a shared heap, it can be the head of shared heap chain, in that case,
|
||||
* attach the shared heap chain, to a module instance
|
||||
*
|
||||
* @param module_inst the module instance
|
||||
* @param shared_heap the shared heap
|
||||
|
@ -2321,7 +2364,8 @@ WASM_RUNTIME_API_EXTERN void
|
|||
wasm_runtime_detach_shared_heap(wasm_module_inst_t module_inst);
|
||||
|
||||
/**
|
||||
* Allocate memory from a shared heap
|
||||
* Allocate memory from a shared heap, or the non-preallocated shared heap from
|
||||
* the shared heap chain
|
||||
*
|
||||
* @param module_inst the module instance
|
||||
* @param size required memory size
|
||||
|
@ -2338,7 +2382,8 @@ wasm_runtime_shared_heap_malloc(wasm_module_inst_t module_inst, uint64_t size,
|
|||
void **p_native_addr);
|
||||
|
||||
/**
|
||||
* Free the memory allocated from shared heap
|
||||
* Free the memory allocated from shared heap, or the non-preallocated shared
|
||||
* heap from the shared heap chain
|
||||
*
|
||||
* @param module_inst the module instance
|
||||
* @param ptr the offset in wasm app
|
||||
|
|
|
@ -135,6 +135,12 @@ typedef void *table_elem_type_t;
|
|||
#define INIT_EXPR_TYPE_F64_CONST 0x44
|
||||
#define INIT_EXPR_TYPE_V128_CONST 0xFD
|
||||
#define INIT_EXPR_TYPE_GET_GLOBAL 0x23
|
||||
#define INIT_EXPR_TYPE_I32_ADD 0x6A
|
||||
#define INIT_EXPR_TYPE_I32_SUB 0x6B
|
||||
#define INIT_EXPR_TYPE_I32_MUL 0x6C
|
||||
#define INIT_EXPR_TYPE_I64_ADD 0x7C
|
||||
#define INIT_EXPR_TYPE_I64_SUB 0x7D
|
||||
#define INIT_EXPR_TYPE_I64_MUL 0x7E
|
||||
#define INIT_EXPR_TYPE_REFNULL_CONST 0xD0
|
||||
#define INIT_EXPR_TYPE_FUNCREF_CONST 0xD2
|
||||
#define INIT_EXPR_TYPE_STRUCT_NEW 0xD3
|
||||
|
@ -277,9 +283,41 @@ typedef struct InitializerExpression {
|
|||
/* type of INIT_EXPR_TYPE_XXX, which is an instruction of
|
||||
constant expression */
|
||||
uint8 init_expr_type;
|
||||
WASMValue u;
|
||||
union {
|
||||
struct {
|
||||
WASMValue v;
|
||||
} unary;
|
||||
struct {
|
||||
struct InitializerExpression *l_expr;
|
||||
struct InitializerExpression *r_expr;
|
||||
} binary;
|
||||
} u;
|
||||
} InitializerExpression;
|
||||
|
||||
static inline bool
|
||||
is_expr_binary_op(uint8 flag)
|
||||
{
|
||||
return flag == INIT_EXPR_TYPE_I32_ADD || flag == INIT_EXPR_TYPE_I32_SUB
|
||||
|| flag == INIT_EXPR_TYPE_I32_MUL || flag == INIT_EXPR_TYPE_I64_ADD
|
||||
|| flag == INIT_EXPR_TYPE_I64_SUB || flag == INIT_EXPR_TYPE_I64_MUL;
|
||||
}
|
||||
|
||||
/* check if table or data offset is valid for i32 offset */
|
||||
static inline bool
|
||||
is_valid_i32_offset(uint8 flag)
|
||||
{
|
||||
return flag == INIT_EXPR_TYPE_I32_CONST || flag == INIT_EXPR_TYPE_I32_ADD
|
||||
|| flag == INIT_EXPR_TYPE_I32_SUB || flag == INIT_EXPR_TYPE_I32_MUL;
|
||||
}
|
||||
|
||||
/* check if table or data offset is valid for i64 offset */
|
||||
static inline bool
|
||||
is_valid_i64_offset(uint8 flag)
|
||||
{
|
||||
return flag == INIT_EXPR_TYPE_I64_CONST || flag == INIT_EXPR_TYPE_I64_ADD
|
||||
|| flag == INIT_EXPR_TYPE_I64_SUB || flag == INIT_EXPR_TYPE_I64_MUL;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/**
|
||||
* Reference type of (ref null ht) or (ref ht),
|
||||
|
@ -1243,7 +1281,7 @@ wasm_value_type_size_internal(uint8 value_type, uint8 pointer_size)
|
|||
return sizeof(int16);
|
||||
#endif
|
||||
else {
|
||||
bh_assert(0);
|
||||
bh_assert(0 && "Unknown value type. It should be handled ahead.");
|
||||
}
|
||||
#if WASM_ENABLE_GC == 0
|
||||
(void)pointer_size;
|
||||
|
|
|
@ -46,28 +46,6 @@ typedef float64 CellType_F64;
|
|||
#define get_linear_mem_size() GET_LINEAR_MEMORY_SIZE(memory)
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
/* Only enable shared heap for the default memory */
|
||||
#define is_default_memory (memidx == 0)
|
||||
#else
|
||||
#define is_default_memory true
|
||||
#endif
|
||||
#define app_addr_in_shared_heap(app_addr, bytes) \
|
||||
(shared_heap && is_default_memory && (app_addr) >= shared_heap_start_off \
|
||||
&& (app_addr) <= shared_heap_end_off - bytes + 1)
|
||||
|
||||
#define shared_heap_addr_app_to_native(app_addr, native_addr) \
|
||||
native_addr = shared_heap_base_addr + ((app_addr)-shared_heap_start_off)
|
||||
|
||||
#define CHECK_SHARED_HEAP_OVERFLOW(app_addr, bytes, native_addr) \
|
||||
if (app_addr_in_shared_heap(app_addr, bytes)) \
|
||||
shared_heap_addr_app_to_native(app_addr, native_addr); \
|
||||
else
|
||||
#else
|
||||
#define CHECK_SHARED_HEAP_OVERFLOW(app_addr, bytes, native_addr)
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MEMORY64 == 0
|
||||
|
||||
#if (!defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|
@ -1516,10 +1494,13 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
|
|||
} \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
} \
|
||||
CHECK_INSTRUCTION_LIMIT(); \
|
||||
goto *handle_table[*frame_ip++]; \
|
||||
} while (0)
|
||||
#else
|
||||
#define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH()
|
||||
#define HANDLE_OP_END() \
|
||||
CHECK_INSTRUCTION_LIMIT(); \
|
||||
FETCH_OPCODE_AND_DISPATCH()
|
||||
#endif
|
||||
|
||||
#else /* else of WASM_ENABLE_LABELS_AS_VALUES */
|
||||
|
@ -1542,9 +1523,12 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
|
|||
} \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
} \
|
||||
CHECK_INSTRUCTION_LIMIT(); \
|
||||
continue;
|
||||
#else
|
||||
#define HANDLE_OP_END() continue
|
||||
#define HANDLE_OP_END() \
|
||||
CHECK_INSTRUCTION_LIMIT(); \
|
||||
continue;
|
||||
#endif
|
||||
|
||||
#endif /* end of WASM_ENABLE_LABELS_AS_VALUES */
|
||||
|
@ -1562,6 +1546,18 @@ get_global_addr(uint8 *global_data, WASMGlobalInstance *global)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_INSTRUCTION_METERING != 0
|
||||
#define CHECK_INSTRUCTION_LIMIT() \
|
||||
if (instructions_left == 0) { \
|
||||
wasm_set_exception(module, "instruction limit exceeded"); \
|
||||
goto got_exception; \
|
||||
} \
|
||||
else if (instructions_left > 0) \
|
||||
instructions_left--;
|
||||
#else
|
||||
#define CHECK_INSTRUCTION_LIMIT() (void)0
|
||||
#endif
|
||||
|
||||
static void
|
||||
wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
WASMExecEnv *exec_env,
|
||||
|
@ -1605,6 +1601,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
uint32 local_idx, local_offset, global_idx;
|
||||
uint8 local_type, *global_addr;
|
||||
uint32 cache_index, type_index, param_cell_num, cell_num;
|
||||
|
||||
#if WASM_ENABLE_INSTRUCTION_METERING != 0
|
||||
int instructions_left = -1;
|
||||
if (exec_env) {
|
||||
instructions_left = exec_env->instructions_to_execute;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_EXCE_HANDLING != 0
|
||||
int32_t exception_tag_index;
|
||||
#endif
|
||||
|
@ -1644,22 +1648,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (memory)
|
||||
is_memory64 = memory->is_memory64;
|
||||
#endif
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
WASMSharedHeap *shared_heap = module->e->shared_heap;
|
||||
uint8 *shared_heap_base_addr = shared_heap ? shared_heap->base_addr : NULL;
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
uint64 shared_heap_start_off =
|
||||
shared_heap ? (is_memory64 ? shared_heap->start_off_mem64
|
||||
: shared_heap->start_off_mem32)
|
||||
: 0;
|
||||
uint64 shared_heap_end_off =
|
||||
shared_heap ? (is_memory64 ? UINT64_MAX : UINT32_MAX) : 0;
|
||||
#else
|
||||
uint64 shared_heap_start_off =
|
||||
shared_heap ? shared_heap->start_off_mem32 : 0;
|
||||
uint64 shared_heap_end_off = shared_heap ? UINT32_MAX : 0;
|
||||
#endif
|
||||
#endif /* end of WASM_ENABLE_SHARED_HEAP != 0 */
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
uint32 memidx = 0;
|
||||
uint32 memidx_cached = (uint32)-1;
|
||||
|
@ -4062,7 +4050,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
case WASM_OP_STRING_ENCODE_LOSSY_UTF8_ARRAY:
|
||||
case WASM_OP_STRING_ENCODE_WTF8_ARRAY:
|
||||
{
|
||||
uint32 start, array_len, count;
|
||||
uint32 start, array_len;
|
||||
int32 bytes_written;
|
||||
EncodingFlag flag = WTF8;
|
||||
WASMArrayType *array_type;
|
||||
|
@ -5970,12 +5958,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
|| init_values[i].init_expr_type
|
||||
== INIT_EXPR_TYPE_FUNCREF_CONST);
|
||||
#if WASM_ENABLE_GC == 0
|
||||
table_elems[i] =
|
||||
(table_elem_type_t)init_values[i].u.ref_index;
|
||||
table_elems[i] = (table_elem_type_t)init_values[i]
|
||||
.u.unary.v.ref_index;
|
||||
#else
|
||||
if (init_values[i].u.ref_index != UINT32_MAX) {
|
||||
if (init_values[i].u.unary.v.ref_index
|
||||
!= UINT32_MAX) {
|
||||
if (!(func_obj = wasm_create_func_obj(
|
||||
module, init_values[i].u.ref_index,
|
||||
module,
|
||||
init_values[i].u.unary.v.ref_index,
|
||||
true, NULL, 0))) {
|
||||
goto got_exception;
|
||||
}
|
||||
|
|
|
@ -41,22 +41,6 @@ typedef float64 CellType_F64;
|
|||
#define get_linear_mem_size() GET_LINEAR_MEMORY_SIZE(memory)
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
#define app_addr_in_shared_heap(app_addr, bytes) \
|
||||
(shared_heap && (app_addr) >= shared_heap_start_off \
|
||||
&& (app_addr) <= shared_heap_end_off - bytes + 1)
|
||||
|
||||
#define shared_heap_addr_app_to_native(app_addr, native_addr) \
|
||||
native_addr = shared_heap_base_addr + ((app_addr)-shared_heap_start_off)
|
||||
|
||||
#define CHECK_SHARED_HEAP_OVERFLOW(app_addr, bytes, native_addr) \
|
||||
if (app_addr_in_shared_heap(app_addr, bytes)) \
|
||||
shared_heap_addr_app_to_native(app_addr, native_addr); \
|
||||
else
|
||||
#else
|
||||
#define CHECK_SHARED_HEAP_OVERFLOW(app_addr, bytes, native_addr)
|
||||
#endif
|
||||
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
|
||||
#define CHECK_MEMORY_OVERFLOW(bytes) \
|
||||
|
@ -105,6 +89,19 @@ typedef float64 CellType_F64;
|
|||
goto unaligned_atomic; \
|
||||
} while (0)
|
||||
|
||||
#if WASM_ENABLE_INSTRUCTION_METERING != 0
|
||||
#define CHECK_INSTRUCTION_LIMIT() \
|
||||
if (instructions_left == 0) { \
|
||||
wasm_set_exception(module, "instruction limit exceeded"); \
|
||||
goto got_exception; \
|
||||
} \
|
||||
else if (instructions_left > 0) \
|
||||
instructions_left--;
|
||||
|
||||
#else
|
||||
#define CHECK_INSTRUCTION_LIMIT() (void)0
|
||||
#endif
|
||||
|
||||
static inline uint32
|
||||
rotl32(uint32 n, uint32 c)
|
||||
{
|
||||
|
@ -1441,6 +1438,7 @@ wasm_interp_dump_op_count()
|
|||
do { \
|
||||
const void *p_label_addr = *(void **)frame_ip; \
|
||||
frame_ip += sizeof(void *); \
|
||||
CHECK_INSTRUCTION_LIMIT(); \
|
||||
goto *p_label_addr; \
|
||||
} while (0)
|
||||
#else
|
||||
|
@ -1452,6 +1450,7 @@ wasm_interp_dump_op_count()
|
|||
/* int32 relative offset was emitted in 64-bit target */ \
|
||||
p_label_addr = label_base + (int32)LOAD_U32_WITH_2U16S(frame_ip); \
|
||||
frame_ip += sizeof(int32); \
|
||||
CHECK_INSTRUCTION_LIMIT(); \
|
||||
goto *p_label_addr; \
|
||||
} while (0)
|
||||
#else
|
||||
|
@ -1462,6 +1461,7 @@ wasm_interp_dump_op_count()
|
|||
/* uint32 label address was emitted in 32-bit target */ \
|
||||
p_label_addr = (void *)(uintptr_t)LOAD_U32_WITH_2U16S(frame_ip); \
|
||||
frame_ip += sizeof(int32); \
|
||||
CHECK_INSTRUCTION_LIMIT(); \
|
||||
goto *p_label_addr; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
@ -1538,6 +1538,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
uint8 *maddr = NULL;
|
||||
uint32 local_idx, local_offset, global_idx;
|
||||
uint8 opcode = 0, local_type, *global_addr;
|
||||
|
||||
#if WASM_ENABLE_INSTRUCTION_METERING != 0
|
||||
int instructions_left = -1;
|
||||
if (exec_env) {
|
||||
instructions_left = exec_env->instructions_to_execute;
|
||||
}
|
||||
#endif
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
|
||||
#if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0
|
||||
|
@ -1567,21 +1574,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
bool is_return_call = false;
|
||||
#endif
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
WASMSharedHeap *shared_heap = module->e ? module->e->shared_heap : NULL;
|
||||
uint8 *shared_heap_base_addr = shared_heap ? shared_heap->base_addr : NULL;
|
||||
/*
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
uint64 shared_heap_start_off =
|
||||
shared_heap ? (is_memory64 ? shared_heap->start_off_mem64
|
||||
: shared_heap->start_off_mem32)
|
||||
: 0;
|
||||
uint64 shared_heap_end_off =
|
||||
shared_heap ? (is_memory64 ? UINT64_MAX : UINT32_MAX) : 0;
|
||||
#else
|
||||
*/ /* TODO: uncomment the code when memory64 is enabled for fast-interp */
|
||||
uint64 shared_heap_start_off =
|
||||
shared_heap ? shared_heap->start_off_mem32 : 0;
|
||||
uint64 shared_heap_end_off = shared_heap ? UINT32_MAX : 0;
|
||||
/* TODO: currently flowing two variables are only dummy for shared heap
|
||||
* boundary check, need to be updated when multi-memory or memory64
|
||||
* proposals are to be implemented */
|
||||
bool is_memory64 = false;
|
||||
uint32 memidx = 0;
|
||||
(void)is_memory64;
|
||||
(void)memidx;
|
||||
/* #endif */
|
||||
#endif /* end of WASM_ENABLE_SHARED_HEAP != 0 */
|
||||
|
||||
|
@ -5351,12 +5350,14 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
|| init_values[i].init_expr_type
|
||||
== INIT_EXPR_TYPE_FUNCREF_CONST);
|
||||
#if WASM_ENABLE_GC == 0
|
||||
table_elems[i] =
|
||||
(table_elem_type_t)init_values[i].u.ref_index;
|
||||
table_elems[i] = (table_elem_type_t)init_values[i]
|
||||
.u.unary.v.ref_index;
|
||||
#else
|
||||
if (init_values[i].u.ref_index != UINT32_MAX) {
|
||||
if (init_values[i].u.unary.v.ref_index
|
||||
!= UINT32_MAX) {
|
||||
if (!(func_obj = wasm_create_func_obj(
|
||||
module, init_values[i].u.ref_index,
|
||||
module,
|
||||
init_values[i].u.unary.v.ref_index,
|
||||
true, NULL, 0))) {
|
||||
goto got_exception;
|
||||
}
|
||||
|
|
|
@ -379,7 +379,6 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
|
|||
mem = mem_new; \
|
||||
} while (0)
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
static bool
|
||||
check_type_index(const WASMModule *module, uint32 type_count, uint32 type_index,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
|
@ -392,6 +391,7 @@ check_type_index(const WASMModule *module, uint32 type_count, uint32 type_index,
|
|||
return true;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
static bool
|
||||
check_array_type(const WASMModule *module, uint32 type_index, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
|
@ -409,6 +409,29 @@ check_array_type(const WASMModule *module, uint32 type_index, char *error_buf,
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* if no GC is enabled, an valid type is always a function type.
|
||||
* but if GC is enabled, we need to check the type flag
|
||||
*/
|
||||
static bool
|
||||
check_function_type(const WASMModule *module, uint32 type_index,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
if (!check_type_index(module, module->type_count, type_index, error_buf,
|
||||
error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (module->types[type_index]->type_flag != WASM_TYPE_FUNC) {
|
||||
set_error_buf(error_buf, error_buf_size, "unknown function type");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_function_index(const WASMModule *module, uint32 function_index,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
|
@ -430,6 +453,9 @@ typedef struct InitValue {
|
|||
WASMRefType ref_type;
|
||||
#endif
|
||||
WASMValue value;
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
InitializerExpression *expr;
|
||||
#endif
|
||||
} InitValue;
|
||||
|
||||
typedef struct ConstExprContext {
|
||||
|
@ -454,7 +480,11 @@ push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type,
|
|||
#if WASM_ENABLE_GC != 0
|
||||
WASMRefType *ref_type, uint8 gc_opcode,
|
||||
#endif
|
||||
WASMValue *value, char *error_buf, uint32 error_buf_size)
|
||||
WASMValue *value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
InitializerExpression *expr,
|
||||
#endif
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
InitValue *cur_value;
|
||||
|
||||
|
@ -480,6 +510,10 @@ push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type,
|
|||
cur_value->flag = flag;
|
||||
cur_value->value = *value;
|
||||
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
cur_value->expr = expr;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
cur_value->gc_opcode = gc_opcode;
|
||||
if (wasm_is_type_multi_byte_type(type)) {
|
||||
|
@ -564,7 +598,11 @@ pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type,
|
|||
#if WASM_ENABLE_GC != 0
|
||||
WASMRefType *ref_type, uint8 *p_gc_opcode,
|
||||
#endif
|
||||
WASMValue *p_value, char *error_buf, uint32 error_buf_size)
|
||||
WASMValue *p_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
InitializerExpression **p_expr,
|
||||
#endif
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
InitValue *cur_value;
|
||||
|
||||
|
@ -600,7 +638,10 @@ pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type,
|
|||
if (p_gc_opcode)
|
||||
*p_gc_opcode = cur_value->gc_opcode;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
if (p_expr)
|
||||
*p_expr = cur_value->expr;
|
||||
#endif
|
||||
return true;
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
|
@ -616,7 +657,7 @@ fail:
|
|||
}
|
||||
|
||||
static void
|
||||
destroy_const_expr_stack(ConstExprContext *ctx)
|
||||
destroy_const_expr_stack(ConstExprContext *ctx, bool free_exprs)
|
||||
{
|
||||
#if WASM_ENABLE_GC != 0
|
||||
uint32 i;
|
||||
|
@ -631,24 +672,62 @@ destroy_const_expr_stack(ConstExprContext *ctx)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
if (free_exprs) {
|
||||
for (uint32 j = 0; j < ctx->sp; j++) {
|
||||
if (is_expr_binary_op(ctx->stack[j].expr->init_expr_type)) {
|
||||
destroy_init_expr_recursive(ctx->stack[j].expr);
|
||||
ctx->stack[j].expr = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ctx->stack != ctx->data) {
|
||||
wasm_runtime_free(ctx->stack);
|
||||
}
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
static void
|
||||
destroy_init_expr(WASMModule *module, InitializerExpression *expr)
|
||||
{
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (expr->init_expr_type == INIT_EXPR_TYPE_STRUCT_NEW
|
||||
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW
|
||||
|| expr->init_expr_type == INIT_EXPR_TYPE_ARRAY_NEW_FIXED) {
|
||||
destroy_init_expr_data_recursive(module, expr->u.data);
|
||||
destroy_init_expr_data_recursive(module, expr->u.unary.v.data);
|
||||
}
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
// free left expr and right exprs for binary oprand
|
||||
if (!is_expr_binary_op(expr->init_expr_type)) {
|
||||
return;
|
||||
}
|
||||
if (expr->u.binary.l_expr) {
|
||||
destroy_init_expr_recursive(expr->u.binary.l_expr);
|
||||
}
|
||||
if (expr->u.binary.r_expr) {
|
||||
destroy_init_expr_recursive(expr->u.binary.r_expr);
|
||||
}
|
||||
expr->u.binary.l_expr = expr->u.binary.r_expr = NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* for init expr
|
||||
* (data (i32.add (i32.const 0) (i32.sub (i32.const 1) (i32.const 2)))),
|
||||
* the binary format is
|
||||
* 0x11: 41 00 ; i32.const 0
|
||||
* 0x13: 41 01 ; i32.const 1
|
||||
* 0x15: 41 02 ; i32.const 2
|
||||
* 0x17: 6b ; i32.sub
|
||||
* 0x18: 6a ; i32.add
|
||||
* for traversal: read opcodes and push them onto the stack. When encountering
|
||||
* a binary opcode, pop two values from the stack which become the left and
|
||||
* right child nodes of this binary operation node.
|
||||
*/
|
||||
static bool
|
||||
load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
||||
InitializerExpression *init_expr, uint8 type, void *ref_type,
|
||||
|
@ -664,6 +743,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
uint8 opcode;
|
||||
WASMRefType cur_ref_type = { 0 };
|
||||
#endif
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
InitializerExpression *cur_expr = NULL;
|
||||
#endif
|
||||
|
||||
init_const_expr_stack(&const_expr_ctx, module);
|
||||
|
||||
|
@ -676,24 +758,32 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
case INIT_EXPR_TYPE_I32_CONST:
|
||||
read_leb_int32(p, p_end, cur_value.i32);
|
||||
|
||||
if (!push_const_expr_stack(
|
||||
&const_expr_ctx, flag, VALUE_TYPE_I32,
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_I32,
|
||||
#if WASM_ENABLE_GC != 0
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
#endif
|
||||
&cur_value, error_buf, error_buf_size))
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
break;
|
||||
/* i64.const */
|
||||
case INIT_EXPR_TYPE_I64_CONST:
|
||||
read_leb_int64(p, p_end, cur_value.i64);
|
||||
|
||||
if (!push_const_expr_stack(
|
||||
&const_expr_ctx, flag, VALUE_TYPE_I64,
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_I64,
|
||||
#if WASM_ENABLE_GC != 0
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
#endif
|
||||
&cur_value, error_buf, error_buf_size))
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
break;
|
||||
/* f32.const */
|
||||
|
@ -703,12 +793,16 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
for (i = 0; i < sizeof(float32); i++)
|
||||
*p_float++ = *p++;
|
||||
|
||||
if (!push_const_expr_stack(
|
||||
&const_expr_ctx, flag, VALUE_TYPE_F32,
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_F32,
|
||||
#if WASM_ENABLE_GC != 0
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
#endif
|
||||
&cur_value, error_buf, error_buf_size))
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
break;
|
||||
/* f64.const */
|
||||
|
@ -718,12 +812,16 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
for (i = 0; i < sizeof(float64); i++)
|
||||
*p_float++ = *p++;
|
||||
|
||||
if (!push_const_expr_stack(
|
||||
&const_expr_ctx, flag, VALUE_TYPE_F64,
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_F64,
|
||||
#if WASM_ENABLE_GC != 0
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
#endif
|
||||
&cur_value, error_buf, error_buf_size))
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
break;
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
|
@ -744,12 +842,16 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
cur_value.v128.i64x2[0] = high;
|
||||
cur_value.v128.i64x2[1] = low;
|
||||
|
||||
if (!push_const_expr_stack(
|
||||
&const_expr_ctx, flag, VALUE_TYPE_V128,
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_V128,
|
||||
#if WASM_ENABLE_GC != 0
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
#endif
|
||||
&cur_value, error_buf, error_buf_size))
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
#if WASM_ENABLE_WAMR_COMPILER != 0
|
||||
/* If any init_expr is v128.const, mark SIMD used */
|
||||
|
@ -760,7 +862,92 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) || \
|
||||
(WASM_ENABLE_FAST_INTERP != 0) */
|
||||
#endif /* end of WASM_ENABLE_SIMD */
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
case INIT_EXPR_TYPE_I32_ADD:
|
||||
case INIT_EXPR_TYPE_I32_SUB:
|
||||
case INIT_EXPR_TYPE_I32_MUL:
|
||||
case INIT_EXPR_TYPE_I64_ADD:
|
||||
case INIT_EXPR_TYPE_I64_SUB:
|
||||
case INIT_EXPR_TYPE_I64_MUL:
|
||||
{
|
||||
|
||||
InitializerExpression *l_expr, *r_expr;
|
||||
WASMValue l_value, r_value;
|
||||
uint8 l_flag, r_flag;
|
||||
uint8 value_type;
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_I32_ADD
|
||||
|| flag == INIT_EXPR_TYPE_I32_SUB
|
||||
|| flag == INIT_EXPR_TYPE_I32_MUL) {
|
||||
value_type = VALUE_TYPE_I32;
|
||||
}
|
||||
else {
|
||||
value_type = VALUE_TYPE_I64;
|
||||
}
|
||||
|
||||
/* If right flag indicates a binary operation, right expr will
|
||||
* be popped from stack. Otherwise, allocate a new expr for
|
||||
* right expr. Same for left expr.
|
||||
*/
|
||||
if (!(pop_const_expr_stack(&const_expr_ctx, &r_flag, value_type,
|
||||
#if WASM_ENABLE_GC != 0
|
||||
NULL, NULL,
|
||||
#endif
|
||||
&r_value, &r_expr, error_buf,
|
||||
error_buf_size))) {
|
||||
goto fail;
|
||||
}
|
||||
if (!is_expr_binary_op(r_flag)) {
|
||||
if (!(r_expr = loader_malloc(sizeof(InitializerExpression),
|
||||
error_buf, error_buf_size))) {
|
||||
goto fail;
|
||||
}
|
||||
r_expr->init_expr_type = r_flag;
|
||||
r_expr->u.unary.v = r_value;
|
||||
}
|
||||
|
||||
if (!(pop_const_expr_stack(&const_expr_ctx, &l_flag, value_type,
|
||||
#if WASM_ENABLE_GC != 0
|
||||
NULL, NULL,
|
||||
#endif
|
||||
&l_value, &l_expr, error_buf,
|
||||
error_buf_size))) {
|
||||
destroy_init_expr_recursive(r_expr);
|
||||
goto fail;
|
||||
}
|
||||
if (!is_expr_binary_op(l_flag)) {
|
||||
if (!(l_expr = loader_malloc(sizeof(InitializerExpression),
|
||||
error_buf, error_buf_size))) {
|
||||
destroy_init_expr_recursive(r_expr);
|
||||
goto fail;
|
||||
}
|
||||
l_expr->init_expr_type = l_flag;
|
||||
l_expr->u.unary.v = l_value;
|
||||
}
|
||||
|
||||
if (!(cur_expr = loader_malloc(sizeof(InitializerExpression),
|
||||
error_buf, error_buf_size))) {
|
||||
destroy_init_expr_recursive(l_expr);
|
||||
destroy_init_expr_recursive(r_expr);
|
||||
goto fail;
|
||||
}
|
||||
cur_expr->init_expr_type = flag;
|
||||
cur_expr->u.binary.l_expr = l_expr;
|
||||
cur_expr->u.binary.r_expr = r_expr;
|
||||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag, value_type,
|
||||
#if WASM_ENABLE_GC != 0
|
||||
NULL, 0,
|
||||
#endif
|
||||
&cur_value, cur_expr, error_buf,
|
||||
error_buf_size)) {
|
||||
destroy_init_expr_recursive(cur_expr);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR */
|
||||
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
|
||||
/* ref.func */
|
||||
case INIT_EXPR_TYPE_FUNCREF_CONST:
|
||||
|
@ -776,6 +963,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
#if WASM_ENABLE_GC == 0
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_FUNCREF, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
#else
|
||||
|
@ -793,8 +983,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
false, type_idx);
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
cur_ref_type.ref_type, &cur_ref_type,
|
||||
0, &cur_value, error_buf,
|
||||
error_buf_size))
|
||||
0, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
#endif
|
||||
#if WASM_ENABLE_WAMR_COMPILER != 0
|
||||
|
@ -808,19 +1001,27 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
{
|
||||
uint8 type1;
|
||||
|
||||
#if WASM_ENABLE_GC == 0
|
||||
CHECK_BUF(p, p_end, 1);
|
||||
type1 = read_uint8(p);
|
||||
|
||||
#if WASM_ENABLE_GC == 0
|
||||
cur_value.ref_index = NULL_REF;
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag, type1,
|
||||
&cur_value, error_buf,
|
||||
error_buf_size))
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
#else
|
||||
int32 heap_type;
|
||||
read_leb_int32(p, p_end, heap_type);
|
||||
type1 = (uint8)((int32)0x80 + heap_type);
|
||||
|
||||
cur_value.gc_obj = NULL_REF;
|
||||
|
||||
if (!is_byte_a_type(type1)
|
||||
|| !wasm_is_valid_heap_type(heap_type)
|
||||
|| wasm_is_type_multi_byte_type(type1)) {
|
||||
p--;
|
||||
read_leb_uint32(p, p_end, type_idx);
|
||||
|
@ -833,13 +1034,19 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
cur_ref_type.ref_type,
|
||||
&cur_ref_type, 0, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag, type1,
|
||||
NULL, 0, &cur_value, error_buf,
|
||||
error_buf_size))
|
||||
NULL, 0, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
@ -928,8 +1135,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
#if WASM_ENABLE_GC != 0
|
||||
&cur_ref_type, 0,
|
||||
#endif
|
||||
&cur_value, error_buf,
|
||||
error_buf_size))
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
|
||||
break;
|
||||
|
@ -992,6 +1202,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
&const_expr_ctx, NULL, field_type,
|
||||
field_ref_type, NULL,
|
||||
&struct_init_values->fields[field_idx],
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
destroy_init_expr_data_recursive(
|
||||
module, struct_init_values);
|
||||
|
@ -1005,6 +1218,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
if (!push_const_expr_stack(
|
||||
&const_expr_ctx, flag, cur_ref_type.ref_type,
|
||||
&cur_ref_type, (uint8)opcode1, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
destroy_init_expr_data_recursive(
|
||||
module, struct_init_values);
|
||||
|
@ -1036,6 +1252,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
if (!push_const_expr_stack(
|
||||
&const_expr_ctx, flag, cur_ref_type.ref_type,
|
||||
&cur_ref_type, (uint8)opcode1, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1084,8 +1303,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
|
||||
if (!pop_const_expr_stack(
|
||||
&const_expr_ctx, NULL, VALUE_TYPE_I32,
|
||||
NULL, NULL, &len_val, error_buf,
|
||||
error_buf_size)) {
|
||||
NULL, NULL, &len_val,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1104,6 +1326,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
&const_expr_ctx, NULL, elem_type,
|
||||
elem_ref_type, NULL,
|
||||
&array_init_values->elem_data[0],
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
destroy_init_expr_data_recursive(
|
||||
module, array_init_values);
|
||||
|
@ -1136,6 +1361,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
elem_ref_type, NULL,
|
||||
&array_init_values
|
||||
->elem_data[i - 1],
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
destroy_init_expr_data_recursive(
|
||||
module, array_init_values);
|
||||
|
@ -1152,10 +1380,13 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
uint32 len;
|
||||
|
||||
/* POP(i32) */
|
||||
if (!pop_const_expr_stack(&const_expr_ctx, NULL,
|
||||
VALUE_TYPE_I32, NULL,
|
||||
NULL, &len_val, error_buf,
|
||||
error_buf_size)) {
|
||||
if (!pop_const_expr_stack(
|
||||
&const_expr_ctx, NULL, VALUE_TYPE_I32, NULL,
|
||||
NULL, &len_val,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
len = len_val.i32;
|
||||
|
@ -1169,6 +1400,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
if (!push_const_expr_stack(
|
||||
&const_expr_ctx, flag, cur_ref_type.ref_type,
|
||||
&cur_ref_type, (uint8)opcode1, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
if (array_init_values) {
|
||||
destroy_init_expr_data_recursive(
|
||||
|
@ -1195,9 +1429,13 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
case WASM_OP_REF_I31:
|
||||
{
|
||||
/* POP(i32) */
|
||||
if (!pop_const_expr_stack(
|
||||
&const_expr_ctx, NULL, VALUE_TYPE_I32, NULL,
|
||||
NULL, &cur_value, error_buf, error_buf_size)) {
|
||||
if (!pop_const_expr_stack(&const_expr_ctx, NULL,
|
||||
VALUE_TYPE_I32, NULL, NULL,
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1206,6 +1444,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
if (!push_const_expr_stack(
|
||||
&const_expr_ctx, flag, cur_ref_type.ref_type,
|
||||
&cur_ref_type, (uint8)opcode1, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1240,7 +1481,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
#if WASM_ENABLE_GC != 0
|
||||
ref_type, &opcode,
|
||||
#endif
|
||||
&cur_value, error_buf, error_buf_size)) {
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
&cur_expr,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1250,8 +1495,21 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
if (cur_expr != NULL) {
|
||||
bh_memcpy_s(init_expr, sizeof(InitializerExpression), cur_expr,
|
||||
sizeof(InitializerExpression));
|
||||
wasm_runtime_free(cur_expr);
|
||||
}
|
||||
else {
|
||||
init_expr->init_expr_type = flag;
|
||||
init_expr->u.unary.v = cur_value;
|
||||
}
|
||||
|
||||
#else
|
||||
init_expr->init_expr_type = flag;
|
||||
init_expr->u = cur_value;
|
||||
init_expr->u.unary.v = cur_value;
|
||||
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (init_expr->init_expr_type == WASM_OP_GC_PREFIX) {
|
||||
|
@ -1282,11 +1540,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
|
||||
*p_buf = p;
|
||||
destroy_const_expr_stack(&const_expr_ctx);
|
||||
destroy_const_expr_stack(&const_expr_ctx, false);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
destroy_const_expr_stack(&const_expr_ctx);
|
||||
destroy_const_expr_stack(&const_expr_ctx, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2014,9 +2272,9 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
"recursive type count too large");
|
||||
return false;
|
||||
}
|
||||
module->type_count += rec_count - 1;
|
||||
new_total_size =
|
||||
sizeof(WASMFuncType *) * (uint64)module->type_count;
|
||||
sizeof(WASMFuncType *)
|
||||
* (uint64)(module->type_count + rec_count - 1);
|
||||
if (new_total_size > UINT32_MAX) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"allocate memory failed");
|
||||
|
@ -2024,6 +2282,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
}
|
||||
MEM_REALLOC(module->types, (uint32)total_size,
|
||||
(uint32)new_total_size);
|
||||
module->type_count += rec_count - 1;
|
||||
total_size = new_total_size;
|
||||
}
|
||||
|
||||
|
@ -2479,8 +2738,8 @@ load_function_import(const uint8 **p_buf, const uint8 *buf_end,
|
|||
read_leb_uint32(p, p_end, declare_type_index);
|
||||
*p_buf = p;
|
||||
|
||||
if (declare_type_index >= parent_module->type_count) {
|
||||
set_error_buf(error_buf, error_buf_size, "unknown type");
|
||||
if (!check_function_type(parent_module, declare_type_index, error_buf,
|
||||
error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2560,7 +2819,8 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
|
|||
error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
if (wasm_is_reftype_htref_non_nullable(ref_type.ref_type)) {
|
||||
if (!wasm_is_type_reftype(ref_type.ref_type)
|
||||
|| wasm_is_reftype_htref_non_nullable(ref_type.ref_type)) {
|
||||
set_error_buf(error_buf, error_buf_size, "type mismatch");
|
||||
return false;
|
||||
}
|
||||
|
@ -2893,8 +3153,8 @@ load_tag_import(const uint8 **p_buf, const uint8 *buf_end,
|
|||
/* get type */
|
||||
read_leb_uint32(p, p_end, declare_type_index);
|
||||
/* compare against module->types */
|
||||
if (declare_type_index >= parent_module->type_count) {
|
||||
set_error_buf(error_buf, error_buf_size, "unknown tag type");
|
||||
if (!check_function_type(parent_module, declare_type_index, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -3086,6 +3346,15 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|||
error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* TODO: add this validator
|
||||
* `wasm_is_reftype_htref_non_nullable(ref_type.ref_type)`
|
||||
* after sync up with the latest GC spec
|
||||
*/
|
||||
if (!wasm_is_type_reftype(ref_type.ref_type)) {
|
||||
set_error_buf(error_buf, error_buf_size, "type mismatch");
|
||||
return false;
|
||||
}
|
||||
table->table_type.elem_type = ref_type.ref_type;
|
||||
if (need_ref_type_map) {
|
||||
if (!(table->table_type.elem_ref_type =
|
||||
|
@ -3259,6 +3528,13 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
CHECK_BUF(p, p_end, 1);
|
||||
/* 0x70 */
|
||||
u8 = read_uint8(p);
|
||||
#if WASM_ENABLE_GC != 0
|
||||
if (wasm_is_reftype_htref_nullable(u8)) {
|
||||
int32 heap_type;
|
||||
read_leb_int32(p, p_end, heap_type);
|
||||
(void)heap_type;
|
||||
}
|
||||
#endif
|
||||
read_leb_uint32(p, p_end, flags);
|
||||
read_leb_uint32(p, p_end, u32);
|
||||
if (flags & 1)
|
||||
|
@ -3306,7 +3582,8 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
/* valtype */
|
||||
CHECK_BUF(p, p_end, 1);
|
||||
global_type = read_uint8(p);
|
||||
if (wasm_is_type_multi_byte_type(global_type)) {
|
||||
if (wasm_is_reftype_htref_nullable(global_type)
|
||||
|| wasm_is_reftype_htref_non_nullable(global_type)) {
|
||||
int32 heap_type;
|
||||
read_leb_int32(p, p_end, heap_type);
|
||||
(void)heap_type;
|
||||
|
@ -3563,8 +3840,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|||
for (i = 0; i < func_count; i++) {
|
||||
/* Resolve function type */
|
||||
read_leb_uint32(p, p_end, type_index);
|
||||
if (type_index >= module->type_count) {
|
||||
set_error_buf(error_buf, error_buf_size, "unknown type");
|
||||
|
||||
if (!check_function_type(module, type_index, error_buf,
|
||||
error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3666,7 +3944,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|||
* we shall make a copy of code body [p_code, p_code + code_size]
|
||||
* when we are worrying about inappropriate releasing behaviour.
|
||||
* all code bodies are actually in a buffer which user allocates in
|
||||
* his embedding environment and we don't have power on them.
|
||||
* their embedding environment and we don't have power over them.
|
||||
* it will be like:
|
||||
* code_body_cp = malloc(code_size);
|
||||
* memcpy(code_body_cp, p_code, code_size);
|
||||
|
@ -4024,9 +4302,9 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
if (global->init_expr.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
uint8 global_type;
|
||||
WASMRefType *global_ref_type;
|
||||
uint32 global_idx = global->init_expr.u.global_index;
|
||||
uint32 global_idx = global->init_expr.u.unary.v.global_index;
|
||||
|
||||
if (global->init_expr.u.global_index
|
||||
if (global->init_expr.u.unary.v.global_index
|
||||
>= module->import_global_count + i) {
|
||||
set_error_buf(error_buf, error_buf_size, "unknown global");
|
||||
return false;
|
||||
|
@ -4423,7 +4701,7 @@ load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end,
|
|||
}
|
||||
|
||||
init_expr->init_expr_type = INIT_EXPR_TYPE_FUNCREF_CONST;
|
||||
init_expr->u.ref_index = function_index;
|
||||
init_expr->u.unary.v.ref_index = function_index;
|
||||
}
|
||||
|
||||
*p_buf = p;
|
||||
|
@ -4696,7 +4974,7 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
|
|||
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
if (table_elem_idx_type == VALUE_TYPE_I64
|
||||
&& table_segment->base_offset.u.u64 > UINT32_MAX) {
|
||||
&& table_segment->base_offset.u.unary.v.u64 > UINT32_MAX) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"In table64, table base offset can't be "
|
||||
"larger than UINT32_MAX");
|
||||
|
@ -4856,6 +5134,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
|
|||
|
||||
if (!(dataseg = module->data_segments[i] = loader_malloc(
|
||||
sizeof(WASMDataSeg), error_buf, error_buf_size))) {
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
destroy_init_expr(module, &init_expr);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -4970,8 +5251,8 @@ load_tag_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_code,
|
|||
/* get type */
|
||||
read_leb_uint32(p, p_end, tag_type);
|
||||
/* compare against module->types */
|
||||
if (tag_type >= module->type_count) {
|
||||
set_error_buf(error_buf, error_buf_size, "unknown type");
|
||||
if (!check_function_type(module, tag_type, error_buf,
|
||||
error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5983,7 +6264,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
&& global->init_expr.init_expr_type
|
||||
== INIT_EXPR_TYPE_I32_CONST) {
|
||||
aux_heap_base_global = global;
|
||||
aux_heap_base = (uint64)(uint32)global->init_expr.u.i32;
|
||||
aux_heap_base =
|
||||
(uint64)(uint32)global->init_expr.u.unary.v.i32;
|
||||
aux_heap_base_global_index = export->index;
|
||||
LOG_VERBOSE("Found aux __heap_base global, value: %" PRIu64,
|
||||
aux_heap_base);
|
||||
|
@ -6004,7 +6286,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
&& global->init_expr.init_expr_type
|
||||
== INIT_EXPR_TYPE_I32_CONST) {
|
||||
aux_data_end_global = global;
|
||||
aux_data_end = (uint64)(uint32)global->init_expr.u.i32;
|
||||
aux_data_end =
|
||||
(uint64)(uint32)global->init_expr.u.unary.v.i32;
|
||||
aux_data_end_global_index = export->index;
|
||||
LOG_VERBOSE("Found aux __data_end global, value: %" PRIu64,
|
||||
aux_data_end);
|
||||
|
@ -6045,10 +6328,11 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
&& global->type.val_type == VALUE_TYPE_I32
|
||||
&& global->init_expr.init_expr_type
|
||||
== INIT_EXPR_TYPE_I32_CONST
|
||||
&& (uint64)(uint32)global->init_expr.u.i32
|
||||
&& (uint64)(uint32)global->init_expr.u.unary.v.i32
|
||||
<= aux_heap_base) {
|
||||
aux_stack_top_global = global;
|
||||
aux_stack_top = (uint64)(uint32)global->init_expr.u.i32;
|
||||
aux_stack_top =
|
||||
(uint64)(uint32)global->init_expr.u.unary.v.i32;
|
||||
module->aux_stack_top_global_index =
|
||||
module->import_global_count + global_index;
|
||||
module->aux_stack_bottom = aux_stack_top;
|
||||
|
@ -6380,10 +6664,16 @@ create_module(char *name, char *error_buf, uint32 error_buf_size)
|
|||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
#if WASM_ENABLE_UVWASI == 0
|
||||
module->wasi_args.stdio[0] = os_invalid_raw_handle();
|
||||
module->wasi_args.stdio[1] = os_invalid_raw_handle();
|
||||
module->wasi_args.stdio[2] = os_invalid_raw_handle();
|
||||
#endif
|
||||
#else
|
||||
module->wasi_args.stdio[0] = os_get_invalid_handle();
|
||||
module->wasi_args.stdio[1] = os_get_invalid_handle();
|
||||
module->wasi_args.stdio[2] = os_get_invalid_handle();
|
||||
#endif /* WASM_ENABLE_UVWASI == 0 */
|
||||
#endif /* WASM_ENABLE_LIBC_WASI != 0 */
|
||||
|
||||
(void)ret;
|
||||
return module;
|
||||
|
@ -6893,7 +7183,7 @@ wasm_loader_unload(WASMModule *module)
|
|||
wasm_runtime_free(module->memories);
|
||||
|
||||
if (module->globals) {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
#if WASM_ENABLE_GC != 0 || WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
for (i = 0; i < module->global_count; i++) {
|
||||
destroy_init_expr(module, &module->globals[i].init_expr);
|
||||
}
|
||||
|
@ -6926,6 +7216,9 @@ wasm_loader_unload(WASMModule *module)
|
|||
#endif
|
||||
wasm_runtime_free(module->table_segments[i].init_values);
|
||||
}
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
destroy_init_expr(module, &module->table_segments[i].base_offset);
|
||||
#endif
|
||||
}
|
||||
wasm_runtime_free(module->table_segments);
|
||||
}
|
||||
|
@ -6935,6 +7228,10 @@ wasm_loader_unload(WASMModule *module)
|
|||
if (module->data_segments[i]) {
|
||||
if (module->data_segments[i]->is_data_cloned)
|
||||
wasm_runtime_free(module->data_segments[i]->data);
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
destroy_init_expr(module,
|
||||
&(module->data_segments[i]->base_offset));
|
||||
#endif
|
||||
wasm_runtime_free(module->data_segments[i]);
|
||||
}
|
||||
}
|
||||
|
@ -10477,7 +10774,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, uint8 opcode,
|
|||
* match block type. */
|
||||
if (cur_block->is_stack_polymorphic) {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
int32 j = reftype_map_count - 1;
|
||||
int32 j = (int32)reftype_map_count - 1;
|
||||
#endif
|
||||
for (i = (int32)arity - 1; i >= 0; i--) {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
|
@ -10780,7 +11077,7 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block,
|
|||
* match block type. */
|
||||
if (block->is_stack_polymorphic) {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
int32 j = return_reftype_map_count - 1;
|
||||
int32 j = (int32)return_reftype_map_count - 1;
|
||||
#endif
|
||||
for (i = (int32)return_count - 1; i >= 0; i--) {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
|
@ -11549,15 +11846,17 @@ re_scan:
|
|||
}
|
||||
else {
|
||||
int32 type_index;
|
||||
|
||||
/* Resolve the leb128 encoded type index as block type */
|
||||
p--;
|
||||
p_org = p - 1;
|
||||
pb_read_leb_int32(p, p_end, type_index);
|
||||
if ((uint32)type_index >= module->type_count) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"unknown type");
|
||||
|
||||
if (!check_function_type(module, type_index, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
block_type.is_value_type = false;
|
||||
block_type.u.type =
|
||||
(WASMFuncType *)module->types[type_index];
|
||||
|
@ -12607,8 +12906,8 @@ re_scan:
|
|||
/* skip elem idx */
|
||||
POP_TBL_ELEM_IDX();
|
||||
|
||||
if (type_idx >= module->type_count) {
|
||||
set_error_buf(error_buf, error_buf_size, "unknown type");
|
||||
if (!check_function_type(module, type_idx, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -13204,7 +13503,8 @@ re_scan:
|
|||
== VALUE_TYPE_FUNCREF
|
||||
&& module->globals[i].init_expr.init_expr_type
|
||||
== INIT_EXPR_TYPE_FUNCREF_CONST
|
||||
&& module->globals[i].init_expr.u.u32 == func_idx) {
|
||||
&& module->globals[i].init_expr.u.unary.v.u32
|
||||
== func_idx) {
|
||||
func_declared = true;
|
||||
break;
|
||||
}
|
||||
|
@ -13233,7 +13533,8 @@ re_scan:
|
|||
#endif
|
||||
) {
|
||||
for (j = 0; j < table_seg->value_count; j++) {
|
||||
if (table_seg->init_values[j].u.ref_index
|
||||
if (table_seg->init_values[j]
|
||||
.u.unary.v.ref_index
|
||||
== func_idx) {
|
||||
func_declared = true;
|
||||
break;
|
||||
|
@ -14969,8 +15270,6 @@ re_scan:
|
|||
case WASM_OP_STRING_NEW_LOSSY_UTF8:
|
||||
case WASM_OP_STRING_NEW_WTF8:
|
||||
{
|
||||
uint32 memidx;
|
||||
|
||||
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
|
||||
func->has_memory_operations = true;
|
||||
#endif
|
||||
|
@ -14982,7 +15281,6 @@ re_scan:
|
|||
POP_I32();
|
||||
POP_I32();
|
||||
PUSH_REF(REF_TYPE_STRINGREF);
|
||||
(void)memidx;
|
||||
break;
|
||||
}
|
||||
case WASM_OP_STRING_CONST:
|
||||
|
@ -15010,8 +15308,6 @@ re_scan:
|
|||
case WASM_OP_STRING_ENCODE_LOSSY_UTF8:
|
||||
case WASM_OP_STRING_ENCODE_WTF8:
|
||||
{
|
||||
uint32 memidx;
|
||||
|
||||
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
|
||||
func->has_memory_operations = true;
|
||||
#endif
|
||||
|
@ -15023,7 +15319,6 @@ re_scan:
|
|||
POP_I32();
|
||||
POP_STRINGREF();
|
||||
PUSH_I32();
|
||||
(void)memidx;
|
||||
break;
|
||||
}
|
||||
case WASM_OP_STRING_CONCAT:
|
||||
|
@ -15064,8 +15359,6 @@ re_scan:
|
|||
case WASM_OP_STRINGVIEW_WTF8_ENCODE_LOSSY_UTF8:
|
||||
case WASM_OP_STRINGVIEW_WTF8_ENCODE_WTF8:
|
||||
{
|
||||
uint32 memidx;
|
||||
|
||||
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
|
||||
func->has_memory_operations = true;
|
||||
#endif
|
||||
|
@ -15080,7 +15373,6 @@ re_scan:
|
|||
POP_REF(REF_TYPE_STRINGVIEWWTF8);
|
||||
PUSH_I32();
|
||||
PUSH_I32();
|
||||
(void)memidx;
|
||||
break;
|
||||
}
|
||||
case WASM_OP_STRINGVIEW_WTF8_SLICE:
|
||||
|
@ -15112,8 +15404,6 @@ re_scan:
|
|||
}
|
||||
case WASM_OP_STRINGVIEW_WTF16_ENCODE:
|
||||
{
|
||||
uint32 memidx;
|
||||
|
||||
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
|
||||
func->has_memory_operations = true;
|
||||
#endif
|
||||
|
@ -15127,7 +15417,6 @@ re_scan:
|
|||
POP_I32();
|
||||
POP_REF(REF_TYPE_STRINGVIEWWTF16);
|
||||
PUSH_I32();
|
||||
(void)memidx;
|
||||
break;
|
||||
}
|
||||
case WASM_OP_STRINGVIEW_WTF16_SLICE:
|
||||
|
|
|
@ -261,6 +261,9 @@ typedef struct InitValue {
|
|||
uint8 type;
|
||||
uint8 flag;
|
||||
WASMValue value;
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
InitializerExpression *expr;
|
||||
#endif
|
||||
} InitValue;
|
||||
|
||||
typedef struct ConstExprContext {
|
||||
|
@ -282,7 +285,11 @@ init_const_expr_stack(ConstExprContext *ctx, WASMModule *module)
|
|||
|
||||
static bool
|
||||
push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type,
|
||||
WASMValue *value, char *error_buf, uint32 error_buf_size)
|
||||
WASMValue *value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
InitializerExpression *expr,
|
||||
#endif
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
InitValue *cur_value;
|
||||
|
||||
|
@ -305,6 +312,9 @@ push_const_expr_stack(ConstExprContext *ctx, uint8 flag, uint8 type,
|
|||
cur_value->type = type;
|
||||
cur_value->flag = flag;
|
||||
cur_value->value = *value;
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
cur_value->expr = expr;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
fail:
|
||||
|
@ -313,7 +323,11 @@ fail:
|
|||
|
||||
static bool
|
||||
pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type,
|
||||
WASMValue *p_value, char *error_buf, uint32 error_buf_size)
|
||||
WASMValue *p_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
InitializerExpression **p_expr,
|
||||
#endif
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
InitValue *cur_value;
|
||||
|
||||
|
@ -331,18 +345,50 @@ pop_const_expr_stack(ConstExprContext *ctx, uint8 *p_flag, uint8 type,
|
|||
*p_flag = cur_value->flag;
|
||||
if (p_value)
|
||||
*p_value = cur_value->value;
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
if (p_expr)
|
||||
*p_expr = cur_value->expr;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_const_expr_stack(ConstExprContext *ctx)
|
||||
destroy_const_expr_stack(ConstExprContext *ctx, bool free_exprs)
|
||||
{
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
if (free_exprs) {
|
||||
for (uint32 j = 0; j < ctx->sp; j++) {
|
||||
if (is_expr_binary_op(ctx->stack[j].expr->init_expr_type)) {
|
||||
destroy_init_expr_recursive(ctx->stack[j].expr);
|
||||
ctx->stack[j].expr = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ctx->stack != ctx->data) {
|
||||
wasm_runtime_free(ctx->stack);
|
||||
}
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
static void
|
||||
destroy_init_expr(InitializerExpression *expr)
|
||||
{
|
||||
// free left expr and right exprs for binary oprand
|
||||
if (is_expr_binary_op(expr->init_expr_type)) {
|
||||
return;
|
||||
}
|
||||
if (expr->u.binary.l_expr) {
|
||||
destroy_init_expr_recursive(expr->u.binary.l_expr);
|
||||
}
|
||||
if (expr->u.binary.r_expr) {
|
||||
destroy_init_expr_recursive(expr->u.binary.r_expr);
|
||||
}
|
||||
expr->u.binary.l_expr = expr->u.binary.r_expr = NULL;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
|
||||
|
||||
static bool
|
||||
load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
||||
InitializerExpression *init_expr, uint8 type, char *error_buf,
|
||||
|
@ -353,6 +399,9 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
uint32 i;
|
||||
ConstExprContext const_expr_ctx = { 0 };
|
||||
WASMValue cur_value = { 0 };
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
InitializerExpression *cur_expr = NULL;
|
||||
#endif
|
||||
|
||||
init_const_expr_stack(&const_expr_ctx, module);
|
||||
|
||||
|
@ -367,8 +416,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_I32, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
/* i64.const */
|
||||
|
@ -377,8 +429,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_I64, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
/* f32.const */
|
||||
|
@ -390,8 +445,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_F32, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
/* f64.const */
|
||||
|
@ -403,8 +461,11 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_F64, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -417,13 +478,16 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
cur_value.ref_index = func_idx;
|
||||
if (!check_function_index(module, func_idx, error_buf,
|
||||
error_buf_size)) {
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag,
|
||||
VALUE_TYPE_FUNCREF, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -438,9 +502,12 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
|
||||
cur_value.ref_index = UINT32_MAX;
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag, type1,
|
||||
&cur_value, error_buf,
|
||||
error_buf_size)) {
|
||||
bh_assert(0);
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -471,15 +538,93 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
}
|
||||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag, global_type,
|
||||
&cur_value, error_buf,
|
||||
error_buf_size))
|
||||
bh_assert(0);
|
||||
&cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
NULL,
|
||||
#endif
|
||||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
|
||||
break;
|
||||
}
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
case INIT_EXPR_TYPE_I32_ADD:
|
||||
case INIT_EXPR_TYPE_I64_ADD:
|
||||
case INIT_EXPR_TYPE_I32_SUB:
|
||||
case INIT_EXPR_TYPE_I64_SUB:
|
||||
case INIT_EXPR_TYPE_I32_MUL:
|
||||
case INIT_EXPR_TYPE_I64_MUL:
|
||||
{
|
||||
InitializerExpression *l_expr, *r_expr;
|
||||
WASMValue l_value, r_value;
|
||||
uint8 l_flag, r_flag;
|
||||
uint8 value_type;
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_I32_ADD
|
||||
|| flag == INIT_EXPR_TYPE_I32_SUB
|
||||
|| flag == INIT_EXPR_TYPE_I32_MUL) {
|
||||
value_type = VALUE_TYPE_I32;
|
||||
}
|
||||
else {
|
||||
value_type = VALUE_TYPE_I64;
|
||||
}
|
||||
|
||||
/* If right flag indicates a binary operation, right expr will
|
||||
* be popped from stack. Otherwise, allocate a new expr for
|
||||
* right expr. Same for left expr.
|
||||
*/
|
||||
if (!(pop_const_expr_stack(&const_expr_ctx, &r_flag, value_type,
|
||||
&r_value, &r_expr, error_buf,
|
||||
error_buf_size))) {
|
||||
goto fail;
|
||||
}
|
||||
if (!is_expr_binary_op(r_flag)) {
|
||||
if (!(r_expr = loader_malloc(sizeof(InitializerExpression),
|
||||
error_buf, error_buf_size))) {
|
||||
goto fail;
|
||||
}
|
||||
r_expr->init_expr_type = r_flag;
|
||||
r_expr->u.unary.v = r_value;
|
||||
}
|
||||
|
||||
if (!(pop_const_expr_stack(&const_expr_ctx, &l_flag, value_type,
|
||||
&l_value, &l_expr, error_buf,
|
||||
error_buf_size))) {
|
||||
destroy_init_expr_recursive(r_expr);
|
||||
goto fail;
|
||||
}
|
||||
if (!is_expr_binary_op(l_flag)) {
|
||||
if (!(l_expr = loader_malloc(sizeof(InitializerExpression),
|
||||
error_buf, error_buf_size))) {
|
||||
destroy_init_expr_recursive(r_expr);
|
||||
goto fail;
|
||||
}
|
||||
l_expr->init_expr_type = l_flag;
|
||||
l_expr->u.unary.v = l_value;
|
||||
}
|
||||
|
||||
if (!(cur_expr = loader_malloc(sizeof(InitializerExpression),
|
||||
error_buf, error_buf_size))) {
|
||||
destroy_init_expr_recursive(l_expr);
|
||||
destroy_init_expr_recursive(r_expr);
|
||||
goto fail;
|
||||
}
|
||||
cur_expr->init_expr_type = flag;
|
||||
cur_expr->u.binary.l_expr = l_expr;
|
||||
cur_expr->u.binary.r_expr = r_expr;
|
||||
|
||||
if (!push_const_expr_stack(&const_expr_ctx, flag, value_type,
|
||||
&cur_value, cur_expr, error_buf,
|
||||
error_buf_size)) {
|
||||
destroy_init_expr_recursive(cur_expr);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -489,18 +634,42 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
|||
|
||||
/* There should be only one value left on the init value stack */
|
||||
if (!pop_const_expr_stack(&const_expr_ctx, &flag, type, &cur_value,
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
&cur_expr,
|
||||
#endif
|
||||
error_buf, error_buf_size)) {
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bh_assert(const_expr_ctx.sp == 0);
|
||||
if (const_expr_ctx.sp != 0) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"type mismatch: illegal constant opcode sequence");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
if (cur_expr != NULL) {
|
||||
bh_memcpy_s(init_expr, sizeof(InitializerExpression), cur_expr,
|
||||
sizeof(InitializerExpression));
|
||||
wasm_runtime_free(cur_expr);
|
||||
}
|
||||
else {
|
||||
init_expr->init_expr_type = flag;
|
||||
init_expr->u.unary.v = cur_value;
|
||||
}
|
||||
|
||||
#else
|
||||
init_expr->init_expr_type = flag;
|
||||
init_expr->u = cur_value;
|
||||
init_expr->u.unary.v = cur_value;
|
||||
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
|
||||
|
||||
*p_buf = p;
|
||||
destroy_const_expr_stack(&const_expr_ctx);
|
||||
destroy_const_expr_stack(&const_expr_ctx, false);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
destroy_const_expr_stack(&const_expr_ctx, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1226,7 +1395,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|||
* we shall make a copy of code body [p_code, p_code + code_size]
|
||||
* when we are worrying about inappropriate releasing behaviour.
|
||||
* all code bodies are actually in a buffer which user allocates in
|
||||
* his embedding environment and we don't have power on them.
|
||||
* their embedding environment and we don't have power over them.
|
||||
* it will be like:
|
||||
* code_body_cp = malloc(code_size);
|
||||
* memcpy(code_body_cp, p_code, code_size);
|
||||
|
@ -1385,13 +1554,14 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
* global.get instructions are
|
||||
* only allowed to refer to imported globals.
|
||||
*/
|
||||
uint32 target_global_index = global->init_expr.u.global_index;
|
||||
uint32 target_global_index =
|
||||
global->init_expr.u.unary.v.global_index;
|
||||
bh_assert(target_global_index < module->import_global_count);
|
||||
(void)target_global_index;
|
||||
}
|
||||
else if (INIT_EXPR_TYPE_FUNCREF_CONST
|
||||
== global->init_expr.init_expr_type) {
|
||||
bh_assert(global->init_expr.u.ref_index
|
||||
bh_assert(global->init_expr.u.unary.v.ref_index
|
||||
< module->import_function_count
|
||||
+ module->function_count);
|
||||
}
|
||||
|
@ -1575,7 +1745,7 @@ load_func_index_vec(const uint8 **p_buf, const uint8 *buf_end,
|
|||
}
|
||||
|
||||
init_expr->init_expr_type = INIT_EXPR_TYPE_FUNCREF_CONST;
|
||||
init_expr->u.ref_index = function_index;
|
||||
init_expr->u.unary.v.ref_index = function_index;
|
||||
}
|
||||
|
||||
*p_buf = p;
|
||||
|
@ -1890,6 +2060,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
|
|||
|
||||
if (!(dataseg = module->data_segments[i] = loader_malloc(
|
||||
sizeof(WASMDataSeg), error_buf, error_buf_size))) {
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
destroy_init_expr(&init_expr);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2778,7 +2951,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
&& global->init_expr.init_expr_type
|
||||
== INIT_EXPR_TYPE_I32_CONST) {
|
||||
aux_heap_base_global = global;
|
||||
aux_heap_base = (uint64)(uint32)global->init_expr.u.i32;
|
||||
aux_heap_base =
|
||||
(uint64)(uint32)global->init_expr.u.unary.v.i32;
|
||||
aux_heap_base_global_index = export->index;
|
||||
LOG_VERBOSE("Found aux __heap_base global, value: %" PRIu64,
|
||||
aux_heap_base);
|
||||
|
@ -2798,7 +2972,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
&& global->init_expr.init_expr_type
|
||||
== INIT_EXPR_TYPE_I32_CONST) {
|
||||
aux_data_end_global = global;
|
||||
aux_data_end = (uint64)(uint32)global->init_expr.u.i32;
|
||||
aux_data_end =
|
||||
(uint64)(uint32)global->init_expr.u.unary.v.i32;
|
||||
aux_data_end_global_index = export->index;
|
||||
LOG_VERBOSE("Found aux __data_end global, value: %" PRIu64,
|
||||
aux_data_end);
|
||||
|
@ -2838,10 +3013,11 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
&& global->type.val_type == VALUE_TYPE_I32
|
||||
&& global->init_expr.init_expr_type
|
||||
== INIT_EXPR_TYPE_I32_CONST
|
||||
&& (uint64)(uint32)global->init_expr.u.i32
|
||||
&& (uint64)(uint32)global->init_expr.u.unary.v.i32
|
||||
<= aux_heap_base) {
|
||||
aux_stack_top_global = global;
|
||||
aux_stack_top = (uint64)(uint32)global->init_expr.u.i32;
|
||||
aux_stack_top =
|
||||
(uint64)(uint32)global->init_expr.u.unary.v.i32;
|
||||
module->aux_stack_top_global_index =
|
||||
module->import_global_count + global_index;
|
||||
module->aux_stack_bottom = aux_stack_top;
|
||||
|
@ -3140,10 +3316,16 @@ create_module(char *name, char *error_buf, uint32 error_buf_size)
|
|||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
#if WASM_ENABLE_LIBC_UVWASI == 0
|
||||
module->wasi_args.stdio[0] = os_invalid_raw_handle();
|
||||
module->wasi_args.stdio[1] = os_invalid_raw_handle();
|
||||
module->wasi_args.stdio[2] = os_invalid_raw_handle();
|
||||
#endif
|
||||
#else
|
||||
module->wasi_args.stdio[0] = os_get_invalid_handle();
|
||||
module->wasi_args.stdio[1] = os_get_invalid_handle();
|
||||
module->wasi_args.stdio[2] = os_get_invalid_handle();
|
||||
#endif /* WASM_ENABLE_UVWASI == 0 */
|
||||
#endif /* WASM_ENABLE_LIBC_WASI != 0 */
|
||||
|
||||
(void)ret;
|
||||
return module;
|
||||
|
@ -3442,8 +3624,14 @@ wasm_loader_unload(WASMModule *module)
|
|||
if (module->memories)
|
||||
wasm_runtime_free(module->memories);
|
||||
|
||||
if (module->globals)
|
||||
if (module->globals) {
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
for (i = 0; i < module->global_count; i++) {
|
||||
destroy_init_expr(&module->globals[i].init_expr);
|
||||
}
|
||||
#endif
|
||||
wasm_runtime_free(module->globals);
|
||||
}
|
||||
|
||||
if (module->exports)
|
||||
wasm_runtime_free(module->exports);
|
||||
|
@ -3452,6 +3640,9 @@ wasm_loader_unload(WASMModule *module)
|
|||
for (i = 0; i < module->table_seg_count; i++) {
|
||||
if (module->table_segments[i].init_values)
|
||||
wasm_runtime_free(module->table_segments[i].init_values);
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
destroy_init_expr(&module->table_segments[i].base_offset);
|
||||
#endif
|
||||
}
|
||||
wasm_runtime_free(module->table_segments);
|
||||
}
|
||||
|
@ -3461,6 +3652,9 @@ wasm_loader_unload(WASMModule *module)
|
|||
if (module->data_segments[i]) {
|
||||
if (module->data_segments[i]->is_data_cloned)
|
||||
wasm_runtime_free(module->data_segments[i]->data);
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
destroy_init_expr(&module->data_segments[i]->base_offset);
|
||||
#endif
|
||||
wasm_runtime_free(module->data_segments[i]);
|
||||
}
|
||||
}
|
||||
|
@ -7314,7 +7508,8 @@ re_scan:
|
|||
== VALUE_TYPE_FUNCREF
|
||||
&& module->globals[i].init_expr.init_expr_type
|
||||
== INIT_EXPR_TYPE_FUNCREF_CONST
|
||||
&& module->globals[i].init_expr.u.u32 == func_idx) {
|
||||
&& module->globals[i].init_expr.u.unary.v.ref_index
|
||||
== func_idx) {
|
||||
func_declared = true;
|
||||
break;
|
||||
}
|
||||
|
@ -7328,7 +7523,8 @@ re_scan:
|
|||
i++, table_seg++) {
|
||||
if (table_seg->elem_type == VALUE_TYPE_FUNCREF) {
|
||||
for (j = 0; j < table_seg->value_count; j++) {
|
||||
if (table_seg->init_values[j].u.ref_index
|
||||
if (table_seg->init_values[j]
|
||||
.u.unary.v.ref_index
|
||||
== func_idx) {
|
||||
func_declared = true;
|
||||
break;
|
||||
|
|
|
@ -1165,6 +1165,81 @@ instantiate_array_global_recursive(WASMModule *module,
|
|||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
get_init_value_recursive(WASMModule *module, InitializerExpression *expr,
|
||||
WASMGlobalInstance *globals, WASMValue *value,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
uint8 flag = expr->init_expr_type;
|
||||
switch (flag) {
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
{
|
||||
if (!check_global_init_expr(module, expr->u.unary.v.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*value = globals[expr->u.unary.v.global_index].initial_value;
|
||||
break;
|
||||
}
|
||||
case INIT_EXPR_TYPE_I32_CONST:
|
||||
case INIT_EXPR_TYPE_I64_CONST:
|
||||
{
|
||||
*value = expr->u.unary.v;
|
||||
break;
|
||||
}
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
case INIT_EXPR_TYPE_I32_ADD:
|
||||
case INIT_EXPR_TYPE_I32_SUB:
|
||||
case INIT_EXPR_TYPE_I32_MUL:
|
||||
case INIT_EXPR_TYPE_I64_ADD:
|
||||
case INIT_EXPR_TYPE_I64_SUB:
|
||||
case INIT_EXPR_TYPE_I64_MUL:
|
||||
{
|
||||
WASMValue l_value, r_value;
|
||||
if (!expr->u.binary.l_expr || !expr->u.binary.r_expr) {
|
||||
goto fail;
|
||||
}
|
||||
if (!get_init_value_recursive(module, expr->u.binary.l_expr,
|
||||
globals, &l_value, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
if (!get_init_value_recursive(module, expr->u.binary.r_expr,
|
||||
globals, &r_value, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_I32_ADD) {
|
||||
value->i32 = l_value.i32 + r_value.i32;
|
||||
}
|
||||
else if (flag == INIT_EXPR_TYPE_I32_SUB) {
|
||||
value->i32 = l_value.i32 - r_value.i32;
|
||||
}
|
||||
else if (flag == INIT_EXPR_TYPE_I32_MUL) {
|
||||
value->i32 = l_value.i32 * r_value.i32;
|
||||
}
|
||||
else if (flag == INIT_EXPR_TYPE_I64_ADD) {
|
||||
value->i64 = l_value.i64 + r_value.i64;
|
||||
}
|
||||
else if (flag == INIT_EXPR_TYPE_I64_SUB) {
|
||||
value->i64 = l_value.i64 - r_value.i64;
|
||||
}
|
||||
else if (flag == INIT_EXPR_TYPE_I64_MUL) {
|
||||
value->i64 = l_value.i64 * r_value.i64;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_EXTENDED_CONST_EXPR != 0 */
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate globals in a module.
|
||||
*/
|
||||
|
@ -1209,7 +1284,7 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
|
|||
/* The linked global instance has been initialized, we
|
||||
just need to copy the value. */
|
||||
global->initial_value =
|
||||
global_import->import_global_linked->init_expr.u;
|
||||
global_import->import_global_linked->init_expr.u.unary.v;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -1245,17 +1320,23 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
|
|||
#endif
|
||||
|
||||
switch (flag) {
|
||||
case INIT_EXPR_TYPE_I32_CONST:
|
||||
case INIT_EXPR_TYPE_I64_CONST:
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
#if WASM_ENABLE_EXTENDED_CONST_EXPR != 0
|
||||
case INIT_EXPR_TYPE_I32_ADD:
|
||||
case INIT_EXPR_TYPE_I32_SUB:
|
||||
case INIT_EXPR_TYPE_I32_MUL:
|
||||
case INIT_EXPR_TYPE_I64_ADD:
|
||||
case INIT_EXPR_TYPE_I64_SUB:
|
||||
case INIT_EXPR_TYPE_I64_MUL:
|
||||
#endif
|
||||
{
|
||||
if (!check_global_init_expr(module, init_expr->u.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
if (!get_init_value_recursive(module, init_expr, globals,
|
||||
&global->initial_value, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bh_memcpy_s(
|
||||
&(global->initial_value), sizeof(WASMValue),
|
||||
&(globals[init_expr->u.global_index].initial_value),
|
||||
sizeof(globals[init_expr->u.global_index].initial_value));
|
||||
break;
|
||||
}
|
||||
#if WASM_ENABLE_GC != 0
|
||||
|
@ -1267,11 +1348,12 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
|
|||
uint32 type_idx;
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
|
||||
init_values = (WASMStructNewInitValues *)init_expr->u.data;
|
||||
init_values =
|
||||
(WASMStructNewInitValues *)init_expr->u.unary.v.data;
|
||||
type_idx = init_values->type_idx;
|
||||
}
|
||||
else {
|
||||
type_idx = init_expr->u.type_index;
|
||||
type_idx = init_expr->u.unary.v.type_index;
|
||||
}
|
||||
|
||||
struct_obj = instantiate_struct_global_recursive(
|
||||
|
@ -1294,12 +1376,14 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
|
|||
uint32 type_idx, len;
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
|
||||
type_idx = init_expr->u.array_new_default.type_index;
|
||||
len = init_expr->u.array_new_default.length;
|
||||
type_idx =
|
||||
init_expr->u.unary.v.array_new_default.type_index;
|
||||
len = init_expr->u.unary.v.array_new_default.length;
|
||||
array_init_value = &empty_value;
|
||||
}
|
||||
else {
|
||||
init_values = (WASMArrayNewInitValues *)init_expr->u.data;
|
||||
init_values =
|
||||
(WASMArrayNewInitValues *)init_expr->u.unary.v.data;
|
||||
type_idx = init_values->type_idx;
|
||||
len = init_values->length;
|
||||
|
||||
|
@ -1318,13 +1402,12 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
|
|||
case INIT_EXPR_TYPE_I31_NEW:
|
||||
{
|
||||
global->initial_value.gc_obj =
|
||||
(wasm_obj_t)wasm_i31_obj_new(init_expr->u.i32);
|
||||
(wasm_obj_t)wasm_i31_obj_new(init_expr->u.unary.v.i32);
|
||||
break;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
default:
|
||||
bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
|
||||
&(init_expr->u), sizeof(init_expr->u));
|
||||
global->initial_value = init_expr->u.unary.v;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2668,7 +2751,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
}
|
||||
STORE_PTR((void **)global_data, func_obj);
|
||||
global_data += sizeof(void *);
|
||||
/* Also update the inital_value since other globals may
|
||||
/* Also update the initial_value since other globals may
|
||||
* refer to this */
|
||||
global->initial_value.gc_obj = (wasm_obj_t)func_obj;
|
||||
break;
|
||||
|
@ -2698,6 +2781,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
uint8 *memory_data = NULL;
|
||||
uint64 memory_size = 0;
|
||||
WASMDataSeg *data_seg = module->data_segments[i];
|
||||
WASMValue offset_value;
|
||||
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
if (data_seg->is_passive)
|
||||
|
@ -2717,54 +2801,37 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
(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
|
||||
== INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| data_seg->base_offset.init_expr_type
|
||||
== (memory->is_memory64 ? INIT_EXPR_TYPE_I64_CONST
|
||||
: INIT_EXPR_TYPE_I32_CONST));
|
||||
uint8 offset_flag = data_seg->base_offset.init_expr_type;
|
||||
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| (memory->is_memory64 ? is_valid_i64_offset(offset_flag)
|
||||
: is_valid_i32_offset(offset_flag)));
|
||||
|
||||
if (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
if (!check_global_init_expr(module,
|
||||
data_seg->base_offset.u.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
if (!get_init_value_recursive(module, &data_seg->base_offset, globals,
|
||||
&offset_value, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (offset_flag == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
if (!globals
|
||||
|| globals[data_seg->base_offset.u.global_index].type
|
||||
|| globals[data_seg->base_offset.u.unary.v.global_index].type
|
||||
!= (memory->is_memory64 ? VALUE_TYPE_I64
|
||||
: VALUE_TYPE_I32)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"data segment does not fit");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
if (memory->is_memory64) {
|
||||
base_offset =
|
||||
(uint64)globals[data_seg->base_offset.u.global_index]
|
||||
.initial_value.i64;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
base_offset =
|
||||
(uint32)globals[data_seg->base_offset.u.global_index]
|
||||
.initial_value.i32;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
if (memory->is_memory64) {
|
||||
base_offset = (uint64)data_seg->base_offset.u.i64;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
base_offset = (uint32)data_seg->base_offset.u.i32;
|
||||
}
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
if (memory->is_memory64) {
|
||||
base_offset = (uint64)offset_value.i64;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
base_offset = (uint32)offset_value.i32;
|
||||
}
|
||||
/* check offset */
|
||||
if (base_offset > memory_size) {
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
|
@ -2818,6 +2885,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
#else
|
||||
module_inst->e->shared_heap_start_off.u32[0] = UINT32_MAX;
|
||||
#endif
|
||||
module_inst->e->shared_heap = NULL;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
|
@ -2841,36 +2909,39 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
|| table->init_expr.init_expr_type == INIT_EXPR_TYPE_REFNULL_CONST);
|
||||
|
||||
if (table->init_expr.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
if (!check_global_init_expr(module, table->init_expr.u.global_index,
|
||||
if (!check_global_init_expr(module,
|
||||
table->init_expr.u.unary.v.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
table->init_expr.u.gc_obj =
|
||||
globals[table->init_expr.u.global_index].initial_value.gc_obj;
|
||||
table->init_expr.u.unary.v.gc_obj =
|
||||
globals[table->init_expr.u.unary.v.global_index]
|
||||
.initial_value.gc_obj;
|
||||
}
|
||||
else if (table->init_expr.init_expr_type
|
||||
== INIT_EXPR_TYPE_FUNCREF_CONST) {
|
||||
uint32 func_idx = table->init_expr.u.ref_index;
|
||||
uint32 func_idx = table->init_expr.u.unary.v.ref_index;
|
||||
if (func_idx != UINT32_MAX) {
|
||||
if (!(table->init_expr.u.gc_obj =
|
||||
if (!(table->init_expr.u.unary.v.gc_obj =
|
||||
wasm_create_func_obj(module_inst, func_idx, false,
|
||||
error_buf, error_buf_size)))
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
table->init_expr.u.gc_obj = NULL_REF;
|
||||
table->init_expr.u.unary.v.gc_obj = NULL_REF;
|
||||
}
|
||||
}
|
||||
else if (table->init_expr.init_expr_type
|
||||
== INIT_EXPR_TYPE_REFNULL_CONST) {
|
||||
table->init_expr.u.gc_obj = NULL_REF;
|
||||
table->init_expr.u.unary.v.gc_obj = NULL_REF;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Init table [%d] elements from [%d] to [%d] as: %p", i, 0,
|
||||
table_inst->cur_size, (void *)table->init_expr.u.gc_obj);
|
||||
table_inst->cur_size,
|
||||
(void *)table->init_expr.u.unary.v.gc_obj);
|
||||
for (j = 0; j < table_inst->cur_size; j++) {
|
||||
*(table_data + j) = table->init_expr.u.gc_obj;
|
||||
*(table_data + j) = table->init_expr.u.unary.v.gc_obj;
|
||||
}
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
|
@ -2882,6 +2953,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
/* has check it in loader */
|
||||
WASMTableInstance *table = module_inst->tables[table_seg->table_index];
|
||||
table_elem_type_t *table_data;
|
||||
WASMValue offset_value;
|
||||
uint32 j;
|
||||
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
|
||||
uint8 tbl_elem_type;
|
||||
|
@ -2940,48 +3012,37 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
continue;
|
||||
#endif
|
||||
|
||||
uint8 offset_flag = table_seg->base_offset.init_expr_type;
|
||||
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
|
||||
bh_assert(table_seg->base_offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_I32_CONST
|
||||
|| table_seg->base_offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| table_seg->base_offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_FUNCREF_CONST
|
||||
|| table_seg->base_offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_REFNULL_CONST);
|
||||
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| offset_flag == INIT_EXPR_TYPE_FUNCREF_CONST
|
||||
|| offset_flag == INIT_EXPR_TYPE_REFNULL_CONST
|
||||
|| is_valid_i32_offset(offset_flag));
|
||||
#else
|
||||
bh_assert(table_seg->base_offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_I32_CONST
|
||||
|| table_seg->base_offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_GET_GLOBAL);
|
||||
bh_assert(offset_flag == INIT_EXPR_TYPE_GET_GLOBAL
|
||||
|| is_valid_i32_offset(offset_flag));
|
||||
#endif
|
||||
|
||||
/* init vec(funcidx) or vec(expr) */
|
||||
if (table_seg->base_offset.init_expr_type
|
||||
== INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
if (!check_global_init_expr(module,
|
||||
table_seg->base_offset.u.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
if (!get_init_value_recursive(module, &table_seg->base_offset, globals,
|
||||
&offset_value, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (offset_flag == INIT_EXPR_TYPE_GET_GLOBAL) {
|
||||
if (!globals
|
||||
|| globals[table_seg->base_offset.u.global_index].type
|
||||
|| globals[table_seg->base_offset.u.unary.v.global_index].type
|
||||
!= VALUE_TYPE_I32) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"type mismatch: elements segment does not fit");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
table_seg->base_offset.u.i32 =
|
||||
globals[table_seg->base_offset.u.global_index]
|
||||
.initial_value.i32;
|
||||
}
|
||||
|
||||
/* check offset since length might negative */
|
||||
if ((uint32)table_seg->base_offset.u.i32 > table->cur_size) {
|
||||
LOG_DEBUG("base_offset(%d) > table->cur_size(%d)",
|
||||
table_seg->base_offset.u.i32, table->cur_size);
|
||||
if ((uint32)offset_value.i32 > table->cur_size) {
|
||||
LOG_DEBUG("base_offset(%d) > table->cur_size(%d)", offset_value.i32,
|
||||
table->cur_size);
|
||||
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"out of bounds table access");
|
||||
|
@ -2994,9 +3055,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
|
||||
/* check offset + length(could be zero) */
|
||||
length = table_seg->value_count;
|
||||
if ((uint32)table_seg->base_offset.u.i32 + length > table->cur_size) {
|
||||
if ((uint32)offset_value.i32 + length > table->cur_size) {
|
||||
LOG_DEBUG("base_offset(%d) + length(%d)> table->cur_size(%d)",
|
||||
table_seg->base_offset.u.i32, length, table->cur_size);
|
||||
offset_value.i32, length, table->cur_size);
|
||||
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"out of bounds table access");
|
||||
|
@ -3026,10 +3087,10 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
case INIT_EXPR_TYPE_FUNCREF_CONST:
|
||||
{
|
||||
#if WASM_ENABLE_GC == 0
|
||||
ref = (void *)(uintptr_t)init_expr->u.ref_index;
|
||||
ref = (void *)(uintptr_t)init_expr->u.unary.v.ref_index;
|
||||
#else
|
||||
WASMFuncObjectRef func_obj;
|
||||
uint32 func_idx = init_expr->u.ref_index;
|
||||
uint32 func_idx = init_expr->u.unary.v.ref_index;
|
||||
/* UINT32_MAX indicates that it is a null reference */
|
||||
if (func_idx != UINT32_MAX) {
|
||||
if (!(func_obj = wasm_create_func_obj(
|
||||
|
@ -3048,14 +3109,14 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
#if WASM_ENABLE_GC != 0
|
||||
case INIT_EXPR_TYPE_GET_GLOBAL:
|
||||
{
|
||||
if (!check_global_init_expr(module,
|
||||
init_expr->u.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
if (!check_global_init_expr(
|
||||
module, init_expr->u.unary.v.global_index,
|
||||
error_buf, error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ref =
|
||||
globals[init_expr->u.global_index].initial_value.gc_obj;
|
||||
ref = globals[init_expr->u.unary.v.global_index]
|
||||
.initial_value.gc_obj;
|
||||
break;
|
||||
}
|
||||
case INIT_EXPR_TYPE_STRUCT_NEW:
|
||||
|
@ -3068,12 +3129,12 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
uint32 type_idx;
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_STRUCT_NEW) {
|
||||
init_values =
|
||||
(WASMStructNewInitValues *)init_expr->u.data;
|
||||
init_values = (WASMStructNewInitValues *)
|
||||
init_expr->u.unary.v.data;
|
||||
type_idx = init_values->type_idx;
|
||||
}
|
||||
else {
|
||||
type_idx = init_expr->u.type_index;
|
||||
type_idx = init_expr->u.unary.v.type_index;
|
||||
}
|
||||
|
||||
struct_type = (WASMStructType *)module->types[type_idx];
|
||||
|
@ -3124,13 +3185,14 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
uint32 type_idx, len;
|
||||
|
||||
if (flag == INIT_EXPR_TYPE_ARRAY_NEW_DEFAULT) {
|
||||
type_idx = init_expr->u.array_new_default.type_index;
|
||||
len = init_expr->u.array_new_default.length;
|
||||
type_idx =
|
||||
init_expr->u.unary.v.array_new_default.type_index;
|
||||
len = init_expr->u.unary.v.array_new_default.length;
|
||||
arr_init_val = &empty_val;
|
||||
}
|
||||
else {
|
||||
init_values =
|
||||
(WASMArrayNewInitValues *)init_expr->u.data;
|
||||
(WASMArrayNewInitValues *)init_expr->u.unary.v.data;
|
||||
type_idx = init_values->type_idx;
|
||||
len = init_values->length;
|
||||
|
||||
|
@ -3176,14 +3238,14 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
|||
}
|
||||
case INIT_EXPR_TYPE_I31_NEW:
|
||||
{
|
||||
ref = (wasm_obj_t)wasm_i31_obj_new(init_expr->u.i32);
|
||||
ref =
|
||||
(wasm_obj_t)wasm_i31_obj_new(init_expr->u.unary.v.i32);
|
||||
break;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_GC != 0 */
|
||||
}
|
||||
|
||||
*(table_data + table_seg->base_offset.u.i32 + j) =
|
||||
(table_elem_type_t)ref;
|
||||
*(table_data + offset_value.i32 + j) = (table_elem_type_t)ref;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4161,7 +4223,7 @@ wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst,
|
|||
sizeof(WASMMemoryInstance *) * module_inst->memory_count;
|
||||
for (i = 0; i < module_inst->memory_count; i++) {
|
||||
WASMMemoryInstance *memory = module_inst->memories[i];
|
||||
size = memory->num_bytes_per_page * memory->cur_page_count;
|
||||
size = (uint64)memory->num_bytes_per_page * memory->cur_page_count;
|
||||
mem_conspn->memories_size += size;
|
||||
mem_conspn->app_heap_size += memory->heap_data_end - memory->heap_data;
|
||||
/* size of app heap structure */
|
||||
|
@ -4195,9 +4257,9 @@ wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst,
|
|||
#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
|
||||
|| (WASM_ENABLE_MEMORY_TRACING != 0) */
|
||||
|
||||
#if WAMR_ENABLE_COPY_CALLSTACK != 0
|
||||
#if WASM_ENABLE_COPY_CALL_STACK != 0
|
||||
uint32
|
||||
wasm_interp_copy_callstack(WASMExecEnv *exec_env, wasm_frame_t *buffer,
|
||||
wasm_interp_copy_callstack(WASMExecEnv *exec_env, WASMCApiFrame *buffer,
|
||||
uint32 length, uint32 skip_n, char *error_buf,
|
||||
uint32_t error_buf_size)
|
||||
{
|
||||
|
@ -4242,7 +4304,7 @@ wasm_interp_copy_callstack(WASMExecEnv *exec_env, wasm_frame_t *buffer,
|
|||
}
|
||||
return count >= skip_n ? count - skip_n : 0;
|
||||
}
|
||||
#endif // WAMR_ENABLE_COPY_CALLSTACK
|
||||
#endif // WASM_ENABLE_COPY_CALL_STACK
|
||||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||
bool
|
||||
|
@ -4705,10 +4767,10 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
|||
for (i = 0; i < length; i++) {
|
||||
#if WASM_ENABLE_GC != 0
|
||||
/* UINT32_MAX indicates that it is a null ref */
|
||||
if (init_values[i].u.ref_index != UINT32_MAX) {
|
||||
if (!(func_obj = wasm_create_func_obj(module_inst,
|
||||
init_values[i].u.ref_index,
|
||||
true, NULL, 0))) {
|
||||
if (init_values[i].u.unary.v.ref_index != UINT32_MAX) {
|
||||
if (!(func_obj = wasm_create_func_obj(
|
||||
module_inst, init_values[i].u.unary.v.ref_index, true,
|
||||
NULL, 0))) {
|
||||
wasm_set_exception(module_inst, "null function reference");
|
||||
return;
|
||||
}
|
||||
|
@ -4718,7 +4780,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
|||
table_elems[i] = NULL_REF;
|
||||
}
|
||||
#else
|
||||
table_elems[i] = init_values[i].u.ref_index;
|
||||
table_elems[i] = init_values[i].u.unary.v.ref_index;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,12 +93,21 @@ typedef union {
|
|||
} MemBound;
|
||||
|
||||
typedef struct WASMSharedHeap {
|
||||
struct WASMSharedHeap *next;
|
||||
void *heap_handle;
|
||||
uint8 *base_addr;
|
||||
/* The global shared heap list maintained in runtime, used for runtime
|
||||
* destroy */
|
||||
DefPointer(struct WASMSharedHeap *, next);
|
||||
/* The logical shared heap chain the shared heap in */
|
||||
DefPointer(struct WASMSharedHeap *, chain_next);
|
||||
/* Will be null if shared heap is created from pre allocated memory chunk
|
||||
* and don't need to dynamic malloc and free */
|
||||
DefPointer(void *, heap_handle);
|
||||
DefPointer(uint8 *, base_addr);
|
||||
uint64 size;
|
||||
uint64 start_off_mem64;
|
||||
uint64 start_off_mem32;
|
||||
/* The number of wasm apps it attached to, for a shared heap chain, only the
|
||||
* list head need to maintain the valid attached_count */
|
||||
uint8 attached_count;
|
||||
} WASMSharedHeap;
|
||||
|
||||
struct WASMMemoryInstance {
|
||||
|
@ -364,8 +373,6 @@ typedef struct WASMModuleInstanceExtra {
|
|||
#endif
|
||||
|
||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||
WASMSharedHeap *shared_heap;
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
/*
|
||||
* Adjusted shared heap based addr to simple the calculation
|
||||
* in the aot code. The value is:
|
||||
|
@ -373,7 +380,8 @@ typedef struct WASMModuleInstanceExtra {
|
|||
*/
|
||||
uint8 *shared_heap_base_addr_adj;
|
||||
MemBound shared_heap_start_off;
|
||||
#endif
|
||||
MemBound shared_heap_end_off;
|
||||
WASMSharedHeap *shared_heap;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
||||
|
@ -731,12 +739,12 @@ wasm_get_table_inst(const WASMModuleInstance *module_inst, uint32 tbl_idx)
|
|||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||
|
||||
#if WAMR_ENABLE_COPY_CALLSTACK != 0
|
||||
#if WASM_ENABLE_COPY_CALL_STACK != 0
|
||||
uint32
|
||||
wasm_interp_copy_callstack(WASMExecEnv *exec_env, wasm_frame_t *buffer,
|
||||
wasm_interp_copy_callstack(WASMExecEnv *exec_env, WASMCApiFrame *buffer,
|
||||
uint32 length, uint32 skip_n, char *error_buf,
|
||||
uint32_t error_buf_size);
|
||||
#endif // WAMR_ENABLE_COPY_CALLSTACK
|
||||
#endif // WASM_ENABLE_COPY_CALL_STACK
|
||||
|
||||
bool
|
||||
wasm_interp_create_call_stack(struct WASMExecEnv *exec_env);
|
||||
|
|
|
@ -743,7 +743,7 @@ wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 offset,
|
|||
module_inst = (WASMModuleInstance *)exec_env->module_inst;
|
||||
|
||||
if (offset + *size > module_inst->module->load_size) {
|
||||
LOG_VERBOSE("wasm_debug_instance_get_data_mem size over flow!\n");
|
||||
LOG_VERBOSE("wasm_debug_instance_get_data_mem size overflow!\n");
|
||||
*size = module_inst->module->load_size >= offset
|
||||
? module_inst->module->load_size - offset
|
||||
: 0;
|
||||
|
@ -797,7 +797,7 @@ wasm_debug_instance_get_linear_mem(WASMDebugInstance *instance, uint64 offset,
|
|||
num_bytes_per_page = memory->num_bytes_per_page;
|
||||
linear_mem_size = num_bytes_per_page * memory->cur_page_count;
|
||||
if (offset + *size > linear_mem_size) {
|
||||
LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n");
|
||||
LOG_VERBOSE("wasm_debug_instance_get_linear_mem size overflow!\n");
|
||||
*size = linear_mem_size >= offset ? linear_mem_size - offset : 0;
|
||||
}
|
||||
bh_memcpy_s(buf, (uint32)*size, memory->memory_data + offset,
|
||||
|
@ -830,7 +830,7 @@ wasm_debug_instance_set_linear_mem(WASMDebugInstance *instance, uint64 offset,
|
|||
num_bytes_per_page = memory->num_bytes_per_page;
|
||||
linear_mem_size = num_bytes_per_page * memory->cur_page_count;
|
||||
if (offset + *size > linear_mem_size) {
|
||||
LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n");
|
||||
LOG_VERBOSE("wasm_debug_instance_get_linear_mem size overflow!\n");
|
||||
*size = linear_mem_size >= offset ? linear_mem_size - offset : 0;
|
||||
}
|
||||
bh_memcpy_s(memory->memory_data + offset, (uint32)*size, buf,
|
||||
|
|
|
@ -175,6 +175,19 @@ process_wasm_global(WASMGDBServer *server, char *args)
|
|||
os_mutex_unlock(&tmpbuf_lock);
|
||||
}
|
||||
|
||||
/* TODO: let server send an empty/error reply.
|
||||
Original issue: 4265
|
||||
Not tested yet, but it should work.
|
||||
*/
|
||||
static void
|
||||
send_reply(WASMGDBServer *server, const char *err)
|
||||
{
|
||||
if (!err || !*err)
|
||||
write_packet(server, "");
|
||||
else
|
||||
write_packet(server, err);
|
||||
}
|
||||
|
||||
void
|
||||
handle_general_query(WASMGDBServer *server, char *payload)
|
||||
{
|
||||
|
@ -214,6 +227,7 @@ handle_general_query(WASMGDBServer *server, char *payload)
|
|||
|
||||
if (!args) {
|
||||
LOG_ERROR("payload parse error during handle_general_query");
|
||||
send_reply(server, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -384,7 +398,7 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
|
|||
if (status == 0) {
|
||||
os_mutex_lock(&tmpbuf_lock);
|
||||
(void)snprintf(tmpbuf, MAX_PACKET_SIZE, "W%02" PRIx32, status);
|
||||
write_packet(server, tmpbuf);
|
||||
send_reply(server, tmpbuf);
|
||||
os_mutex_unlock(&tmpbuf_lock);
|
||||
return;
|
||||
}
|
||||
|
@ -403,6 +417,7 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
|
|||
"T%02" PRIx32 "thread:%" PRIx64 ";name:%s;", gdb_status,
|
||||
(uint64)(uintptr_t)tid, "nobody");
|
||||
if (len < 0 || len >= MAX_PACKET_SIZE) {
|
||||
send_reply(server, "E01");
|
||||
os_mutex_unlock(&tmpbuf_lock);
|
||||
return;
|
||||
}
|
||||
|
@ -410,6 +425,7 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
|
|||
if (tids_count > 0) {
|
||||
int n = snprintf(tmpbuf + len, MAX_PACKET_SIZE - len, "threads:");
|
||||
if (n < 0 || n >= MAX_PACKET_SIZE - len) {
|
||||
send_reply(server, "E01");
|
||||
os_mutex_unlock(&tmpbuf_lock);
|
||||
return;
|
||||
}
|
||||
|
@ -426,6 +442,7 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
|
|||
}
|
||||
|
||||
if (n < 0 || n >= MAX_PACKET_SIZE - len) {
|
||||
send_reply(server, "E01");
|
||||
os_mutex_unlock(&tmpbuf_lock);
|
||||
return;
|
||||
}
|
||||
|
@ -452,6 +469,7 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
|
|||
"thread-pcs:%" PRIx64 ";00:%s;reason:%s;description:", pc,
|
||||
pc_string, "exception");
|
||||
if (n < 0 || n >= MAX_PACKET_SIZE - len) {
|
||||
send_reply(server, "E01");
|
||||
os_mutex_unlock(&tmpbuf_lock);
|
||||
return;
|
||||
}
|
||||
|
@ -462,6 +480,7 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
|
|||
n = snprintf(tmpbuf + len, MAX_PACKET_SIZE - len, "%02x",
|
||||
exception[i]);
|
||||
if (n < 0 || n >= MAX_PACKET_SIZE - len) {
|
||||
send_reply(server, "E01");
|
||||
os_mutex_unlock(&tmpbuf_lock);
|
||||
return;
|
||||
}
|
||||
|
@ -592,7 +611,7 @@ handle_get_register(WASMGDBServer *server, char *payload)
|
|||
int32 i = strtol(payload, NULL, 16);
|
||||
|
||||
if (i != 0) {
|
||||
write_packet(server, "E01");
|
||||
send_reply(server, "E01");
|
||||
return;
|
||||
}
|
||||
regdata = wasm_debug_instance_get_pc(
|
||||
|
@ -748,7 +767,7 @@ handle_add_break(WASMGDBServer *server, char *payload)
|
|||
if ((arg_c = sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length))
|
||||
!= 3) {
|
||||
LOG_ERROR("Unsupported number of add break arguments %d", arg_c);
|
||||
write_packet(server, "");
|
||||
send_reply(server, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -783,7 +802,7 @@ handle_remove_break(WASMGDBServer *server, char *payload)
|
|||
if ((arg_c = sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length))
|
||||
!= 3) {
|
||||
LOG_ERROR("Unsupported number of remove break arguments %d", arg_c);
|
||||
write_packet(server, "");
|
||||
send_reply(server, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -835,6 +854,7 @@ handle_malloc(WASMGDBServer *server, char *payload)
|
|||
}
|
||||
else {
|
||||
LOG_ERROR("Payload parse error during handle malloc");
|
||||
send_reply(server, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,26 @@
|
|||
#include <wasi/api.h>
|
||||
#include <wasi_socket_ext.h>
|
||||
|
||||
/*
|
||||
* Avoid direct TLS access to allow a single library to be
|
||||
* linked to both of threaded and non-threaded applications.
|
||||
*
|
||||
* wasi-libc's errno is a TLS variable, exposed directly via
|
||||
* errno.h. if we use it here, LLVM may lower it differently,
|
||||
* depending on enabled features like atomcs and bulk-memory.
|
||||
* we tweak the way to access errno here in order to make us
|
||||
* compatible with both of threaded and non-threaded applications.
|
||||
* __errno_location() should be reasonably stable because
|
||||
* it was introduced as an alternative ABI for non-C software.
|
||||
* https://github.com/WebAssembly/wasi-libc/pull/347
|
||||
*/
|
||||
#if defined(errno)
|
||||
#undef errno
|
||||
#endif
|
||||
int *
|
||||
__errno_location(void);
|
||||
#define errno (*__errno_location())
|
||||
|
||||
#define HANDLE_ERROR(error) \
|
||||
if (error != __WASI_ERRNO_SUCCESS) { \
|
||||
errno = error; \
|
||||
|
|
|
@ -43,7 +43,7 @@ else()
|
|||
FetchContent_Declare(
|
||||
uvwasi
|
||||
GIT_REPOSITORY https://github.com/nodejs/uvwasi.git
|
||||
GIT_TAG v0.0.21
|
||||
GIT_TAG 392e1f1c1c8a2d2102c9f2e0b9f35959a149d133
|
||||
)
|
||||
FetchContent_MakeAvailable(uvwasi)
|
||||
include_directories("${uvwasi_SOURCE_DIR}/include")
|
||||
|
|
|
@ -890,24 +890,6 @@ wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path,
|
|||
if (!uvwasi)
|
||||
return (wasi_errno_t)-1;
|
||||
|
||||
/*
|
||||
* check if old_path is valid.
|
||||
* if it is a symlink, follow it.
|
||||
*
|
||||
* this is a workaround for the fact that
|
||||
* uvwasi_path_symlink does not check if the old_path is valid
|
||||
*
|
||||
* the goal is trigger uvwasi__resolve_path() to check
|
||||
*/
|
||||
{
|
||||
uvwasi_filestat_t filestat = { 0 };
|
||||
wasi_errno_t err =
|
||||
uvwasi_path_filestat_get(uvwasi, fd, UVWASI_LOOKUP_SYMLINK_FOLLOW,
|
||||
old_path, old_path_len, &filestat);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return uvwasi_path_symlink(uvwasi, old_path, old_path_len, fd, new_path,
|
||||
new_path_len);
|
||||
}
|
||||
|
|
|
@ -375,6 +375,9 @@ wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app,
|
|||
return (wasi_errno_t)-1;
|
||||
|
||||
total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len;
|
||||
if (total_size == 0) {
|
||||
total_size = 1; /* avoid user-triggered 0-sized allocation */
|
||||
}
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
|
||||
return (wasi_errno_t)-1;
|
||||
|
@ -430,6 +433,9 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd,
|
|||
return (wasi_errno_t)-1;
|
||||
|
||||
total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len;
|
||||
if (total_size == 0) {
|
||||
total_size = 1; /* avoid user-triggered 0-sized allocation */
|
||||
}
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
|
||||
return (wasi_errno_t)-1;
|
||||
|
@ -484,6 +490,9 @@ wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd,
|
|||
return (wasi_errno_t)-1;
|
||||
|
||||
total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len;
|
||||
if (total_size == 0) {
|
||||
total_size = 1; /* avoid user-triggered 0-sized allocation */
|
||||
}
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
|
||||
return (wasi_errno_t)-1;
|
||||
|
@ -654,6 +663,9 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd,
|
|||
return (wasi_errno_t)-1;
|
||||
|
||||
total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len;
|
||||
if (total_size == 0) {
|
||||
total_size = 1; /* avoid user-triggered 0-sized allocation */
|
||||
}
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
|
||||
return (wasi_errno_t)-1;
|
||||
|
|
|
@ -301,7 +301,8 @@ wasm_cluster_create(WASMExecEnv *exec_env)
|
|||
aux_stack_start -= cluster->stack_size;
|
||||
|
||||
for (i = 0; i < cluster_max_thread_num; i++) {
|
||||
cluster->stack_tops[i] = aux_stack_start - cluster->stack_size * i;
|
||||
cluster->stack_tops[i] =
|
||||
aux_stack_start - (uint64)cluster->stack_size * i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -37,7 +37,7 @@ There is a big difference between the two sets of functions, `tensor_type`.
|
|||
|
||||
```c
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
typedef enum { fp16 = 0, fp32, fp64, bf16, u8, i32, i64 } tensor_type;
|
||||
typedef enum { fp16 = 0, fp32, fp64, u8, i32, i64 } tensor_type;
|
||||
#else
|
||||
typedef enum { fp16 = 0, fp32, up8, ip32 } tensor_type;
|
||||
#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */
|
||||
|
|
12
core/iwasm/libraries/wasi-nn/include/wasi_ephemeral_nn.h
Normal file
12
core/iwasm/libraries/wasi-nn/include/wasi_ephemeral_nn.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright (C) 2025 Midokura Japan KK. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#define WASM_ENABLE_WASI_EPHEMERAL_NN 1
|
||||
#define WASI_NN_NAME(name) wasi_ephemeral_nn_##name
|
||||
|
||||
#include "wasi_nn.h"
|
||||
|
||||
#undef WASM_ENABLE_WASI_EPHEMERAL_NN
|
||||
#undef WASI_NN_NAME
|
|
@ -15,23 +15,43 @@
|
|||
#include <stdint.h>
|
||||
#include "wasi_nn_types.h"
|
||||
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
#define WASI_NN_IMPORT(name) \
|
||||
__attribute__((import_module("wasi_ephemeral_nn"), import_name(name)))
|
||||
#else
|
||||
#define WASI_NN_IMPORT(name) \
|
||||
__attribute__((import_module("wasi_nn"), import_name(name)))
|
||||
#warning You are using "wasi_nn", which is a legacy WAMR-specific ABI. It's deperecated and will likely be removed in future versions of WAMR. Please use "wasi_ephemeral_nn" instead. (For a WASM module, use the wasi_ephemeral_nn.h header instead. For the runtime configurations, enable WASM_ENABLE_WASI_EPHEMERAL_NN/WAMR_BUILD_WASI_EPHEMERAL_NN.)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Load an opaque sequence of bytes to use for inference.
|
||||
*
|
||||
* @param builder Model builder.
|
||||
* @param builder_len The size of model builder.
|
||||
* @param encoding Model encoding.
|
||||
* @param target Execution target.
|
||||
* @param g Graph.
|
||||
* @return wasi_nn_error Execution status.
|
||||
*/
|
||||
wasi_nn_error
|
||||
load(graph_builder_array *builder, graph_encoding encoding,
|
||||
execution_target target, graph *g)
|
||||
__attribute__((import_module("wasi_nn")));
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
WASI_NN_ERROR_TYPE
|
||||
WASI_NN_NAME(load)
|
||||
(WASI_NN_NAME(graph_builder) * builder, uint32_t builder_len,
|
||||
WASI_NN_NAME(graph_encoding) encoding, WASI_NN_NAME(execution_target) target,
|
||||
WASI_NN_NAME(graph) * g) WASI_NN_IMPORT("load");
|
||||
#else
|
||||
WASI_NN_ERROR_TYPE
|
||||
WASI_NN_NAME(load)
|
||||
(WASI_NN_NAME(graph_builder_array) * builder,
|
||||
WASI_NN_NAME(graph_encoding) encoding, WASI_NN_NAME(execution_target) target,
|
||||
WASI_NN_NAME(graph) * g) WASI_NN_IMPORT("load");
|
||||
#endif
|
||||
|
||||
wasi_nn_error
|
||||
load_by_name(const char *name, graph *g)
|
||||
__attribute__((import_module("wasi_nn")));
|
||||
WASI_NN_ERROR_TYPE
|
||||
WASI_NN_NAME(load_by_name)
|
||||
(const char *name, uint32_t name_len, WASI_NN_NAME(graph) * g)
|
||||
WASI_NN_IMPORT("load_by_name");
|
||||
|
||||
/**
|
||||
* INFERENCE
|
||||
|
@ -45,9 +65,10 @@ load_by_name(const char *name, graph *g)
|
|||
* @param ctx Execution context.
|
||||
* @return wasi_nn_error Execution status.
|
||||
*/
|
||||
wasi_nn_error
|
||||
init_execution_context(graph g, graph_execution_context *ctx)
|
||||
__attribute__((import_module("wasi_nn")));
|
||||
WASI_NN_ERROR_TYPE
|
||||
WASI_NN_NAME(init_execution_context)
|
||||
(WASI_NN_NAME(graph) g, WASI_NN_NAME(graph_execution_context) * ctx)
|
||||
WASI_NN_IMPORT("init_execution_context");
|
||||
|
||||
/**
|
||||
* @brief Define the inputs to use for inference.
|
||||
|
@ -57,9 +78,10 @@ init_execution_context(graph g, graph_execution_context *ctx)
|
|||
* @param tensor Input tensor.
|
||||
* @return wasi_nn_error Execution status.
|
||||
*/
|
||||
wasi_nn_error
|
||||
set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
|
||||
__attribute__((import_module("wasi_nn")));
|
||||
WASI_NN_ERROR_TYPE
|
||||
WASI_NN_NAME(set_input)
|
||||
(WASI_NN_NAME(graph_execution_context) ctx, uint32_t index,
|
||||
WASI_NN_NAME(tensor) * tensor) WASI_NN_IMPORT("set_input");
|
||||
|
||||
/**
|
||||
* @brief Compute the inference on the given inputs.
|
||||
|
@ -67,8 +89,9 @@ set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
|
|||
* @param ctx Execution context.
|
||||
* @return wasi_nn_error Execution status.
|
||||
*/
|
||||
wasi_nn_error
|
||||
compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn")));
|
||||
WASI_NN_ERROR_TYPE
|
||||
WASI_NN_NAME(compute)
|
||||
(WASI_NN_NAME(graph_execution_context) ctx) WASI_NN_IMPORT("compute");
|
||||
|
||||
/**
|
||||
* @brief Extract the outputs after inference.
|
||||
|
@ -82,9 +105,17 @@ compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn")));
|
|||
* copied number of bytes.
|
||||
* @return wasi_nn_error Execution status.
|
||||
*/
|
||||
wasi_nn_error
|
||||
get_output(graph_execution_context ctx, uint32_t index,
|
||||
tensor_data output_tensor, uint32_t *output_tensor_size)
|
||||
__attribute__((import_module("wasi_nn")));
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
WASI_NN_ERROR_TYPE
|
||||
WASI_NN_NAME(get_output)
|
||||
(WASI_NN_NAME(graph_execution_context) ctx, uint32_t index,
|
||||
uint8_t *output_tensor, uint32_t output_tensor_max_size,
|
||||
uint32_t *output_tensor_size) WASI_NN_IMPORT("get_output");
|
||||
#else
|
||||
WASI_NN_ERROR_TYPE
|
||||
WASI_NN_NAME(get_output)
|
||||
(graph_execution_context ctx, uint32_t index, uint8_t *output_tensor,
|
||||
uint32_t *output_tensor_size) WASI_NN_IMPORT("get_output");
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,42 +13,48 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* our host logic doesn't use any prefix. neither legacy wasi_nn.h does. */
|
||||
|
||||
#if !defined(__wasm__) || !defined(WASI_NN_NAME)
|
||||
#define WASI_NN_NAME(name) name
|
||||
#define WASI_NN_ERROR_NAME(name) name
|
||||
#define WASI_NN_TYPE_NAME(name) name
|
||||
#define WASI_NN_ENCODING_NAME(name) name
|
||||
#define WASI_NN_TARGET_NAME(name) name
|
||||
#define WASI_NN_ERROR_TYPE wasi_nn_error
|
||||
#else
|
||||
#define WASI_NN_ERROR_NAME(name) WASI_NN_NAME(error_##name)
|
||||
#define WASI_NN_TYPE_NAME(name) WASI_NN_NAME(type_##name)
|
||||
#define WASI_NN_ENCODING_NAME(name) WASI_NN_NAME(encoding_##name)
|
||||
#define WASI_NN_TARGET_NAME(name) WASI_NN_NAME(target_##name)
|
||||
#define WASI_NN_ERROR_TYPE WASI_NN_NAME(error);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ERRORS
|
||||
*
|
||||
*/
|
||||
|
||||
// sync up with
|
||||
// https://github.com/WebAssembly/wasi-nn/blob/main/wit/wasi-nn.wit#L136 Error
|
||||
// codes returned by functions in this API.
|
||||
// https://github.com/WebAssembly/wasi-nn/blob/71320d95b8c6d43f9af7f44e18b1839db85d89b4/wasi-nn.witx#L5-L17
|
||||
// Error codes returned by functions in this API.
|
||||
typedef enum {
|
||||
// No error occurred.
|
||||
success = 0,
|
||||
// Caller module passed an invalid argument.
|
||||
invalid_argument,
|
||||
// Invalid encoding.
|
||||
invalid_encoding,
|
||||
// The operation timed out.
|
||||
timeout,
|
||||
// Runtime Error.
|
||||
runtime_error,
|
||||
// Unsupported operation.
|
||||
unsupported_operation,
|
||||
// Graph is too large.
|
||||
too_large,
|
||||
// Graph not found.
|
||||
not_found,
|
||||
// The operation is insecure or has insufficient privilege to be performed.
|
||||
// e.g., cannot access a hardware feature requested
|
||||
security,
|
||||
// The operation failed for an unspecified reason.
|
||||
unknown,
|
||||
WASI_NN_ERROR_NAME(success) = 0,
|
||||
WASI_NN_ERROR_NAME(invalid_argument),
|
||||
WASI_NN_ERROR_NAME(invalid_encoding),
|
||||
WASI_NN_ERROR_NAME(missing_memory),
|
||||
WASI_NN_ERROR_NAME(busy),
|
||||
WASI_NN_ERROR_NAME(runtime_error),
|
||||
WASI_NN_ERROR_NAME(unsupported_operation),
|
||||
WASI_NN_ERROR_NAME(too_large),
|
||||
WASI_NN_ERROR_NAME(not_found),
|
||||
|
||||
// for WasmEdge-wasi-nn
|
||||
end_of_sequence = 100, // End of Sequence Found.
|
||||
context_full = 101, // Context Full.
|
||||
prompt_tool_long = 102, // Prompt Too Long.
|
||||
model_not_found = 103, // Model Not Found.
|
||||
} wasi_nn_error;
|
||||
WASI_NN_ERROR_NAME(end_of_sequence) = 100, // End of Sequence Found.
|
||||
WASI_NN_ERROR_NAME(context_full) = 101, // Context Full.
|
||||
WASI_NN_ERROR_NAME(prompt_tool_long) = 102, // Prompt Too Long.
|
||||
WASI_NN_ERROR_NAME(model_not_found) = 103, // Model Not Found.
|
||||
} WASI_NN_ERROR_TYPE;
|
||||
|
||||
/**
|
||||
* TENSOR
|
||||
|
@ -62,15 +68,27 @@ typedef enum {
|
|||
typedef struct {
|
||||
uint32_t *buf;
|
||||
uint32_t size;
|
||||
} tensor_dimensions;
|
||||
} WASI_NN_NAME(tensor_dimensions);
|
||||
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
// sync up with
|
||||
// https://github.com/WebAssembly/wasi-nn/blob/main/wit/wasi-nn.wit#L27
|
||||
// https://github.com/WebAssembly/wasi-nn/blob/71320d95b8c6d43f9af7f44e18b1839db85d89b4/wasi-nn.witx#L19-L28
|
||||
// The type of the elements in a tensor.
|
||||
typedef enum { fp16 = 0, fp32, fp64, bf16, u8, i32, i64 } tensor_type;
|
||||
typedef enum {
|
||||
WASI_NN_TYPE_NAME(fp16) = 0,
|
||||
WASI_NN_TYPE_NAME(fp32),
|
||||
WASI_NN_TYPE_NAME(fp64),
|
||||
WASI_NN_TYPE_NAME(u8),
|
||||
WASI_NN_TYPE_NAME(i32),
|
||||
WASI_NN_TYPE_NAME(i64),
|
||||
} WASI_NN_NAME(tensor_type);
|
||||
#else
|
||||
typedef enum { fp16 = 0, fp32, up8, ip32 } tensor_type;
|
||||
typedef enum {
|
||||
WASI_NN_TYPE_NAME(fp16) = 0,
|
||||
WASI_NN_TYPE_NAME(fp32),
|
||||
WASI_NN_TYPE_NAME(up8),
|
||||
WASI_NN_TYPE_NAME(ip32),
|
||||
} WASI_NN_NAME(tensor_type);
|
||||
#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */
|
||||
|
||||
// The tensor data.
|
||||
|
@ -81,19 +99,31 @@ typedef enum { fp16 = 0, fp32, up8, ip32 } tensor_type;
|
|||
// 4-byte f32 elements would have a data array of length 16). Naturally, this
|
||||
// representation requires some knowledge of how to lay out data in
|
||||
// memory--e.g., using row-major ordering--and could perhaps be improved.
|
||||
typedef uint8_t *tensor_data;
|
||||
#if !defined(__wasm__) || WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
typedef struct {
|
||||
uint8_t *buf;
|
||||
uint32_t size;
|
||||
} WASI_NN_NAME(tensor_data);
|
||||
#else
|
||||
typedef uint8_t *WASI_NN_NAME(tensor_data);
|
||||
#endif
|
||||
|
||||
// A tensor.
|
||||
typedef struct {
|
||||
// Describe the size of the tensor (e.g., 2x2x2x2 -> [2, 2, 2, 2]). To
|
||||
// represent a tensor containing a single value, use `[1]` for the tensor
|
||||
// dimensions.
|
||||
tensor_dimensions *dimensions;
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 && defined(__wasm__)
|
||||
WASI_NN_NAME(tensor_dimensions) dimensions;
|
||||
#else
|
||||
WASI_NN_NAME(tensor_dimensions) * dimensions;
|
||||
#endif
|
||||
// Describe the type of element in the tensor (e.g., f32).
|
||||
tensor_type type;
|
||||
uint8_t type;
|
||||
uint8_t _pad[3];
|
||||
// Contains the tensor data.
|
||||
tensor_data data;
|
||||
} tensor;
|
||||
WASI_NN_NAME(tensor_data) data;
|
||||
} WASI_NN_NAME(tensor);
|
||||
|
||||
/**
|
||||
* GRAPH
|
||||
|
@ -108,15 +138,15 @@ typedef struct {
|
|||
typedef struct {
|
||||
uint8_t *buf;
|
||||
uint32_t size;
|
||||
} graph_builder;
|
||||
} WASI_NN_NAME(graph_builder);
|
||||
|
||||
typedef struct {
|
||||
graph_builder *buf;
|
||||
WASI_NN_NAME(graph_builder) * buf;
|
||||
uint32_t size;
|
||||
} graph_builder_array;
|
||||
} WASI_NN_NAME(graph_builder_array);
|
||||
|
||||
// An execution graph for performing inference (i.e., a model).
|
||||
typedef uint32_t graph;
|
||||
typedef uint32_t WASI_NN_NAME(graph);
|
||||
|
||||
// sync up with
|
||||
// https://github.com/WebAssembly/wasi-nn/blob/main/wit/wasi-nn.wit#L75
|
||||
|
@ -124,56 +154,25 @@ typedef uint32_t graph;
|
|||
// various backends that encode (i.e., serialize) their graph IR with different
|
||||
// formats.
|
||||
typedef enum {
|
||||
openvino = 0,
|
||||
onnx,
|
||||
tensorflow,
|
||||
pytorch,
|
||||
tensorflowlite,
|
||||
ggml,
|
||||
autodetect,
|
||||
unknown_backend,
|
||||
} graph_encoding;
|
||||
WASI_NN_ENCODING_NAME(openvino) = 0,
|
||||
WASI_NN_ENCODING_NAME(onnx),
|
||||
WASI_NN_ENCODING_NAME(tensorflow),
|
||||
WASI_NN_ENCODING_NAME(pytorch),
|
||||
WASI_NN_ENCODING_NAME(tensorflowlite),
|
||||
WASI_NN_ENCODING_NAME(ggml),
|
||||
WASI_NN_ENCODING_NAME(autodetect),
|
||||
WASI_NN_ENCODING_NAME(unknown_backend),
|
||||
} WASI_NN_NAME(graph_encoding);
|
||||
|
||||
// Define where the graph should be executed.
|
||||
typedef enum execution_target { cpu = 0, gpu, tpu } execution_target;
|
||||
typedef enum WASI_NN_NAME(execution_target) {
|
||||
WASI_NN_TARGET_NAME(cpu) = 0,
|
||||
WASI_NN_TARGET_NAME(gpu),
|
||||
WASI_NN_TARGET_NAME(tpu),
|
||||
} WASI_NN_NAME(execution_target);
|
||||
|
||||
// Bind a `graph` to the input and output tensors for an inference.
|
||||
typedef uint32_t graph_execution_context;
|
||||
|
||||
/* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */
|
||||
|
||||
typedef wasi_nn_error (*LOAD)(void *, graph_builder_array *, graph_encoding,
|
||||
execution_target, graph *);
|
||||
typedef wasi_nn_error (*LOAD_BY_NAME)(void *, const char *, uint32_t, graph *);
|
||||
typedef wasi_nn_error (*LOAD_BY_NAME_WITH_CONFIG)(void *, const char *,
|
||||
uint32_t, void *, uint32_t,
|
||||
graph *);
|
||||
typedef wasi_nn_error (*INIT_EXECUTION_CONTEXT)(void *, graph,
|
||||
graph_execution_context *);
|
||||
typedef wasi_nn_error (*SET_INPUT)(void *, graph_execution_context, uint32_t,
|
||||
tensor *);
|
||||
typedef wasi_nn_error (*COMPUTE)(void *, graph_execution_context);
|
||||
typedef wasi_nn_error (*GET_OUTPUT)(void *, graph_execution_context, uint32_t,
|
||||
tensor_data, uint32_t *);
|
||||
/* wasi-nn general APIs */
|
||||
typedef wasi_nn_error (*BACKEND_INITIALIZE)(void **);
|
||||
typedef wasi_nn_error (*BACKEND_DEINITIALIZE)(void *);
|
||||
|
||||
typedef struct {
|
||||
LOAD load;
|
||||
LOAD_BY_NAME load_by_name;
|
||||
LOAD_BY_NAME_WITH_CONFIG load_by_name_with_config;
|
||||
INIT_EXECUTION_CONTEXT init_execution_context;
|
||||
SET_INPUT set_input;
|
||||
COMPUTE compute;
|
||||
GET_OUTPUT get_output;
|
||||
BACKEND_INITIALIZE init;
|
||||
BACKEND_DEINITIALIZE deinit;
|
||||
} api_function;
|
||||
|
||||
void
|
||||
wasi_nn_dump_tensor_dimension(tensor_dimensions *dim, int32_t output_len,
|
||||
char *output);
|
||||
typedef uint32_t WASI_NN_NAME(graph_execution_context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -99,7 +99,8 @@ graph_builder_array_app_native(wasm_module_inst_t instance,
|
|||
|
||||
static wasi_nn_error
|
||||
tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements,
|
||||
tensor_wasm *input_tensor_wasm, tensor_data *data)
|
||||
tensor_wasm *input_tensor_wasm, void **data,
|
||||
uint32_t *size)
|
||||
{
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
#define data_size input_tensor_wasm->data_size
|
||||
|
@ -113,8 +114,9 @@ tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements,
|
|||
NN_ERR_PRINTF("input_tensor_wasm->data_offset is invalid");
|
||||
return invalid_argument;
|
||||
}
|
||||
*data = (tensor_data)wasm_runtime_addr_app_to_native(
|
||||
*data = wasm_runtime_addr_app_to_native(
|
||||
instance, (uint64)input_tensor_wasm->data_offset);
|
||||
*size = data_size;
|
||||
return success;
|
||||
#undef data_size
|
||||
}
|
||||
|
@ -188,16 +190,19 @@ tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm,
|
|||
NN_DBG_PRINTF("Tensor type: %d", input_tensor_wasm->type);
|
||||
NN_DBG_PRINTF("Total number of elements: %d", total_elements);
|
||||
|
||||
tensor_data data = NULL;
|
||||
void *data = NULL;
|
||||
uint32_t datasize;
|
||||
if (success
|
||||
!= (res = tensor_data_app_native(instance, total_elements,
|
||||
input_tensor_wasm, &data))) {
|
||||
!= (res =
|
||||
tensor_data_app_native(instance, total_elements,
|
||||
input_tensor_wasm, &data, &datasize))) {
|
||||
wasm_runtime_free(dimensions);
|
||||
return res;
|
||||
}
|
||||
|
||||
input_tensor->type = input_tensor_wasm->type;
|
||||
input_tensor->dimensions = dimensions;
|
||||
input_tensor->data = data;
|
||||
input_tensor->data.buf = data;
|
||||
input_tensor->data.size = datasize;
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -20,12 +20,29 @@
|
|||
#include "wasi_nn_types.h"
|
||||
#include "wasm_export.h"
|
||||
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN == 0
|
||||
#warning You are using "wasi_nn", which is a legacy WAMR-specific ABI. It's deperecated and will likely be removed in future versions of WAMR. Please use "wasi_ephemeral_nn" instead. (For a WASM module, use the wasi_ephemeral_nn.h header instead. For the runtime configurations, enable WASM_ENABLE_WASI_EPHEMERAL_NN/WAMR_BUILD_WASI_EPHEMERAL_NN.)
|
||||
#endif
|
||||
|
||||
#define HASHMAP_INITIAL_SIZE 20
|
||||
#define TFLITE_BACKEND_LIB "libwasi_nn_tflite.so"
|
||||
#define OPENVINO_BACKEND_LIB "libwasi_nn_openvino.so"
|
||||
#define LLAMACPP_BACKEND_LIB "libwasi_nn_llamacpp.so"
|
||||
#if defined(__APPLE__)
|
||||
#define LIB_EXTENTION ".dylib"
|
||||
#else
|
||||
#define LIB_EXTENTION ".so"
|
||||
#endif
|
||||
#define TFLITE_BACKEND_LIB "libwasi_nn_tflite" LIB_EXTENTION
|
||||
#define OPENVINO_BACKEND_LIB "libwasi_nn_openvino" LIB_EXTENTION
|
||||
#define LLAMACPP_BACKEND_LIB "libwasi_nn_llamacpp" LIB_EXTENTION
|
||||
|
||||
/* Global variables */
|
||||
static korp_mutex wasi_nn_lock;
|
||||
/*
|
||||
* the "lookup" table is protected by wasi_nn_lock.
|
||||
*
|
||||
* an exception: during wasm_runtime_destroy, wasi_nn_destroy tears down
|
||||
* the table without acquiring the lock. it's ok because there should be
|
||||
* no other threads using the runtime at this point.
|
||||
*/
|
||||
struct backends_api_functions {
|
||||
void *backend_handle;
|
||||
api_function functions;
|
||||
|
@ -38,65 +55,36 @@ struct backends_api_functions {
|
|||
NN_ERR_PRINTF("Error %s() -> %d", #func, wasi_error); \
|
||||
} while (0)
|
||||
|
||||
/* HashMap utils */
|
||||
static HashMap *hashmap;
|
||||
|
||||
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)
|
||||
{
|
||||
/* key type is wasm_module_inst_t*. do nothing */
|
||||
}
|
||||
static void *wasi_nn_key;
|
||||
|
||||
static void
|
||||
wasi_nn_ctx_destroy(WASINNContext *wasi_nn_ctx)
|
||||
{
|
||||
NN_DBG_PRINTF("[WASI NN] DEINIT...");
|
||||
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
NN_ERR_PRINTF(
|
||||
"Error when deallocating memory. WASI-NN context is NULL");
|
||||
return;
|
||||
}
|
||||
NN_DBG_PRINTF("[WASI NN] DEINIT...");
|
||||
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->backend);
|
||||
|
||||
/* deinit() the backend */
|
||||
wasi_nn_error res;
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, deinit, res,
|
||||
wasi_nn_ctx->backend_ctx);
|
||||
bh_assert(!wasi_nn_ctx->busy);
|
||||
|
||||
/* deinit() the backend */
|
||||
if (wasi_nn_ctx->is_backend_ctx_initialized) {
|
||||
wasi_nn_error res;
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, deinit, res,
|
||||
wasi_nn_ctx->backend_ctx);
|
||||
}
|
||||
|
||||
os_mutex_destroy(&wasi_nn_ctx->lock);
|
||||
wasm_runtime_free(wasi_nn_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
value_destroy_func(void *value)
|
||||
dtor(wasm_module_inst_t inst, void *ctx)
|
||||
{
|
||||
wasi_nn_ctx_destroy((WASINNContext *)value);
|
||||
wasi_nn_ctx_destroy(ctx);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -104,12 +92,15 @@ wasi_nn_initialize()
|
|||
{
|
||||
NN_DBG_PRINTF("[WASI NN General] Initializing wasi-nn");
|
||||
|
||||
// hashmap { instance: wasi_nn_ctx }
|
||||
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");
|
||||
if (os_mutex_init(&wasi_nn_lock)) {
|
||||
NN_ERR_PRINTF("Error while initializing global lock");
|
||||
return false;
|
||||
}
|
||||
|
||||
wasi_nn_key = wasm_runtime_create_context_key(dtor);
|
||||
if (wasi_nn_key == NULL) {
|
||||
NN_ERR_PRINTF("Failed to create context key");
|
||||
os_mutex_destroy(&wasi_nn_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -129,6 +120,11 @@ wasi_nn_initialize_context()
|
|||
}
|
||||
|
||||
memset(wasi_nn_ctx, 0, sizeof(WASINNContext));
|
||||
if (os_mutex_init(&wasi_nn_ctx->lock)) {
|
||||
NN_ERR_PRINTF("Error when initializing a lock for WASI-NN context");
|
||||
wasm_runtime_free(wasi_nn_ctx);
|
||||
return NULL;
|
||||
}
|
||||
return wasi_nn_ctx;
|
||||
}
|
||||
|
||||
|
@ -137,29 +133,59 @@ 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);
|
||||
wasm_runtime_get_context(instance, wasi_nn_key);
|
||||
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);
|
||||
WASINNContext *newctx = wasi_nn_initialize_context();
|
||||
if (newctx == NULL)
|
||||
return NULL;
|
||||
os_mutex_lock(&wasi_nn_lock);
|
||||
wasi_nn_ctx = wasm_runtime_get_context(instance, wasi_nn_key);
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
wasm_runtime_set_context_spread(instance, wasi_nn_key, newctx);
|
||||
wasi_nn_ctx = newctx;
|
||||
newctx = NULL;
|
||||
}
|
||||
os_mutex_unlock(&wasi_nn_lock);
|
||||
if (newctx != NULL) {
|
||||
wasi_nn_ctx_destroy(newctx);
|
||||
}
|
||||
}
|
||||
|
||||
return wasi_nn_ctx;
|
||||
}
|
||||
|
||||
static WASINNContext *
|
||||
lock_ctx(wasm_module_inst_t instance)
|
||||
{
|
||||
WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
os_mutex_lock(&wasi_nn_ctx->lock);
|
||||
if (wasi_nn_ctx->busy) {
|
||||
os_mutex_unlock(&wasi_nn_ctx->lock);
|
||||
return NULL;
|
||||
}
|
||||
wasi_nn_ctx->busy = true;
|
||||
os_mutex_unlock(&wasi_nn_ctx->lock);
|
||||
return wasi_nn_ctx;
|
||||
}
|
||||
|
||||
static void
|
||||
unlock_ctx(WASINNContext *wasi_nn_ctx)
|
||||
{
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
os_mutex_lock(&wasi_nn_ctx->lock);
|
||||
bh_assert(wasi_nn_ctx->busy);
|
||||
wasi_nn_ctx->busy = false;
|
||||
os_mutex_unlock(&wasi_nn_ctx->lock);
|
||||
}
|
||||
|
||||
void
|
||||
wasi_nn_destroy()
|
||||
{
|
||||
// destroy hashmap will destroy keys and values
|
||||
bh_hash_map_destroy(hashmap);
|
||||
wasm_runtime_destroy_context_key(wasi_nn_key);
|
||||
|
||||
// close backends' libraries and registered functions
|
||||
for (unsigned i = 0; i < sizeof(lookup) / sizeof(lookup[0]); i++) {
|
||||
|
@ -170,6 +196,8 @@ wasi_nn_destroy()
|
|||
|
||||
memset(&lookup[i].functions, 0, sizeof(api_function));
|
||||
}
|
||||
|
||||
os_mutex_destroy(&wasi_nn_lock);
|
||||
}
|
||||
|
||||
/* Utils */
|
||||
|
@ -342,9 +370,10 @@ graph_encoding_to_backend_lib_name(graph_encoding encoding)
|
|||
|
||||
static bool
|
||||
detect_and_load_backend(graph_encoding backend_hint,
|
||||
struct backends_api_functions *backends,
|
||||
graph_encoding *loaded_backend)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (backend_hint > autodetect)
|
||||
return false;
|
||||
|
||||
|
@ -356,16 +385,58 @@ detect_and_load_backend(graph_encoding backend_hint,
|
|||
|
||||
*loaded_backend = backend_hint;
|
||||
|
||||
os_mutex_lock(&wasi_nn_lock);
|
||||
/* if already loaded */
|
||||
if (lookup[backend_hint].backend_handle)
|
||||
if (lookup[backend_hint].backend_handle) {
|
||||
os_mutex_unlock(&wasi_nn_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *backend_lib_name =
|
||||
graph_encoding_to_backend_lib_name(backend_hint);
|
||||
if (!backend_lib_name)
|
||||
if (!backend_lib_name) {
|
||||
os_mutex_unlock(&wasi_nn_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
return prepare_backend(backend_lib_name, backends + backend_hint);
|
||||
ret = prepare_backend(backend_lib_name, lookup + backend_hint);
|
||||
os_mutex_unlock(&wasi_nn_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static wasi_nn_error
|
||||
ensure_backend(wasm_module_inst_t instance, graph_encoding encoding,
|
||||
WASINNContext *wasi_nn_ctx)
|
||||
{
|
||||
wasi_nn_error res;
|
||||
|
||||
graph_encoding loaded_backend = autodetect;
|
||||
if (!detect_and_load_backend(encoding, &loaded_backend)) {
|
||||
res = invalid_encoding;
|
||||
NN_ERR_PRINTF("load backend failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (wasi_nn_ctx->is_backend_ctx_initialized) {
|
||||
if (wasi_nn_ctx->backend != loaded_backend) {
|
||||
res = unsupported_operation;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
wasi_nn_ctx->backend = loaded_backend;
|
||||
|
||||
/* init() the backend */
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, init, res,
|
||||
&wasi_nn_ctx->backend_ctx);
|
||||
if (res != success)
|
||||
goto fail;
|
||||
|
||||
wasi_nn_ctx->is_backend_ctx_initialized = true;
|
||||
}
|
||||
return success;
|
||||
fail:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* WASI-NN implementation */
|
||||
|
@ -381,6 +452,8 @@ wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
|
|||
graph_encoding encoding, execution_target target, graph *g)
|
||||
#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */
|
||||
{
|
||||
wasi_nn_error res;
|
||||
|
||||
NN_DBG_PRINTF("[WASI NN] LOAD [encoding=%d, target=%d]...", encoding,
|
||||
target);
|
||||
|
||||
|
@ -388,18 +461,23 @@ wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
|
|||
if (!instance)
|
||||
return runtime_error;
|
||||
|
||||
wasi_nn_error res;
|
||||
WASINNContext *wasi_nn_ctx = lock_ctx(instance);
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
res = busy;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
graph_builder_array builder_native = { 0 };
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
if (success
|
||||
!= (res = graph_builder_array_app_native(
|
||||
instance, builder, builder_wasm_size, &builder_native)))
|
||||
return res;
|
||||
goto fail;
|
||||
#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
|
||||
if (success
|
||||
!= (res = graph_builder_array_app_native(instance, builder,
|
||||
&builder_native)))
|
||||
return res;
|
||||
goto fail;
|
||||
#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */
|
||||
|
||||
if (!wasm_runtime_validate_native_addr(instance, g,
|
||||
|
@ -409,19 +487,7 @@ wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
graph_encoding loaded_backend = autodetect;
|
||||
if (!detect_and_load_backend(encoding, lookup, &loaded_backend)) {
|
||||
res = invalid_encoding;
|
||||
NN_ERR_PRINTF("load backend failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
|
||||
wasi_nn_ctx->backend = loaded_backend;
|
||||
|
||||
/* init() the backend */
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, init, res,
|
||||
&wasi_nn_ctx->backend_ctx);
|
||||
res = ensure_backend(instance, encoding, wasi_nn_ctx);
|
||||
if (res != success)
|
||||
goto fail;
|
||||
|
||||
|
@ -436,6 +502,7 @@ fail:
|
|||
// XXX: Free intermediate structure pointers
|
||||
if (builder_native.buf)
|
||||
wasm_runtime_free(builder_native.buf);
|
||||
unlock_ctx(wasi_nn_ctx);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -444,6 +511,8 @@ wasi_nn_error
|
|||
wasi_nn_load_by_name(wasm_exec_env_t exec_env, char *name, uint32_t name_len,
|
||||
graph *g)
|
||||
{
|
||||
wasi_nn_error res;
|
||||
|
||||
wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
|
||||
if (!instance) {
|
||||
return runtime_error;
|
||||
|
@ -467,30 +536,26 @@ wasi_nn_load_by_name(wasm_exec_env_t exec_env, char *name, uint32_t name_len,
|
|||
|
||||
NN_DBG_PRINTF("[WASI NN] LOAD_BY_NAME %s...", name);
|
||||
|
||||
graph_encoding loaded_backend = autodetect;
|
||||
if (!detect_and_load_backend(autodetect, lookup, &loaded_backend)) {
|
||||
NN_ERR_PRINTF("load backend failed");
|
||||
return invalid_encoding;
|
||||
WASINNContext *wasi_nn_ctx = lock_ctx(instance);
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
res = busy;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
|
||||
wasi_nn_ctx->backend = loaded_backend;
|
||||
|
||||
wasi_nn_error res;
|
||||
/* init() the backend */
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, init, res,
|
||||
&wasi_nn_ctx->backend_ctx);
|
||||
res = ensure_backend(instance, autodetect, wasi_nn_ctx);
|
||||
if (res != success)
|
||||
return res;
|
||||
goto fail;
|
||||
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, load_by_name, res,
|
||||
wasi_nn_ctx->backend_ctx, name, name_len, g);
|
||||
if (res != success)
|
||||
return res;
|
||||
goto fail;
|
||||
|
||||
wasi_nn_ctx->backend = loaded_backend;
|
||||
wasi_nn_ctx->is_model_loaded = true;
|
||||
return success;
|
||||
res = success;
|
||||
fail:
|
||||
unlock_ctx(wasi_nn_ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
wasi_nn_error
|
||||
|
@ -498,6 +563,8 @@ wasi_nn_load_by_name_with_config(wasm_exec_env_t exec_env, char *name,
|
|||
int32_t name_len, char *config,
|
||||
int32_t config_len, graph *g)
|
||||
{
|
||||
wasi_nn_error res;
|
||||
|
||||
wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
|
||||
if (!instance) {
|
||||
return runtime_error;
|
||||
|
@ -526,31 +593,28 @@ wasi_nn_load_by_name_with_config(wasm_exec_env_t exec_env, char *name,
|
|||
|
||||
NN_DBG_PRINTF("[WASI NN] LOAD_BY_NAME_WITH_CONFIG %s %s...", name, config);
|
||||
|
||||
graph_encoding loaded_backend = autodetect;
|
||||
if (!detect_and_load_backend(autodetect, lookup, &loaded_backend)) {
|
||||
NN_ERR_PRINTF("load backend failed");
|
||||
return invalid_encoding;
|
||||
WASINNContext *wasi_nn_ctx = lock_ctx(instance);
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
res = busy;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
|
||||
wasi_nn_ctx->backend = loaded_backend;
|
||||
|
||||
wasi_nn_error res;
|
||||
/* init() the backend */
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, init, res,
|
||||
&wasi_nn_ctx->backend_ctx);
|
||||
res = ensure_backend(instance, autodetect, wasi_nn_ctx);
|
||||
if (res != success)
|
||||
return res;
|
||||
goto fail;
|
||||
;
|
||||
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, load_by_name_with_config, res,
|
||||
wasi_nn_ctx->backend_ctx, name, name_len, config,
|
||||
config_len, g);
|
||||
if (res != success)
|
||||
return res;
|
||||
goto fail;
|
||||
|
||||
wasi_nn_ctx->backend = loaded_backend;
|
||||
wasi_nn_ctx->is_model_loaded = true;
|
||||
return success;
|
||||
res = success;
|
||||
fail:
|
||||
unlock_ctx(wasi_nn_ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
wasi_nn_error
|
||||
|
@ -564,20 +628,27 @@ wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
|
|||
return runtime_error;
|
||||
}
|
||||
|
||||
WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
|
||||
|
||||
wasi_nn_error res;
|
||||
WASINNContext *wasi_nn_ctx = lock_ctx(instance);
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
res = busy;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (success != (res = is_model_initialized(wasi_nn_ctx)))
|
||||
return res;
|
||||
goto fail;
|
||||
|
||||
if (!wasm_runtime_validate_native_addr(
|
||||
instance, ctx, (uint64)sizeof(graph_execution_context))) {
|
||||
NN_ERR_PRINTF("ctx is invalid");
|
||||
return invalid_argument;
|
||||
res = invalid_argument;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, init_execution_context, res,
|
||||
wasi_nn_ctx->backend_ctx, g, ctx);
|
||||
fail:
|
||||
unlock_ctx(wasi_nn_ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -592,17 +663,21 @@ wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
|
|||
return runtime_error;
|
||||
}
|
||||
|
||||
WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
|
||||
|
||||
wasi_nn_error res;
|
||||
WASINNContext *wasi_nn_ctx = lock_ctx(instance);
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
res = busy;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (success != (res = is_model_initialized(wasi_nn_ctx)))
|
||||
return res;
|
||||
goto fail;
|
||||
|
||||
tensor input_tensor_native = { 0 };
|
||||
if (success
|
||||
!= (res = tensor_app_native(instance, input_tensor,
|
||||
&input_tensor_native)))
|
||||
return res;
|
||||
goto fail;
|
||||
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, set_input, res,
|
||||
wasi_nn_ctx->backend_ctx, ctx, index,
|
||||
|
@ -610,7 +685,8 @@ wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
|
|||
// XXX: Free intermediate structure pointers
|
||||
if (input_tensor_native.dimensions)
|
||||
wasm_runtime_free(input_tensor_native.dimensions);
|
||||
|
||||
fail:
|
||||
unlock_ctx(wasi_nn_ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -624,26 +700,32 @@ wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx)
|
|||
return runtime_error;
|
||||
}
|
||||
|
||||
WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
|
||||
|
||||
wasi_nn_error res;
|
||||
WASINNContext *wasi_nn_ctx = lock_ctx(instance);
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
res = busy;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (success != (res = is_model_initialized(wasi_nn_ctx)))
|
||||
return res;
|
||||
goto fail;
|
||||
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, compute, res,
|
||||
wasi_nn_ctx->backend_ctx, ctx);
|
||||
fail:
|
||||
unlock_ctx(wasi_nn_ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
wasi_nn_error
|
||||
wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
|
||||
uint32_t index, tensor_data output_tensor,
|
||||
uint32_t index, void *output_tensor,
|
||||
uint32_t output_tensor_len, uint32_t *output_tensor_size)
|
||||
#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
|
||||
wasi_nn_error
|
||||
wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
|
||||
uint32_t index, tensor_data output_tensor,
|
||||
uint32_t index, void *output_tensor,
|
||||
uint32_t *output_tensor_size)
|
||||
#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */
|
||||
{
|
||||
|
@ -654,28 +736,36 @@ wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
|
|||
return runtime_error;
|
||||
}
|
||||
|
||||
WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
|
||||
|
||||
wasi_nn_error res;
|
||||
WASINNContext *wasi_nn_ctx = lock_ctx(instance);
|
||||
if (wasi_nn_ctx == NULL) {
|
||||
res = busy;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (success != (res = is_model_initialized(wasi_nn_ctx)))
|
||||
return res;
|
||||
goto fail;
|
||||
|
||||
if (!wasm_runtime_validate_native_addr(instance, output_tensor_size,
|
||||
(uint64)sizeof(uint32_t))) {
|
||||
NN_ERR_PRINTF("output_tensor_size is invalid");
|
||||
return invalid_argument;
|
||||
res = invalid_argument;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
tensor_data tensor = {
|
||||
.buf = output_tensor,
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
.size = output_tensor_len,
|
||||
#else
|
||||
.size = *output_tensor_size,
|
||||
#endif
|
||||
};
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, get_output, res,
|
||||
wasi_nn_ctx->backend_ctx, ctx, index, output_tensor,
|
||||
&output_tensor_len);
|
||||
*output_tensor_size = output_tensor_len;
|
||||
#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
|
||||
call_wasi_nn_func(wasi_nn_ctx->backend, get_output, res,
|
||||
wasi_nn_ctx->backend_ctx, ctx, index, output_tensor,
|
||||
wasi_nn_ctx->backend_ctx, ctx, index, &tensor,
|
||||
output_tensor_size);
|
||||
#endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */
|
||||
fail:
|
||||
unlock_ctx(wasi_nn_ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -697,6 +787,7 @@ static NativeSymbol native_symbols_wasi_nn[] = {
|
|||
REG_NATIVE_FUNC(get_output, "(ii*i*)i"),
|
||||
#else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
|
||||
REG_NATIVE_FUNC(load, "(*ii*)i"),
|
||||
REG_NATIVE_FUNC(load_by_name, "(*i*)i"),
|
||||
REG_NATIVE_FUNC(init_execution_context, "(i*)i"),
|
||||
REG_NATIVE_FUNC(set_input, "(ii*)i"),
|
||||
REG_NATIVE_FUNC(compute, "(i)i"),
|
||||
|
|
|
@ -3,15 +3,26 @@
|
|||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WASI_NN_OPENVINO_HPP
|
||||
#define WASI_NN_OPENVINO_HPP
|
||||
#ifndef WASI_NN_BACKEND_H
|
||||
#define WASI_NN_BACKEND_H
|
||||
|
||||
#include "wasi_nn_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
load(void *ctx, graph_builder_array *builder, graph_encoding encoding,
|
||||
execution_target target, graph *g);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
load_by_name(void *tflite_ctx, const char *name, uint32_t namelen, graph *g);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
load_by_name_with_config(void *ctx, const char *name, uint32_t namelen,
|
||||
const char *config, uint32_t config_len, graph *g);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
init_execution_context(void *ctx, graph g, graph_execution_context *exec_ctx);
|
||||
|
||||
|
@ -24,7 +35,7 @@ compute(void *ctx, graph_execution_context exec_ctx);
|
|||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index,
|
||||
tensor_data output_tensor, uint32_t *output_tensor_size);
|
||||
tensor_data *output_tensor, uint32_t *output_tensor_size);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
init_backend(void **ctx);
|
||||
|
@ -32,4 +43,8 @@ init_backend(void **ctx);
|
|||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
deinit_backend(void *ctx);
|
||||
|
||||
#endif /* WASI_NN_OPENVINO_HPP */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WASI_NN_BACKEND_H */
|
|
@ -2,7 +2,10 @@
|
|||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
#include "wasi_nn_types.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "wasi_nn_backend.h"
|
||||
#include "utils/logger.h"
|
||||
#include "llama.h"
|
||||
#include "ggml.h"
|
||||
|
@ -286,7 +289,7 @@ deinit_backend(void *ctx)
|
|||
|
||||
llama_backend_free();
|
||||
|
||||
os_free(backend_ctx);
|
||||
free(backend_ctx);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -302,6 +305,11 @@ __load_by_name_with_configuration(void *ctx, const char *filename, graph *g)
|
|||
{
|
||||
struct LlamaContext *backend_ctx = (struct LlamaContext *)ctx;
|
||||
|
||||
if (backend_ctx->model != NULL) {
|
||||
// we only implement a single graph
|
||||
return unsupported_operation;
|
||||
}
|
||||
|
||||
// make sure backend_ctx->config is initialized
|
||||
|
||||
struct llama_model_params model_params =
|
||||
|
@ -320,6 +328,7 @@ __load_by_name_with_configuration(void *ctx, const char *filename, graph *g)
|
|||
#endif
|
||||
|
||||
backend_ctx->model = model;
|
||||
*g = 0;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@ -360,6 +369,16 @@ init_execution_context(void *ctx, graph g, graph_execution_context *exec_ctx)
|
|||
{
|
||||
struct LlamaContext *backend_ctx = (struct LlamaContext *)ctx;
|
||||
|
||||
if (g != 0 || backend_ctx->model == NULL) {
|
||||
// we only implement a single graph
|
||||
return runtime_error;
|
||||
}
|
||||
|
||||
if (backend_ctx->ctx != NULL) {
|
||||
// we only implement a single context
|
||||
return unsupported_operation;
|
||||
}
|
||||
|
||||
struct llama_context_params ctx_params =
|
||||
llama_context_params_from_wasi_nn_llama_config(&backend_ctx->config);
|
||||
struct llama_context *llama_ctx =
|
||||
|
@ -370,6 +389,7 @@ init_execution_context(void *ctx, graph g, graph_execution_context *exec_ctx)
|
|||
}
|
||||
|
||||
backend_ctx->ctx = llama_ctx;
|
||||
*exec_ctx = 0;
|
||||
|
||||
NN_INFO_PRINTF("n_predict = %d, n_ctx = %d", backend_ctx->config.n_predict,
|
||||
llama_n_ctx(backend_ctx->ctx));
|
||||
|
@ -381,18 +401,41 @@ set_input(void *ctx, graph_execution_context exec_ctx, uint32_t index,
|
|||
tensor *wasi_nn_tensor)
|
||||
{
|
||||
struct LlamaContext *backend_ctx = (struct LlamaContext *)ctx;
|
||||
// tensor->data is the prompt string. ends with \0
|
||||
char *prompt_text = (char *)wasi_nn_tensor->data;
|
||||
|
||||
if (exec_ctx != 0 || backend_ctx->ctx == NULL) {
|
||||
// we only implement a single context
|
||||
return runtime_error;
|
||||
}
|
||||
|
||||
if (index != 0) {
|
||||
NN_ERR_PRINTF("Invalid input index %d", index);
|
||||
return invalid_argument;
|
||||
}
|
||||
|
||||
// tensor->data is the prompt string.
|
||||
char *prompt_text = (char *)wasi_nn_tensor->data.buf;
|
||||
uint32_t prompt_text_len = wasi_nn_tensor->data.size;
|
||||
|
||||
// note: buf[0] == 1 is a workaround for
|
||||
// https://github.com/second-state/WasmEdge-WASINN-examples/issues/196.
|
||||
// we may remove it in future.
|
||||
if (wasi_nn_tensor->type != u8 || wasi_nn_tensor->dimensions->size != 1
|
||||
|| !(wasi_nn_tensor->dimensions->buf[0] == 1
|
||||
|| wasi_nn_tensor->dimensions->buf[0] == prompt_text_len)) {
|
||||
return invalid_argument;
|
||||
}
|
||||
if (wasi_nn_tensor->dimensions->buf[0] == 1 && prompt_text_len != 1) {
|
||||
NN_WARN_PRINTF("Ignoring seemingly wrong input tensor dimensions.");
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
NN_DBG_PRINTF("--------------------------------------------------");
|
||||
NN_DBG_PRINTF("prompt_text: %s", prompt_text);
|
||||
NN_DBG_PRINTF("prompt_text: %.*s", (int)prompt_text_len, prompt_text);
|
||||
NN_DBG_PRINTF("--------------------------------------------------");
|
||||
#endif
|
||||
|
||||
// tokenize the prompt
|
||||
uint32_t n_token_max = llama_n_ctx(backend_ctx->ctx);
|
||||
uint32_t prompt_text_len = strlen(prompt_text);
|
||||
|
||||
if (backend_ctx->prompt == NULL) {
|
||||
backend_ctx->prompt = calloc(n_token_max, sizeof(llama_token));
|
||||
|
@ -430,6 +473,11 @@ compute(void *ctx, graph_execution_context exec_ctx)
|
|||
struct LlamaContext *backend_ctx = (struct LlamaContext *)ctx;
|
||||
wasi_nn_error ret = runtime_error;
|
||||
|
||||
if (exec_ctx != 0 || backend_ctx->ctx == NULL) {
|
||||
// we only implement a single context
|
||||
return runtime_error;
|
||||
}
|
||||
|
||||
// reset the generation buffer
|
||||
if (backend_ctx->generation == NULL) {
|
||||
backend_ctx->generation =
|
||||
|
@ -477,7 +525,6 @@ compute(void *ctx, graph_execution_context exec_ctx)
|
|||
|
||||
// main loop
|
||||
int32_t n_cur = batch.n_tokens;
|
||||
int n_decode = 0;
|
||||
int32_t n_vocab = llama_n_vocab(backend_ctx->model);
|
||||
llama_token_data *candidates = NULL;
|
||||
|
||||
|
@ -528,7 +575,6 @@ compute(void *ctx, graph_execution_context exec_ctx)
|
|||
// push this new token for next evaluation
|
||||
llama_batch_add(&batch, new_token_id, n_cur, seq_ids,
|
||||
sizeof(seq_ids) / sizeof(seq_ids[0]), true);
|
||||
n_decode++;
|
||||
n_cur++;
|
||||
|
||||
if (llama_decode(backend_ctx->ctx, batch) != 0) {
|
||||
|
@ -549,10 +595,15 @@ fail:
|
|||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index,
|
||||
tensor_data output_tensor, uint32_t *output_tensor_size)
|
||||
tensor_data *output_tensor, uint32_t *output_tensor_size)
|
||||
{
|
||||
struct LlamaContext *backend_ctx = (struct LlamaContext *)ctx;
|
||||
|
||||
if (exec_ctx != 0 || backend_ctx->ctx == NULL) {
|
||||
// we only implement a single context
|
||||
return runtime_error;
|
||||
}
|
||||
|
||||
// Compatibility with WasmEdge
|
||||
if (index > 1) {
|
||||
NN_ERR_PRINTF("Invalid output index %d", index);
|
||||
|
@ -568,7 +619,7 @@ get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index,
|
|||
printf("%s\n", output_metadata);
|
||||
}
|
||||
|
||||
memcpy(output_tensor, output_metadata, strlen(output_metadata));
|
||||
memcpy(output_tensor->buf, output_metadata, strlen(output_metadata));
|
||||
*output_tensor_size = strlen(output_metadata);
|
||||
return success;
|
||||
}
|
||||
|
@ -588,7 +639,7 @@ get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index,
|
|||
printf("%s", buf);
|
||||
}
|
||||
|
||||
memcpy(output_tensor + end_pos, buf, strlen(buf));
|
||||
memcpy(output_tensor->buf + end_pos, buf, strlen(buf));
|
||||
end_pos += strlen(buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wasi_nn_types.h"
|
||||
#include "wasi_nn_openvino.h"
|
||||
#include "wasi_nn_backend.h"
|
||||
#include "utils/logger.h"
|
||||
#include "bh_platform.h"
|
||||
|
||||
|
@ -26,17 +25,25 @@
|
|||
* from 4. to 6. is the Inference Loop
|
||||
*/
|
||||
|
||||
/* these limits are arbitrary. */
|
||||
#define MAX_GRAPHS 4
|
||||
#define MAX_EXECUTION_CONTEXTS 4
|
||||
|
||||
typedef struct {
|
||||
ov_core_t *core;
|
||||
/* keep input model files */
|
||||
void *weight_data;
|
||||
ov_tensor_t *weights_tensor;
|
||||
ov_model_t *model;
|
||||
/* add prepostprocess */
|
||||
ov_model_t *new_model;
|
||||
ov_compiled_model_t *compiled_model;
|
||||
ov_infer_request_t *infer_request;
|
||||
ov_tensor_t *input_tensor;
|
||||
struct OpenVINOGraph {
|
||||
void *weight_data;
|
||||
ov_tensor_t *weights_tensor;
|
||||
ov_model_t *model;
|
||||
ov_compiled_model_t *compiled_model;
|
||||
} graphs[MAX_GRAPHS];
|
||||
struct OpenVINOExecutionContext {
|
||||
struct OpenVINOGraph *graph;
|
||||
ov_infer_request_t *infer_request;
|
||||
} execution_contexts[MAX_EXECUTION_CONTEXTS];
|
||||
unsigned int n_graphs;
|
||||
unsigned int n_execution_contexts;
|
||||
} OpenVINOContext;
|
||||
|
||||
/*
|
||||
|
@ -58,7 +65,7 @@ dump_ov_shape_t(const ov_shape_t *shape, int32_t output_len, char *output)
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = snprintf(output, output_len, "%ld,[", shape->rank);
|
||||
ret = snprintf(output, output_len, "%" PRId64 ",[", shape->rank);
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
|
@ -66,7 +73,7 @@ dump_ov_shape_t(const ov_shape_t *shape, int32_t output_len, char *output)
|
|||
output += ret;
|
||||
|
||||
for (unsigned i = 0; i < shape->rank && output_len; i++) {
|
||||
ret = snprintf(output, output_len, " %ld", shape->dims[i]);
|
||||
ret = snprintf(output, output_len, " %" PRId64, shape->dims[i]);
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
|
@ -136,7 +143,7 @@ print_model_input_output_info(ov_model_t *model)
|
|||
output_port = NULL;
|
||||
}
|
||||
|
||||
ov_error = ov_error;
|
||||
(void)ov_error;
|
||||
fail:
|
||||
if (friendly_name)
|
||||
ov_free(friendly_name);
|
||||
|
@ -161,8 +168,6 @@ wasi_nn_tensor_type_to_openvino_element_type(tensor_type wasi_nn_type)
|
|||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
case fp64:
|
||||
return F64;
|
||||
case bf16:
|
||||
return BF16;
|
||||
case i64:
|
||||
return I64;
|
||||
case u8:
|
||||
|
@ -183,6 +188,29 @@ wasi_nn_tensor_type_to_openvino_element_type(tensor_type wasi_nn_type)
|
|||
return UNDEFINED;
|
||||
}
|
||||
|
||||
static void
|
||||
free_graph(struct OpenVINOGraph *graph)
|
||||
{
|
||||
if (graph->weight_data)
|
||||
os_free(graph->weight_data);
|
||||
|
||||
if (graph->weights_tensor)
|
||||
ov_tensor_free(graph->weights_tensor);
|
||||
|
||||
if (graph->model)
|
||||
ov_model_free(graph->model);
|
||||
|
||||
if (graph->compiled_model)
|
||||
ov_compiled_model_free(graph->compiled_model);
|
||||
}
|
||||
|
||||
static void
|
||||
free_execution_context(struct OpenVINOExecutionContext *c)
|
||||
{
|
||||
if (c->infer_request)
|
||||
ov_infer_request_free(c->infer_request);
|
||||
}
|
||||
|
||||
static wasi_nn_error
|
||||
uint32_array_to_int64_array(uint32_t array_size, uint32_t *src, int64_t **dst)
|
||||
{
|
||||
|
@ -202,6 +230,8 @@ load(void *ctx, graph_builder_array *builder, graph_encoding encoding,
|
|||
execution_target target, graph *g)
|
||||
{
|
||||
OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx;
|
||||
struct OpenVINOGraph *graph;
|
||||
unsigned int graph_idx;
|
||||
wasi_nn_error ret = unsupported_operation;
|
||||
|
||||
if (encoding != openvino) {
|
||||
|
@ -227,39 +257,47 @@ load(void *ctx, graph_builder_array *builder, graph_encoding encoding,
|
|||
graph_builder xml = builder->buf[0];
|
||||
graph_builder weight = builder->buf[1];
|
||||
|
||||
/* if xml is a String with a model in IR */
|
||||
if (!(xml.buf[xml.size] == '\0' && xml.buf[xml.size - 1] != '\0')) {
|
||||
NN_ERR_PRINTF("Invalid xml string.");
|
||||
return invalid_argument;
|
||||
graph_idx = ov_ctx->n_graphs;
|
||||
if (graph_idx >= MAX_GRAPHS) {
|
||||
return runtime_error;
|
||||
}
|
||||
graph = &ov_ctx->graphs[graph_idx];
|
||||
memset(graph, 0, sizeof(*graph));
|
||||
|
||||
/* transfer weight to an ov tensor */
|
||||
{
|
||||
ov_ctx->weight_data = os_malloc(weight.size);
|
||||
if (!ov_ctx->weight_data)
|
||||
graph->weight_data = os_malloc(weight.size);
|
||||
if (!graph->weight_data)
|
||||
goto fail;
|
||||
memcpy(ov_ctx->weight_data, weight.buf, weight.size);
|
||||
memcpy(graph->weight_data, weight.buf, weight.size);
|
||||
|
||||
ov_element_type_e type = U8;
|
||||
int64_t dims[1] = { weight.size };
|
||||
ov_shape_t shape = { 1, dims };
|
||||
CHECK_OV_STATUS(ov_tensor_create_from_host_ptr(type, shape,
|
||||
ov_ctx->weight_data,
|
||||
&ov_ctx->weights_tensor),
|
||||
graph->weight_data,
|
||||
&graph->weights_tensor),
|
||||
ret);
|
||||
}
|
||||
|
||||
/* load model from buffer */
|
||||
CHECK_OV_STATUS(ov_core_read_model_from_memory_buffer(
|
||||
ov_ctx->core, (char *)xml.buf, xml.size,
|
||||
ov_ctx->weights_tensor, &ov_ctx->model),
|
||||
graph->weights_tensor, &graph->model),
|
||||
ret);
|
||||
#ifndef NDEBUG
|
||||
print_model_input_output_info(ov_ctx->model);
|
||||
print_model_input_output_info(graph->model);
|
||||
#endif
|
||||
|
||||
ret = success;
|
||||
CHECK_OV_STATUS(ov_core_compile_model(ov_ctx->core, graph->model, "CPU", 0,
|
||||
&graph->compiled_model),
|
||||
ret);
|
||||
|
||||
*g = graph_idx;
|
||||
ov_ctx->n_graphs++;
|
||||
return success;
|
||||
fail:
|
||||
free_graph(graph);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -267,20 +305,62 @@ __attribute__((visibility("default"))) wasi_nn_error
|
|||
load_by_name(void *ctx, const char *filename, uint32_t filename_len, graph *g)
|
||||
{
|
||||
OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx;
|
||||
struct OpenVINOGraph *graph;
|
||||
unsigned int graph_idx;
|
||||
wasi_nn_error ret = unsupported_operation;
|
||||
|
||||
CHECK_OV_STATUS(
|
||||
ov_core_read_model(ov_ctx->core, filename, NULL, &ov_ctx->model), ret);
|
||||
graph_idx = ov_ctx->n_graphs;
|
||||
if (graph_idx >= MAX_GRAPHS) {
|
||||
return runtime_error;
|
||||
}
|
||||
graph = &ov_ctx->graphs[graph_idx];
|
||||
|
||||
ret = success;
|
||||
memset(graph, 0, sizeof(*graph));
|
||||
CHECK_OV_STATUS(
|
||||
ov_core_read_model(ov_ctx->core, filename, NULL, &graph->model), ret);
|
||||
|
||||
CHECK_OV_STATUS(ov_core_compile_model(ov_ctx->core, graph->model, "CPU", 0,
|
||||
&graph->compiled_model),
|
||||
ret);
|
||||
|
||||
*g = graph_idx;
|
||||
ov_ctx->n_graphs++;
|
||||
return success;
|
||||
fail:
|
||||
free_graph(graph);
|
||||
return ret;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
init_execution_context(void *ctx, graph g, graph_execution_context *exec_ctx)
|
||||
{
|
||||
OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx;
|
||||
struct OpenVINOGraph *graph;
|
||||
struct OpenVINOExecutionContext *exec;
|
||||
unsigned int exec_idx;
|
||||
wasi_nn_error ret;
|
||||
|
||||
if (g >= ov_ctx->n_graphs)
|
||||
return runtime_error;
|
||||
graph = &ov_ctx->graphs[g];
|
||||
|
||||
exec_idx = ov_ctx->n_execution_contexts;
|
||||
if (exec_idx >= MAX_EXECUTION_CONTEXTS)
|
||||
return runtime_error;
|
||||
exec = &ov_ctx->execution_contexts[exec_idx];
|
||||
|
||||
memset(exec, 0, sizeof(*exec));
|
||||
exec->graph = graph;
|
||||
|
||||
CHECK_OV_STATUS(ov_compiled_model_create_infer_request(
|
||||
graph->compiled_model, &exec->infer_request),
|
||||
ret);
|
||||
|
||||
*exec_ctx = exec_idx;
|
||||
ov_ctx->n_execution_contexts++;
|
||||
return success;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
|
@ -288,19 +368,15 @@ set_input(void *ctx, graph_execution_context exec_ctx, uint32_t index,
|
|||
tensor *wasi_nn_tensor)
|
||||
{
|
||||
OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx;
|
||||
struct OpenVINOExecutionContext *exec;
|
||||
wasi_nn_error ret = unsupported_operation;
|
||||
ov_shape_t input_shape = { 0 };
|
||||
ov_tensor_t *input_tensor = NULL;
|
||||
int64_t *ov_dims = NULL;
|
||||
|
||||
ov_preprocess_prepostprocessor_t *ppp = NULL;
|
||||
ov_preprocess_input_info_t *input_info = NULL;
|
||||
ov_preprocess_input_tensor_info_t *input_tensor_info = NULL;
|
||||
ov_layout_t *input_layout = NULL;
|
||||
ov_preprocess_preprocess_steps_t *input_process = NULL;
|
||||
ov_preprocess_input_model_info_t *p_input_model = NULL;
|
||||
ov_layout_t *model_layout = NULL;
|
||||
ov_preprocess_output_info_t *output_info = NULL;
|
||||
ov_preprocess_output_tensor_info_t *output_tensor_info = NULL;
|
||||
if (exec_ctx >= ov_ctx->n_execution_contexts)
|
||||
return runtime_error;
|
||||
exec = &ov_ctx->execution_contexts[exec_ctx];
|
||||
|
||||
/* wasi_nn_tensor -> ov_tensor */
|
||||
{
|
||||
|
@ -310,17 +386,6 @@ set_input(void *ctx, graph_execution_context exec_ctx, uint32_t index,
|
|||
if (ret != success)
|
||||
goto fail;
|
||||
|
||||
/* NCHW -> NHWC */
|
||||
if (wasi_nn_tensor->dimensions->size == 4 || ov_dims[1] == 3) {
|
||||
/* N */
|
||||
/* H */
|
||||
ov_dims[1] = ov_dims[2];
|
||||
/* W */
|
||||
ov_dims[2] = ov_dims[3];
|
||||
/* C */
|
||||
ov_dims[3] = 3;
|
||||
}
|
||||
|
||||
CHECK_OV_STATUS(ov_shape_create(wasi_nn_tensor->dimensions->size,
|
||||
ov_dims, &input_shape),
|
||||
ret);
|
||||
|
@ -336,101 +401,22 @@ set_input(void *ctx, graph_execution_context exec_ctx, uint32_t index,
|
|||
shape_info);
|
||||
|
||||
CHECK_OV_STATUS(ov_tensor_create_from_host_ptr(input_type, input_shape,
|
||||
wasi_nn_tensor->data,
|
||||
&ov_ctx->input_tensor),
|
||||
wasi_nn_tensor->data.buf,
|
||||
&input_tensor),
|
||||
ret);
|
||||
}
|
||||
|
||||
/* set preprocess based on wasi_nn_tensor */
|
||||
{
|
||||
CHECK_OV_STATUS(
|
||||
ov_preprocess_prepostprocessor_create(ov_ctx->model, &ppp), ret);
|
||||
|
||||
/* reuse user' created tensor's info */
|
||||
CHECK_OV_STATUS(ov_preprocess_prepostprocessor_get_input_info_by_index(
|
||||
ppp, index, &input_info),
|
||||
ret);
|
||||
CHECK_OV_STATUS(ov_preprocess_input_info_get_tensor_info(
|
||||
input_info, &input_tensor_info),
|
||||
ret);
|
||||
CHECK_OV_STATUS(ov_preprocess_input_tensor_info_set_from(
|
||||
input_tensor_info, ov_ctx->input_tensor),
|
||||
ret);
|
||||
/* ! HAS TO BE NHWC. Match previous layout conversion */
|
||||
CHECK_OV_STATUS(ov_layout_create("NHWC", &input_layout), ret);
|
||||
CHECK_OV_STATUS(ov_preprocess_input_tensor_info_set_layout(
|
||||
input_tensor_info, input_layout),
|
||||
ret);
|
||||
|
||||
/* add RESIZE */
|
||||
CHECK_OV_STATUS(ov_preprocess_input_info_get_preprocess_steps(
|
||||
input_info, &input_process),
|
||||
ret);
|
||||
CHECK_OV_STATUS(
|
||||
ov_preprocess_preprocess_steps_resize(input_process, RESIZE_LINEAR),
|
||||
ret);
|
||||
|
||||
/* input model */
|
||||
CHECK_OV_STATUS(
|
||||
ov_preprocess_input_info_get_model_info(input_info, &p_input_model),
|
||||
ret);
|
||||
// TODO: what if not?
|
||||
CHECK_OV_STATUS(ov_layout_create("NCHW", &model_layout), ret);
|
||||
CHECK_OV_STATUS(ov_preprocess_input_model_info_set_layout(p_input_model,
|
||||
model_layout),
|
||||
ret);
|
||||
|
||||
/* output -> F32(possibility) */
|
||||
CHECK_OV_STATUS(ov_preprocess_prepostprocessor_get_output_info_by_index(
|
||||
ppp, index, &output_info),
|
||||
ret);
|
||||
CHECK_OV_STATUS(ov_preprocess_output_info_get_tensor_info(
|
||||
output_info, &output_tensor_info),
|
||||
ret);
|
||||
CHECK_OV_STATUS(
|
||||
ov_preprocess_output_set_element_type(output_tensor_info, F32),
|
||||
ret);
|
||||
|
||||
CHECK_OV_STATUS(
|
||||
ov_preprocess_prepostprocessor_build(ppp, &ov_ctx->new_model), ret);
|
||||
}
|
||||
|
||||
CHECK_OV_STATUS(ov_core_compile_model(ov_ctx->core, ov_ctx->new_model,
|
||||
"CPU", 0, &ov_ctx->compiled_model),
|
||||
ret);
|
||||
|
||||
CHECK_OV_STATUS(ov_compiled_model_create_infer_request(
|
||||
ov_ctx->compiled_model, &ov_ctx->infer_request),
|
||||
ret);
|
||||
|
||||
/* install ov_tensor -> infer_request */
|
||||
CHECK_OV_STATUS(ov_infer_request_set_input_tensor_by_index(
|
||||
ov_ctx->infer_request, index, ov_ctx->input_tensor),
|
||||
exec->infer_request, index, input_tensor),
|
||||
ret);
|
||||
ret = success;
|
||||
|
||||
fail:
|
||||
if (ov_dims)
|
||||
os_free(ov_dims);
|
||||
if (input_tensor)
|
||||
ov_tensor_free(input_tensor);
|
||||
ov_shape_free(&input_shape);
|
||||
if (ppp)
|
||||
ov_preprocess_prepostprocessor_free(ppp);
|
||||
if (input_info)
|
||||
ov_preprocess_input_info_free(input_info);
|
||||
if (input_tensor_info)
|
||||
ov_preprocess_input_tensor_info_free(input_tensor_info);
|
||||
if (input_layout)
|
||||
ov_layout_free(input_layout);
|
||||
if (input_process)
|
||||
ov_preprocess_preprocess_steps_free(input_process);
|
||||
if (p_input_model)
|
||||
ov_preprocess_input_model_info_free(p_input_model);
|
||||
if (model_layout)
|
||||
ov_layout_free(model_layout);
|
||||
if (output_info)
|
||||
ov_preprocess_output_info_free(output_info);
|
||||
if (output_tensor_info)
|
||||
ov_preprocess_output_tensor_info_free(output_tensor_info);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -439,9 +425,14 @@ __attribute__((visibility("default"))) wasi_nn_error
|
|||
compute(void *ctx, graph_execution_context exec_ctx)
|
||||
{
|
||||
OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx;
|
||||
struct OpenVINOExecutionContext *exec;
|
||||
wasi_nn_error ret = unsupported_operation;
|
||||
|
||||
CHECK_OV_STATUS(ov_infer_request_infer(ov_ctx->infer_request), ret);
|
||||
if (exec_ctx >= ov_ctx->n_execution_contexts)
|
||||
return runtime_error;
|
||||
exec = &ov_ctx->execution_contexts[exec_ctx];
|
||||
|
||||
CHECK_OV_STATUS(ov_infer_request_infer(exec->infer_request), ret);
|
||||
ret = success;
|
||||
fail:
|
||||
return ret;
|
||||
|
@ -449,23 +440,33 @@ fail:
|
|||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
get_output(void *ctx, graph_execution_context exec_ctx, uint32_t index,
|
||||
tensor_data output_tensor, uint32_t *output_tensor_size)
|
||||
tensor_data *output_tensor, uint32_t *output_tensor_size)
|
||||
{
|
||||
OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx;
|
||||
struct OpenVINOExecutionContext *exec;
|
||||
wasi_nn_error ret = unsupported_operation;
|
||||
ov_tensor_t *ov_tensor = NULL;
|
||||
void *data = NULL;
|
||||
size_t byte_size = 0;
|
||||
|
||||
if (exec_ctx >= ov_ctx->n_execution_contexts)
|
||||
return runtime_error;
|
||||
exec = &ov_ctx->execution_contexts[exec_ctx];
|
||||
|
||||
CHECK_OV_STATUS(ov_infer_request_get_output_tensor_by_index(
|
||||
ov_ctx->infer_request, index, &ov_tensor),
|
||||
exec->infer_request, index, &ov_tensor),
|
||||
ret);
|
||||
|
||||
CHECK_OV_STATUS(ov_tensor_get_byte_size(ov_tensor, &byte_size), ret);
|
||||
|
||||
if (byte_size > output_tensor->size) {
|
||||
ret = too_large;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
CHECK_OV_STATUS(ov_tensor_data(ov_tensor, &data), ret);
|
||||
|
||||
memcpy(output_tensor, data, byte_size);
|
||||
memcpy(output_tensor->buf, data, byte_size);
|
||||
|
||||
*output_tensor_size = (uint32_t)byte_size;
|
||||
|
||||
|
@ -511,7 +512,7 @@ init_backend(void **ctx)
|
|||
*ctx = (void *)ov_ctx;
|
||||
return success;
|
||||
fail:
|
||||
openvino_destroy((void *)ov_ctx);
|
||||
os_free(ov_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -519,27 +520,16 @@ __attribute__((visibility("default"))) wasi_nn_error
|
|||
deinit_backend(void *ctx)
|
||||
{
|
||||
OpenVINOContext *ov_ctx = (OpenVINOContext *)ctx;
|
||||
unsigned int i;
|
||||
|
||||
if (!ov_ctx)
|
||||
return invalid_argument;
|
||||
|
||||
if (ov_ctx->weight_data)
|
||||
os_free(ov_ctx->weight_data);
|
||||
for (i = 0; i < ov_ctx->n_execution_contexts; i++)
|
||||
free_execution_context(&ov_ctx->execution_contexts[i]);
|
||||
|
||||
if (ov_ctx->weights_tensor)
|
||||
ov_tensor_free(ov_ctx->weights_tensor);
|
||||
|
||||
if (ov_ctx->input_tensor)
|
||||
ov_tensor_free(ov_ctx->input_tensor);
|
||||
|
||||
if (ov_ctx->infer_request)
|
||||
ov_infer_request_free(ov_ctx->infer_request);
|
||||
|
||||
if (ov_ctx->compiled_model)
|
||||
ov_compiled_model_free(ov_ctx->compiled_model);
|
||||
|
||||
if (ov_ctx->model)
|
||||
ov_model_free(ov_ctx->model);
|
||||
for (i = 0; i < ov_ctx->n_graphs; i++)
|
||||
free_graph(&ov_ctx->graphs[i]);
|
||||
|
||||
if (ov_ctx->core)
|
||||
ov_core_free(ov_ctx->core);
|
||||
|
|
|
@ -9,10 +9,44 @@
|
|||
#include "wasi_nn_types.h"
|
||||
#include "wasm_export.h"
|
||||
|
||||
#include "bh_platform.h"
|
||||
|
||||
typedef struct {
|
||||
korp_mutex lock;
|
||||
bool busy;
|
||||
bool is_backend_ctx_initialized;
|
||||
bool is_model_loaded;
|
||||
graph_encoding backend;
|
||||
void *backend_ctx;
|
||||
} WASINNContext;
|
||||
|
||||
typedef wasi_nn_error (*LOAD)(void *, graph_builder_array *, graph_encoding,
|
||||
execution_target, graph *);
|
||||
typedef wasi_nn_error (*LOAD_BY_NAME)(void *, const char *, uint32_t, graph *);
|
||||
typedef wasi_nn_error (*LOAD_BY_NAME_WITH_CONFIG)(void *, const char *,
|
||||
uint32_t, void *, uint32_t,
|
||||
graph *);
|
||||
typedef wasi_nn_error (*INIT_EXECUTION_CONTEXT)(void *, graph,
|
||||
graph_execution_context *);
|
||||
typedef wasi_nn_error (*SET_INPUT)(void *, graph_execution_context, uint32_t,
|
||||
tensor *);
|
||||
typedef wasi_nn_error (*COMPUTE)(void *, graph_execution_context);
|
||||
typedef wasi_nn_error (*GET_OUTPUT)(void *, graph_execution_context, uint32_t,
|
||||
tensor_data *, uint32_t *);
|
||||
/* wasi-nn general APIs */
|
||||
typedef wasi_nn_error (*BACKEND_INITIALIZE)(void **);
|
||||
typedef wasi_nn_error (*BACKEND_DEINITIALIZE)(void *);
|
||||
|
||||
typedef struct {
|
||||
LOAD load;
|
||||
LOAD_BY_NAME load_by_name;
|
||||
LOAD_BY_NAME_WITH_CONFIG load_by_name_with_config;
|
||||
INIT_EXECUTION_CONTEXT init_execution_context;
|
||||
SET_INPUT set_input;
|
||||
COMPUTE compute;
|
||||
GET_OUTPUT get_output;
|
||||
BACKEND_INITIALIZE init;
|
||||
BACKEND_DEINITIALIZE deinit;
|
||||
} api_function;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wasi_nn_tensorflowlite.hpp"
|
||||
#include "utils/logger.h"
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include "wasi_nn_types.h"
|
||||
#include "wasi_nn_backend.h"
|
||||
#include "wasm_export.h"
|
||||
|
||||
#include <tensorflow/lite/interpreter.h>
|
||||
|
@ -85,12 +84,8 @@ is_valid_graph(TFLiteContext *tfl_ctx, graph g)
|
|||
NN_ERR_PRINTF("Invalid graph: %d >= %d.", g, MAX_GRAPHS_PER_INST);
|
||||
return runtime_error;
|
||||
}
|
||||
if (tfl_ctx->models[g].model_pointer == NULL) {
|
||||
NN_ERR_PRINTF("Context (model) non-initialized.");
|
||||
return runtime_error;
|
||||
}
|
||||
if (tfl_ctx->models[g].model == NULL) {
|
||||
NN_ERR_PRINTF("Context (tflite model) non-initialized.");
|
||||
NN_ERR_PRINTF("Context (model) non-initialized.");
|
||||
return runtime_error;
|
||||
}
|
||||
return success;
|
||||
|
@ -285,6 +280,11 @@ set_input(void *tflite_ctx, graph_execution_context ctx, uint32_t index,
|
|||
{
|
||||
TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
|
||||
|
||||
if (input_tensor->type != fp32) {
|
||||
NN_ERR_PRINTF("unsupported input tensor type %u", input_tensor->type);
|
||||
return runtime_error;
|
||||
}
|
||||
|
||||
wasi_nn_error res;
|
||||
if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
|
||||
return res;
|
||||
|
@ -323,7 +323,7 @@ set_input(void *tflite_ctx, graph_execution_context ctx, uint32_t index,
|
|||
index);
|
||||
|
||||
int size = model_tensor_size * sizeof(float);
|
||||
bh_memcpy_s(it, size, input_tensor->data, size);
|
||||
bh_memcpy_s(it, size, input_tensor->data.buf, size);
|
||||
}
|
||||
else { // TODO: Assuming uint8 quantized networks.
|
||||
TfLiteAffineQuantization *quant_info =
|
||||
|
@ -341,7 +341,7 @@ set_input(void *tflite_ctx, graph_execution_context ctx, uint32_t index,
|
|||
NN_DBG_PRINTF("input tensor: (scale, offset) = (%f, %f)", scale,
|
||||
zero_point);
|
||||
|
||||
float *input_tensor_f = (float *)input_tensor->data;
|
||||
float *input_tensor_f = (float *)input_tensor->data.buf;
|
||||
for (uint32_t i = 0; i < model_tensor_size; ++i) {
|
||||
it[i] = (uint8_t)(input_tensor_f[i] / scale + zero_point);
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ compute(void *tflite_ctx, graph_execution_context ctx)
|
|||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
get_output(void *tflite_ctx, graph_execution_context ctx, uint32_t index,
|
||||
tensor_data output_tensor, uint32_t *output_tensor_size)
|
||||
tensor_data *output_tensor, uint32_t *output_tensor_size)
|
||||
{
|
||||
TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
|
||||
|
||||
|
@ -388,23 +388,34 @@ get_output(void *tflite_ctx, graph_execution_context ctx, uint32_t index,
|
|||
return too_large;
|
||||
}
|
||||
|
||||
uint32_t model_tensor_size = 1;
|
||||
for (int i = 0; i < (int)tensor->dims->size; ++i)
|
||||
model_tensor_size *= (uint32_t)tensor->dims->data[i];
|
||||
|
||||
if (*output_tensor_size < model_tensor_size) {
|
||||
NN_ERR_PRINTF("Insufficient memory to copy tensor %d", index);
|
||||
return too_large;
|
||||
}
|
||||
|
||||
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);
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
if (output_tensor->size < tensor->bytes) {
|
||||
NN_ERR_PRINTF("Insufficient memory to copy tensor %d", index);
|
||||
return too_large;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* for now, maintain the bug-to-bug compatibility with the old abi,
|
||||
* where the size here is the number of fp32, not bytes.
|
||||
*/
|
||||
if (output_tensor->size < tensor->bytes / sizeof(float)) {
|
||||
NN_ERR_PRINTF("Insufficient memory to copy tensor %d", index);
|
||||
return too_large;
|
||||
}
|
||||
#endif
|
||||
bh_memcpy_s(output_tensor->buf, output_tensor->size, tensor->data.data,
|
||||
tensor->bytes);
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
*output_tensor_size = tensor->bytes;
|
||||
#else
|
||||
/*
|
||||
* for now, maintain the bug-to-bug compatibility with the old abi,
|
||||
* where the size here is the number of fp32, not bytes.
|
||||
*/
|
||||
*output_tensor_size = tensor->bytes / sizeof(float);
|
||||
#endif
|
||||
}
|
||||
else { // TODO: Assuming uint8 quantized networks.
|
||||
TfLiteAffineQuantization *quant_info =
|
||||
|
@ -413,6 +424,27 @@ get_output(void *tflite_ctx, graph_execution_context ctx, uint32_t index,
|
|||
NN_ERR_PRINTF("Quantization per channel is not supported");
|
||||
return runtime_error;
|
||||
}
|
||||
|
||||
uint32_t model_tensor_size = 1;
|
||||
for (int i = 0; i < (int)tensor->dims->size; ++i)
|
||||
model_tensor_size *= (uint32_t)tensor->dims->data[i];
|
||||
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
if (output_tensor->size / sizeof(float) < model_tensor_size) {
|
||||
NN_ERR_PRINTF("Insufficient memory to copy tensor %d", index);
|
||||
return too_large;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* for now, maintain the bug-to-bug compatibility with the old abi,
|
||||
* where the size here is the number of fp32, not bytes.
|
||||
*/
|
||||
if (output_tensor->size < model_tensor_size) {
|
||||
NN_ERR_PRINTF("Insufficient memory to copy tensor %d", index);
|
||||
return too_large;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t *ot = tfl_ctx->interpreters[ctx]
|
||||
.interpreter->typed_output_tensor<uint8_t>(index);
|
||||
|
||||
|
@ -421,13 +453,22 @@ get_output(void *tflite_ctx, graph_execution_context ctx, uint32_t index,
|
|||
NN_DBG_PRINTF("output tensor: (scale, offset) = (%f, %f)", scale,
|
||||
zero_point);
|
||||
|
||||
float *output_tensor_f = (float *)output_tensor;
|
||||
float *output_tensor_f = (float *)output_tensor->buf;
|
||||
for (uint32_t i = 0; i < model_tensor_size; ++i) {
|
||||
output_tensor_f[i] = (ot[i] - zero_point) * scale;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
|
||||
*output_tensor_size = model_tensor_size * sizeof(float);
|
||||
#else
|
||||
/*
|
||||
* for now, maintain the bug-to-bug compatibility with the old abi,
|
||||
* where the size here is the number of fp32, not bytes.
|
||||
*/
|
||||
*output_tensor_size = model_tensor_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
*output_tensor_size = model_tensor_size;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -472,32 +513,31 @@ deinit_backend(void *tflite_ctx)
|
|||
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->delegate) {
|
||||
switch (tfl_ctx->models[i].target) {
|
||||
case gpu:
|
||||
{
|
||||
if (tfl_ctx->delegate) {
|
||||
switch (tfl_ctx->models[i].target) {
|
||||
case gpu:
|
||||
{
|
||||
#if WASM_ENABLE_WASI_NN_GPU != 0
|
||||
TfLiteGpuDelegateV2Delete(tfl_ctx->delegate);
|
||||
TfLiteGpuDelegateV2Delete(tfl_ctx->delegate);
|
||||
#else
|
||||
NN_ERR_PRINTF("GPU delegate delete but not enabled.");
|
||||
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;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
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;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tfl_ctx->models[i].model_pointer) {
|
||||
wasm_runtime_free(tfl_ctx->models[i].model_pointer);
|
||||
}
|
||||
tfl_ctx->models[i].model_pointer = NULL;
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef WASI_NN_TENSORFLOWLITE_HPP
|
||||
#define WASI_NN_TENSORFLOWLITE_HPP
|
||||
|
||||
#include "wasi_nn_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
load(void *tflite_ctx, graph_builder_array *builder, graph_encoding encoding,
|
||||
execution_target target, graph *g);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
load_by_name(void *tflite_ctx, const char *filename, uint32_t filename_len,
|
||||
graph *g);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
init_execution_context(void *tflite_ctx, graph g, graph_execution_context *ctx);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
set_input(void *tflite_ctx, graph_execution_context ctx, uint32_t index,
|
||||
tensor *input_tensor);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
compute(void *tflite_ctx, graph_execution_context ctx);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
get_output(void *tflite_ctx, graph_execution_context ctx, uint32_t index,
|
||||
tensor_data output_tensor, uint32_t *output_tensor_size);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
init_backend(void **tflite_ctx);
|
||||
|
||||
__attribute__((visibility("default"))) wasi_nn_error
|
||||
deinit_backend(void *tflite_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -37,7 +37,10 @@ RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-
|
|||
WORKDIR /tmp
|
||||
RUN git clone https://github.com/VeriSilicon/TIM-VX.git tim-vx \
|
||||
&& git clone https://github.com/VeriSilicon/tflite-vx-delegate.git \
|
||||
&& git clone https://github.com/tensorflow/tensorflow.git
|
||||
&& git clone https://github.com/tensorflow/tensorflow.git --branch v2.12.0
|
||||
|
||||
WORKDIR /tmp/tensorflow
|
||||
RUN git cherry-pick -n 5115fa96d7c5b41451674892317be43e30b7c389
|
||||
|
||||
|
||||
# Build TIM-VX
|
||||
|
@ -99,28 +102,24 @@ RUN cp --parents \
|
|||
ENV VIVANTE_SDK_DIR=/tmp/tim-vx/prebuilt-sdk/x86_64_linux/
|
||||
ENV VSIMULATOR_CONFIG=czl
|
||||
|
||||
ENV LD_LIBRARY_PATH=/tmp/tim-vx/prebuilt-sdk/x86_64_linux/lib:/usr/local/lib:/lib/x86_64-linux-gnu/:/lib64/:/usr/lib:$LD_LIBRARY_PATH
|
||||
|
||||
# Build WASI-NN
|
||||
WORKDIR /home/wamr
|
||||
|
||||
COPY . .
|
||||
|
||||
WORKDIR /home/wamr/core/iwasm/libraries/wasi-nn/test/build
|
||||
WORKDIR /home/wamr/product-mini/platforms/linux
|
||||
|
||||
# hadolint ignore=SC2086
|
||||
RUN cmake \
|
||||
-DCMAKE_LIBRARY_PATH=${CMAKE_LIBRARY_PATH}:/usr/local/lib/ \
|
||||
-DCMAKE_INCLUDE_PATH=${CMAKE_INCLUDE_PATH}:/usr/local/include/ \
|
||||
RUN rm -rf build \
|
||||
&& cmake -S . -B build\
|
||||
-DCMAKE_LIBRARY_PATH="/usr/local/lib/" \
|
||||
-DCMAKE_INCLUDE_PATH="/usr/local/include/" \
|
||||
-DWAMR_BUILD_WASI_NN=1 \
|
||||
-DWAMR_BUILD_WASI_NN_TFLITE=1\
|
||||
-DWAMR_BUILD_WASI_NN_ENABLE_EXT=1 \
|
||||
-DWASI_NN_EXT_DELEGATE_PATH="/usr/lib/libvx_delegate.so" \
|
||||
..
|
||||
&& cmake --build build -j "$(grep -c ^processor /proc/cpuinfo)"
|
||||
|
||||
RUN make -j "$(grep -c ^processor /proc/cpuinfo)"
|
||||
|
||||
RUN cp /home/wamr/core/iwasm/libraries/wasi-nn/test/build/iwasm /run/iwasm \
|
||||
RUN cp /home/wamr/product-mini/platforms/linux/build/iwasm /run/iwasm \
|
||||
&& cp /home/wamr/product-mini/platforms/linux/build/lib*.so /usr/lib
|
||||
|
||||
ENTRYPOINT [ "/run/iwasm" ]
|
||||
|
|
|
@ -3,6 +3,17 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
# on intel mac, this ends up with a lot of the following error.
|
||||
#
|
||||
# AttributeError: 'Sequential' object has no attribute '_get_save_spec'.
|
||||
#
|
||||
# * "pip install tensorflow" installs tensorflow 2.16.2 on intel mac.
|
||||
# (because it's the last version before tf deprecated the target.)
|
||||
# * keras 3 support in the version seems incomplete (thus the error)
|
||||
# * a workaround: use keras 2 as mentioned in:
|
||||
# https://github.com/tensorflow/tensorflow/releases/tag/v2.16.1
|
||||
# https://blog.tensorflow.org/2024/03/whats-new-in-tensorflow-216.html
|
||||
|
||||
CURR_PATH=$(cd $(dirname $0) && pwd -P)
|
||||
|
||||
# WASM application that uses WASI-NN
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import tensorflow as tf
|
||||
import numpy as np
|
||||
from keras.layers import AveragePooling2D, Conv2D
|
||||
from tensorflow.keras.layers import AveragePooling2D, Conv2D
|
||||
|
||||
from tensorflow.keras import Input, Model
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ wasm_load(char *model_name, graph *g, execution_target target)
|
|||
wasi_nn_error
|
||||
wasm_load_by_name(const char *model_name, graph *g)
|
||||
{
|
||||
wasi_nn_error res = load_by_name(model_name, g);
|
||||
wasi_nn_error res = load_by_name(model_name, strlen(model_name), g);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,8 @@ run_inference(execution_target target, float *input, uint32_t *input_size,
|
|||
uint32_t num_output_tensors)
|
||||
{
|
||||
graph graph;
|
||||
if (wasm_load(model_name, &graph, target) != success) {
|
||||
|
||||
if (wasm_load_by_name(model_name, &graph) != success) {
|
||||
NN_ERR_PRINTF("Error when loading model.");
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -201,10 +201,20 @@ openat(int fd, const char *pathname, int flags, ...)
|
|||
int ret;
|
||||
char dir_path[DIR_PATH_LEN];
|
||||
char *full_path;
|
||||
mode_t mode = 0;
|
||||
bool has_mode = false;
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap;
|
||||
va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, int);
|
||||
va_end(ap);
|
||||
has_mode = true;
|
||||
}
|
||||
|
||||
ret = fcntl(fd, F_GETPATH, dir_path);
|
||||
if (ret != 0) {
|
||||
errno = -EINVAL;
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -214,7 +224,7 @@ openat(int fd, const char *pathname, int flags, ...)
|
|||
return -1;
|
||||
}
|
||||
|
||||
new_fd = open(full_path, flags);
|
||||
new_fd = has_mode ? open(full_path, flags, mode) : open(full_path, flags);
|
||||
free(full_path);
|
||||
|
||||
return new_fd;
|
||||
|
|
|
@ -35,8 +35,8 @@ extend_vector(Vector *vector, size_t length)
|
|||
if (length <= vector->max_elems)
|
||||
return true;
|
||||
|
||||
if (length < vector->size_elem * 3 / 2)
|
||||
length = vector->size_elem * 3 / 2;
|
||||
if (length < vector->max_elems * 3 / 2)
|
||||
length = vector->max_elems * 3 / 2;
|
||||
|
||||
if (!(data = alloc_vector_data(length, vector->size_elem))) {
|
||||
return false;
|
||||
|
@ -194,12 +194,12 @@ bh_vector_append(Vector *vector, const void *elem_buf)
|
|||
goto just_return;
|
||||
}
|
||||
|
||||
/* make sure one more slot is used by the thread who allocas it */
|
||||
/* make sure one more slot is used by the thread who allocates it */
|
||||
if (vector->lock)
|
||||
os_mutex_lock(vector->lock);
|
||||
|
||||
if (!extend_vector(vector, vector->num_elems + 1)) {
|
||||
LOG_ERROR("Append ector elem failed: extend vector failed.\n");
|
||||
LOG_ERROR("Append vector elem failed: extend vector failed.\n");
|
||||
goto unlock_return;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
/* clang-format off */
|
||||
#define WAMR_VERSION_MAJOR 2
|
||||
#define WAMR_VERSION_MINOR 3
|
||||
#define WAMR_VERSION_PATCH 0
|
||||
#define WAMR_VERSION_PATCH 1
|
||||
/* clang-format on */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -102,6 +102,7 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM
|
|||
|
||||
### **Enable lib wasi-nn**
|
||||
- **WAMR_BUILD_WASI_NN**=1/0, default to disable if not set
|
||||
> Note: WAMR_BUILD_WASI_NN without WAMR_BUILD_WASI_EPHEMERAL_NN is deprecated and will likely be removed in future versions of WAMR. Please consider to enable WAMR_BUILD_WASI_EPHEMERAL_NN as well.
|
||||
> Note: See [WASI-NN](../core/iwasm/libraries/wasi-nn) for more details.
|
||||
|
||||
### **Enable lib wasi-nn GPU mode**
|
||||
|
@ -113,7 +114,7 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM
|
|||
- **WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH**=Path to the external delegate shared library (e.g. `libedgetpu.so.1.0` for Coral USB)
|
||||
|
||||
### **Enable lib wasi-nn with `wasi_ephemeral_nn` module support**
|
||||
- **WAMR_BUILD_WASI_EPHEMERAL_NN**=1/0, default to disable if not set
|
||||
- **WAMR_BUILD_WASI_EPHEMERAL_NN**=1/0, default to enable if not set
|
||||
|
||||
### **Disable boundary check with hardware trap**
|
||||
- **WAMR_DISABLE_HW_BOUND_CHECK**=1/0, default to enable if not set and supported by platform
|
||||
|
@ -292,6 +293,10 @@ Currently we only profile the memory consumption of module, module_instance and
|
|||
- **WAMR_BUILD_AOT_INTRINSICS**=1/0, enable the AOT intrinsic functions, default to enable if not set. These functions can be called from the AOT code when `--disable-llvm-intrinsics` flag or `--enable-builtin-intrinsics=<intr1,intr2,...>` flag is used by wamrc to generate the AOT file.
|
||||
> Note: See [Tuning the XIP intrinsic functions](./xip.md#tuning-the-xip-intrinsic-functions) for more details.
|
||||
|
||||
### **Enable extended constant expression**
|
||||
- **WAMR_BUILD_EXTENDED_CONST_EXPR**=1/0, default to disable if not set.
|
||||
> Note: See [Extended Constant Expressions](https://github.com/WebAssembly/extended-const/blob/main/proposals/extended-const/Overview.md) for more details.
|
||||
|
||||
### **Configurable memory access boundary check**
|
||||
- **WAMR_CONFIGURABLE_BOUNDS_CHECKS**=1/0, default to disable if not set
|
||||
> Note: If it is enabled, allow to run `iwasm --disable-bounds-checks` to disable the memory access boundary checks for interpreter mode.
|
||||
|
@ -327,6 +332,10 @@ And the wasm app can calls below APIs to allocate/free memory from/to the shared
|
|||
- **WAMR_BUILD_SHRUNK_MEMORY**=1/0, default to enable if not set
|
||||
> Note: When enabled, this feature will reduce memory usage by decreasing the size of the linear memory, particularly when the `memory.grow` opcode is not used and memory usage is somewhat predictable.
|
||||
|
||||
## **Instruction metering**
|
||||
- **WAMR_BUILD_INSTRUCTION_METERING**=1/0, default to disable if not set
|
||||
> Note: Enabling this feature allows limiting the number of instructions a wasm module instance can execute. Use the `wasm_runtime_set_instruction_count_limit(...)` API before calling `wasm_runtime_call_*(...)` APIs to enforce this limit.
|
||||
|
||||
## **Combination of configurations:**
|
||||
|
||||
We can combine the configurations. For example, if we want to disable interpreter, enable AOT and WASI, we can run command:
|
||||
|
@ -356,4 +365,4 @@ For Valgrind, begin with the following configurations and add additional ones as
|
|||
-DWAMR_DISABLE_HW_BOUND_CHECK=0 \
|
||||
-DWAMR_DISABLE_WRITE_GS_BASE=0
|
||||
#...
|
||||
```
|
||||
```
|
||||
|
|
|
@ -22,7 +22,12 @@ set (WAMR_ROOT_DIR path/to/wamr/root)
|
|||
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
|
||||
target_link_libraries (your_project vmlib)
|
||||
# include bh_read_file.h
|
||||
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
||||
|
||||
add_executable (your_project main.c ${UNCOMMON_SHARED_SOURCE})
|
||||
|
||||
target_link_libraries (your_project vmlib -lm)
|
||||
```
|
||||
Examples can be found in [CMakeLists.txt of linux platform](../product-mini/platforms/linux/CMakeLists.txt) and [other platforms](../product-mini/platforms). The available features to configure can be found in [Build WAMR vmcore](./build_wamr.md#wamr-vmcore-cmake-building-configurations).
|
||||
|
||||
|
@ -31,6 +36,10 @@ Developer can also use Makefile to embed WAMR, by defining macros and including
|
|||
## The runtime initialization
|
||||
|
||||
``` C
|
||||
#include "bh_platform.h"
|
||||
#include "bh_read_file.h"
|
||||
#include "wasm_export.h"
|
||||
|
||||
char *buffer, error_buf[128];
|
||||
wasm_module_t module;
|
||||
wasm_module_inst_t module_inst;
|
||||
|
@ -42,7 +51,7 @@ Developer can also use Makefile to embed WAMR, by defining macros and including
|
|||
wasm_runtime_init();
|
||||
|
||||
/* read WASM file into a memory buffer */
|
||||
buffer = read_wasm_binary_to_buffer(…, &size);
|
||||
buffer = bh_read_file_to_buffer(…, &size);
|
||||
|
||||
/* add line below if we want to export native functions to WASM app */
|
||||
wasm_runtime_register_natives(...);
|
||||
|
|
|
@ -4,6 +4,6 @@ WebAssembly [reference-types](https://github.com/WebAssembly/reference-types) pr
|
|||
|
||||
WAMR has implemented the reference-types proposal. WAMR allows a native method to pass a host object to a WASM application as an `externref` parameter or receives a host object from a WASM application as an `externref` result. Internally, WAMR won't try to parse or dereference `externref`. It is an opaque type.
|
||||
|
||||
The restriction of using `externref` in a native method is the host object has to be the value of a `unintptr_t` variable. In other words, it takes **8 bytes** on 64-bit machine and **4 bytes** on 32-bit machines. Please keep that in mind especially when calling `wasm_runtime_call_wasm`.
|
||||
The restriction of using `externref` in a native method is the host object has to be the value of a `uintptr_t` variable. In other words, it takes **8 bytes** on 64-bit machine and **4 bytes** on 32-bit machines. Please keep that in mind especially when calling `wasm_runtime_call_wasm`.
|
||||
|
||||
Please ref to the [sample](../samples/ref-types) for more details.
|
||||
|
|
46
doc/security_issue_runbook.md
Normal file
46
doc/security_issue_runbook.md
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Security Issue Runbook
|
||||
|
||||
This runbook provides step-by-step guidance on handling a security advisory. Typically, it begins with a draft security advisory when we initiate the process outlined in this runbook. The draft security advisory is created by a contributor or a maintainer.
|
||||
|
||||
For information on what types of issues are considered security vulnerabilities and require a security advisory for resolution, please refer to [identifying a security issue](./security_need_to_know.md#identifying-a-security-issue).
|
||||
|
||||
## Step 1: Initial Response to Security Advisory
|
||||
|
||||
- Receive Security Advisory: When a new security advisory is received, the Incident Manager, typically the maintainer who opened the advisory, becomes the first responder. If the advisory was opened by someone else, a maintainer should take on the role of Incident Manager. The Incident Manager can hand off this role to another maintainer if necessary.
|
||||
- Acknowledge Receipt: The Incident Manager should promptly acknowledge receipt of the advisory and communicate that the investigation will begin immediately. Security issues are the highest priority.
|
||||
|
||||
## Step 2: Investigating the Vulnerability
|
||||
|
||||
- Identify the Vulnerability: Reproduce the issue to understand the vulnerability. Determine which versions and platforms are affected. Fill out the advisory details with this information.
|
||||
- Accept the Report: Accept the security report and create a temporary private fork to collaborate on a fix. Invite necessary helpers and stakeholders to this fork, as their input can be valuable.
|
||||
|
||||
## Step 3: Communication and Collaboration
|
||||
|
||||
- Use Non-Public Channels: Communicate through non-public channels, preferably email, during the resolution process. Avoid filing issues or pull requests on third-party repositories if they are involved.
|
||||
- Workaround for Third-Party Dependencies: If third-party dependencies are involved, consider a workaround to patch the issue quickly unless the third party can release a fix promptly.
|
||||
|
||||
## Step 4: Finalizing and Preparing for Release
|
||||
|
||||
- Finalize Details: Once a fix is developed and the vulnerability is fully understood, finalize the advisory details and prepare for public release. Ensure the security issues are resolved in the private fork.
|
||||
- Request CVE: Use the Big Green Button on the advisory to request a CVE number from GitHub staff.
|
||||
- Advanced Disclosure Email: Decide on a disclosure date, typically within a week, and send an email to sec-announce@bytecodealliance.org about the upcoming security release. Other ways are also available to communicate the disclosure date.
|
||||
|
||||
## Step 5: Preparing and Testing Patch Releases
|
||||
|
||||
- Prepare PRs for Patch Releases: Create pull requests in the private fork for each version being patched. Ensure each PR is ready to apply cleanly and includes release notes for each release branch.
|
||||
- Run Full Test Suite: Run the full test suite locally for the main branch. Attempt to run as much of the CI matrix locally as possible.
|
||||
|
||||
## Step 6: Public Release and Communication
|
||||
|
||||
- Open Version Bump PRs: Open version bump pull requests on the public repository without including patch notes or release notes for the fix.
|
||||
- Manually Make PRs from Private Fork: Transfer the necessary pull requests from the private fork to the public repository.
|
||||
- Merge and Trigger Releases: Merge the version bump PRs and trigger the release process.
|
||||
- Publish GitHub Advisories: Delete the private forks and use the Big Green Button to publish the advisory.
|
||||
- Send Security Release Email: Send a follow-up email to sec-announce@bytecodealliance.org describing the security release. Other communication channels can also be used to inform users about the security release.
|
||||
|
||||
By following these steps, you can effectively manage and resolve security issues for your open source project, ensuring timely communication and collaboration while maintaining the integrity and security of your software.
|
||||
|
||||
## References
|
||||
|
||||
- [Vulnerability Response Runbook](https://github.com/bytecodealliance/rfcs/blob/main/accepted/vulnerability-response-runbook.md)
|
||||
- [Wasmtime Security Vulnerability Runbook](https://docs.wasmtime.dev/security-vulnerability-runbook.html)
|
|
@ -30,4 +30,4 @@ Before reporting an issue, particularly one related to crashing, consult [the ch
|
|||
|
||||
Upon receiving an issue, thoroughly review [the cheat sheet](https://github.com/bytecodealliance/rfcs/blob/main/accepted/what-is-considered-a-security-bug.md#cheat-sheet-is-this-bug-considered-a-security-vulnerability) to assess and _Report a security vulnerability_ if the issue is indeed a security vulnerability.
|
||||
|
||||
Once a security issue is confirmed, please refer to [the runbook](https://github.com/bytecodealliance/rfcs/blob/main/accepted/vulnerability-response-runbook.md) for the subsequent steps to take.
|
||||
Once a security issue is confirmed, please refer to [the runbook](./security_issue_runbook.md) for the subsequent steps to take.
|
||||
|
|
|
@ -112,12 +112,12 @@ def wasm_vec_to_list(vec):
|
|||
wasm_frame_vec_t,
|
||||
wasm_extern_vec_t,
|
||||
]
|
||||
known_vec_pointer_type = [POINTER(type) for type in known_vec_type]
|
||||
known_vec_pointer_type = [POINTER(vec_type) for vec_type in known_vec_type]
|
||||
|
||||
if any([isinstance(vec, type) for type in known_vec_pointer_type]):
|
||||
if any([isinstance(vec, pointer_type) for pointer_type in known_vec_pointer_type]):
|
||||
vec = dereference(vec)
|
||||
return [vec.data[i] for i in range(vec.num_elems)]
|
||||
elif any([isinstance(vec, type) for type in known_vec_type]):
|
||||
elif any([isinstance(vec, vec_type) for vec_type in known_vec_type]):
|
||||
return [vec.data[i] for i in range(vec.num_elems)]
|
||||
else:
|
||||
raise RuntimeError("not a known vector type")
|
||||
|
@ -405,7 +405,7 @@ def __compare_wasm_val_t(self, other):
|
|||
elif WASM_F32 == self.kind:
|
||||
return self.of.f32 == other.of.f32
|
||||
elif WASM_F64 == self.kind:
|
||||
return self.of.f64 == other.of.f63
|
||||
return self.of.f64 == other.of.f64
|
||||
elif WASM_EXTERNREF == self.kind:
|
||||
raise RuntimeError("FIXME")
|
||||
else:
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
### Pre-requisites
|
||||
#### Install requirements
|
||||
Before proceeding it is necessary to make sure your Python environment is correctly configured. To do ths open a terminal session in this directory and perfom the following:
|
||||
Before proceeding it is necessary to make sure your Python environment is correctly configured. To do this open a terminal session in this directory and perform the following:
|
||||
|
||||
|
||||
```shell
|
||||
|
|
|
@ -353,12 +353,12 @@ writable and needs to be copied into a ctype array.
|
|||
|
||||
#### variable arguments
|
||||
|
||||
A function with _variable arugments_ makes it hard to specify the required
|
||||
A function with _variable arguments_ makes it hard to specify the required
|
||||
argument types for the function prototype. It leaves us one way to call it
|
||||
directly without any arguments type checking.
|
||||
|
||||
```python
|
||||
libc.printf(b"Hello, an int %d, a float %f, a string %s\n", c_int(1), c_doulbe(3.14), "World!")
|
||||
libc.printf(b"Hello, an int %d, a float %f, a string %s\n", c_int(1), c_double(3.14), "World!")
|
||||
```
|
||||
|
||||
#### Use `c_bool` to represent `wasm_mutability_t `
|
||||
|
@ -373,7 +373,7 @@ libc.printf(b"Hello, an int %d, a float %f, a string %s\n", c_int(1), c_doulbe(3
|
|||
|
||||
### bindgen.py
|
||||
|
||||
`bindge.py` is a tool to create WAMR python binding automatically. `binding.py`
|
||||
`bindgen.py` is a tool to create WAMR python binding automatically. `binding.py`
|
||||
is generated. We should avoid modification on it. Additional helpers should go
|
||||
to `ffi.py`.
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ The Fast JIT is a lightweight JIT engine with quick startup, small footprint and
|
|||
(6) To enable the `Multi-tier JIT` mode:
|
||||
``` Bash
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_FAST_JTI=1 -DWAMR_BUILD_JIT=1
|
||||
cmake .. -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1
|
||||
make
|
||||
```
|
||||
The Multi-tier JIT is a two level JIT tier-up engine, which launches Fast JIT to run the wasm module as soon as possible and creates backend threads to compile the LLVM JIT functions at the same time, and when the LLVM JIT functions are compiled, the runtime will switch the extecution from the Fast JIT jitted code to LLVM JIT jitted code gradually, so as to gain the best performance.
|
||||
|
|
|
@ -114,6 +114,12 @@ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
|
|||
|
||||
set (CMAKE_MACOSX_RPATH True)
|
||||
|
||||
# if enable wasi-nn, both wasi-nn-backends and iwasm
|
||||
# need to use same WAMR (dynamic) libraries
|
||||
if (WAMR_BUILD_WASI_NN EQUAL 1)
|
||||
set (BUILD_SHARED_LIBS ON)
|
||||
endif ()
|
||||
|
||||
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
|
||||
|
||||
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
|
@ -132,7 +138,7 @@ add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
|||
set_version_info (vmlib)
|
||||
|
||||
target_include_directories(vmlib INTERFACE
|
||||
$<INSTALL_INTERFACE:include/iwasm>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
set (WAMR_PUBLIC_HEADERS
|
||||
|
@ -151,7 +157,7 @@ target_link_libraries (vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthr
|
|||
install (TARGETS vmlib
|
||||
EXPORT iwasmTargets
|
||||
DESTINATION lib
|
||||
PUBLIC_HEADER DESTINATION include/iwasm
|
||||
PUBLIC_HEADER DESTINATION include
|
||||
)
|
||||
|
||||
install_iwasm_package ()
|
||||
|
|
|
@ -79,7 +79,7 @@ struct wamr_pal_create_process_args {
|
|||
// Untrusted environment variable array pass to new process.
|
||||
//
|
||||
// The untrusted env vars to the command. And the last element of the array
|
||||
// must be NULL to indicate the length of array.
|
||||
// must be NULL to indicate the end of the array.
|
||||
//
|
||||
// Optional field.
|
||||
const char **env;
|
||||
|
|
|
@ -177,7 +177,7 @@ add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
|||
set_version_info (vmlib)
|
||||
|
||||
target_include_directories(vmlib INTERFACE
|
||||
$<INSTALL_INTERFACE:include/iwasm>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
set (WAMR_PUBLIC_HEADERS
|
||||
|
@ -197,7 +197,7 @@ target_link_libraries (vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthr
|
|||
install (TARGETS vmlib
|
||||
EXPORT iwasmTargets
|
||||
DESTINATION lib
|
||||
PUBLIC_HEADER DESTINATION include/iwasm
|
||||
PUBLIC_HEADER DESTINATION include
|
||||
)
|
||||
|
||||
install_iwasm_package ()
|
||||
|
|
|
@ -16,8 +16,6 @@ set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
|||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_definitions(-DCOMPILING_WASM_RUNTIME_API=1)
|
||||
|
||||
# Set WAMR_BUILD_TARGET, currently values supported:
|
||||
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
|
||||
if (NOT DEFINED WAMR_BUILD_TARGET)
|
||||
|
@ -147,7 +145,7 @@ add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
|||
set_version_info (vmlib)
|
||||
|
||||
target_include_directories(vmlib INTERFACE
|
||||
$<INSTALL_INTERFACE:include/iwasm>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
set (WAMR_PUBLIC_HEADERS
|
||||
|
@ -174,7 +172,7 @@ endif()
|
|||
install (TARGETS vmlib
|
||||
EXPORT iwasmTargets
|
||||
DESTINATION lib
|
||||
PUBLIC_HEADER DESTINATION include/iwasm
|
||||
PUBLIC_HEADER DESTINATION include
|
||||
)
|
||||
|
||||
install_iwasm_package ()
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
# Refer to https://docs.zephyrproject.org/3.7.0/develop/getting_started/index.html
|
||||
# for more information on how to set up the Zephyr development environment.
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Asian/Shanghai
|
||||
ARG ZEPHYR_SDK_VERSION=0.16.9
|
||||
# In west_lite.yml, the Zephyr version is set to v3.7.0
|
||||
#ARG ZEPHYR_VERSION=3.7.0
|
||||
|
||||
# Install dependencies for Zephyr
|
||||
# hadolint ignore=DL3008
|
||||
|
@ -16,28 +22,34 @@ RUN apt-get update && apt-get install -y --no-install-recommends git cmake ninja
|
|||
# Install the Zephyr Software Development Kit (SDK)
|
||||
WORKDIR /opt
|
||||
# hadolint ignore=DL4006
|
||||
RUN wget --progress=dot:giga https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/zephyr-sdk-0.16.3_linux-x86_64.tar.xz \
|
||||
&& wget --progress=dot:giga -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.3/sha256.sum | shasum --check --ignore-missing \
|
||||
&& tar xvf zephyr-sdk-0.16.3_linux-x86_64.tar.xz && rm zephyr-sdk-0.16.3_linux-x86_64.tar.xz
|
||||
RUN wget --progress=dot:giga https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZEPHYR_SDK_VERSION}/zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64.tar.xz \
|
||||
&& wget --progress=dot:giga -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZEPHYR_SDK_VERSION}/sha256.sum | shasum --check --ignore-missing \
|
||||
&& tar xf zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64.tar.xz && rm zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64.tar.xz
|
||||
|
||||
WORKDIR /opt/zephyr-sdk-0.16.3
|
||||
WORKDIR /opt/zephyr-sdk-${ZEPHYR_SDK_VERSION}
|
||||
# hadolint ignore=DL4006
|
||||
RUN yes | ./setup.sh
|
||||
# Install host tools and Register Zephyr SDK CMake package
|
||||
RUN ./setup.sh -h -c
|
||||
|
||||
# Get Zephyr
|
||||
WORKDIR /root/zephyrproject/smoke-test
|
||||
|
||||
# hadolint ignore=DL3013
|
||||
RUN pip3 install --no-cache-dir west && west init -m https://github.com/zephyrproject-rtos/zephyr --mr v3.5.0 /root/zephyrproject
|
||||
RUN pip3 install --no-cache-dir west
|
||||
COPY ./west_lite.yml ./west.yml
|
||||
|
||||
# init the west workspace with a minimal manifest
|
||||
RUN west init -l
|
||||
|
||||
WORKDIR /root/zephyrproject
|
||||
RUN west update
|
||||
RUN west update --stats
|
||||
|
||||
WORKDIR /root/zephyrproject/zephyr
|
||||
RUN west zephyr-export && pip install --no-cache-dir -r ~/zephyrproject/zephyr/scripts/requirements.txt
|
||||
WORKDIR /root/zephyrproject/modules/zephyr
|
||||
RUN west zephyr-export && pip install --no-cache-dir -r ./scripts/requirements.txt
|
||||
|
||||
ENV ZEPHYR_BASE="/root/zephyrproject/modules/zephyr"
|
||||
|
||||
# Git clone wamr
|
||||
WORKDIR /root
|
||||
RUN git clone https://github.com/bytecodealliance/wasm-micro-runtime.git
|
||||
|
||||
WORKDIR /root/wasm-micro-runtime/product-mini/platforms/zephyr/simple
|
||||
|
||||
ENV ZEPHYR_BASE="/root/zephyrproject/zephyr"
|
||||
WORKDIR /root/zephyrproject/modules/
|
||||
RUN git clone https://github.com/bytecodealliance/wasm-micro-runtime.git wasm-micro-runtime
|
||||
WORKDIR /root/zephyrproject/modules/wasm-micro-runtime/product-mini/platforms/zephyr
|
||||
|
|
|
@ -87,6 +87,12 @@ is a 64-bit ARM target for emulating the Cortex-A53 platform.
|
|||
west build . -b qemu_cortex_a53 -p always -- -DWAMR_BUILD_TARGET=AARCH64
|
||||
```
|
||||
|
||||
[ARC QEMU](https://docs.zephyrproject.org/latest/boards/qemu/arc/doc/index.html)
|
||||
is a 32-bit ARC target for emulating the ARC platform.
|
||||
|
||||
```shell
|
||||
west build . -b qemu_arc/qemu_arc_em -p always -- -DWAMR_BUILD_TARGET=ARC
|
||||
```
|
||||
|
||||
## Flashing or Running Image
|
||||
|
||||
|
|
15
product-mini/platforms/zephyr/simple/west_lite.yml
Normal file
15
product-mini/platforms/zephyr/simple/west_lite.yml
Normal file
|
@ -0,0 +1,15 @@
|
|||
# The west manifest file for WAMR on Zephyr smoke test.
|
||||
#
|
||||
manifest:
|
||||
#
|
||||
# Please add items below based on alphabetical order
|
||||
projects:
|
||||
- name: zephyr
|
||||
url: https://github.com/zephyrproject-rtos/zephyr
|
||||
revision: v3.7.0
|
||||
clone-depth: 1
|
||||
path: modules/zephyr
|
||||
west-commands: scripts/west-commands.yml
|
||||
|
||||
self:
|
||||
path: smoke-test
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "wasm_export.h"
|
||||
#include "bh_read_file.h"
|
||||
#include "bh_getopt.h"
|
||||
|
||||
void
|
||||
my_log(uint32 log_level, const char *file, int line, const char *fmt, ...)
|
||||
|
|
10
samples/printversion/CMakeLists.txt
Normal file
10
samples/printversion/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Copyright (C) 2025 Midokura Japan KK. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(printversion LANGUAGES C)
|
||||
|
||||
add_executable(printversion printversion.c)
|
||||
find_package(iwasm REQUIRED)
|
||||
target_link_libraries(printversion iwasm::vmlib)
|
21
samples/printversion/printversion.c
Normal file
21
samples/printversion/printversion.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (C) 2025 Midokura Japan KK. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <wasm_export.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
uint32_t patch;
|
||||
wasm_runtime_get_version(&major, &minor, &patch);
|
||||
printf("wasm-micro-runtime %" PRIu32 ".%" PRIu32 ".%" PRIu32 "\n", major,
|
||||
minor, patch);
|
||||
}
|
24
samples/printversion/test.sh
Executable file
24
samples/printversion/test.sh
Executable file
|
@ -0,0 +1,24 @@
|
|||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2025 Midokura Japan KK. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
set -e
|
||||
|
||||
DIST=$(mktemp -d)
|
||||
|
||||
# WAMR_BUILD_SIMD=0 to avoid fetching simde, which is
|
||||
# not relevant to this particular test.
|
||||
cmake -B build-wamr \
|
||||
-D CMAKE_INSTALL_PREFIX=${DIST} \
|
||||
-D WAMR_BUILD_SIMD=0 \
|
||||
../..
|
||||
cmake --build build-wamr -t install
|
||||
|
||||
cmake -B build-app \
|
||||
-D CMAKE_PREFIX_PATH=${DIST} \
|
||||
-D CMAKE_INSTALL_PREFIX=${DIST} \
|
||||
.
|
||||
cmake --build build-app
|
||||
|
||||
./build-app/printversion
|
|
@ -83,17 +83,21 @@ target_link_libraries(vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthre
|
|||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
||||
|
||||
add_executable (shared_heap_chain_test src/shared_heap_chain.c ${UNCOMMON_SHARED_SOURCE})
|
||||
add_executable (shared_heap_test src/main.c ${UNCOMMON_SHARED_SOURCE})
|
||||
|
||||
check_pie_supported()
|
||||
set_target_properties (shared_heap_test PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries (shared_heap_test vmlib -lm -ldl -lpthread)
|
||||
set (LIBS vmlib -lm -ldl -lpthread)
|
||||
else ()
|
||||
target_link_libraries (shared_heap_test vmlib -lm -ldl -lpthread -lrt)
|
||||
set (LIBS vmlib -lm -ldl -lpthread -lrt)
|
||||
endif ()
|
||||
|
||||
target_link_libraries (shared_heap_chain_test ${LIBS})
|
||||
target_link_libraries (shared_heap_test ${LIBS})
|
||||
|
||||
add_subdirectory(wasm-apps)
|
||||
|
||||
if (WAMR_BUILD_AOT EQUAL 1)
|
||||
|
@ -107,21 +111,31 @@ if (WAMR_BUILD_AOT EQUAL 1)
|
|||
)
|
||||
if (WAMR_COMPILER)
|
||||
message (CHECK_PASS "found")
|
||||
else()
|
||||
else ()
|
||||
message (CHECK_FAIL "not found")
|
||||
endif()
|
||||
endif ()
|
||||
if (NOT EXISTS ${WAMR_COMPILER})
|
||||
message (FATAL_ERROR "Please build wamrc under ${WAMR_ROOT_DIR}/wamr-compiler")
|
||||
else()
|
||||
else ()
|
||||
message (STATUS "WAMR_COMPILER is ${WAMR_COMPILER}")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_TARGET STREQUAL "X86_32")
|
||||
set (WAMR_COMPILER_FLAGS --enable-shared-heap --target=i386)
|
||||
set (WAMR_COMPILER_CHAIN_FLAGS --enable-shared-chain --target=i386)
|
||||
else ()
|
||||
set (WAMR_COMPILER_FLAGS --enable-shared-heap)
|
||||
set (WAMR_COMPILER_CHAIN_FLAGS --enable-shared-chain)
|
||||
endif ()
|
||||
|
||||
add_custom_target(
|
||||
wasm_to_aot
|
||||
ALL
|
||||
DEPENDS wasm-apps/test1.wasm wasm-apps/test2.wasm ${WAMR_COMPILER}
|
||||
COMMAND ${WAMR_COMPILER} --enable-shared-heap -o wasm-apps/test1.aot wasm-apps/test1.wasm
|
||||
COMMAND ${WAMR_COMPILER} --enable-shared-heap -o wasm-apps/test2.aot wasm-apps/test2.wasm
|
||||
COMMAND ${WAMR_COMPILER} ${WAMR_COMPILER_FLAGS} -o wasm-apps/test1.aot wasm-apps/test1.wasm
|
||||
COMMAND ${WAMR_COMPILER} ${WAMR_COMPILER_FLAGS} -o wasm-apps/test2.aot wasm-apps/test2.wasm
|
||||
COMMAND ${WAMR_COMPILER} ${WAMR_COMPILER_CHAIN_FLAGS} -o wasm-apps/test1_chain.aot wasm-apps/test1.wasm
|
||||
COMMAND ${WAMR_COMPILER} ${WAMR_COMPILER_CHAIN_FLAGS} -o wasm-apps/test2_chain.aot wasm-apps/test2.wasm
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
endif()
|
||||
|
|
50
samples/shared-heap/README.md
Normal file
50
samples/shared-heap/README.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
# Shared heap Sample introduction
|
||||
|
||||
This is a sample to show how to use the shared heap feature in WAMR. The shared heap feature allows multiple WASM instances to share the same memory space. This feature is useful when you want to run multiple WASM instances in the same process and share data between them. The sandbox nature of WASM is still maintained in the shared heap by WAMR. But the data management and correct data synchronization in shared heap is relied on the user's implementation.
|
||||
|
||||
> Note: The shared heap feature is experimental feature, it should be used with caution. It's optional and only available when building WAMR with the CMake cache variable `WAMR_BUILD_SHARED_HEAP` set to 1.
|
||||
|
||||
## Build and run the sample
|
||||
|
||||
To build the shared heap used in multi thread sample and the shared heap chain sample with following commands:
|
||||
|
||||
```bash
|
||||
cmake -S . -B build
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
For the shared heap sample, it demonstrates how to create a shared heap and use it shares data between two WASM instances, which would satisfy most of the use cases. Use the following commands to run the sample:
|
||||
|
||||
```bash
|
||||
cd build
|
||||
./shared_heap_test
|
||||
```
|
||||
|
||||
For the shared heap chain sample. It chains a pre-allocated heap and a normal shared heap to one chain(linked list) as a whole and attaches/detaches all together, and pass the WASM address directly between two WASM instances. Use the following commands to run the sample:
|
||||
|
||||
```bash
|
||||
cd build
|
||||
./shared_heap_chain_test
|
||||
```
|
||||
|
||||
## How to use shared heap
|
||||
|
||||
The shared heap is an advanced feature in WAMR that gives the user flexibility to share data between multiple WASM instances(it will be the same address mapping for different WASM instance) or between WebAssembly and the host without incurring any copy overhead. The shared heap can be regarded as an extension of the WebAssembly linear memory. But it also heavily relies on the user's implementation to manage the shared data correctly. The following are some takeaway points to help the user use the shared heap correctly.
|
||||
|
||||
### Create and manage shared heap
|
||||
|
||||
You can create a shared heap by calling the `wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args)` API. And based on the `init_args`, you can create a shared heap in two ways:
|
||||
|
||||
1. WAMR managed shared heap: when only `init_args.size` is given and `init_args.pre_allocated_addr` stays as NULL, WAMR will allocate a shared heap(not from the linear memory) with the given size. The shared heap will be managed by WAMR, the wasm app or host(WAMR users) can dynamically manage memory from it by calling `wasm_runtime_shared_heap_malloc()` and `wasm_runtime_shared_heap_free()` on demand. Only the memory allocated from the shared heap is valid and can be shared, not the unallocated part of shared heap memory. And it will be automatically freed when runtime is destroyed(when `wasm_runtime_destroy()` is called).
|
||||
|
||||
2. Preallocated shared heap: the user can also use a pre-allocated memory(it can be allocated from the system heap, or is a static global buffer, the correctness of its accessibility and size needs to be ensured by the user) as a shared heap by giving `init_args.pre_allocated_addr` and `init_args.size`. This kind of shared heap serves as an area for data exchange, primarily between the host and WebAssembly. Any data within this area can be directly accessed by both sides (assuming the layout of the data structure is known). For instance, the host can store large structured variables in this space, allowing the WebAssembly application to operate on them without the need for copying. And the pre-allocated memory will relies on user to manage its life cycle.
|
||||
|
||||
After creation, the shared heap can be attached to a WASM instance(an additional segment appended to the end of the linear memory) by calling `wasm_runtime_attach_shared_heap(wasm_module_inst_t module_inst, wasm_shared_heap_t shared_heap)`. And it can be detached by calling `wasm_runtime_detach_shared_heap(wasm_module_inst_t module_inst)`. So that the data sharing can only happen between the WASM instances that have the same shared heap attached, complete by user's choice.
|
||||
|
||||
#### Shared heap chain
|
||||
|
||||
Sometimes you may want to use multiple shared heaps to attach together as a chain(linked list) and to share data more flexibly. You can call `wasm_runtime_chain_shared_heaps(wasm_shared_heap_t head, wasm_shared_heap_t body)` to chain two shared heaps together. The shared heap list remains one continuous shared heap in wasm app's point of view. To create a shared heap chain, the shared heaps can't be currently attached to any WASM instance.
|
||||
|
||||
> PS: At most one shared heap in shared heap list can be WAMR managed shared heap, the rest have to be the pre-allocated shared heap.
|
||||
|
||||

|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user