mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-11 20:21:11 +00:00
Merge main into dev/fast_jit
This commit is contained in:
commit
8ee2e0a22b
4
.github/workflows/codeing_guildelines.yml
vendored
4
.github/workflows/codeing_guildelines.yml
vendored
|
@ -21,7 +21,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Workflow Action
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
|
@ -30,7 +30,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
name: compilation on android, ubuntu-18.04, ubuntu-20.04, macos-latest
|
||||
name: compilation on android, ubuntu-18.04, ubuntu-20.04
|
||||
|
||||
on:
|
||||
# will be triggered on PR events
|
||||
|
@ -11,7 +11,7 @@ on:
|
|||
- "ci/**"
|
||||
- "doc/**"
|
||||
- "test-tools/**"
|
||||
- ".github/workflows/compilation_on_android_ubuntu_macos.yml"
|
||||
- ".github/workflows/compilation_on_android_ubuntu.yml"
|
||||
# will be triggered on push events
|
||||
push:
|
||||
paths-ignore:
|
||||
|
@ -19,7 +19,7 @@ on:
|
|||
- "ci/**"
|
||||
- "doc/**"
|
||||
- "test-tools/**"
|
||||
- ".github/workflows/compilation_on_android_ubuntu_macos.yml"
|
||||
- ".github/workflows/compilation_on_android_ubuntu.yml"
|
||||
# allow to be triggered manually
|
||||
workflow_dispatch:
|
||||
|
||||
|
@ -30,12 +30,20 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
# For BUILD
|
||||
AOT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
|
||||
MC_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
# LLVM
|
||||
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
|
||||
# For Spec Test
|
||||
DEFAULT_TEST_OPTIONS: "-s spec -P"
|
||||
MULTI_MODULES_TEST_OPTIONS: "-s spec -M -P"
|
||||
SIMD_TEST_OPTIONS: "-s spec -S -P"
|
||||
THREADS_TEST_OPTIONS: "-s spec -p -P"
|
||||
X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P"
|
||||
|
||||
jobs:
|
||||
# Cancel any in-flight jobs for the same PR/branch so there's only one active
|
||||
|
@ -44,25 +52,25 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04, ubuntu-20.04, macos-latest]
|
||||
os: [ubuntu-18.04, ubuntu-20.04]
|
||||
steps:
|
||||
- name: Cancel Workflow Action
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
# set different traffic lights based on the current repo and the running OS.
|
||||
# according to light colors, the workflow will run different jobs
|
||||
# it is used to separate between the public repo and the private repo
|
||||
check_repo:
|
||||
needs: cancel_previous
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04, ubuntu-20.04, macos-latest]
|
||||
os: [ubuntu-18.04, ubuntu-20.04]
|
||||
outputs:
|
||||
traffic_light_on_ubuntu_1804: ${{ steps.do_check_on_ubuntu_1804.outputs.light }}
|
||||
traffic_light_on_ubuntu_2004: ${{ steps.do_check_on_ubuntu_2004.outputs.light }}
|
||||
traffic_light_on_macos_latest: ${{ steps.do_check_on_macos_latest.outputs.light }}
|
||||
steps:
|
||||
- name: do_check_on_ubuntu_1804
|
||||
id: do_check_on_ubuntu_1804
|
||||
|
@ -84,41 +92,29 @@ jobs:
|
|||
echo "::set-output name=light::green"
|
||||
fi
|
||||
|
||||
- name: do_check_on_macos_latest
|
||||
id: do_check_on_macos_latest
|
||||
if: ${{ matrix.os == 'macos-latest' }}
|
||||
run: |
|
||||
if [[ ${{ github.repository }} == */wasm-micro-runtime ]]; then
|
||||
echo "::set-output name=light::green"
|
||||
else
|
||||
echo "::set-output name=light::red"
|
||||
fi
|
||||
|
||||
build_llvm_libraries:
|
||||
needs: check_repo
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04, ubuntu-20.04, macos-latest]
|
||||
os: [ubuntu-18.04, ubuntu-20.04]
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }}
|
||||
- os: ubuntu-20.04
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
|
||||
- os: macos-latest
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_macos_latest }}
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Cache LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
|
@ -128,43 +124,35 @@ jobs:
|
|||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Build llvm and clang from source on ubuntu
|
||||
id: build_llvm_ubuntu
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' && matrix.os != 'macos-latest' }}
|
||||
- name: Build llvm and clang from source
|
||||
id: build_llvm
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly --project clang lldb
|
||||
working-directory: build-scripts
|
||||
|
||||
- name: Build llvm and clang from source on macos
|
||||
id: build_llvm_macos
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' && matrix.os == 'macos-latest' }}
|
||||
run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly
|
||||
working-directory: build-scripts
|
||||
|
||||
build_wamrc:
|
||||
needs: [build_llvm_libraries, check_repo]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04, ubuntu-20.04, macos-latest]
|
||||
os: [ubuntu-18.04, ubuntu-20.04]
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }}
|
||||
- os: ubuntu-20.04
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
|
||||
- os: macos-latest
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_macos_latest }}
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
|
@ -193,11 +181,11 @@ jobs:
|
|||
matrix:
|
||||
make_options_run_mode: [
|
||||
# Running mode
|
||||
$AOT_BUILD_OPTIONS,
|
||||
$CLASSIC_INTERP_BUILD_OPTIONS,
|
||||
$FAST_INTERP_BUILD_OPTIONS,
|
||||
$LAZY_JIT_BUILD_OPTIONS,
|
||||
$MC_JIT_BUILD_OPTIONS,
|
||||
$AOT_BUILD_OPTIONS,
|
||||
]
|
||||
make_options_feature: [
|
||||
# Features
|
||||
|
@ -206,6 +194,7 @@ jobs:
|
|||
"-DWAMR_BUILD_DEBUG_INTERP=1",
|
||||
"-DWAMR_BUILD_DUMP_CALL_STACK=1",
|
||||
"-DWAMR_BUILD_LIB_PTHREAD=1",
|
||||
"-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1",
|
||||
"-DWAMR_BUILD_MINI_LOADER=1",
|
||||
"-DWAMR_BUILD_MEMORY_PROFILING=1",
|
||||
"-DWAMR_BUILD_MULTI_MODULE=1",
|
||||
|
@ -215,23 +204,10 @@ jobs:
|
|||
"-DWAMR_BUILD_TAIL_CALL=1",
|
||||
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
|
||||
]
|
||||
os: [ubuntu-18.04, ubuntu-20.04, macos-latest]
|
||||
platform: [android, linux, darwin]
|
||||
os: [ubuntu-18.04, ubuntu-20.04]
|
||||
platform: [android, linux]
|
||||
exclude:
|
||||
# uncompatiable os and platform
|
||||
# ubuntu can not go with darwin
|
||||
- os: ubuntu-18.04
|
||||
platform: darwin
|
||||
- os: ubuntu-20.04
|
||||
platform: darwin
|
||||
# macos can not go with android, linux
|
||||
- os: macos-latest
|
||||
platform: android
|
||||
- os: macos-latest
|
||||
platform: linux
|
||||
# uncompatiable feature and platform
|
||||
- os: macos-latest
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
# uncompatiable mode and feature
|
||||
# MULTI_MODULE only on INTERP mode
|
||||
- make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
|
||||
|
@ -276,20 +252,19 @@ jobs:
|
|||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }}
|
||||
- os: ubuntu-20.04
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
|
||||
- os: macos-latest
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_macos_latest }}
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# only download llvm cache when needed
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v2
|
||||
if: (matrix.light == 'green') && (endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS'))
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
|
@ -300,7 +275,7 @@ jobs:
|
|||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
if: (matrix.light == 'green') && (endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true')
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: Build iwasm
|
||||
|
@ -324,7 +299,7 @@ jobs:
|
|||
$MC_JIT_BUILD_OPTIONS,
|
||||
$AOT_BUILD_OPTIONS,
|
||||
]
|
||||
os: [ubuntu-18.04, ubuntu-20.04, macos-latest]
|
||||
os: [ubuntu-18.04, ubuntu-20.04]
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }}
|
||||
|
@ -334,30 +309,18 @@ jobs:
|
|||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
|
||||
wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
|
||||
wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz
|
||||
- os: macos-latest
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_macos_latest }}
|
||||
wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz
|
||||
wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz
|
||||
exclude:
|
||||
# TODO: a .aot compatiable problem
|
||||
- os: macos-latest
|
||||
make_options: $LAZY_JIT_BUILD_OPTIONS
|
||||
- os: macos-latest
|
||||
make_options: $AOT_BUILD_OPTIONS
|
||||
- os: macos-latest
|
||||
make_options: $MC_JIT_BUILD_OPTIONS
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v2
|
||||
if: (matrix.light == 'green') && (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
|
@ -368,7 +331,7 @@ jobs:
|
|||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
if: (matrix.light == 'green') && (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true')
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: download and install wabt
|
||||
|
@ -380,7 +343,7 @@ jobs:
|
|||
sudo mv wabt-1.0.24 wabt
|
||||
|
||||
- name: Build wamrc
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
if: (matrix.light == 'green') && (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
|
@ -406,7 +369,7 @@ jobs:
|
|||
working-directory: samples/wasm-c-api
|
||||
|
||||
build_samples_others:
|
||||
needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo]
|
||||
needs: [build_iwasm, check_repo]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -419,34 +382,13 @@ jobs:
|
|||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
|
||||
wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
|
||||
wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz
|
||||
- os: macos-latest
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_macos_latest }}
|
||||
wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz
|
||||
wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: download and install wasi-sdk
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
|
@ -464,14 +406,6 @@ jobs:
|
|||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
||||
sudo mv wabt-1.0.24 wabt
|
||||
|
||||
- name: Build wamrc
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
working-directory: wamr-compiler
|
||||
|
||||
- name: Build Sample [basic]
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
|
@ -514,3 +448,110 @@ jobs:
|
|||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
./hello
|
||||
|
||||
spec_test_default:
|
||||
needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo]
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
test_option: [$DEFAULT_TEST_OPTIONS, $SIMD_TEST_OPTIONS]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: steps.cache_llvm.outputs.cache-hit != 'true'
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: install Ninja
|
||||
run: sudo apt install -y ninja-build
|
||||
|
||||
- name: run spec tests
|
||||
run: ./test_wamr.sh ${{ matrix.test_option }}
|
||||
working-directory: ./tests/wamr-test-suites
|
||||
|
||||
spec_test_extra:
|
||||
if: ${{ endsWith(github.repository, 'wasm-micro-runtime') }}
|
||||
needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo]
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
test_option: [$MULTI_MODULES_TEST_OPTIONS, $THREADS_TEST_OPTIONS]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: steps.cache_llvm.outputs.cache-hit != 'true'
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: install Ninja
|
||||
run: sudo apt install -y ninja-build
|
||||
|
||||
- name: run spec tests
|
||||
run: ./test_wamr.sh ${{ matrix.test_option }}
|
||||
working-directory: ./tests/wamr-test-suites
|
||||
|
||||
spec_test_x86_32:
|
||||
if: ${{ endsWith(github.repository, 'wasm-micro-runtime') }}
|
||||
needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo]
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
test_option: [$DEFAULT_TEST_OPTIONS, $THREADS_TEST_OPTIONS]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: steps.cache_llvm.outputs.cache-hit != 'true'
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: install Ninja and x32 support libraries
|
||||
run:
|
||||
# Add another apt repository as some packages cannot
|
||||
# be downloaded with the github default repository
|
||||
sudo curl -sSL https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc &&
|
||||
sudo apt-add-repository https://packages.microsoft.com/ubuntu/20.04/prod &&
|
||||
sudo apt-get update &&
|
||||
sudo apt install -y g++-multilib lib32gcc-9-dev ninja-build
|
||||
|
||||
- name: run spec tests
|
||||
run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }}
|
||||
working-directory: ./tests/wamr-test-suites
|
393
.github/workflows/compilation_on_macos.yml
vendored
Normal file
393
.github/workflows/compilation_on_macos.yml
vendored
Normal file
|
@ -0,0 +1,393 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
name: compilation on macos-latest
|
||||
|
||||
on:
|
||||
# will be triggered on PR events
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "assembly-script/**"
|
||||
- "ci/**"
|
||||
- "doc/**"
|
||||
- "test-tools/**"
|
||||
- ".github/workflows/compilation_on_macos.yml"
|
||||
# will be triggered on push events
|
||||
push:
|
||||
paths-ignore:
|
||||
- "assembly-script/**"
|
||||
- "ci/**"
|
||||
- "doc/**"
|
||||
- "test-tools/**"
|
||||
- ".github/workflows/compilation_on_macos.yml"
|
||||
# allow to be triggered manually
|
||||
workflow_dispatch:
|
||||
|
||||
# Cancel any in-flight jobs for the same PR/branch so there's only one active
|
||||
# at a time
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
AOT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
|
||||
MC_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
|
||||
|
||||
jobs:
|
||||
# Cancel any in-flight jobs for the same PR/branch so there's only one active
|
||||
# at a time
|
||||
cancel_previous:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
steps:
|
||||
- name: Cancel Workflow Action
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
# set different traffic lights based on the current repo and the running OS.
|
||||
# according to light colors, the workflow will run different jobs
|
||||
check_repo:
|
||||
needs: cancel_previous
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
outputs:
|
||||
traffic_light: ${{ steps.do_check.outputs.light }}
|
||||
steps:
|
||||
- name: do_check
|
||||
id: do_check
|
||||
if: ${{ matrix.os == 'macos-latest' }}
|
||||
run: |
|
||||
if [[ ${{ github.repository }} == */wasm-micro-runtime ]]; then
|
||||
echo "::set-output name=light::green"
|
||||
else
|
||||
echo "::set-output name=light::red"
|
||||
fi
|
||||
|
||||
build_llvm_libraries:
|
||||
needs: check_repo
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
include:
|
||||
- os: macos-latest
|
||||
light: ${{ needs.check_repo.outputs.traffic_light }}
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Cache LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Build llvm and clang from source
|
||||
id: build_llvm
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly
|
||||
working-directory: build-scripts
|
||||
|
||||
build_wamrc:
|
||||
needs: [build_llvm_libraries, check_repo]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
include:
|
||||
- os: macos-latest
|
||||
light: ${{ needs.check_repo.outputs.traffic_light }}
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: Build wamrc
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
working-directory: wamr-compiler
|
||||
|
||||
build_iwasm:
|
||||
needs: [build_llvm_libraries, check_repo]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
make_options_run_mode: [
|
||||
# Running mode
|
||||
$AOT_BUILD_OPTIONS,
|
||||
$CLASSIC_INTERP_BUILD_OPTIONS,
|
||||
$FAST_INTERP_BUILD_OPTIONS,
|
||||
$LAZY_JIT_BUILD_OPTIONS,
|
||||
$MC_JIT_BUILD_OPTIONS,
|
||||
]
|
||||
make_options_feature: [
|
||||
# Features
|
||||
"-DWAMR_BUILD_CUSTOM_NAME_SECTION=1",
|
||||
# doesn't support
|
||||
#"-DWAMR_BUILD_DEBUG_AOT=1",
|
||||
"-DWAMR_BUILD_DEBUG_INTERP=1",
|
||||
"-DWAMR_BUILD_DUMP_CALL_STACK=1",
|
||||
"-DWAMR_BUILD_LIB_PTHREAD=1",
|
||||
"-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1",
|
||||
"-DWAMR_BUILD_MINI_LOADER=1",
|
||||
"-DWAMR_BUILD_MEMORY_PROFILING=1",
|
||||
"-DWAMR_BUILD_MULTI_MODULE=1",
|
||||
"-DWAMR_BUILD_PERF_PROFILING=1",
|
||||
"-DWAMR_BUILD_REF_TYPES=1",
|
||||
"-DWAMR_BUILD_SIMD=1",
|
||||
"-DWAMR_BUILD_TAIL_CALL=1",
|
||||
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
|
||||
]
|
||||
os: [macos-latest]
|
||||
platform: [darwin]
|
||||
exclude:
|
||||
# uncompatiable feature and platform
|
||||
# uncompatiable mode and feature
|
||||
# MULTI_MODULE only on INTERP mode
|
||||
- make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
|
||||
- make_options_run_mode: $AOT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
|
||||
- make_options_run_mode: $MC_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
|
||||
# SIMD only on JIT/AOT mode
|
||||
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_SIMD=1"
|
||||
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_SIMD=1"
|
||||
# DEBUG_INTERP only on CLASSIC INTERP mode
|
||||
- make_options_run_mode: $AOT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||
- make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||
- make_options_run_mode: $MC_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||
# DEBUG_AOT only on JIT/AOT mode
|
||||
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
# TODO: DEBUG_AOT on JIT
|
||||
- make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
- make_options_run_mode: $MC_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
# MINI_LOADER only on INTERP mode
|
||||
- make_options_run_mode: $AOT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
- make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
- make_options_run_mode: $MC_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
include:
|
||||
- os: macos-latest
|
||||
light: ${{ needs.check_repo.outputs.traffic_light }}
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# only download llvm cache when needed
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
if: (matrix.light == 'green') && (endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS'))
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: (matrix.light == 'green') && (endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true')
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: Build iwasm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }}
|
||||
cmake --build . --config Release --parallel 4
|
||||
working-directory: product-mini/platforms/${{ matrix.platform }}
|
||||
|
||||
build_samples_wasm_c_api:
|
||||
needs: [build_iwasm, check_repo]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
make_options: [
|
||||
# Running mode
|
||||
$CLASSIC_INTERP_BUILD_OPTIONS,
|
||||
$FAST_INTERP_BUILD_OPTIONS,
|
||||
# doesn't support
|
||||
#$LAZY_JIT_BUILD_OPTIONS,
|
||||
#$MC_JIT_BUILD_OPTIONS,
|
||||
#$AOT_BUILD_OPTIONS,
|
||||
]
|
||||
os: [macos-latest]
|
||||
include:
|
||||
- os: macos-latest
|
||||
light: ${{ needs.check_repo.outputs.traffic_light }}
|
||||
wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz
|
||||
wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: download and install wabt
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wabt_release }}
|
||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
||||
sudo mv wabt-1.0.24 wabt
|
||||
|
||||
- name: Build Sample [wasm-c-api]
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. ${{ matrix.make_options }}
|
||||
cmake --build . --config Release --parallel 4
|
||||
./callback
|
||||
./callback_chain
|
||||
./empty_imports
|
||||
./global
|
||||
./hello
|
||||
./hostref
|
||||
./memory
|
||||
./reflect
|
||||
./table
|
||||
./trap
|
||||
working-directory: samples/wasm-c-api
|
||||
|
||||
build_samples_others:
|
||||
needs: [build_iwasm, check_repo]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: macos-latest
|
||||
light: ${{ needs.check_repo.outputs.traffic_light }}
|
||||
wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz
|
||||
wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: download and install wasi-sdk
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wasi_sdk_release }}
|
||||
sudo tar -xzf wasi-sdk-12.0-*.tar.gz
|
||||
sudo mv wasi-sdk-12.0 wasi-sdk
|
||||
|
||||
- name: download and install wabt
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wabt_release }}
|
||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
||||
sudo mv wabt-1.0.24 wabt
|
||||
|
||||
- name: Build Sample [basic]
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
cd samples/basic
|
||||
./build.sh
|
||||
./run.sh
|
||||
|
||||
- name: Build Sample [multi-thread]
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
cd samples/multi-thread
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
./iwasm wasm-apps/test.wasm
|
||||
|
||||
- name: Build Sample [multi-module]
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
cd samples/multi-module
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
./multi_module
|
||||
|
||||
- name: Build Sample [spawn-thread]
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
cd samples/spawn-thread
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
./spawn_thread
|
||||
|
||||
- name: Build Sample [ref-types]
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
cd samples/ref-types
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
./hello
|
140
.github/workflows/compilation_on_sgx.yml
vendored
140
.github/workflows/compilation_on_sgx.yml
vendored
|
@ -1,7 +1,7 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
name: CI on SGX
|
||||
name: compilation on SGX
|
||||
|
||||
on:
|
||||
# will be triggered on PR events
|
||||
|
@ -47,7 +47,7 @@ jobs:
|
|||
os: [ubuntu-20.04]
|
||||
steps:
|
||||
- name: Cancel Workflow Action
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
|
@ -87,12 +87,12 @@ jobs:
|
|||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Cache LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
|
@ -103,24 +103,24 @@ jobs:
|
|||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Build llvm and clang from source
|
||||
id: build_llvm_ubuntu
|
||||
id: build_llvm
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly --project clang lldb
|
||||
working-directory: build-scripts
|
||||
|
||||
build_iwasm:
|
||||
needs: [build_llvm_libraries, check_repo]
|
||||
needs: [check_repo]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
make_options_run_mode: [
|
||||
# Running mode
|
||||
$AOT_BUILD_OPTIONS,
|
||||
$CLASSIC_INTERP_BUILD_OPTIONS,
|
||||
$FAST_INTERP_BUILD_OPTIONS,
|
||||
# doesn't support
|
||||
# $LAZY_JIT_BUILD_OPTIONS,
|
||||
# $MC_JIT_BUILD_OPTIONS,
|
||||
$AOT_BUILD_OPTIONS,
|
||||
]
|
||||
make_options_feature: [
|
||||
# Features
|
||||
|
@ -130,6 +130,7 @@ jobs:
|
|||
# "-DWAMR_BUILD_DEBUG_INTERP=1",
|
||||
"-DWAMR_BUILD_DUMP_CALL_STACK=1",
|
||||
"-DWAMR_BUILD_LIB_PTHREAD=1",
|
||||
"-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1",
|
||||
"-DWAMR_BUILD_MINI_LOADER=1",
|
||||
"-DWAMR_BUILD_MEMORY_PROFILING=1",
|
||||
"-DWAMR_BUILD_MULTI_MODULE=1",
|
||||
|
@ -160,7 +161,7 @@ jobs:
|
|||
- name: install SGX SDK and necessary libraries
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir -p /opt/intel
|
||||
mkdir -p /opt/intel
|
||||
cd /opt/intel
|
||||
wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
chmod +x sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
|
@ -173,12 +174,51 @@ jobs:
|
|||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Build iwasm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }}
|
||||
cmake --build . --config Release --parallel 4
|
||||
working-directory: product-mini/platforms/${{ matrix.platform }}
|
||||
|
||||
build_wamrc:
|
||||
needs: [build_llvm_libraries, check_repo]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
||||
- name: install SGX SDK and necessary libraries
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir -p /opt/intel
|
||||
cd /opt/intel
|
||||
wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
chmod +x sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
echo 'yes' | ./sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu focal main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list
|
||||
wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo apt-key add -
|
||||
sudo apt update
|
||||
sudo apt install -y libsgx-launch libsgx-urts
|
||||
source /opt/intel/sgxsdk/environment
|
||||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
|
@ -192,16 +232,16 @@ jobs:
|
|||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: Build iwasm
|
||||
- name: Build wamrc
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }}
|
||||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
working-directory: product-mini/platforms/${{ matrix.platform }}
|
||||
working-directory: wamr-compiler
|
||||
|
||||
build_samples_wasm_c_api:
|
||||
needs: [build_iwasm, build_llvm_libraries, check_repo]
|
||||
needs: [build_iwasm, check_repo]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -226,24 +266,7 @@ jobs:
|
|||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: download and install wabt
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
|
@ -256,7 +279,7 @@ jobs:
|
|||
- name: install SGX SDK and necessary libraries
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir -p /opt/intel
|
||||
mkdir -p /opt/intel
|
||||
cd /opt/intel
|
||||
wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
chmod +x sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
|
@ -267,14 +290,6 @@ jobs:
|
|||
sudo apt install -y libsgx-launch libsgx-urts
|
||||
source /opt/intel/sgxsdk/environment
|
||||
|
||||
- name: Build wamrc
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
working-directory: wamr-compiler
|
||||
|
||||
- name: Build Sample [wasm-c-api]
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
|
@ -294,7 +309,7 @@ jobs:
|
|||
working-directory: samples/wasm-c-api
|
||||
|
||||
build_samples_others:
|
||||
needs: [build_iwasm, build_llvm_libraries, check_repo]
|
||||
needs: [build_iwasm, check_repo]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -309,24 +324,7 @@ jobs:
|
|||
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: download and install wasi-sdk
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
|
@ -347,7 +345,7 @@ jobs:
|
|||
- name: install SGX SDK and necessary libraries
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir -p /opt/intel
|
||||
mkdir -p /opt/intel
|
||||
cd /opt/intel
|
||||
wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
chmod +x sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
|
@ -358,14 +356,6 @@ jobs:
|
|||
sudo apt install -y libsgx-launch libsgx-urts
|
||||
source /opt/intel/sgxsdk/environment
|
||||
|
||||
- name: Build wamrc
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
working-directory: wamr-compiler
|
||||
|
||||
- name: Build Sample [basic]
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
|
@ -410,7 +400,7 @@ jobs:
|
|||
./hello
|
||||
|
||||
spec_test_default:
|
||||
needs: [build_iwasm, build_llvm_libraries, check_repo]
|
||||
needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo]
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -422,12 +412,12 @@ jobs:
|
|||
steps:
|
||||
- name: checkout
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
id: cache_llvm
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
|
@ -437,6 +427,10 @@ jobs:
|
|||
./core/deps/llvm/build/share
|
||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: install Ninja
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: sudo apt install -y ninja-build
|
||||
|
@ -444,7 +438,7 @@ jobs:
|
|||
- name: install SGX SDK and necessary libraries
|
||||
if: ${{ matrix.light == 'green' }}
|
||||
run: |
|
||||
mkdir -p /opt/intel
|
||||
mkdir -p /opt/intel
|
||||
cd /opt/intel
|
||||
wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
chmod +x sgx_linux_x64_sdk_2.15.100.3.bin
|
||||
|
|
4
.github/workflows/compilation_on_windows.yml
vendored
4
.github/workflows/compilation_on_windows.yml
vendored
|
@ -36,7 +36,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Cancel Workflow Action
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
|
@ -44,7 +44,7 @@ jobs:
|
|||
needs: cancel_previous
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: clone uvwasi library
|
||||
run: |
|
||||
|
|
155
.github/workflows/spec_test.yml
vendored
155
.github/workflows/spec_test.yml
vendored
|
@ -1,155 +0,0 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
name: Spec tests on non-windows
|
||||
|
||||
on:
|
||||
# will be triggered on PR events
|
||||
pull_request:
|
||||
paths:
|
||||
- "core/config.h"
|
||||
- "core/iwasm/**"
|
||||
- "core/shared/**"
|
||||
- "wamr-compiler/**"
|
||||
- "product-mini/**"
|
||||
- "tests/wamr-test-suites/spec-test-script/**"
|
||||
- "tests/wamr-test-suites/test_wamr.sh"
|
||||
- ".github/workflows/spec_test.yml"
|
||||
# will be triggered on push events
|
||||
push:
|
||||
paths:
|
||||
- "core/config.h"
|
||||
- "core/iwasm/**"
|
||||
- "core/shared/**"
|
||||
- "wamr-compiler/**"
|
||||
- "product-mini/**"
|
||||
- "tests/wamr-test-suites/spec-test-script/**"
|
||||
- "tests/wamr-test-suites/test_wamr.sh"
|
||||
- ".github/workflows/spec_test.yml"
|
||||
# allow to be triggered manually
|
||||
workflow_dispatch:
|
||||
|
||||
# Cancel any in-flight jobs for the same PR/branch so there's only one active
|
||||
# at a time
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
DEFAULT_TEST_OPTIONS: "-s spec -P"
|
||||
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
|
||||
MULTI_MODULES_TEST_OPTIONS: "-s spec -M -P"
|
||||
SIMD_TEST_OPTIONS: "-s spec -S -P"
|
||||
THREADS_TEST_OPTIONS: "-s spec -p -P"
|
||||
X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P"
|
||||
|
||||
jobs:
|
||||
cancel_previous:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Cancel Workflow Action
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
spec_test_default:
|
||||
needs: cancel_previous
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
test_option: [$DEFAULT_TEST_OPTIONS, $SIMD_TEST_OPTIONS]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: install Ninja
|
||||
run: sudo apt install -y ninja-build
|
||||
|
||||
- name: run spec tests
|
||||
run: ./test_wamr.sh ${{ matrix.test_option }}
|
||||
working-directory: ./tests/wamr-test-suites
|
||||
|
||||
spec_test_extra:
|
||||
needs: cancel_previous
|
||||
if: ${{ endsWith(github.repository, 'wasm-micro-runtime') }}
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
test_option: [$MULTI_MODULES_TEST_OPTIONS, $THREADS_TEST_OPTIONS]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: steps.cache_llvm.outputs.cache-hit != 'true'
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: install Ninja
|
||||
run: sudo apt install -y ninja-build
|
||||
|
||||
- name: run spec tests
|
||||
run: ./test_wamr.sh ${{ matrix.test_option }}
|
||||
working-directory: ./tests/wamr-test-suites
|
||||
|
||||
spec_test_x86_32:
|
||||
if: ${{ endsWith(github.repository, 'wasm-micro-runtime') }}
|
||||
needs: cancel_previous
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
test_option: [$DEFAULT_TEST_OPTIONS, $THREADS_TEST_OPTIONS]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
./core/deps/llvm/build/bin
|
||||
./core/deps/llvm/build/include
|
||||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
|
||||
- name: Quit if cache miss
|
||||
if: steps.cache_llvm.outputs.cache-hit != 'true'
|
||||
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
|
||||
|
||||
- name: install Ninja and x32 support libraries
|
||||
run:
|
||||
# Add another apt repository as some packages cannot
|
||||
# be downloaded with the github default repository
|
||||
sudo curl -sSL https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc &&
|
||||
sudo apt-add-repository https://packages.microsoft.com/ubuntu/20.04/prod &&
|
||||
sudo apt-get update &&
|
||||
sudo apt install -y g++-multilib lib32gcc-9-dev ninja-build
|
||||
|
||||
- name: run spec tests
|
||||
run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }}
|
||||
working-directory: ./tests/wamr-test-suites
|
|
@ -19,6 +19,8 @@ Getting started
|
|||
==================
|
||||
- [Build iwasm VM core](./doc/build_wamr.md) on [Linux](./doc/build_wamr.md#linux), [SGX](./doc/linux_sgx.md), [MacOS](./doc/build_wamr.md#macos) and [Windows](./doc/build_wamr.md#windows), and [Build wamrc AOT compiler](./README.md#build-wamrc-aot-compiler)
|
||||
- [Embed WAMR into host applications](./doc/embed_wamr.md)
|
||||
- [Embed into C/C++](./doc/embed_wamr.md), [Embed into Python](./language-bindings/python), [Embed into Go](./language-bindings/go)
|
||||
|
||||
- [Register native APIs for WASM applications](./doc/export_native_api.md)
|
||||
- [Build WASM applications](./doc/build_wasm_app.md)
|
||||
- [Port WAMR to a new platform](./doc/port_wamr.md)
|
||||
|
|
|
@ -259,3 +259,7 @@ endif ()
|
|||
if (WAMR_BUILD_DEBUG_AOT EQUAL 1)
|
||||
message (" Debug AOT enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_LOAD_CUSTOM_SECTION EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1)
|
||||
message (" Load custom section enabled")
|
||||
endif ()
|
||||
|
|
|
@ -176,6 +176,11 @@
|
|||
#define WASM_ENABLE_DEBUG_AOT 0
|
||||
#endif
|
||||
|
||||
/* Custom sections */
|
||||
#ifndef WASM_ENABLE_LOAD_CUSTOM_SECTION
|
||||
#define WASM_ENABLE_LOAD_CUSTOM_SECTION 0
|
||||
#endif
|
||||
|
||||
/* WASM log system */
|
||||
#ifndef WASM_ENABLE_LOG
|
||||
#define WASM_ENABLE_LOG 1
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "../compilation/aot_llvm.h"
|
||||
#include "../interpreter/wasm_loader.h"
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
#include "debug/elf_parser.h"
|
||||
#include "debug/jit_debug.h"
|
||||
|
@ -151,7 +152,7 @@ GET_U64_FROM_ADDR(uint32 *addr)
|
|||
#define read_byte_array(p, p_end, addr, len) \
|
||||
do { \
|
||||
CHECK_BUF(p, p_end, len); \
|
||||
memcpy(addr, p, len); \
|
||||
bh_memcpy_s(addr, len, p, len); \
|
||||
p += len; \
|
||||
} while (0)
|
||||
|
||||
|
@ -674,6 +675,36 @@ load_custom_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
|
|||
error_buf, error_buf_size))
|
||||
goto fail;
|
||||
break;
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
case AOT_CUSTOM_SECTION_RAW:
|
||||
{
|
||||
const char *section_name;
|
||||
WASMCustomSection *section;
|
||||
|
||||
if (p >= p_end) {
|
||||
set_error_buf(error_buf, error_buf_size, "unexpected end");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
read_string(p, p_end, section_name);
|
||||
|
||||
section = loader_malloc(sizeof(WASMCustomSection), error_buf,
|
||||
error_buf_size);
|
||||
if (!section) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
section->name_addr = (char *)section_name;
|
||||
section->name_len = strlen(section_name);
|
||||
section->content_addr = (uint8 *)p;
|
||||
section->content_len = p_end - p;
|
||||
|
||||
section->next = module->custom_section_list;
|
||||
module->custom_section_list = section;
|
||||
LOG_VERBOSE("Load custom section [%s] success.", section_name);
|
||||
break;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1816,7 +1847,7 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group,
|
|||
return false;
|
||||
}
|
||||
}
|
||||
memcpy(symbol, relocation->symbol_name, symbol_len);
|
||||
bh_memcpy_s(symbol, symbol_len, relocation->symbol_name, symbol_len);
|
||||
symbol[symbol_len] = '\0';
|
||||
|
||||
if (!strncmp(symbol, AOT_FUNC_PREFIX, strlen(AOT_FUNC_PREFIX))) {
|
||||
|
@ -3261,6 +3292,10 @@ aot_unload(AOTModule *module)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
wasm_runtime_destroy_custom_sections(module->custom_section_list);
|
||||
#endif
|
||||
|
||||
wasm_runtime_free(module);
|
||||
}
|
||||
|
||||
|
@ -3269,3 +3304,24 @@ aot_get_plt_table_size()
|
|||
{
|
||||
return get_plt_table_size();
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
const uint8 *
|
||||
aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len)
|
||||
{
|
||||
WASMCustomSection *section = module->custom_section_list;
|
||||
|
||||
while (section) {
|
||||
if (strcmp(section->name_addr, name) == 0) {
|
||||
if (len) {
|
||||
*len = section->content_len;
|
||||
}
|
||||
return section->content_addr;
|
||||
}
|
||||
|
||||
section = section->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION */
|
||||
|
|
|
@ -1837,7 +1837,7 @@ aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr, uint32 size,
|
|||
if (memory_inst->heap_handle.ptr) {
|
||||
addr = mem_allocator_realloc(
|
||||
memory_inst->heap_handle.ptr,
|
||||
(uint8 *)memory_inst->memory_data.ptr + ptr, size);
|
||||
ptr ? (uint8 *)memory_inst->memory_data.ptr + ptr : NULL, size);
|
||||
}
|
||||
|
||||
/* Only support realloc in WAMR's app heap */
|
||||
|
|
|
@ -50,6 +50,7 @@ typedef enum AOTSectionType {
|
|||
} AOTSectionType;
|
||||
|
||||
typedef enum AOTCustomSectionType {
|
||||
AOT_CUSTOM_SECTION_RAW = 0,
|
||||
AOT_CUSTOM_SECTION_NATIVE_SYMBOL = 1,
|
||||
AOT_CUSTOM_SECTION_ACCESS_CONTROL = 2,
|
||||
AOT_CUSTOM_SECTION_NAME = 3,
|
||||
|
@ -268,6 +269,9 @@ typedef struct AOTModule {
|
|||
uint32 *aux_func_indexes;
|
||||
uint32 aux_func_name_count;
|
||||
#endif
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
WASMCustomSection *custom_section_list;
|
||||
#endif
|
||||
} AOTModule;
|
||||
|
||||
typedef union {
|
||||
|
@ -733,6 +737,9 @@ aot_dump_call_stack(WASMExecEnv *exec_env);
|
|||
void
|
||||
aot_dump_perf_profiling(const AOTModuleInstance *module_inst);
|
||||
|
||||
const uint8 *
|
||||
aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define R_ARC_32_ME 27
|
||||
|
||||
/* clang-format off */
|
||||
#ifndef __CCAC__
|
||||
void __st_r13_to_r15();
|
||||
void __st_r13_to_r16();
|
||||
void __st_r13_to_r17();
|
||||
|
@ -41,29 +42,86 @@ void __divdf3();
|
|||
void __divdi3();
|
||||
void __divsf3();
|
||||
void __divsi3();
|
||||
void __eqsf2();
|
||||
void __extendsfdf2();
|
||||
void __fixdfsi();
|
||||
void __floatsidf();
|
||||
void __floatsisf();
|
||||
void __gedf2();
|
||||
void __gtdf2();
|
||||
void __ledf2();
|
||||
void __lesf2();
|
||||
void __ltdf2();
|
||||
void __muldf3();
|
||||
void __mulsf3();
|
||||
void __subdf3();
|
||||
void __subsf3();
|
||||
void __truncdfsf2();
|
||||
#else
|
||||
void __ac_push_13_to_13();
|
||||
void __ac_push_13_to_14();
|
||||
void __ac_push_13_to_15();
|
||||
void __ac_push_13_to_16();
|
||||
void __ac_push_13_to_17();
|
||||
void __ac_push_13_to_18();
|
||||
void __ac_push_13_to_19();
|
||||
void __ac_push_13_to_20();
|
||||
void __ac_push_13_to_21();
|
||||
void __ac_push_13_to_22();
|
||||
void __ac_push_13_to_23();
|
||||
void __ac_push_13_to_24();
|
||||
void __ac_push_13_to_25();
|
||||
void __ac_push_13_to_26();
|
||||
void __ac_push_none();
|
||||
void __ac_pop_13_to_26();
|
||||
void __ac_pop_13_to_26v();
|
||||
void __ac_pop_13_to_25();
|
||||
void __ac_pop_13_to_25v();
|
||||
void __ac_pop_13_to_24();
|
||||
void __ac_pop_13_to_24v();
|
||||
void __ac_pop_13_to_23();
|
||||
void __ac_pop_13_to_23v();
|
||||
void __ac_pop_13_to_22();
|
||||
void __ac_pop_13_to_22v();
|
||||
void __ac_pop_13_to_21();
|
||||
void __ac_pop_13_to_21v();
|
||||
void __ac_pop_13_to_20();
|
||||
void __ac_pop_13_to_20v();
|
||||
void __ac_pop_13_to_19();
|
||||
void __ac_pop_13_to_19v();
|
||||
void __ac_pop_13_to_18();
|
||||
void __ac_pop_13_to_18v();
|
||||
void __ac_pop_13_to_17();
|
||||
void __ac_pop_13_to_17v();
|
||||
void __ac_pop_13_to_16();
|
||||
void __ac_pop_13_to_16v();
|
||||
void __ac_pop_13_to_15();
|
||||
void __ac_pop_13_to_15v();
|
||||
void __ac_pop_13_to_14();
|
||||
void __ac_pop_13_to_14v();
|
||||
void __ac_pop_13_to_13();
|
||||
void __ac_pop_13_to_13v();
|
||||
void __ac_pop_none();
|
||||
void __ac_pop_nonev();
|
||||
void __eqdf2();
|
||||
void __nedf2();
|
||||
void __ltsf2();
|
||||
void __nesf2();
|
||||
void __gesf2();
|
||||
void __gtsf2();
|
||||
void __unordsf2();
|
||||
void __truncdfhf2();
|
||||
void __truncsfhf2();
|
||||
#endif /* end of __CCAC__ */
|
||||
|
||||
void __ledf2();
|
||||
void __ltdf2();
|
||||
void __gedf2();
|
||||
void __gtdf2();
|
||||
void __eqsf2();
|
||||
void __lesf2();
|
||||
void __unorddf2();
|
||||
/* clang-format on */
|
||||
|
||||
static SymbolMap target_sym_map[] = {
|
||||
/* clang-format off */
|
||||
REG_COMMON_SYMBOLS
|
||||
#ifndef __CCAC__
|
||||
REG_SYM(__st_r13_to_r15),
|
||||
/* clang-format on */
|
||||
REG_SYM(__st_r13_to_r16),
|
||||
REG_SYM(__st_r13_to_r17),
|
||||
REG_SYM(__st_r13_to_r18),
|
||||
|
@ -91,22 +149,80 @@ static SymbolMap target_sym_map[] = {
|
|||
REG_SYM(__divdi3),
|
||||
REG_SYM(__divsf3),
|
||||
REG_SYM(__divsi3),
|
||||
REG_SYM(__eqsf2),
|
||||
REG_SYM(__extendsfdf2),
|
||||
REG_SYM(__fixdfsi),
|
||||
REG_SYM(__floatsidf),
|
||||
REG_SYM(__floatsisf),
|
||||
REG_SYM(__gedf2),
|
||||
REG_SYM(__gtdf2),
|
||||
REG_SYM(__ledf2),
|
||||
REG_SYM(__lesf2),
|
||||
REG_SYM(__ltdf2),
|
||||
REG_SYM(__muldf3),
|
||||
REG_SYM(__mulsf3),
|
||||
REG_SYM(__subdf3),
|
||||
REG_SYM(__subsf3),
|
||||
REG_SYM(__truncdfsf2),
|
||||
#else
|
||||
REG_SYM(__ac_push_13_to_13),
|
||||
REG_SYM(__ac_push_13_to_14),
|
||||
REG_SYM(__ac_push_13_to_15),
|
||||
REG_SYM(__ac_push_13_to_16),
|
||||
REG_SYM(__ac_push_13_to_17),
|
||||
REG_SYM(__ac_push_13_to_18),
|
||||
REG_SYM(__ac_push_13_to_19),
|
||||
REG_SYM(__ac_push_13_to_20),
|
||||
REG_SYM(__ac_push_13_to_21),
|
||||
REG_SYM(__ac_push_13_to_22),
|
||||
REG_SYM(__ac_push_13_to_23),
|
||||
REG_SYM(__ac_push_13_to_24),
|
||||
REG_SYM(__ac_push_13_to_25),
|
||||
REG_SYM(__ac_push_13_to_26),
|
||||
REG_SYM(__ac_push_none),
|
||||
REG_SYM(__ac_pop_13_to_26),
|
||||
REG_SYM(__ac_pop_13_to_26v),
|
||||
REG_SYM(__ac_pop_13_to_25),
|
||||
REG_SYM(__ac_pop_13_to_25v),
|
||||
REG_SYM(__ac_pop_13_to_24),
|
||||
REG_SYM(__ac_pop_13_to_24v),
|
||||
REG_SYM(__ac_pop_13_to_23),
|
||||
REG_SYM(__ac_pop_13_to_23v),
|
||||
REG_SYM(__ac_pop_13_to_22),
|
||||
REG_SYM(__ac_pop_13_to_22v),
|
||||
REG_SYM(__ac_pop_13_to_21),
|
||||
REG_SYM(__ac_pop_13_to_21v),
|
||||
REG_SYM(__ac_pop_13_to_20),
|
||||
REG_SYM(__ac_pop_13_to_20v),
|
||||
REG_SYM(__ac_pop_13_to_19),
|
||||
REG_SYM(__ac_pop_13_to_19v),
|
||||
REG_SYM(__ac_pop_13_to_18),
|
||||
REG_SYM(__ac_pop_13_to_18v),
|
||||
REG_SYM(__ac_pop_13_to_17),
|
||||
REG_SYM(__ac_pop_13_to_17v),
|
||||
REG_SYM(__ac_pop_13_to_16),
|
||||
REG_SYM(__ac_pop_13_to_16v),
|
||||
REG_SYM(__ac_pop_13_to_15),
|
||||
REG_SYM(__ac_pop_13_to_15v),
|
||||
REG_SYM(__ac_pop_13_to_14),
|
||||
REG_SYM(__ac_pop_13_to_14v),
|
||||
REG_SYM(__ac_pop_13_to_13),
|
||||
REG_SYM(__ac_pop_13_to_13v),
|
||||
REG_SYM(__ac_pop_none),
|
||||
REG_SYM(__ac_pop_nonev),
|
||||
REG_SYM(__eqdf2),
|
||||
REG_SYM(__nedf2),
|
||||
REG_SYM(__ltsf2),
|
||||
REG_SYM(__nesf2),
|
||||
REG_SYM(__gesf2),
|
||||
REG_SYM(__gtsf2),
|
||||
REG_SYM(__unordsf2),
|
||||
REG_SYM(__truncdfhf2),
|
||||
REG_SYM(__truncsfhf2),
|
||||
#endif /* end of __CCAC__ */
|
||||
|
||||
REG_SYM(__ledf2),
|
||||
REG_SYM(__ltdf2),
|
||||
REG_SYM(__gedf2),
|
||||
REG_SYM(__gtdf2),
|
||||
REG_SYM(__eqsf2),
|
||||
REG_SYM(__lesf2),
|
||||
REG_SYM(__unorddf2),
|
||||
/* clang-format on */
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -168,6 +284,45 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
|
|||
int32 symbol_index, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_ARC_S25H_PCREL:
|
||||
{
|
||||
uint32 insn = LOAD_I32(target_section_addr + reloc_offset);
|
||||
int32 addend, value;
|
||||
uintptr_t S, P;
|
||||
intptr_t A;
|
||||
|
||||
CHECK_RELOC_OFFSET(sizeof(void *));
|
||||
|
||||
/* Convert from middle endian */
|
||||
insn = middle_endian_convert(insn);
|
||||
|
||||
addend = ((insn << 28) >> 28) << 10;
|
||||
/* Extract the next 10 bits from Position 6 to 15 in insn */
|
||||
addend |= ((insn << 16) >> 22);
|
||||
addend = addend << 10;
|
||||
/* Extract the remaining 10 bits from Position 17 to 26 in insn */
|
||||
addend |= ((insn << 5) >> 22);
|
||||
/* Fill in 1 bits to get the 25 bit Offset Value */
|
||||
addend = addend << 1;
|
||||
|
||||
/* (S + A) - P */
|
||||
S = (uintptr_t)(uint8 *)symbol_addr;
|
||||
A = (intptr_t)reloc_addend;
|
||||
P = (uintptr_t)(target_section_addr + reloc_offset);
|
||||
P &= (uintptr_t)~1;
|
||||
value = (int32)(S + A + addend - P);
|
||||
|
||||
insn = insn & 0xf8010030;
|
||||
insn |= ((((value >> 1) & 0x3ff) << 17)
|
||||
| (((value >> 1) & 0xffc00) >> 3)
|
||||
| (((value >> 1) & 0xf00000) >> 19));
|
||||
|
||||
/* Convert to middle endian */
|
||||
insn = middle_endian_convert(insn);
|
||||
|
||||
STORE_U32(target_section_addr + reloc_offset, insn);
|
||||
break;
|
||||
}
|
||||
case R_ARC_S25W_PCREL:
|
||||
{
|
||||
uint32 insn = LOAD_I32(target_section_addr + reloc_offset);
|
||||
|
|
|
@ -22,6 +22,26 @@ void __modsi3();
|
|||
|
||||
void __divdi3();
|
||||
|
||||
void __udivdi3();
|
||||
void __unorddf2();
|
||||
void __adddf3();
|
||||
void __eqdf2();
|
||||
void __muldf3();
|
||||
void __gedf2();
|
||||
void __ledf2();
|
||||
void __fixunsdfsi();
|
||||
void __floatunsidf();
|
||||
void __subdf3();
|
||||
void __nedf2();
|
||||
void __fixdfsi();
|
||||
void __moddi3();
|
||||
void __extendsfdf2();
|
||||
void __truncdfsf2();
|
||||
void __gtdf2();
|
||||
void __umoddi3();
|
||||
void __floatdidf();
|
||||
void __divsf3();
|
||||
|
||||
static SymbolMap target_sym_map[] = {
|
||||
REG_COMMON_SYMBOLS
|
||||
|
||||
|
@ -40,6 +60,28 @@ static SymbolMap target_sym_map[] = {
|
|||
|
||||
REG_SYM(__modsi3),
|
||||
REG_SYM(__divdi3),
|
||||
|
||||
REG_SYM(__udivdi3),
|
||||
REG_SYM(__unorddf2),
|
||||
REG_SYM(__adddf3),
|
||||
REG_SYM(__eqdf2),
|
||||
REG_SYM(__muldf3),
|
||||
REG_SYM(__gedf2),
|
||||
REG_SYM(__ledf2),
|
||||
REG_SYM(__fixunsdfsi),
|
||||
REG_SYM(__floatunsidf),
|
||||
REG_SYM(__subdf3),
|
||||
REG_SYM(__nedf2),
|
||||
REG_SYM(__fixdfsi),
|
||||
REG_SYM(__moddi3),
|
||||
REG_SYM(__extendsfdf2),
|
||||
REG_SYM(__truncdfsf2),
|
||||
REG_SYM(__gtdf2),
|
||||
REG_SYM(__umoddi3),
|
||||
REG_SYM(__floatdidf),
|
||||
REG_SYM(__divsf3),
|
||||
REG_SYM(sqrt),
|
||||
REG_SYM(sqrtf),
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
|
@ -130,6 +172,16 @@ static union {
|
|||
|
||||
#define is_little_endian() (__ue.b == 1)
|
||||
|
||||
#if !defined(__packed)
|
||||
/*
|
||||
* Note: This version check is a bit relaxed.
|
||||
* The __packed__ attribute has been there since gcc 2 era.
|
||||
*/
|
||||
#if __GNUC__ >= 3
|
||||
#define __packed __attribute__((__packed__))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
struct l32r_le {
|
||||
int8 other;
|
||||
|
|
|
@ -485,7 +485,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
|
|||
u.ieee.ieee_little_endian.negative = 1;
|
||||
else
|
||||
u.ieee.ieee_big_endian.negative = 1;
|
||||
memcpy(&f32, &u.f, sizeof(float));
|
||||
bh_memcpy_s(&f32, sizeof(float), &u.f, sizeof(float));
|
||||
}
|
||||
if (endptr[0] == ':') {
|
||||
uint32 sig;
|
||||
|
@ -496,10 +496,11 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
|
|||
u.ieee.ieee_little_endian.mantissa = sig;
|
||||
else
|
||||
u.ieee.ieee_big_endian.mantissa = sig;
|
||||
memcpy(&f32, &u.f, sizeof(float));
|
||||
bh_memcpy_s(&f32, sizeof(float), &u.f, sizeof(float));
|
||||
}
|
||||
}
|
||||
memcpy(&argv1[p++], &f32, sizeof(float));
|
||||
bh_memcpy_s(&argv1[p], total_size - p, &f32, sizeof(float));
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F64:
|
||||
|
@ -517,7 +518,8 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
|
|||
ud.ieee.ieee_little_endian.negative = 1;
|
||||
else
|
||||
ud.ieee.ieee_big_endian.negative = 1;
|
||||
memcpy(&u.val, &ud.d, sizeof(double));
|
||||
bh_memcpy_s(&u.val, sizeof(double), &ud.d,
|
||||
sizeof(double));
|
||||
}
|
||||
if (endptr[0] == ':') {
|
||||
uint64 sig;
|
||||
|
@ -532,7 +534,8 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
|
|||
ud.ieee.ieee_big_endian.mantissa0 = sig >> 32;
|
||||
ud.ieee.ieee_big_endian.mantissa1 = (uint32)sig;
|
||||
}
|
||||
memcpy(&u.val, &ud.d, sizeof(double));
|
||||
bh_memcpy_s(&u.val, sizeof(double), &ud.d,
|
||||
sizeof(double));
|
||||
}
|
||||
}
|
||||
argv1[p++] = u.parts[0];
|
||||
|
@ -755,7 +758,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WAMR_ENABLE_PERF_PROFILING != 0
|
||||
#if WASM_ENABLE_PERF_PROFILING != 0
|
||||
wasm_runtime_dump_perf_profiling(module_inst);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -464,7 +464,7 @@ wasm_runtime_register_module_internal(const char *module_name,
|
|||
WASMModuleCommon *module,
|
||||
uint8 *orig_file_buf,
|
||||
uint32 orig_file_buf_size,
|
||||
char *error_buf, uint32_t error_buf_size)
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
WASMRegisteredModule *node = NULL;
|
||||
|
||||
|
@ -519,7 +519,7 @@ wasm_runtime_register_module_internal(const char *module_name,
|
|||
|
||||
bool
|
||||
wasm_runtime_register_module(const char *module_name, WASMModuleCommon *module,
|
||||
char *error_buf, uint32_t error_buf_size)
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
if (!error_buf || !error_buf_size) {
|
||||
LOG_ERROR("error buffer is required");
|
||||
|
@ -842,7 +842,7 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
|
|||
|
||||
WASMModuleCommon *
|
||||
wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
|
||||
char *error_buf, uint32_t error_buf_size)
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
WASMModuleCommon *module_common;
|
||||
|
||||
|
@ -999,6 +999,23 @@ wasm_runtime_destroy_thread_env(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_thread_env_inited(void)
|
||||
{
|
||||
#ifdef BH_PLATFORM_WINDOWS
|
||||
if (!os_thread_env_inited())
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
if (!os_thread_signal_inited())
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#if (WASM_ENABLE_MEMORY_PROFILING != 0) || (WASM_ENABLE_MEMORY_TRACING != 0)
|
||||
void
|
||||
wasm_runtime_dump_module_mem_consumption(const WASMModuleCommon *module)
|
||||
|
@ -1241,8 +1258,85 @@ wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
uint32
|
||||
wasm_func_get_param_count(WASMFunctionInstanceCommon *const func_inst,
|
||||
WASMModuleInstanceCommon *const module_inst)
|
||||
{
|
||||
WASMType *type =
|
||||
wasm_runtime_get_function_type(func_inst, module_inst->module_type);
|
||||
bh_assert(type);
|
||||
|
||||
return type->param_count;
|
||||
}
|
||||
|
||||
uint32
|
||||
wasm_func_get_result_count(WASMFunctionInstanceCommon *const func_inst,
|
||||
WASMModuleInstanceCommon *const module_inst)
|
||||
{
|
||||
WASMType *type =
|
||||
wasm_runtime_get_function_type(func_inst, module_inst->module_type);
|
||||
bh_assert(type);
|
||||
|
||||
return type->result_count;
|
||||
}
|
||||
|
||||
static uint8
|
||||
val_type_to_val_kind(uint8 value_type)
|
||||
{
|
||||
switch (value_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
return WASM_I32;
|
||||
case VALUE_TYPE_I64:
|
||||
return WASM_I64;
|
||||
case VALUE_TYPE_F32:
|
||||
return WASM_F32;
|
||||
case VALUE_TYPE_F64:
|
||||
return WASM_F64;
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
return WASM_FUNCREF;
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
return WASM_ANYREF;
|
||||
default:
|
||||
bh_assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wasm_func_get_param_types(WASMFunctionInstanceCommon *const func_inst,
|
||||
WASMModuleInstanceCommon *const module_inst,
|
||||
wasm_valkind_t *param_types)
|
||||
{
|
||||
WASMType *type =
|
||||
wasm_runtime_get_function_type(func_inst, module_inst->module_type);
|
||||
uint32 i;
|
||||
|
||||
bh_assert(type);
|
||||
|
||||
for (i = 0; i < type->param_count; i++) {
|
||||
param_types[i] = val_type_to_val_kind(type->types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wasm_func_get_result_types(WASMFunctionInstanceCommon *const func_inst,
|
||||
WASMModuleInstanceCommon *const module_inst,
|
||||
wasm_valkind_t *result_types)
|
||||
{
|
||||
WASMType *type =
|
||||
wasm_runtime_get_function_type(func_inst, module_inst->module_type);
|
||||
uint32 i;
|
||||
|
||||
bh_assert(type);
|
||||
|
||||
for (i = 0; i < type->result_count; i++) {
|
||||
result_types[i] =
|
||||
val_type_to_val_kind(type->types[type->param_count + i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
/* (uintptr_t)externref -> (uint32_t)index */
|
||||
/* (uintptr_t)externref -> (uint32)index */
|
||||
/* argv -> *ret_argv */
|
||||
static bool
|
||||
wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
|
||||
|
@ -1340,7 +1434,7 @@ wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* (uintptr_t)externref <- (uint32_t)index */
|
||||
/* (uintptr_t)externref <- (uint32)index */
|
||||
/* argv <- new_argv */
|
||||
static bool
|
||||
wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
|
||||
|
@ -2776,6 +2870,24 @@ wasm_exec_env_get_module(WASMExecEnv *exec_env)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
const uint8 *
|
||||
wasm_runtime_get_custom_section(WASMModuleCommon *const module_comm,
|
||||
const char *name, uint32 *len)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_comm->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_loader_get_custom_section((WASMModule *)module_comm, name,
|
||||
len);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_comm->module_type == Wasm_Module_AoT)
|
||||
return aot_get_custom_section((AOTModule *)module_comm, name, len);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */
|
||||
|
||||
static union {
|
||||
int a;
|
||||
char b;
|
||||
|
@ -3971,8 +4083,8 @@ fail:
|
|||
|| defined(BUILD_TARGET_RISCV64_LP64) */
|
||||
|
||||
bool
|
||||
wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32_t element_indices,
|
||||
uint32_t argc, uint32_t argv[])
|
||||
wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices,
|
||||
uint32 argc, uint32 argv[])
|
||||
{
|
||||
if (!wasm_runtime_exec_env_check(exec_env)) {
|
||||
LOG_ERROR("Invalid exec env stack info.");
|
||||
|
@ -4820,3 +4932,16 @@ wasm_runtime_show_app_heap_corrupted_prompt()
|
|||
"compiled by asc, please add --exportRuntime to "
|
||||
"export the runtime helpers.");
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
void
|
||||
wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list)
|
||||
{
|
||||
WASMCustomSection *section = section_list, *next;
|
||||
while (section) {
|
||||
next = section->next;
|
||||
wasm_runtime_free(section);
|
||||
section = next;
|
||||
}
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION */
|
||||
|
|
|
@ -303,6 +303,11 @@ typedef struct WASMModuleCommon {
|
|||
Wasm_Module_AoT, and this structure should be treated as
|
||||
AOTModule structure. */
|
||||
uint32 module_type;
|
||||
|
||||
/* The following uint8[1] member is a dummy just to indicate
|
||||
some module_type dependent members follow.
|
||||
Typically it should be accessed by casting to the corresponding
|
||||
actual module_type dependent structure, not via this member. */
|
||||
uint8 module_data[1];
|
||||
} WASMModuleCommon;
|
||||
|
||||
|
@ -314,6 +319,11 @@ typedef struct WASMModuleInstanceCommon {
|
|||
Wasm_Module_AoT, and this structure should be treated as
|
||||
AOTModuleInstance structure. */
|
||||
uint32 module_type;
|
||||
|
||||
/* The following uint8[1] member is a dummy just to indicate
|
||||
some module_type dependent members follow.
|
||||
Typically it should be accessed by casting to the corresponding
|
||||
actual module_type dependent structure, not via this member. */
|
||||
uint8 module_inst_data[1];
|
||||
} WASMModuleInstanceCommon;
|
||||
|
||||
|
@ -377,6 +387,11 @@ typedef struct WASMRegisteredModule {
|
|||
|
||||
typedef struct WASMMemoryInstanceCommon {
|
||||
uint32 module_type;
|
||||
|
||||
/* The following uint8[1] member is a dummy just to indicate
|
||||
some module_type dependent members follow.
|
||||
Typically it should be accessed by casting to the corresponding
|
||||
actual module_type dependent structure, not via this member. */
|
||||
uint8 memory_inst_data[1];
|
||||
} WASMMemoryInstanceCommon;
|
||||
|
||||
|
@ -456,6 +471,28 @@ WASMType *
|
|||
wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function,
|
||||
uint32 module_type);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN uint32
|
||||
wasm_func_get_param_count(WASMFunctionInstanceCommon *const func_inst,
|
||||
WASMModuleInstanceCommon *const module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN uint32
|
||||
wasm_func_get_result_count(WASMFunctionInstanceCommon *const func_inst,
|
||||
WASMModuleInstanceCommon *const module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_func_get_param_types(WASMFunctionInstanceCommon *const func_inst,
|
||||
WASMModuleInstanceCommon *const module_inst,
|
||||
wasm_valkind_t *param_types);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_func_get_result_types(WASMFunctionInstanceCommon *const func_inst,
|
||||
WASMModuleInstanceCommon *const module_inst,
|
||||
wasm_valkind_t *result_types);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN WASMExecEnv *
|
||||
wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst,
|
||||
|
@ -621,6 +658,11 @@ wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst,
|
|||
uint8 **p_native_start_addr,
|
||||
uint8 **p_native_end_addr);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN const uint8 *
|
||||
wasm_runtime_get_custom_section(WASMModuleCommon *const module_comm,
|
||||
const char *name, uint32 *len);
|
||||
|
||||
uint32
|
||||
wasm_runtime_get_temp_ret(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
|
@ -842,6 +884,11 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
|
|||
void
|
||||
wasm_runtime_show_app_heap_corrupted_prompt();
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
void
|
||||
wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef AOT_FUNC_PREFIX
|
||||
#define AOT_FUNC_PREFIX "aot_func#"
|
||||
#endif
|
||||
|
||||
typedef InitializerExpression AOTInitExpr;
|
||||
typedef WASMType AOTFuncType;
|
||||
|
|
|
@ -2886,6 +2886,36 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
|
|||
return true;
|
||||
}
|
||||
|
||||
#if !(defined(_WIN32) || defined(_WIN32_))
|
||||
char *
|
||||
aot_generate_tempfile_name(const char *prefix, const char *extension,
|
||||
char *buffer, uint32 len)
|
||||
{
|
||||
int fd, name_len;
|
||||
|
||||
name_len = snprintf(buffer, len, "%s-XXXXXX", prefix);
|
||||
|
||||
if ((fd = mkstemp(buffer)) <= 0) {
|
||||
aot_set_last_error("make temp file failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* close and remove temp file */
|
||||
close(fd);
|
||||
unlink(buffer);
|
||||
|
||||
/* Check if buffer length is enough */
|
||||
/* name_len + '.' + extension + '\0' */
|
||||
if (name_len + 1 + strlen(extension) + 1 > len) {
|
||||
aot_set_last_error("temp file name too long.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(buffer + name_len, len - name_len, ".%s", extension);
|
||||
return buffer;
|
||||
}
|
||||
#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
bool
|
||||
aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name)
|
||||
|
@ -2915,6 +2945,83 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
|
|||
|
||||
bh_print_time("Begin to emit object file");
|
||||
|
||||
#if !(defined(_WIN32) || defined(_WIN32_))
|
||||
if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) {
|
||||
char cmd[1024];
|
||||
int ret;
|
||||
|
||||
if (comp_ctx->external_llc_compiler) {
|
||||
char bc_file_name[64];
|
||||
|
||||
if (!aot_generate_tempfile_name("wamrc-bc", "bc", bc_file_name,
|
||||
sizeof(bc_file_name))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LLVMWriteBitcodeToFile(comp_ctx->module, bc_file_name) != 0) {
|
||||
aot_set_last_error("emit llvm bitcode file failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "%s %s -o %s %s",
|
||||
comp_ctx->external_llc_compiler,
|
||||
comp_ctx->llc_compiler_flags ? comp_ctx->llc_compiler_flags
|
||||
: "-O3 -c",
|
||||
file_name, bc_file_name);
|
||||
LOG_VERBOSE("invoking external LLC compiler:\n\t%s", cmd);
|
||||
|
||||
ret = system(cmd);
|
||||
/* remove temp bitcode file */
|
||||
unlink(bc_file_name);
|
||||
|
||||
if (ret != 0) {
|
||||
aot_set_last_error("failed to compile LLVM bitcode to obj file "
|
||||
"with external LLC compiler.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (comp_ctx->external_asm_compiler) {
|
||||
char asm_file_name[64];
|
||||
|
||||
if (!aot_generate_tempfile_name("wamrc-asm", "s", asm_file_name,
|
||||
sizeof(asm_file_name))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
|
||||
comp_ctx->module, asm_file_name,
|
||||
LLVMAssemblyFile, &err)
|
||||
!= 0) {
|
||||
if (err) {
|
||||
LLVMDisposeMessage(err);
|
||||
err = NULL;
|
||||
}
|
||||
aot_set_last_error("emit elf to assembly file failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "%s %s -o %s %s",
|
||||
comp_ctx->external_asm_compiler,
|
||||
comp_ctx->asm_compiler_flags ? comp_ctx->asm_compiler_flags
|
||||
: "-O3 -c",
|
||||
file_name, asm_file_name);
|
||||
LOG_VERBOSE("invoking external ASM compiler:\n\t%s", cmd);
|
||||
|
||||
ret = system(cmd);
|
||||
/* remove temp assembly file */
|
||||
unlink(asm_file_name);
|
||||
|
||||
if (ret != 0) {
|
||||
aot_set_last_error("failed to compile Assembly file to obj "
|
||||
"file with external ASM compiler.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */
|
||||
|
||||
if (!strncmp(LLVMGetTargetName(target), "arc", 3))
|
||||
/* Emit to assmelby file instead for arc target
|
||||
as it cannot emit to object file */
|
||||
|
|
|
@ -371,6 +371,10 @@ aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
|||
bool
|
||||
aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name);
|
||||
|
||||
char *
|
||||
aot_generate_tempfile_name(const char *prefix, const char *extension,
|
||||
char *buffer, uint32 len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -877,11 +877,15 @@ get_native_symbol_list_size(AOTCompContext *comp_ctx)
|
|||
static uint32
|
||||
get_name_section_size(AOTCompData *comp_data);
|
||||
|
||||
static uint32
|
||||
get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data);
|
||||
|
||||
static uint32
|
||||
get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
||||
AOTObjectData *obj_data)
|
||||
{
|
||||
uint32 size = 0;
|
||||
uint32 size_custom_section = 0;
|
||||
|
||||
/* aot file header */
|
||||
size += get_file_header_size();
|
||||
|
@ -939,6 +943,12 @@ get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
|||
get_name_section_size(comp_data));
|
||||
}
|
||||
|
||||
size_custom_section = get_custom_sections_size(comp_ctx, comp_data);
|
||||
if (size_custom_section > 0) {
|
||||
size = align_uint(size, 4);
|
||||
size += size_custom_section;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -1274,6 +1284,40 @@ fail:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
|
||||
{
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
uint32 size = 0, i;
|
||||
|
||||
for (i = 0; i < comp_ctx->custom_sections_count; i++) {
|
||||
const char *section_name = comp_ctx->custom_sections_wp[i];
|
||||
const uint8 *content = NULL;
|
||||
uint32 length = 0;
|
||||
|
||||
content = wasm_loader_get_custom_section(comp_data->wasm_module,
|
||||
section_name, &length);
|
||||
if (!content) {
|
||||
LOG_WARNING("Can't find custom section [%s], ignore it",
|
||||
section_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
size = align_uint(size, 4);
|
||||
/* section id + section size + sub section id */
|
||||
size += (uint32)sizeof(uint32) * 3;
|
||||
/* section name and len */
|
||||
size += get_string_size(comp_ctx, section_name);
|
||||
/* section content */
|
||||
size += length;
|
||||
}
|
||||
|
||||
return size;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
aot_emit_file_header(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||
AOTCompData *comp_data, AOTObjectData *obj_data)
|
||||
|
@ -1897,6 +1941,43 @@ aot_emit_name_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
aot_emit_custom_sections(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||
AOTCompData *comp_data, AOTCompContext *comp_ctx)
|
||||
{
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
uint32 offset = *p_offset, i;
|
||||
|
||||
for (i = 0; i < comp_ctx->custom_sections_count; i++) {
|
||||
const char *section_name = comp_ctx->custom_sections_wp[i];
|
||||
const uint8 *content = NULL;
|
||||
uint32 length = 0;
|
||||
|
||||
content = wasm_loader_get_custom_section(comp_data->wasm_module,
|
||||
section_name, &length);
|
||||
if (!content) {
|
||||
/* Warning has been reported during calculating size */
|
||||
continue;
|
||||
}
|
||||
|
||||
offset = align_uint(offset, 4);
|
||||
EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
|
||||
/* sub section id + content */
|
||||
EMIT_U32(sizeof(uint32) * 1 + get_string_size(comp_ctx, section_name)
|
||||
+ length);
|
||||
EMIT_U32(AOT_CUSTOM_SECTION_RAW);
|
||||
EMIT_STR(section_name);
|
||||
bh_memcpy_s((uint8 *)(buf + offset), (uint32)(buf_end - buf), content,
|
||||
length);
|
||||
offset += length;
|
||||
}
|
||||
|
||||
*p_offset = offset;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef uint32 U32;
|
||||
typedef int32 I32;
|
||||
typedef uint16 U16;
|
||||
|
@ -2611,8 +2692,41 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
|
|||
memset(obj_data, 0, sizeof(AOTObjectData));
|
||||
|
||||
bh_print_time("Begin to emit object file");
|
||||
if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) {
|
||||
#if defined(_WIN32) || defined(_WIN32_)
|
||||
aot_set_last_error("external toolchain not supported on Windows");
|
||||
goto fail;
|
||||
#else
|
||||
/* Generate a temp file name */
|
||||
int ret;
|
||||
char obj_file_name[64];
|
||||
|
||||
if (!strncmp(LLVMGetTargetName(target), "arc", 3)) {
|
||||
if (!aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name,
|
||||
sizeof(obj_file_name))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!aot_emit_object_file(comp_ctx, obj_file_name)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* create memory buffer from object file */
|
||||
ret = LLVMCreateMemoryBufferWithContentsOfFile(
|
||||
obj_file_name, &obj_data->mem_buf, &err);
|
||||
/* remove temp object file */
|
||||
unlink(obj_file_name);
|
||||
|
||||
if (ret != 0) {
|
||||
if (err) {
|
||||
LLVMDisposeMessage(err);
|
||||
err = NULL;
|
||||
}
|
||||
aot_set_last_error("create mem buffer with file failed.");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* end of defined(_WIN32) || defined(_WIN32_) */
|
||||
}
|
||||
else if (!strncmp(LLVMGetTargetName(target), "arc", 3)) {
|
||||
#if defined(_WIN32) || defined(_WIN32_)
|
||||
aot_set_last_error("emit object file on Windows is unsupported.");
|
||||
goto fail;
|
||||
|
@ -2751,7 +2865,9 @@ aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
|||
|| !aot_emit_relocation_section(buf, buf_end, &offset, comp_ctx,
|
||||
comp_data, obj_data)
|
||||
|| !aot_emit_native_symbol(buf, buf_end, &offset, comp_ctx)
|
||||
|| !aot_emit_name_section(buf, buf_end, &offset, comp_data, comp_ctx))
|
||||
|| !aot_emit_name_section(buf, buf_end, &offset, comp_data, comp_ctx)
|
||||
|| !aot_emit_custom_sections(buf, buf_end, &offset, comp_data,
|
||||
comp_ctx))
|
||||
goto fail2;
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -1587,6 +1587,9 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
comp_ctx->opt_level = option->opt_level;
|
||||
comp_ctx->size_level = option->size_level;
|
||||
|
||||
comp_ctx->custom_sections_wp = option->custom_sections;
|
||||
comp_ctx->custom_sections_count = option->custom_sections_count;
|
||||
|
||||
if (option->is_jit_mode) {
|
||||
char *triple_jit = NULL;
|
||||
|
||||
|
@ -1657,6 +1660,51 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
opt_level = option->opt_level;
|
||||
size_level = option->size_level;
|
||||
|
||||
/* verify external llc compiler */
|
||||
comp_ctx->external_llc_compiler = getenv("WAMRC_LLC_COMPILER");
|
||||
if (comp_ctx->external_llc_compiler) {
|
||||
#if defined(_WIN32) || defined(_WIN32_)
|
||||
comp_ctx->external_llc_compiler = NULL;
|
||||
LOG_WARNING("External LLC compiler not supported on Windows.");
|
||||
#else
|
||||
if (access(comp_ctx->external_llc_compiler, X_OK) != 0) {
|
||||
LOG_WARNING("WAMRC_LLC_COMPILER [%s] not found, fallback to "
|
||||
"default pipeline",
|
||||
comp_ctx->external_llc_compiler);
|
||||
comp_ctx->external_llc_compiler = NULL;
|
||||
}
|
||||
else {
|
||||
comp_ctx->llc_compiler_flags = getenv("WAMRC_LLC_FLAGS");
|
||||
LOG_VERBOSE("Using external LLC compiler [%s]",
|
||||
comp_ctx->external_llc_compiler);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* verify external asm compiler */
|
||||
if (!comp_ctx->external_llc_compiler) {
|
||||
comp_ctx->external_asm_compiler = getenv("WAMRC_ASM_COMPILER");
|
||||
if (comp_ctx->external_asm_compiler) {
|
||||
#if defined(_WIN32) || defined(_WIN32_)
|
||||
comp_ctx->external_asm_compiler = NULL;
|
||||
LOG_WARNING("External ASM compiler not supported on Windows.");
|
||||
#else
|
||||
if (access(comp_ctx->external_asm_compiler, X_OK) != 0) {
|
||||
LOG_WARNING(
|
||||
"WAMRC_ASM_COMPILER [%s] not found, fallback to "
|
||||
"default pipeline",
|
||||
comp_ctx->external_asm_compiler);
|
||||
comp_ctx->external_asm_compiler = NULL;
|
||||
}
|
||||
else {
|
||||
comp_ctx->asm_compiler_flags = getenv("WAMRC_ASM_FLAGS");
|
||||
LOG_VERBOSE("Using external ASM compiler [%s]",
|
||||
comp_ctx->external_asm_compiler);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (arch) {
|
||||
/* Add default sub-arch if not specified */
|
||||
if (!strcmp(arch, "arm"))
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "llvm-c/Object.h"
|
||||
#include "llvm-c/ExecutionEngine.h"
|
||||
#include "llvm-c/Analysis.h"
|
||||
#include "llvm-c/BitWriter.h"
|
||||
#include "llvm-c/Transforms/Utils.h"
|
||||
#include "llvm-c/Transforms/Scalar.h"
|
||||
#include "llvm-c/Transforms/Vectorize.h"
|
||||
|
@ -348,6 +349,22 @@ typedef struct AOTCompContext {
|
|||
/* Function contexts */
|
||||
AOTFuncContext **func_ctxes;
|
||||
uint32 func_ctx_count;
|
||||
char **custom_sections_wp;
|
||||
uint32 custom_sections_count;
|
||||
|
||||
/* 3rd-party toolchains */
|
||||
/* External llc compiler, if specified, wamrc will emit the llvm-ir file and
|
||||
* invoke the llc compiler to generate object file.
|
||||
* This can be used when we want to benefit from the optimization of other
|
||||
* LLVM based toolchains */
|
||||
const char *external_llc_compiler;
|
||||
const char *llc_compiler_flags;
|
||||
/* External asm compiler, if specified, wamrc will emit the text-based
|
||||
* assembly file (.s) and invoke the llc compiler to generate object file.
|
||||
* This will be useful when the upstream LLVM doesn't support to emit object
|
||||
* file for some architecture (such as arc) */
|
||||
const char *external_asm_compiler;
|
||||
const char *asm_compiler_flags;
|
||||
} AOTCompContext;
|
||||
|
||||
enum {
|
||||
|
@ -378,6 +395,8 @@ typedef struct AOTCompOption {
|
|||
uint32 size_level;
|
||||
uint32 output_format;
|
||||
uint32 bounds_checks;
|
||||
char **custom_sections;
|
||||
uint32 custom_sections_count;
|
||||
} AOTCompOption, *aot_comp_option_t;
|
||||
|
||||
AOTCompContext *
|
||||
|
|
|
@ -59,6 +59,8 @@ typedef struct AOTCompOption {
|
|||
uint32_t size_level;
|
||||
uint32_t output_format;
|
||||
uint32_t bounds_checks;
|
||||
char **custom_sections;
|
||||
uint32_t custom_sections_count;
|
||||
} AOTCompOption, *aot_comp_option_t;
|
||||
|
||||
aot_comp_context_t
|
||||
|
|
|
@ -133,11 +133,12 @@ typedef struct RuntimeInitArgs {
|
|||
/* maximum thread number, only used when
|
||||
WASM_ENABLE_THREAD_MGR is defined */
|
||||
uint32_t max_thread_num;
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
|
||||
/* Debug settings, only used when
|
||||
WASM_ENABLE_DEBUG_INTERP != 0 */
|
||||
char ip_addr[128];
|
||||
int platform_port;
|
||||
int instance_port;
|
||||
#endif
|
||||
} RuntimeInitArgs;
|
||||
|
||||
#ifndef WASM_VALKIND_T_DEFINED
|
||||
|
@ -406,6 +407,54 @@ WASM_RUNTIME_API_EXTERN wasm_function_inst_t
|
|||
wasm_runtime_lookup_function(wasm_module_inst_t const module_inst,
|
||||
const char *name, const char *signature);
|
||||
|
||||
/**
|
||||
* Get parameter count of the function instance
|
||||
*
|
||||
* @param func_inst the function instance
|
||||
* @param module_inst the module instance the function instance belongs to
|
||||
*
|
||||
* @return the parameter count of the function instance
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN uint32_t
|
||||
wasm_func_get_param_count(wasm_function_inst_t const func_inst,
|
||||
wasm_module_inst_t const module_inst);
|
||||
|
||||
/**
|
||||
* Get result count of the function instance
|
||||
*
|
||||
* @param func_inst the function instance
|
||||
* @param module_inst the module instance the function instance belongs to
|
||||
*
|
||||
* @return the result count of the function instance
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN uint32_t
|
||||
wasm_func_get_result_count(wasm_function_inst_t const func_inst,
|
||||
wasm_module_inst_t const module_inst);
|
||||
|
||||
/**
|
||||
* Get parameter types of the function instance
|
||||
*
|
||||
* @param func_inst the function instance
|
||||
* @param module_inst the module instance the function instance belongs to
|
||||
* @param param_types the parameter types returned
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_func_get_param_types(wasm_function_inst_t const func_inst,
|
||||
wasm_module_inst_t const module_inst,
|
||||
wasm_valkind_t *param_types);
|
||||
|
||||
/**
|
||||
* Get result types of the function instance
|
||||
*
|
||||
* @param func_inst the function instance
|
||||
* @param module_inst the module instance the function instance belongs to
|
||||
* @param result_types the result types returned
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_func_get_result_types(wasm_function_inst_t const func_inst,
|
||||
wasm_module_inst_t const module_inst,
|
||||
wasm_valkind_t *result_types);
|
||||
|
||||
/**
|
||||
* Create execution environment for a WASM module instance.
|
||||
*
|
||||
|
@ -448,7 +497,7 @@ WASM_RUNTIME_API_EXTERN uint32_t
|
|||
wasm_runtime_start_debug_instance(wasm_exec_env_t exec_env);
|
||||
|
||||
/**
|
||||
* Initialize thread environment.
|
||||
* Initialize the thread environment.
|
||||
* Note:
|
||||
* If developer creates a child thread by himself to call the
|
||||
* the wasm function in that thread, he should call this API
|
||||
|
@ -463,11 +512,17 @@ WASM_RUNTIME_API_EXTERN bool
|
|||
wasm_runtime_init_thread_env(void);
|
||||
|
||||
/**
|
||||
* Destroy thread environment
|
||||
* Destroy the thread environment
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_destroy_thread_env(void);
|
||||
|
||||
/**
|
||||
* Whether the thread environment is initialized
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_thread_env_inited(void);
|
||||
|
||||
/**
|
||||
* Get WASM module instance from execution environment
|
||||
*
|
||||
|
@ -998,6 +1053,20 @@ wasm_externref_retain(uint32_t externref_idx);
|
|||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_dump_call_stack(wasm_exec_env_t exec_env);
|
||||
|
||||
/**
|
||||
* Get a custom section by name
|
||||
*
|
||||
* @param module_comm the module to find
|
||||
* @param name name of the custom section
|
||||
* @param len return the length of the content if found
|
||||
*
|
||||
* @return Custom section content (not including the name length
|
||||
* and name string) if found, NULL otherwise
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN const uint8_t *
|
||||
wasm_runtime_get_custom_section(wasm_module_t const module_comm,
|
||||
const char *name, uint32_t *len);
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -346,6 +346,19 @@ typedef struct WASMFastOPCodeNode {
|
|||
} WASMFastOPCodeNode;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
typedef struct WASMCustomSection {
|
||||
struct WASMCustomSection *next;
|
||||
/* Start address of the section name */
|
||||
char *name_addr;
|
||||
/* Length of the section name decoded from leb */
|
||||
uint32 name_len;
|
||||
/* Start address of the content (name len and name skipped) */
|
||||
uint8 *content_addr;
|
||||
uint32 content_len;
|
||||
} WASMCustomSection;
|
||||
#endif
|
||||
|
||||
struct WASMModule {
|
||||
/* Module type, for module loaded from WASM bytecode binary,
|
||||
this field is Wasm_Module_Bytecode;
|
||||
|
@ -468,6 +481,10 @@ struct WASMModule {
|
|||
const uint8 *name_section_buf_end;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
WASMCustomSection *custom_section_list;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
/* point to JITed functions */
|
||||
void **fast_jit_func_ptrs;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#endif
|
||||
#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
|
||||
#include "../libraries/thread-mgr/thread_manager.h"
|
||||
#include "../libraries/debug-engine/debug_engine.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
#include "../fast-jit/jit_compiler.h"
|
||||
|
@ -947,6 +948,9 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
|
|||
#if WASM_ENABLE_THREAD_MGR != 0 && WASM_ENABLE_DEBUG_INTERP != 0
|
||||
#define HANDLE_OP_END() \
|
||||
do { \
|
||||
/* Record the current frame_ip, so when exception occurs, \
|
||||
debugger can know the exact opcode who caused the exception */ \
|
||||
frame_ip_orig = frame_ip; \
|
||||
while (exec_env->current_status->signal_flag == WAMR_SIG_SINGSTEP \
|
||||
&& exec_env->current_status->step_count++ == 1) { \
|
||||
exec_env->current_status->step_count = 0; \
|
||||
|
@ -1024,6 +1028,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
uint32 cache_index, type_index, param_cell_num, cell_num;
|
||||
uint8 value_type;
|
||||
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
uint8 *frame_ip_orig = NULL;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||
#define HANDLE_OPCODE(op) &&HANDLE_##op
|
||||
DEFINE_GOTO_TABLE(const void *, handle_table);
|
||||
|
@ -3751,6 +3759,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
wasm_set_exception(module, "out of bounds memory access");
|
||||
|
||||
got_exception:
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
if (wasm_exec_env_get_instance(exec_env) != NULL) {
|
||||
uint8 *frame_ip_temp = frame_ip;
|
||||
frame_ip = frame_ip_orig;
|
||||
wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP);
|
||||
CHECK_SUSPEND_FLAGS();
|
||||
frame_ip = frame_ip_temp;
|
||||
}
|
||||
#endif
|
||||
SYNC_ALL_TO_FRAME();
|
||||
return;
|
||||
|
||||
|
|
|
@ -2815,7 +2815,8 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *p = buf, *p_end = buf_end;
|
||||
uint32 name_len;
|
||||
char section_name[32];
|
||||
uint32 name_len, buffer_len;
|
||||
|
||||
if (p >= p_end) {
|
||||
set_error_buf(error_buf, error_buf_size, "unexpected end");
|
||||
|
@ -2834,6 +2835,16 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
return false;
|
||||
}
|
||||
|
||||
buffer_len = sizeof(section_name);
|
||||
memset(section_name, 0, buffer_len);
|
||||
if (name_len < buffer_len) {
|
||||
bh_memcpy_s(section_name, buffer_len, p, name_len);
|
||||
}
|
||||
else {
|
||||
bh_memcpy_s(section_name, buffer_len, p, buffer_len - 4);
|
||||
memset(section_name + buffer_len - 4, '.', 3);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
|
||||
if (memcmp(p, "name", 4) == 0) {
|
||||
module->name_section_buf = buf;
|
||||
|
@ -2841,9 +2852,34 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
p += name_len;
|
||||
handle_name_section(p, p_end, module, is_load_from_file_buf, error_buf,
|
||||
error_buf_size);
|
||||
LOG_VERBOSE("Load custom name section success.");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
LOG_VERBOSE("Load custom section success.\n");
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
{
|
||||
WASMCustomSection *section =
|
||||
loader_malloc(sizeof(WASMCustomSection), error_buf, error_buf_size);
|
||||
|
||||
if (!section) {
|
||||
return false;
|
||||
}
|
||||
|
||||
section->name_addr = (char *)p;
|
||||
section->name_len = name_len;
|
||||
section->content_addr = (uint8 *)(p + name_len);
|
||||
section->content_len = p_end - p - name_len;
|
||||
|
||||
section->next = module->custom_section_list;
|
||||
module->custom_section_list = section;
|
||||
LOG_VERBOSE("Load custom section [%s] success.", section_name);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
LOG_VERBOSE("Ignore custom section [%s].", section_name);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
|
@ -3792,6 +3828,10 @@ wasm_loader_unload(WASMModule *module)
|
|||
os_mutex_destroy(&module->ref_count_lock);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
wasm_runtime_destroy_custom_sections(module->custom_section_list);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
if (module->fast_jit_func_ptrs) {
|
||||
for (i = 0; i < module->function_count; i++) {
|
||||
|
@ -6493,6 +6533,29 @@ get_table_seg_elem_type(const WASMModule *module, uint32 table_seg_idx,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
const uint8 *
|
||||
wasm_loader_get_custom_section(WASMModule *module, const char *name,
|
||||
uint32 *len)
|
||||
{
|
||||
WASMCustomSection *section = module->custom_section_list;
|
||||
|
||||
while (section) {
|
||||
if ((section->name_len == strlen(name))
|
||||
&& (memcmp(section->name_addr, name, section->name_len) == 0)) {
|
||||
if (len) {
|
||||
*len = section->content_len;
|
||||
}
|
||||
return section->content_addr;
|
||||
}
|
||||
|
||||
section = section->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
||||
uint32 cur_func_idx, char *error_buf,
|
||||
|
@ -6540,6 +6603,16 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
|||
}
|
||||
|
||||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
/* For the first traverse, the initial value of preserved_local_offset has
|
||||
* not been determined, we use the INT16_MAX to represent that a slot has
|
||||
* been copied to preserve space. For second traverse, this field will be
|
||||
* set to the appropriate value in wasm_loader_ctx_reinit.
|
||||
* This is for Issue #1230,
|
||||
* https://github.com/bytecodealliance/wasm-micro-runtime/issues/1230, the
|
||||
* drop opcodes need to know which slots are preserved, so those slots will
|
||||
* not be treated as dynamically allocated slots */
|
||||
loader_ctx->preserved_local_offset = INT16_MAX;
|
||||
|
||||
re_scan:
|
||||
if (loader_ctx->code_compiled_size > 0) {
|
||||
if (!wasm_loader_ctx_reinit(loader_ctx)) {
|
||||
|
@ -7197,8 +7270,10 @@ re_scan:
|
|||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
skip_label();
|
||||
loader_ctx->frame_offset--;
|
||||
if (*(loader_ctx->frame_offset)
|
||||
> loader_ctx->start_dynamic_offset)
|
||||
if ((*(loader_ctx->frame_offset)
|
||||
> loader_ctx->start_dynamic_offset)
|
||||
&& (*(loader_ctx->frame_offset)
|
||||
< loader_ctx->max_dynamic_offset))
|
||||
loader_ctx->dynamic_offset--;
|
||||
#endif
|
||||
}
|
||||
|
@ -7211,8 +7286,10 @@ re_scan:
|
|||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
skip_label();
|
||||
loader_ctx->frame_offset -= 2;
|
||||
if (*(loader_ctx->frame_offset)
|
||||
> loader_ctx->start_dynamic_offset)
|
||||
if ((*(loader_ctx->frame_offset)
|
||||
> loader_ctx->start_dynamic_offset)
|
||||
&& (*(loader_ctx->frame_offset)
|
||||
< loader_ctx->max_dynamic_offset))
|
||||
loader_ctx->dynamic_offset -= 2;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -4901,6 +4901,16 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
|||
}
|
||||
|
||||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
/* For the first traverse, the initial value of preserved_local_offset has
|
||||
* not been determined, we use the INT16_MAX to represent that a slot has
|
||||
* been copied to preserve space. For second traverse, this field will be
|
||||
* set to the appropriate value in wasm_loader_ctx_reinit.
|
||||
* This is for Issue #1230,
|
||||
* https://github.com/bytecodealliance/wasm-micro-runtime/issues/1230, the
|
||||
* drop opcodes need to know which slots are preserved, so those slots will
|
||||
* not be treated as dynamically allocated slots */
|
||||
loader_ctx->preserved_local_offset = INT16_MAX;
|
||||
|
||||
re_scan:
|
||||
if (loader_ctx->code_compiled_size > 0) {
|
||||
if (!wasm_loader_ctx_reinit(loader_ctx)) {
|
||||
|
@ -5477,8 +5487,10 @@ re_scan:
|
|||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
skip_label();
|
||||
loader_ctx->frame_offset--;
|
||||
if (*(loader_ctx->frame_offset)
|
||||
> loader_ctx->start_dynamic_offset)
|
||||
if ((*(loader_ctx->frame_offset)
|
||||
> loader_ctx->start_dynamic_offset)
|
||||
&& (*(loader_ctx->frame_offset)
|
||||
< loader_ctx->max_dynamic_offset))
|
||||
loader_ctx->dynamic_offset--;
|
||||
#endif
|
||||
}
|
||||
|
@ -5491,8 +5503,10 @@ re_scan:
|
|||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
skip_label();
|
||||
loader_ctx->frame_offset -= 2;
|
||||
if (*(loader_ctx->frame_offset)
|
||||
> loader_ctx->start_dynamic_offset)
|
||||
if ((*(loader_ctx->frame_offset)
|
||||
> loader_ctx->start_dynamic_offset)
|
||||
&& (*(loader_ctx->frame_offset)
|
||||
< loader_ctx->max_dynamic_offset))
|
||||
loader_ctx->dynamic_offset -= 2;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1935,8 +1935,8 @@ wasm_module_realloc(WASMModuleInstance *module_inst, uint32 ptr, uint32 size,
|
|||
}
|
||||
|
||||
if (memory->heap_handle) {
|
||||
addr = mem_allocator_realloc(memory->heap_handle,
|
||||
memory->memory_data + ptr, size);
|
||||
addr = mem_allocator_realloc(
|
||||
memory->heap_handle, ptr ? memory->memory_data + ptr : NULL, size);
|
||||
}
|
||||
|
||||
/* Only support realloc in WAMR's app heap */
|
||||
|
|
|
@ -458,6 +458,10 @@ void
|
|||
wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env);
|
||||
#endif
|
||||
|
||||
const uint8 *
|
||||
wasm_loader_get_custom_section(WASMModule *module, const char *name,
|
||||
uint32 *len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -456,7 +456,7 @@ wasm_debug_instance_destroy(WASMCluster *cluster)
|
|||
}
|
||||
}
|
||||
|
||||
static WASMExecEnv *
|
||||
WASMExecEnv *
|
||||
wasm_debug_instance_get_current_env(WASMDebugInstance *instance)
|
||||
{
|
||||
WASMExecEnv *exec_env = NULL;
|
||||
|
@ -829,7 +829,10 @@ WASMDebugInstance *
|
|||
wasm_exec_env_get_instance(WASMExecEnv *exec_env)
|
||||
{
|
||||
WASMDebugInstance *instance = NULL;
|
||||
bh_assert(g_debug_engine);
|
||||
|
||||
if (!g_debug_engine) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_mutex_lock(&g_debug_engine->instance_list_lock);
|
||||
instance = bh_list_first_elem(&g_debug_engine->debug_instance_list);
|
||||
|
|
|
@ -128,6 +128,9 @@ wasm_debug_set_engine_active(bool active);
|
|||
bool
|
||||
wasm_debug_get_engine_active(void);
|
||||
|
||||
WASMExecEnv *
|
||||
wasm_debug_instance_get_current_env(WASMDebugInstance *instance);
|
||||
|
||||
uint64
|
||||
wasm_debug_instance_get_pid(WASMDebugInstance *instance);
|
||||
|
||||
|
|
|
@ -334,6 +334,8 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
|
|||
char pc_string[17];
|
||||
uint32 tids_count, i = 0;
|
||||
uint32 gdb_status = status;
|
||||
WASMExecEnv *exec_env;
|
||||
const char *exception;
|
||||
|
||||
if (status == 0) {
|
||||
os_mutex_lock(&tmpbuf_lock);
|
||||
|
@ -370,20 +372,43 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
|
|||
mem2hex((void *)&pc, pc_string, 8);
|
||||
pc_string[8 * 2] = '\0';
|
||||
|
||||
if (status == WAMR_SIG_TRAP) {
|
||||
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
|
||||
"thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc,
|
||||
pc_string, "breakpoint");
|
||||
exec_env = wasm_debug_instance_get_current_env(
|
||||
(WASMDebugInstance *)server->thread->debug_instance);
|
||||
bh_assert(exec_env);
|
||||
|
||||
exception =
|
||||
wasm_runtime_get_exception(wasm_runtime_get_module_inst(exec_env));
|
||||
if (exception) {
|
||||
/* When exception occurs, use reason:exception so the description can be
|
||||
* correctly processed by LLDB */
|
||||
uint32 exception_len = strlen(exception);
|
||||
len +=
|
||||
snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
|
||||
"thread-pcs:%" PRIx64 ";00:%s;reason:%s;description:", pc,
|
||||
pc_string, "exception");
|
||||
/* The description should be encoded as HEX */
|
||||
for (i = 0; i < exception_len; i++) {
|
||||
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, "%02x",
|
||||
exception[i]);
|
||||
}
|
||||
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, ";");
|
||||
}
|
||||
else if (status == WAMR_SIG_SINGSTEP) {
|
||||
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
|
||||
"thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc,
|
||||
pc_string, "trace");
|
||||
}
|
||||
else if (status > 0) {
|
||||
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
|
||||
"thread-pcs:%" PRIx64 ";00:%s,reason:%s;", pc,
|
||||
pc_string, "signal");
|
||||
else {
|
||||
if (status == WAMR_SIG_TRAP) {
|
||||
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
|
||||
"thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
|
||||
pc_string, "breakpoint");
|
||||
}
|
||||
else if (status == WAMR_SIG_SINGSTEP) {
|
||||
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
|
||||
"thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
|
||||
pc_string, "trace");
|
||||
}
|
||||
else if (status > 0) {
|
||||
len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len,
|
||||
"thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
|
||||
pc_string, "signal");
|
||||
}
|
||||
}
|
||||
write_packet(server, tmpbuf);
|
||||
os_mutex_unlock(&tmpbuf_lock);
|
||||
|
|
|
@ -1091,7 +1091,7 @@ static float
|
|||
freebsd_fminf(float x, float y)
|
||||
{
|
||||
if (is_little_endian()) {
|
||||
IEEEf2bits_L u[2];
|
||||
IEEEf2bits_L u[2] = { 0 };
|
||||
|
||||
u[0].f = x;
|
||||
u[1].f = y;
|
||||
|
@ -1107,7 +1107,7 @@ freebsd_fminf(float x, float y)
|
|||
return (u[u[1].bits.sign].f);
|
||||
}
|
||||
else {
|
||||
IEEEf2bits_B u[2];
|
||||
IEEEf2bits_B u[2] = { 0 };
|
||||
|
||||
u[0].f = x;
|
||||
u[1].f = y;
|
||||
|
@ -1130,7 +1130,7 @@ static float
|
|||
freebsd_fmaxf(float x, float y)
|
||||
{
|
||||
if (is_little_endian()) {
|
||||
IEEEf2bits_L u[2];
|
||||
IEEEf2bits_L u[2] = { 0 };
|
||||
|
||||
u[0].f = x;
|
||||
u[1].f = y;
|
||||
|
@ -1146,7 +1146,7 @@ freebsd_fmaxf(float x, float y)
|
|||
return (u[u[0].bits.sign].f);
|
||||
}
|
||||
else {
|
||||
IEEEf2bits_B u[2];
|
||||
IEEEf2bits_B u[2] = { 0 };
|
||||
|
||||
u[0].f = x;
|
||||
u[1].f = y;
|
||||
|
|
|
@ -107,6 +107,12 @@ os_thread_env_init();
|
|||
void
|
||||
os_thread_env_destroy();
|
||||
|
||||
/**
|
||||
* Whether the thread environment is initialized
|
||||
*/
|
||||
bool
|
||||
os_thread_env_inited();
|
||||
|
||||
/**
|
||||
* Suspend execution of the calling thread for (at least)
|
||||
* usec microseconds
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "sgx_time.h"
|
||||
#include "sgx_socket.h"
|
||||
#include "sgx_signal.h"
|
||||
#include "sgx_trts.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -116,10 +116,6 @@ int
|
|||
ocall_getopt(int *p_ret, int argc, char *argv_buf, unsigned int argv_buf_len,
|
||||
const char *optstring);
|
||||
int
|
||||
ocall_getrandom(ssize_t *p_ret, void *buf, size_t buflen, unsigned int flags);
|
||||
int
|
||||
ocall_getentropy(int *p_ret, void *buffer, size_t length);
|
||||
int
|
||||
ocall_sched_yield(int *p_ret);
|
||||
|
||||
/** struct iovec **/
|
||||
|
@ -891,29 +887,124 @@ sched_yield(void)
|
|||
ssize_t
|
||||
getrandom(void *buf, size_t buflen, unsigned int flags)
|
||||
{
|
||||
ssize_t ret;
|
||||
sgx_status_t ret;
|
||||
|
||||
if (ocall_getrandom(&ret, buf, buflen, flags) != SGX_SUCCESS) {
|
||||
TRACE_OCALL_FAIL();
|
||||
if (!buf || buflen > INT32_MAX || flags != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (ret == -1)
|
||||
errno = get_errno();
|
||||
return ret;
|
||||
|
||||
ret = sgx_read_rand(buf, buflen);
|
||||
if (ret != SGX_SUCCESS) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (ssize_t)buflen;
|
||||
}
|
||||
|
||||
#define RDRAND_RETRIES 3
|
||||
|
||||
static int
|
||||
rdrand64_step(uint64 *seed)
|
||||
{
|
||||
uint8 ok;
|
||||
__asm__ volatile("rdseed %0; setc %1" : "=r"(*seed), "=qm"(ok));
|
||||
return (int)ok;
|
||||
}
|
||||
|
||||
static int
|
||||
rdrand64_retry(uint64 *rand, uint32 retries)
|
||||
{
|
||||
uint32 count = 0;
|
||||
|
||||
while (count++ <= retries) {
|
||||
if (rdrand64_step(rand)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32
|
||||
rdrand_get_bytes(uint8 *dest, uint32 n)
|
||||
{
|
||||
uint8 *head_start = dest, *tail_start = NULL;
|
||||
uint64 *block_start;
|
||||
uint32 count, ltail, lhead, lblock;
|
||||
uint64 i, temp_rand;
|
||||
|
||||
/* Get the address of the first 64-bit aligned block in the
|
||||
destination buffer. */
|
||||
if (((uintptr_t)head_start & (uintptr_t)7) == 0) {
|
||||
/* already 8-byte aligned */
|
||||
block_start = (uint64 *)head_start;
|
||||
lhead = 0;
|
||||
lblock = n & ~7;
|
||||
}
|
||||
else {
|
||||
/* next 8-byte aligned */
|
||||
block_start = (uint64 *)(((uintptr_t)head_start + 7) & ~(uintptr_t)7);
|
||||
lhead = (uint32)((uintptr_t)block_start - (uintptr_t)head_start);
|
||||
lblock = (n - lhead) & ~7;
|
||||
}
|
||||
|
||||
/* Compute the number of 64-bit blocks and the remaining number
|
||||
of bytes (the tail) */
|
||||
ltail = n - lblock - lhead;
|
||||
if (ltail > 0) {
|
||||
tail_start = (uint8 *)block_start + lblock;
|
||||
}
|
||||
|
||||
/* Populate the starting, mis-aligned section (the head) */
|
||||
if (lhead > 0) {
|
||||
if (!rdrand64_retry(&temp_rand, RDRAND_RETRIES)) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(head_start, &temp_rand, lhead);
|
||||
}
|
||||
|
||||
/* Populate the central, aligned blocks */
|
||||
count = lblock / 8;
|
||||
for (i = 0; i < count; i++, block_start++) {
|
||||
if (!rdrand64_retry(block_start, RDRAND_RETRIES)) {
|
||||
return i * 8 + lhead;
|
||||
}
|
||||
}
|
||||
|
||||
/* Populate the tail */
|
||||
if (ltail > 0) {
|
||||
if (!rdrand64_retry(&temp_rand, RDRAND_RETRIES)) {
|
||||
return count * 8 + lhead;
|
||||
}
|
||||
|
||||
memcpy(tail_start, &temp_rand, ltail);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
getentropy(void *buffer, size_t length)
|
||||
{
|
||||
int ret;
|
||||
uint32 size;
|
||||
|
||||
if (ocall_getentropy(&ret, buffer, length) != SGX_SUCCESS) {
|
||||
TRACE_OCALL_FAIL();
|
||||
if (!buffer || length > INT32_MAX) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (ret == -1)
|
||||
errno = get_errno();
|
||||
return ret;
|
||||
|
||||
if (length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = rdrand_get_bytes(buffer, (uint32)length);
|
||||
if (size != length) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -250,6 +250,7 @@ sched_yield(void);
|
|||
|
||||
ssize_t
|
||||
getrandom(void *buf, size_t buflen, unsigned int flags);
|
||||
|
||||
int
|
||||
getentropy(void *buffer, size_t length);
|
||||
|
||||
|
|
|
@ -77,9 +77,6 @@ enclave {
|
|||
[in, size=argv_buf_len]char *argv_buf,
|
||||
unsigned int argv_buf_len,
|
||||
[in, string]const char *optstring);
|
||||
ssize_t ocall_getrandom([out, size=buflen]void *buf, size_t buflen,
|
||||
unsigned int flags);
|
||||
int ocall_getentropy([out, size=length]void *buffer, size_t length);
|
||||
ssize_t ocall_readv(int fd,
|
||||
[in, out, size=buf_size]char *iov_buf,
|
||||
unsigned int buf_size, int iovcnt,
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/uio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
@ -303,18 +302,6 @@ ocall_getopt(int argc, char *argv_buf, unsigned int argv_buf_len,
|
|||
return getopt(argc, argv, optstring);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ocall_getrandom(void *buf, size_t buflen, unsigned int flags)
|
||||
{
|
||||
return getrandom(buf, buflen, flags);
|
||||
}
|
||||
|
||||
int
|
||||
ocall_getentropy(void *buffer, size_t length)
|
||||
{
|
||||
return getentropy(buffer, length);
|
||||
}
|
||||
|
||||
int
|
||||
ocall_sched_yield()
|
||||
{
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
#include "platform_api_extension.h"
|
||||
#include "platform_api_vmcore.h"
|
||||
|
||||
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
||||
#include <nuttx/arch.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
bh_platform_init()
|
||||
{
|
||||
|
@ -37,6 +41,12 @@ os_free(void *ptr)
|
|||
void *
|
||||
os_mmap(void *hint, size_t size, int prot, int flags)
|
||||
{
|
||||
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
||||
if ((prot & MMAP_PROT_EXEC) != 0) {
|
||||
return up_textheap_memalign(sizeof(void *), size);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((uint64)size >= UINT32_MAX)
|
||||
return NULL;
|
||||
return malloc((uint32)size);
|
||||
|
@ -45,6 +55,12 @@ os_mmap(void *hint, size_t size, int prot, int flags)
|
|||
void
|
||||
os_munmap(void *addr, size_t size)
|
||||
{
|
||||
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
||||
if (up_textheap_heapmember(addr)) {
|
||||
up_textheap_free(addr);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
return free(addr);
|
||||
}
|
||||
|
||||
|
@ -57,3 +73,75 @@ os_mprotect(void *addr, size_t size, int prot)
|
|||
void
|
||||
os_dcache_flush()
|
||||
{}
|
||||
|
||||
/* If AT_FDCWD is provided, maybe we have openat family */
|
||||
#if !defined(AT_FDCWD)
|
||||
|
||||
int
|
||||
openat(int fd, const char *path, int oflags, ...)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
fstatat(int fd, const char *path, struct stat *buf, int flag)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
mkdirat(int fd, const char *path, mode_t mode)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
readlinkat(int fd, const char *path, char *buf, size_t bufsize)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
linkat(int fd1, const char *path1, int fd2, const char *path2, int flag)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
renameat(int fromfd, const char *from, int tofd, const char *to)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
symlinkat(const char *target, int fd, const char *path)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
unlinkat(int fd, const char *path, int flag)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
utimensat(int fd, const char *path, const struct timespec ts[2], int flag)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* !defined(AT_FDCWD) */
|
||||
|
||||
DIR *
|
||||
fdopendir(int fd)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -8,15 +8,21 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
@ -50,6 +56,63 @@ typedef pthread_t korp_thread;
|
|||
/* On NuttX, time_t is uint32_t */
|
||||
#define BH_TIME_T_MAX 0xffffffff
|
||||
|
||||
/*
|
||||
* NuttX doesn't have O_DIRECTORY or directory open.
|
||||
* REVISIT: maybe this is safer to be disabled at higher level.
|
||||
*/
|
||||
#if !defined(O_DIRECTORY)
|
||||
#define O_DIRECTORY 0
|
||||
#endif
|
||||
|
||||
#if !defined(O_NOFOLLOW)
|
||||
#define O_NOFOLLOW 0
|
||||
#endif
|
||||
|
||||
#undef CONFIG_HAS_ISATTY
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
#define CONFIG_HAS_ISATTY 1
|
||||
#else
|
||||
#define CONFIG_HAS_ISATTY 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NuttX doesn't have openat family.
|
||||
*/
|
||||
|
||||
/* If AT_FDCWD is provided, maybe we have openat family */
|
||||
#if !defined(AT_FDCWD)
|
||||
|
||||
int
|
||||
openat(int fd, const char *path, int oflags, ...);
|
||||
int
|
||||
fstatat(int fd, const char *path, struct stat *buf, int flag);
|
||||
int
|
||||
mkdirat(int fd, const char *path, mode_t mode);
|
||||
ssize_t
|
||||
readlinkat(int fd, const char *path, char *buf, size_t bufsize);
|
||||
int
|
||||
linkat(int fd1, const char *path1, int fd2, const char *path2, int flag);
|
||||
int
|
||||
renameat(int fromfd, const char *from, int tofd, const char *to);
|
||||
int
|
||||
symlinkat(const char *target, int fd, const char *path);
|
||||
int
|
||||
unlinkat(int fd, const char *path, int flag);
|
||||
int
|
||||
utimensat(int fd, const char *path, const struct timespec ts[2], int flag);
|
||||
#define AT_SYMLINK_NOFOLLOW 0
|
||||
#define AT_SYMLINK_FOLLOW 0
|
||||
#define AT_REMOVEDIR 0
|
||||
|
||||
#endif /* !defined(AT_FDCWD) */
|
||||
|
||||
/*
|
||||
* NuttX doesn't have fdopendir.
|
||||
*/
|
||||
|
||||
DIR *
|
||||
fdopendir(int fd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -360,6 +360,13 @@ os_thread_env_destroy()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
os_thread_env_inited()
|
||||
{
|
||||
os_thread_data *thread_data = TlsGetValue(thread_data_key);
|
||||
return thread_data ? true : false;
|
||||
}
|
||||
|
||||
int
|
||||
os_sem_init(korp_sem *sem)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,10 @@ alloc_vector_data(size_t length, size_t size_elem)
|
|||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* every caller of `extend_vector` must provide
|
||||
* a thread-safe environment.
|
||||
*/
|
||||
static bool
|
||||
extend_vector(Vector *vector, size_t length)
|
||||
{
|
||||
|
@ -38,15 +42,12 @@ extend_vector(Vector *vector, size_t length)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (vector->lock)
|
||||
os_mutex_lock(vector->lock);
|
||||
memcpy(data, vector->data, vector->size_elem * vector->max_elems);
|
||||
bh_memcpy_s(data, vector->size_elem * length, vector->data,
|
||||
vector->size_elem * vector->max_elems);
|
||||
BH_FREE(vector->data);
|
||||
|
||||
vector->data = data;
|
||||
vector->max_elems = length;
|
||||
if (vector->lock)
|
||||
os_mutex_unlock(vector->lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -109,8 +110,8 @@ bh_vector_set(Vector *vector, uint32 index, const void *elem_buf)
|
|||
|
||||
if (vector->lock)
|
||||
os_mutex_lock(vector->lock);
|
||||
memcpy(vector->data + vector->size_elem * index, elem_buf,
|
||||
vector->size_elem);
|
||||
bh_memcpy_s(vector->data + vector->size_elem * index, vector->size_elem,
|
||||
elem_buf, vector->size_elem);
|
||||
if (vector->lock)
|
||||
os_mutex_unlock(vector->lock);
|
||||
return true;
|
||||
|
@ -131,8 +132,8 @@ bh_vector_get(Vector *vector, uint32 index, void *elem_buf)
|
|||
|
||||
if (vector->lock)
|
||||
os_mutex_lock(vector->lock);
|
||||
memcpy(elem_buf, vector->data + vector->size_elem * index,
|
||||
vector->size_elem);
|
||||
bh_memcpy_s(elem_buf, vector->size_elem,
|
||||
vector->data + vector->size_elem * index, vector->size_elem);
|
||||
if (vector->lock)
|
||||
os_mutex_unlock(vector->lock);
|
||||
return true;
|
||||
|
@ -143,58 +144,73 @@ bh_vector_insert(Vector *vector, uint32 index, const void *elem_buf)
|
|||
{
|
||||
size_t i;
|
||||
uint8 *p;
|
||||
bool ret = false;
|
||||
|
||||
if (!vector || !elem_buf) {
|
||||
LOG_ERROR("Insert vector elem failed: vector or elem buf is NULL.\n");
|
||||
return false;
|
||||
goto just_return;
|
||||
}
|
||||
|
||||
if (index >= vector->num_elems) {
|
||||
LOG_ERROR("Insert vector elem failed: invalid elem index.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!extend_vector(vector, vector->num_elems + 1)) {
|
||||
LOG_ERROR("Insert vector elem failed: extend vector failed.\n");
|
||||
return false;
|
||||
goto just_return;
|
||||
}
|
||||
|
||||
if (vector->lock)
|
||||
os_mutex_lock(vector->lock);
|
||||
|
||||
if (!extend_vector(vector, vector->num_elems + 1)) {
|
||||
LOG_ERROR("Insert vector elem failed: extend vector failed.\n");
|
||||
goto unlock_return;
|
||||
}
|
||||
|
||||
p = vector->data + vector->size_elem * vector->num_elems;
|
||||
for (i = vector->num_elems - 1; i > index; i--) {
|
||||
memcpy(p, p - vector->size_elem, vector->size_elem);
|
||||
bh_memcpy_s(p, vector->size_elem, p - vector->size_elem,
|
||||
vector->size_elem);
|
||||
p -= vector->size_elem;
|
||||
}
|
||||
|
||||
memcpy(p, elem_buf, vector->size_elem);
|
||||
bh_memcpy_s(p, vector->size_elem, elem_buf, vector->size_elem);
|
||||
vector->num_elems++;
|
||||
ret = true;
|
||||
|
||||
unlock_return:
|
||||
if (vector->lock)
|
||||
os_mutex_unlock(vector->lock);
|
||||
return true;
|
||||
just_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
bh_vector_append(Vector *vector, const void *elem_buf)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (!vector || !elem_buf) {
|
||||
LOG_ERROR("Append vector elem failed: vector or elem buf is NULL.\n");
|
||||
return false;
|
||||
goto just_return;
|
||||
}
|
||||
|
||||
/* make sure one more slot is used by the thread who allocas it */
|
||||
if (vector->lock)
|
||||
os_mutex_lock(vector->lock);
|
||||
|
||||
if (!extend_vector(vector, vector->num_elems + 1)) {
|
||||
LOG_ERROR("Append ector elem failed: extend vector failed.\n");
|
||||
return false;
|
||||
goto unlock_return;
|
||||
}
|
||||
|
||||
if (vector->lock)
|
||||
os_mutex_lock(vector->lock);
|
||||
memcpy(vector->data + vector->size_elem * vector->num_elems, elem_buf,
|
||||
vector->size_elem);
|
||||
bh_memcpy_s(vector->data + vector->size_elem * vector->num_elems,
|
||||
vector->size_elem, elem_buf, vector->size_elem);
|
||||
vector->num_elems++;
|
||||
ret = true;
|
||||
|
||||
unlock_return:
|
||||
if (vector->lock)
|
||||
os_mutex_unlock(vector->lock);
|
||||
return true;
|
||||
just_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -218,11 +234,12 @@ bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf)
|
|||
p = vector->data + vector->size_elem * index;
|
||||
|
||||
if (old_elem_buf) {
|
||||
memcpy(old_elem_buf, p, vector->size_elem);
|
||||
bh_memcpy_s(old_elem_buf, vector->size_elem, p, vector->size_elem);
|
||||
}
|
||||
|
||||
for (i = index; i < vector->num_elems - 1; i++) {
|
||||
memcpy(p, p + vector->size_elem, vector->size_elem);
|
||||
bh_memcpy_s(p, vector->size_elem, p + vector->size_elem,
|
||||
vector->size_elem);
|
||||
p += vector->size_elem;
|
||||
}
|
||||
|
||||
|
|
|
@ -148,6 +148,15 @@ Currently we only profile the memory consumption of module, module_instance and
|
|||
- **WAMR_BUILD_DEBUG_INTERP**=1/0, default to 0 if not set
|
||||
> Note: There are some other setup required by source debugging, please refer to [source_debugging.md](./source_debugging.md) for more details.
|
||||
|
||||
#### **Enable load wasm custom sections**
|
||||
- **WAMR_BUILD_LOAD_CUSTOM_SECTION**=1/0, default to disable if not set
|
||||
|
||||
> Note: By default, the custom sections are ignored. If the embedder wants to get custom sections from `wasm_module_t`, then `WAMR_BUILD_LOAD_CUSTOM_SECTION` should be enabled, and then `wasm_runtime_get_custom_section` can be used to get a custom section by name.
|
||||
|
||||
> Note: If `WAMR_BUILD_CUSTOM_NAME_SECTION` is enabled, then the `custom name section` will be treated as a special section and consumed by the runtime, not available to the embedder.
|
||||
|
||||
> For AoT file, must use `--emit-custom-sections` to specify which sections need to be emitted into AoT file, otherwise all custom sections (except custom name section) will be ignored.
|
||||
|
||||
**Combination of configurations:**
|
||||
|
||||
We can combine the configurations. For example, if we want to disable interpreter, enable AOT and WASI, we can run command:
|
||||
|
@ -216,7 +225,7 @@ To run an AOT file, firstly please refer to [Build wamrc AOT compiler](../README
|
|||
wamrc -o <AOT file> <WASM file>
|
||||
iwasm <AOT file>
|
||||
```
|
||||
|
||||
|
||||
To enable the `JIT` mode, firstly we should build LLVM:
|
||||
|
||||
``` Bash
|
||||
|
@ -246,7 +255,7 @@ cd build
|
|||
cmake .. -DWAMR_BUILD_FAST_INTERP=0
|
||||
make
|
||||
```
|
||||
|
||||
|
||||
Linux SGX (Intel Software Guard Extension)
|
||||
-------------------------
|
||||
|
||||
|
@ -546,14 +555,14 @@ WAMR is intergrated with NuttX, just enable the WAMR in Kconfig option (Applicat
|
|||
|
||||
ESP-IDF
|
||||
-------------------------
|
||||
WAMR integrates with ESP-IDF both for the XTENSA and RISC-V chips (esp32x and esp32c3 respectively).
|
||||
WAMR integrates with ESP-IDF both for the XTENSA and RISC-V chips (esp32x and esp32c3 respectively).
|
||||
|
||||
In order to use this, you need at least version 4.3.1 of ESP-IDF.
|
||||
If you don't have it installed, follow the instructions [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/#get-started-get-prerequisites).
|
||||
ESP-IDF also installs the toolchains needed for compiling WAMR and ESP-IDF.
|
||||
A small demonstration of how to use WAMR and ESP-IDF can be found under [product_mini](/product-mini/platforms/esp-idf).
|
||||
The demo builds WAMR for ESP-IDF and runs a small wasm program.
|
||||
In order to run it for your specific Espressif chip, edit the ['build.sh'](/product-mini/platforms/esp-idf/build.sh) file and put the correct toolchain file (see #Cross-compilation) and `IDF_TARGET`.
|
||||
The demo builds WAMR for ESP-IDF and runs a small wasm program.
|
||||
In order to run it for your specific Espressif chip, edit the ['build_and_run.sh'](/product-mini/platforms/esp-idf/build_and_run.sh) file and put the correct toolchain file (see #Cross-compilation) and `IDF_TARGET`.
|
||||
Before compiling it is also necessary to call ESP-IDF's `export.sh` script to bring all compile time relevant information in scope.
|
||||
|
||||
Docker
|
||||
|
|
|
@ -330,6 +330,36 @@ Examples: wamrc -o test.aot test.wasm
|
|||
wamrc --target=i386 --format=object -o test.o test.wasm
|
||||
```
|
||||
|
||||
## AoT compilation with 3rd-party toolchains
|
||||
|
||||
`wamrc` uses LLVM to compile wasm bytecode to AoT file, this works for most of the architectures, but there may be circumstances where you want to use 3rd-party toolchains to take over some steps of the compilation pipeline, e.g.
|
||||
|
||||
1. The upstream LLVM doesn't support generating object file for your CPU architecture (such as ARC), then we may need some other assembler to do such things.
|
||||
2. You may get some other LLVM-based toolchains which may have better optimizations for the specific target, then you may want your toolchain to take over all optimization steps.
|
||||
|
||||
`wamrc` provides two environment variables to achieve these:
|
||||
- `WAMRC_LLC_COMPILER`
|
||||
|
||||
When specified, `wamrc` will emit the optimized LLVM-IR (.bc) to a file, and invoke `$WAMRC_LLC_COMPILER` with ` -c -O3 ` to generate the object file.
|
||||
|
||||
Optionally, you can use environment variable `WAMRC_LLC_FLAGS` to overwrite the default flags.
|
||||
|
||||
- `WAMRC_ASM_COMPILER`
|
||||
|
||||
When specified, `wamrc` will emit the text based assembly file (.s), and invoke `$WAMRC_ASM_COMPILER` with ` -c -O3 ` to generate the object file.
|
||||
|
||||
Optionally, you can use environment variable `WAMRC_ASM_FLAGS` to overwrite the default flags.
|
||||
|
||||
### Usage example
|
||||
``` bash
|
||||
WAMRC_LLC_COMPILER=<path/to/your/compiler/driver> ./wamrc -o test.aot test.wasm
|
||||
```
|
||||
|
||||
> Note: `wamrc` will verify whether the specified file exists and executable. If verification failed, `wamrc` will report a warning and fallback to normal pipeline. Since the verification is based on file, you **must specify the absolute path to the binary** even if it's in `$PATH`
|
||||
|
||||
> Note: `WAMRC_LLC_COMPILER` has higher priority than `WAMRC_ASM_COMPILER`, if `WAMRC_LLC_COMPILER` is set and verified, then `WAMRC_ASM_COMPILER` will be ignored.
|
||||
|
||||
> Note: the `LLC` and `ASM` in the env name just means this compiler will be used to compile the `LLVM IR file`/`assembly file` to object file, usually passing the compiler driver is the simplest way. (e.g. for LLVM toolchain, you don't need to pass `/usr/bin/llc`, using `/usr/bin/clang` is OK)
|
||||
|
||||
Run WASM app in WAMR mini product build
|
||||
=======================================
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
Embedding WAMR guideline
|
||||
=====================================
|
||||
|
||||
**Note**: All the embedding APIs supported by the runtime are defined under folder [core/iwasm/include](../core/iwasm/include). The API details are available in the header files.
|
||||
**Note**: This document is about how to embed WAMR into C/C++ host applications, for other languages, please refer to: [Embed WAMR into Python](../language-bindings/go), [Embed WAMR into Go](../language-bindings/go).
|
||||
|
||||
All the embedding APIs supported by the runtime are defined under folder [core/iwasm/include](../core/iwasm/include). The API details are available in the header files.
|
||||
|
||||
## Embed WAMR into developer's project
|
||||
|
||||
|
@ -109,7 +111,7 @@ There are several ways to call WASM function:
|
|||
1. Function call with parameters in an array of 32 bits elements and size:
|
||||
|
||||
```c
|
||||
unit32 argv[2];
|
||||
uint32 argv[2];
|
||||
|
||||
/* arguments are always transferred in 32-bit element */
|
||||
argv[0] = 8;
|
||||
|
@ -128,11 +130,11 @@ There are several ways to call WASM function:
|
|||
The parameters are transferred in an array of 32 bits elements. For parameters that occupy 4 or fewer bytes, each parameter can be a single array element. For parameters in types like double or int64, each parameter will take two array elements. The function return value will be sent back in the first one or two elements of the array according to the value type. See the sample code below:
|
||||
|
||||
```c
|
||||
unit32 argv[6];
|
||||
uint32 argv[6];
|
||||
char arg1 = 'a';
|
||||
int arg2 = 10;
|
||||
double arg3 = 1.0;
|
||||
int 64 arg4 = 100;
|
||||
int64 arg4 = 100;
|
||||
double ret;
|
||||
|
||||
argv[0] = arg1;
|
||||
|
@ -160,7 +162,7 @@ The parameters are transferred in an array of 32 bits elements. For parameters t
|
|||
2. Function call with results and arguments both in `wasm_val_t` struct and size:
|
||||
|
||||
```c
|
||||
unit32 num_args = 1, num_results = 1;
|
||||
uint32 num_args = 1, num_results = 1;
|
||||
wasm_val_t args[1], results[1];
|
||||
|
||||
/* set the argument type and value */
|
||||
|
@ -181,7 +183,7 @@ The parameters are transferred in an array of 32 bits elements. For parameters t
|
|||
3. Function call with variant argument support:
|
||||
|
||||
```c
|
||||
unit32 num_args = 1, num_results = 1;
|
||||
uint32 num_args = 1, num_results = 1;
|
||||
wasm_val_t results[1];
|
||||
|
||||
/* call the WASM function */
|
||||
|
@ -238,7 +240,7 @@ uint32_t buffer_for_wasm;
|
|||
|
||||
buffer_for_wasm = wasm_runtime_module_malloc(module_inst, 100, &buffer);
|
||||
if (buffer_for_wasm != 0) {
|
||||
unit32 argv[2];
|
||||
uint32 argv[2];
|
||||
strncpy(buffer, "hello", 100); /* use native address for accessing in runtime */
|
||||
argv[0] = buffer_for_wasm; /* pass the buffer address for WASM space */
|
||||
argv[1] = 100; /* the size of buffer */
|
||||
|
|
104
language-bindings/go/README.md
Normal file
104
language-bindings/go/README.md
Normal file
|
@ -0,0 +1,104 @@
|
|||
WAMR Go binding: Embedding WAMR in Go guideline
|
||||
===============================================
|
||||
|
||||
This Go library uses CGO to consume the runtime APIs of the WAMR project which are defined in [core/iwasm/include/wasm_export.h](../../core/iwasm/include/wasm_export.h). The API details are available in the header files.
|
||||
|
||||
## Installation
|
||||
|
||||
### Installing from the source code
|
||||
|
||||
Installing from local source tree is in _development mode_.
|
||||
|
||||
Run `./build.sh` in this folder to build the package, which builds the WAMR runtime library firstly and then builds the Go binding library.
|
||||
|
||||
Run `./build.sh` under `samples` folder to build and test the sample.
|
||||
|
||||
```bash
|
||||
cd samples
|
||||
./build.sh
|
||||
```
|
||||
|
||||
## Supported APIs
|
||||
|
||||
All the embedding APIs supported are defined under folder [wamr](./wamr).
|
||||
|
||||
### Runtime APIs
|
||||
|
||||
```Go
|
||||
func Runtime() *_Runtime
|
||||
func (self *_Runtime) FullInit(alloc_with_pool bool, heap_buf []byte,
|
||||
max_thread_num uint) error
|
||||
func (self *_Runtime) Init() error
|
||||
func (self *_Runtime) Destroy()
|
||||
func (self *_Runtime) SetLogLevel(level LogLevel)
|
||||
func (self *_Runtime) Malloc(size uint32) *uint8
|
||||
func (self *_Runtime) Free(ptr *uint8)
|
||||
```
|
||||
|
||||
### Module APIs
|
||||
|
||||
```Go
|
||||
func NewModule(wasmBytes []byte) (*Module, error)
|
||||
func (self *Module) Destroy()
|
||||
func (self *Module) SetWasiArgs(dirList [][]byte, mapDirList [][]byte,
|
||||
env [][]byte, argv[][]byte)
|
||||
func (self *Module) SetWasiArgsEx(dirList [][]byte, mapDirList [][]byte,
|
||||
env [][]byte, argv[][]byte,
|
||||
stdinfd int, stdoutfd int, stderrfd int)
|
||||
func (self *Module) SetWasiAddrPool(addrPool [][]byte)
|
||||
```
|
||||
|
||||
### Instance APIs
|
||||
|
||||
```Go
|
||||
func NewInstance(module *Module,
|
||||
stackSize uint, heapSize uint) (*Instance, error)
|
||||
func (self *Instance) Destroy()
|
||||
func (self *Instance) CallFunc(funcName string,
|
||||
argc uint32, args []uint32) error
|
||||
func (self *Instance) CallFuncV(funcName string,
|
||||
num_results uint32, results []interface{},
|
||||
args ... interface{}) error
|
||||
func (self *Instance) GetException() string
|
||||
func (self Instance) ModuleMalloc(size uint32) (uint32, *uint8)
|
||||
func (self Instance) ModuleFree(offset uint32)
|
||||
func (self Instance) ValidateAppAddr(app_offset uint32, size uint32) bool
|
||||
func (self Instance) ValidateNativeAddr(native_ptr *uint8, size uint32) bool
|
||||
func (self Instance) AddrAppToNative(app_offset uint32) *uint8
|
||||
func (self Instance) AddrNativeToApp(native_ptr *uint8) uint32
|
||||
func (self Instance) GetAppAddrRange(app_offset uint32) (bool, uint32, uint32)
|
||||
func (self Instance) GetNativeAddrRange(native_ptr *uint8) (bool, *uint8, *uint8)
|
||||
func (self Instance) DumpMemoryConsumption()
|
||||
func (self Instance) DumpCallStack()
|
||||
```
|
||||
|
||||
## Sample codes
|
||||
|
||||
```Go
|
||||
var module *wamr.Module
|
||||
var instance *wamr.Instance
|
||||
var results []interface{}
|
||||
var err error
|
||||
|
||||
/* Runtime initialization */
|
||||
err = wamr.Runtime().FullInit(false, nil, 1)
|
||||
|
||||
/* Read WASM/AOT file into a memory buffer */
|
||||
wasmBytes := read_wasm_binary_to_buffer(...)
|
||||
|
||||
/* Load WASM/AOT module from the memory buffer */
|
||||
module, err = wamr.NewModule(wasmBytes)
|
||||
|
||||
/* Create WASM/AOT instance from the module */
|
||||
instance, err = wamr.NewInstance(module, 16384, 16384)
|
||||
|
||||
/* Call the `fib` function */
|
||||
results = make([]interface{}, 1, 1)
|
||||
err = instance.CallFuncV("fib", 1, results, (int32)32)
|
||||
fmt.Printf("fib(32) return: %d\n", results[0].(int32));
|
||||
|
||||
/* Destroy runtime */
|
||||
wamr.Runtime().Destroy()
|
||||
```
|
||||
|
||||
More samples can be found in [test.go](./samples/test.go)
|
21
language-bindings/go/build.sh
Executable file
21
language-bindings/go/build.sh
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
PLATFORM=$(uname -s | tr A-Z a-z)
|
||||
CUR_DIR=$PWD
|
||||
WAMR_DIR=$PWD/../..
|
||||
WAMR_GO_DIR=$PWD/wamr
|
||||
|
||||
cp -a ${WAMR_DIR}/core/iwasm/include/*.h ${WAMR_GO_DIR}/packaged/include
|
||||
|
||||
mkdir -p build && cd build
|
||||
cmake ${WAMR_DIR}/product-mini/platforms/${PLATFORM} \
|
||||
-DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 \
|
||||
-DWAMR_BUILD_MEMORY_PROFILING=1
|
||||
make -j ${nproc}
|
||||
cp -a libvmlib.a ${WAMR_GO_DIR}/packaged/lib/${PLATFORM}-amd64
|
||||
|
||||
cd ${WAMR_GO_DIR}
|
||||
go test
|
5
language-bindings/go/go.mod
Normal file
5
language-bindings/go/go.mod
Normal file
|
@ -0,0 +1,5 @@
|
|||
module gitlab.alipay-inc.com/TNT_Runtime/ant-runtime/bindings/go
|
||||
|
||||
go 1.15
|
||||
|
||||
require github.com/stretchr/testify v1.7.0
|
10
language-bindings/go/go.sum
Normal file
10
language-bindings/go/go.sum
Normal file
|
@ -0,0 +1,10 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
23
language-bindings/go/samples/build.sh
Executable file
23
language-bindings/go/samples/build.sh
Executable file
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
PLATFORM=$(uname -s | tr A-Z a-z)
|
||||
CUR_DIR=$PWD
|
||||
WAMR_DIR=$PWD/../../..
|
||||
WAMR_GO_DIR=$PWD/../wamr
|
||||
|
||||
cp -a ${WAMR_DIR}/core/iwasm/include/*.h ${WAMR_GO_DIR}/packaged/include
|
||||
|
||||
mkdir -p build && cd build
|
||||
cmake ${WAMR_DIR}/product-mini/platforms/${PLATFORM} \
|
||||
-DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 \
|
||||
-DWAMR_BUILD_MEMORY_PROFILING=1
|
||||
make -j ${nproc}
|
||||
cp -a libvmlib.a ${WAMR_GO_DIR}/packaged/lib/${PLATFORM}-amd64
|
||||
|
||||
cd ${CUR_DIR}
|
||||
rm -f test
|
||||
go build test.go
|
||||
./test
|
7
language-bindings/go/samples/run.sh
Executable file
7
language-bindings/go/samples/run.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
go build test.go
|
||||
./test
|
235
language-bindings/go/samples/test.go
Normal file
235
language-bindings/go/samples/test.go
Normal file
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"gitlab.alipay-inc.com/TNT_Runtime/ant-runtime/bindings/go/wamr"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var wasmBytes = []byte {
|
||||
0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x29, 0x07, 0x60,
|
||||
0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x01,
|
||||
0x7F, 0x00, 0x60, 0x04, 0x7F, 0x7E, 0x7D, 0x7C, 0x00, 0x60, 0x02, 0x7E,
|
||||
0x7E, 0x01, 0x7E, 0x60, 0x02, 0x7C, 0x7F, 0x01, 0x7D, 0x60, 0x02, 0x7D,
|
||||
0x7C, 0x01, 0x7C, 0x02, 0x31, 0x04, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x70,
|
||||
0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x04,
|
||||
0x70, 0x75, 0x74, 0x73, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D,
|
||||
0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x04,
|
||||
0x66, 0x72, 0x65, 0x65, 0x00, 0x02, 0x03, 0x07, 0x06, 0x00, 0x03, 0x04,
|
||||
0x06, 0x05, 0x01, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x13, 0x03, 0x7F,
|
||||
0x01, 0x41, 0x90, 0x29, 0x0B, 0x7F, 0x00, 0x41, 0x90, 0x09, 0x0B, 0x7F,
|
||||
0x00, 0x41, 0x90, 0x29, 0x0B, 0x07, 0x5F, 0x09, 0x06, 0x6D, 0x65, 0x6D,
|
||||
0x6F, 0x72, 0x79, 0x02, 0x00, 0x04, 0x66, 0x69, 0x62, 0x32, 0x00, 0x04,
|
||||
0x05, 0x74, 0x65, 0x73, 0x74, 0x31, 0x00, 0x05, 0x05, 0x74, 0x65, 0x73,
|
||||
0x74, 0x32, 0x00, 0x06, 0x05, 0x74, 0x65, 0x73, 0x74, 0x33, 0x00, 0x07,
|
||||
0x05, 0x74, 0x65, 0x73, 0x74, 0x34, 0x00, 0x08, 0x10, 0x5F, 0x5F, 0x6D,
|
||||
0x61, 0x69, 0x6E, 0x5F, 0x61, 0x72, 0x67, 0x63, 0x5F, 0x61, 0x72, 0x67,
|
||||
0x76, 0x00, 0x09, 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x65,
|
||||
0x6E, 0x64, 0x03, 0x01, 0x0B, 0x5F, 0x5F, 0x68, 0x65, 0x61, 0x70, 0x5F,
|
||||
0x62, 0x61, 0x73, 0x65, 0x03, 0x02, 0x0A, 0xA5, 0x03, 0x06, 0x37, 0x01,
|
||||
0x01, 0x7F, 0x41, 0x01, 0x21, 0x01, 0x20, 0x00, 0x41, 0x02, 0x4F, 0x04,
|
||||
0x7F, 0x41, 0x00, 0x21, 0x01, 0x03, 0x40, 0x20, 0x00, 0x41, 0x02, 0x6B,
|
||||
0x10, 0x04, 0x20, 0x01, 0x6A, 0x21, 0x01, 0x20, 0x00, 0x41, 0x01, 0x6B,
|
||||
0x22, 0x00, 0x41, 0x01, 0x4B, 0x0D, 0x00, 0x0B, 0x20, 0x01, 0x41, 0x01,
|
||||
0x6A, 0x05, 0x41, 0x01, 0x0B, 0x0B, 0x3F, 0x01, 0x01, 0x7F, 0x23, 0x00,
|
||||
0x41, 0x20, 0x6B, 0x22, 0x04, 0x24, 0x00, 0x20, 0x04, 0x41, 0x18, 0x6A,
|
||||
0x20, 0x03, 0x39, 0x03, 0x00, 0x20, 0x04, 0x41, 0x10, 0x6A, 0x20, 0x02,
|
||||
0xBB, 0x39, 0x03, 0x00, 0x20, 0x04, 0x20, 0x01, 0x37, 0x03, 0x08, 0x20,
|
||||
0x04, 0x20, 0x00, 0x36, 0x02, 0x00, 0x41, 0xD0, 0x08, 0x20, 0x04, 0x10,
|
||||
0x00, 0x1A, 0x20, 0x04, 0x41, 0x20, 0x6A, 0x24, 0x00, 0x0B, 0x3B, 0x01,
|
||||
0x01, 0x7F, 0x23, 0x00, 0x41, 0x20, 0x6B, 0x22, 0x02, 0x24, 0x00, 0x20,
|
||||
0x02, 0x20, 0x00, 0x37, 0x03, 0x00, 0x20, 0x02, 0x20, 0x01, 0x37, 0x03,
|
||||
0x08, 0x20, 0x02, 0x41, 0x10, 0x6A, 0x20, 0x00, 0x20, 0x01, 0x7C, 0x22,
|
||||
0x00, 0x37, 0x03, 0x00, 0x41, 0xF6, 0x08, 0x20, 0x02, 0x10, 0x00, 0x1A,
|
||||
0x20, 0x02, 0x41, 0x20, 0x6A, 0x24, 0x00, 0x20, 0x00, 0x0B, 0x40, 0x02,
|
||||
0x01, 0x7F, 0x01, 0x7C, 0x23, 0x00, 0x41, 0x20, 0x6B, 0x22, 0x02, 0x24,
|
||||
0x00, 0x20, 0x02, 0x20, 0x01, 0x39, 0x03, 0x08, 0x20, 0x02, 0x20, 0x00,
|
||||
0xBB, 0x22, 0x03, 0x39, 0x03, 0x00, 0x20, 0x02, 0x41, 0x10, 0x6A, 0x20,
|
||||
0x03, 0x20, 0x01, 0xA2, 0x22, 0x01, 0x39, 0x03, 0x00, 0x41, 0xB4, 0x08,
|
||||
0x20, 0x02, 0x10, 0x00, 0x1A, 0x20, 0x02, 0x41, 0x20, 0x6A, 0x24, 0x00,
|
||||
0x20, 0x01, 0x0B, 0x3D, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x20, 0x6B,
|
||||
0x22, 0x02, 0x24, 0x00, 0x20, 0x02, 0x20, 0x00, 0x39, 0x03, 0x00, 0x20,
|
||||
0x02, 0x20, 0x01, 0x36, 0x02, 0x08, 0x20, 0x02, 0x41, 0x10, 0x6A, 0x20,
|
||||
0x00, 0x20, 0x01, 0xB7, 0xA3, 0x22, 0x00, 0x39, 0x03, 0x00, 0x41, 0xC2,
|
||||
0x08, 0x20, 0x02, 0x10, 0x00, 0x1A, 0x20, 0x02, 0x41, 0x20, 0x6A, 0x24,
|
||||
0x00, 0x20, 0x00, 0xB6, 0x0B, 0x70, 0x00, 0x23, 0x00, 0x41, 0x20, 0x6B,
|
||||
0x22, 0x00, 0x24, 0x00, 0x41, 0x9A, 0x08, 0x10, 0x01, 0x1A, 0x02, 0x7F,
|
||||
0x41, 0x80, 0x08, 0x10, 0x02, 0x22, 0x01, 0x45, 0x04, 0x40, 0x41, 0x88,
|
||||
0x08, 0x10, 0x01, 0x1A, 0x41, 0x7F, 0x0C, 0x01, 0x0B, 0x20, 0x00, 0x20,
|
||||
0x01, 0x36, 0x02, 0x10, 0x41, 0xA7, 0x08, 0x20, 0x00, 0x41, 0x10, 0x6A,
|
||||
0x10, 0x00, 0x1A, 0x20, 0x01, 0x41, 0x04, 0x6A, 0x41, 0x8E, 0x09, 0x2F,
|
||||
0x00, 0x00, 0x3B, 0x00, 0x00, 0x20, 0x01, 0x41, 0x8A, 0x09, 0x28, 0x00,
|
||||
0x00, 0x36, 0x00, 0x00, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x00, 0x41,
|
||||
0x80, 0x08, 0x20, 0x00, 0x10, 0x00, 0x1A, 0x20, 0x01, 0x10, 0x03, 0x41,
|
||||
0x00, 0x0B, 0x20, 0x00, 0x41, 0x20, 0x6A, 0x24, 0x00, 0x0B, 0x0B, 0x97,
|
||||
0x01, 0x01, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x8F, 0x01, 0x62, 0x75, 0x66,
|
||||
0x3A, 0x20, 0x25, 0x73, 0x00, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x20,
|
||||
0x62, 0x75, 0x66, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x00, 0x48,
|
||||
0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00,
|
||||
0x62, 0x75, 0x66, 0x20, 0x70, 0x74, 0x72, 0x3A, 0x20, 0x25, 0x70, 0x0A,
|
||||
0x00, 0x25, 0x66, 0x20, 0x2A, 0x20, 0x25, 0x66, 0x20, 0x3D, 0x20, 0x25,
|
||||
0x66, 0x0A, 0x00, 0x25, 0x66, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x20, 0x3D,
|
||||
0x20, 0x25, 0x66, 0x0A, 0x00, 0x69, 0x33, 0x32, 0x3A, 0x20, 0x25, 0x64,
|
||||
0x2C, 0x20, 0x69, 0x36, 0x34, 0x3A, 0x20, 0x25, 0x6C, 0x6C, 0x64, 0x2C,
|
||||
0x20, 0x66, 0x33, 0x32, 0x3A, 0x20, 0x25, 0x66, 0x2C, 0x20, 0x66, 0x36,
|
||||
0x34, 0x3A, 0x20, 0x25, 0x66, 0x0A, 0x00, 0x25, 0x6C, 0x6C, 0x64, 0x20,
|
||||
0x2B, 0x20, 0x25, 0x6C, 0x6C, 0x64, 0x20, 0x3D, 0x20, 0x25, 0x6C, 0x6C,
|
||||
0x64, 0x0A, 0x00, 0x31, 0x32, 0x33, 0x34, 0x0A }
|
||||
|
||||
var global_heap []byte = make([]byte, 128 * 1024, 128 * 1024)
|
||||
|
||||
func main() {
|
||||
var module *wamr.Module
|
||||
var instance *wamr.Instance
|
||||
var argv []uint32
|
||||
var results []interface{}
|
||||
var offset uint32
|
||||
var native_addr *uint8
|
||||
var err error
|
||||
|
||||
fmt.Print("Init wasm runtime with global heap buf\n");
|
||||
err = wamr.Runtime().FullInit(true, global_heap, 1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Print("Destroy runtime\n");
|
||||
wamr.Runtime().Destroy()
|
||||
|
||||
fmt.Print("Init wasm runtime without global heap buf\n");
|
||||
err = wamr.Runtime().FullInit(false, nil, 1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
wamr.Runtime().SetLogLevel(wamr.LOG_LEVEL_WARNING)
|
||||
|
||||
fmt.Print("Load wasm module\n");
|
||||
module, err = wamr.NewModule(wasmBytes)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
goto fail
|
||||
}
|
||||
|
||||
fmt.Print("Instantiate wasm module\n");
|
||||
instance, err = wamr.NewInstance(module, 16384, 16384)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
goto fail
|
||||
}
|
||||
|
||||
results = make([]interface{}, 8, 8)
|
||||
argv = make([]uint32, 8)
|
||||
|
||||
fmt.Print("\nCall func __main_argc_argv with CallFunc:\n");
|
||||
err = instance.CallFunc("__main_argc_argv", 2, argv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
goto fail
|
||||
}
|
||||
|
||||
fmt.Print("\nCall func __main_argc_argv with CallFuncV:\n");
|
||||
err = instance.CallFuncV("__main_argc_argv", 2, results,
|
||||
(int32)(0), (int32)(0))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
goto fail
|
||||
}
|
||||
|
||||
fmt.Print("\nCall func `i32 fib2(i32)` with CallFunc:\n");
|
||||
argv[0] = 32
|
||||
err = instance.CallFunc("fib2", 1, argv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
goto fail
|
||||
}
|
||||
fmt.Printf("fib2(32) return: %d\n", argv[0]);
|
||||
|
||||
fmt.Print("\nCall func `void test1(i32, i64, f32, f64)` with CallFuncV:\n");
|
||||
err = instance.CallFuncV("test1", 0, nil,
|
||||
(int32)(12345678),
|
||||
(int64)(3344556677889900),
|
||||
(float32)(5678.1234),
|
||||
(float64)(987654321.5678))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
goto fail
|
||||
}
|
||||
|
||||
fmt.Print("\nCall func `i64 test2(i64, i64)` with CallFuncV:\n");
|
||||
err = instance.CallFuncV("test2", 1, results,
|
||||
(int64)(3344556677889900),
|
||||
(int64)(1122331122110099))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
goto fail
|
||||
}
|
||||
fmt.Printf("test2(3344556677889900, 1122331122110099) return: %d\n",
|
||||
results[0].(int64))
|
||||
|
||||
fmt.Print("\nCall func `f64 test3(f32, f64)` with CallFuncV:\n");
|
||||
err = instance.CallFuncV("test3", 1, results,
|
||||
(float32)(3456.1234),
|
||||
(float64)(7890.4567))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
goto fail
|
||||
}
|
||||
fmt.Printf("test3(3456.1234, 7890.4567) return: %f\n",
|
||||
results[0].(float64))
|
||||
|
||||
fmt.Print("\nCall func `f32 test4(f64, i32)` with CallFuncV:\n");
|
||||
err = instance.CallFuncV("test4", 1, results,
|
||||
(float64)(8912.3456),
|
||||
(int32)(123))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
goto fail
|
||||
}
|
||||
fmt.Printf("test4(8912.3456, 123) return: %f\n",
|
||||
results[0].(float32))
|
||||
|
||||
fmt.Print("\nTest ModuleMalloc")
|
||||
offset, native_addr = instance.ModuleMalloc(1024)
|
||||
fmt.Printf("ModuleMalloc(%d) return offset: %d, native addr: %p\n",
|
||||
1024, offset, native_addr)
|
||||
|
||||
if (!instance.ValidateAppAddr(offset, 1024)) {
|
||||
fmt.Print("Validate app addr failed\n")
|
||||
}
|
||||
if (!instance.ValidateNativeAddr(native_addr, 1024)) {
|
||||
fmt.Print("Validate native addr failed\n")
|
||||
}
|
||||
if (native_addr != instance.AddrAppToNative(offset)) {
|
||||
fmt.Print("Convert app addr to native addr failed\n")
|
||||
}
|
||||
if (offset != instance.AddrNativeToApp(native_addr)) {
|
||||
fmt.Print("Convert app addr to native addr failed\n")
|
||||
}
|
||||
|
||||
instance.ModuleFree(offset)
|
||||
|
||||
/*
|
||||
instance.DumpMemoryConsumption()
|
||||
instance.DumpCallStack()
|
||||
*/
|
||||
|
||||
fmt.Print("\n");
|
||||
|
||||
fail:
|
||||
if (instance != nil) {
|
||||
fmt.Print("Destroy instance\n");
|
||||
instance.Destroy()
|
||||
}
|
||||
|
||||
if (module != nil) {
|
||||
fmt.Print("Destroy module\n");
|
||||
module.Destroy()
|
||||
}
|
||||
|
||||
fmt.Print("Destroy wasm runtime\n");
|
||||
wamr.Runtime().Destroy()
|
||||
}
|
32
language-bindings/go/samples/wasm-app/build.sh
Executable file
32
language-bindings/go/samples/wasm-app/build.sh
Executable file
|
@ -0,0 +1,32 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
WAMR_DIR=${PWD}/../../..
|
||||
|
||||
echo "Build wasm app .."
|
||||
/opt/wasi-sdk/bin/clang -O3 \
|
||||
-z stack-size=4096 -Wl,--initial-memory=65536 \
|
||||
-o test.wasm main.c \
|
||||
-Wl,--export=main -Wl,--export=__main_argc_argv \
|
||||
-Wl,--export=fib2 \
|
||||
-Wl,--export=test1 \
|
||||
-Wl,--export=test2 \
|
||||
-Wl,--export=test3 \
|
||||
-Wl,--export=test4 \
|
||||
-Wl,--export=__data_end -Wl,--export=__heap_base \
|
||||
-Wl,--strip-all,--no-entry \
|
||||
-Wl,--allow-undefined \
|
||||
-nostdlib \
|
||||
|
||||
echo "Build binarydump tool .."
|
||||
rm -fr build && mkdir build && cd build
|
||||
cmake ../../../../../test-tools/binarydump-tool
|
||||
make
|
||||
cd ..
|
||||
|
||||
echo "Generate test_wasm.h .."
|
||||
./build/binarydump -o test_wasm.h -n wasm_test_file test.wasm
|
||||
|
||||
rm -fr build
|
||||
|
||||
echo "Done"
|
65
language-bindings/go/samples/wasm-app/main.c
Normal file
65
language-bindings/go/samples/wasm-app/main.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned
|
||||
fib2(unsigned n)
|
||||
{
|
||||
if (n < 2) {
|
||||
return 1;
|
||||
}
|
||||
return fib2(n - 2) + fib2(n - 1);
|
||||
}
|
||||
|
||||
void
|
||||
test1(int32_t i32, int64_t i64, float f32, double f64)
|
||||
{
|
||||
printf("i32: %d, i64: %lld, f32: %f, f64: %f\n", i32, i64, f32, f64);
|
||||
}
|
||||
|
||||
int64_t
|
||||
test2(int64_t x, int64_t y)
|
||||
{
|
||||
printf("%lld + %lld = %lld\n", x, y, x + y);
|
||||
return x + y;
|
||||
}
|
||||
|
||||
double
|
||||
test3(float x, double y)
|
||||
{
|
||||
printf("%f * %f = %f\n", x, y, x * y);
|
||||
return x * y;
|
||||
}
|
||||
|
||||
float
|
||||
test4(double x, int32_t y)
|
||||
{
|
||||
printf("%f / %d = %f\n", x, y, x / y);
|
||||
return x / y;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
printf("Hello world!\n");
|
||||
|
||||
buf = malloc(1024);
|
||||
if (!buf) {
|
||||
printf("malloc buf failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("buf ptr: %p\n", buf);
|
||||
|
||||
snprintf(buf, 1024, "%s", "1234\n");
|
||||
printf("buf: %s", buf);
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
20
language-bindings/go/wamr/cgo.go
Normal file
20
language-bindings/go/wamr/cgo.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package wamr
|
||||
|
||||
// #cgo CFLAGS: -I${SRCDIR}/packaged/include
|
||||
// #cgo LDFLAGS: -lvmlib -lm
|
||||
//
|
||||
// #cgo linux,amd64 LDFLAGS: -Wl,-rpath,${SRCDIR}/packaged/lib/linux-amd64 -L${SRCDIR}/packaged/lib/linux-amd64
|
||||
// #cgo linux,arm64 LDFLAGS: -Wl,-rpath,${SRCDIR}/packaged/lib/linux-aarch64 -L${SRCDIR}/packaged/lib/linux-aarch64
|
||||
// #cgo darwin,amd64 LDFLAGS: -Wl,-rpath,${SRCDIR}/packaged/lib/darwin-amd64 -L${SRCDIR}/packaged/lib/darwin-amd64
|
||||
// #cgo darwin,arm64 LDFLAGS: -Wl,-rpath,${SRCDIR}/packaged/lib/darwin-aarch64 -L${SRCDIR}/packaged/lib/darwin-aarch64
|
||||
//
|
||||
// #include <wasm_export.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
)
|
385
language-bindings/go/wamr/instance.go
Normal file
385
language-bindings/go/wamr/instance.go
Normal file
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package wamr
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <wasm_export.h>
|
||||
|
||||
static inline void
|
||||
PUT_I64_TO_ADDR(uint32_t *addr, int64_t value)
|
||||
{
|
||||
union {
|
||||
int64_t val;
|
||||
uint32_t parts[2];
|
||||
} u;
|
||||
u.val = value;
|
||||
addr[0] = u.parts[0];
|
||||
addr[1] = u.parts[1];
|
||||
}
|
||||
|
||||
static inline void
|
||||
PUT_F64_TO_ADDR(uint32_t *addr, double value)
|
||||
{
|
||||
union {
|
||||
double val;
|
||||
uint32_t parts[2];
|
||||
} u;
|
||||
u.val = value;
|
||||
addr[0] = u.parts[0];
|
||||
addr[1] = u.parts[1];
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
GET_I64_FROM_ADDR(uint32_t *addr)
|
||||
{
|
||||
union {
|
||||
int64_t val;
|
||||
uint32_t parts[2];
|
||||
} u;
|
||||
u.parts[0] = addr[0];
|
||||
u.parts[1] = addr[1];
|
||||
return u.val;
|
||||
}
|
||||
|
||||
static inline double
|
||||
GET_F64_FROM_ADDR(uint32_t *addr)
|
||||
{
|
||||
union {
|
||||
double val;
|
||||
uint32_t parts[2];
|
||||
} u;
|
||||
u.parts[0] = addr[0];
|
||||
u.parts[1] = addr[1];
|
||||
return u.val;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Instance struct {
|
||||
_instance C.wasm_module_inst_t
|
||||
_exec_env C.wasm_exec_env_t
|
||||
_module *Module
|
||||
_exportsCache map[string]C.wasm_function_inst_t
|
||||
}
|
||||
|
||||
/* Create instance from the module */
|
||||
func NewInstance(module *Module,
|
||||
stackSize uint, heapSize uint) (*Instance, error) {
|
||||
if (module == nil) {
|
||||
return nil, fmt.Errorf("NewInstance error: invalid input")
|
||||
}
|
||||
|
||||
errorBytes := make([]byte, 128)
|
||||
errorPtr := (*C.char)(unsafe.Pointer(&errorBytes[0]))
|
||||
errorLen := C.uint(len(errorBytes))
|
||||
|
||||
instance := C.wasm_runtime_instantiate(module.module, C.uint(stackSize),
|
||||
C.uint(heapSize), errorPtr, errorLen)
|
||||
if (instance == nil) {
|
||||
return nil, fmt.Errorf("NewInstance Error: %s", string(errorBytes))
|
||||
}
|
||||
|
||||
exec_env := C.wasm_runtime_create_exec_env(instance, C.uint(stackSize))
|
||||
if (exec_env == nil) {
|
||||
C.wasm_runtime_deinstantiate(instance)
|
||||
return nil, fmt.Errorf("NewInstance Error: create exec_env failed")
|
||||
}
|
||||
|
||||
self := &Instance{
|
||||
_instance: instance,
|
||||
_exec_env: exec_env,
|
||||
_module: module,
|
||||
_exportsCache: make(map[string]C.wasm_function_inst_t),
|
||||
}
|
||||
|
||||
runtime.SetFinalizer(self, func(self *Instance) {
|
||||
self.Destroy()
|
||||
})
|
||||
|
||||
return self, nil
|
||||
}
|
||||
|
||||
/* Destroy the instance */
|
||||
func (self *Instance) Destroy() {
|
||||
runtime.SetFinalizer(self, nil)
|
||||
if (self._instance != nil) {
|
||||
C.wasm_runtime_deinstantiate(self._instance)
|
||||
}
|
||||
if (self._exec_env != nil) {
|
||||
C.wasm_runtime_destroy_exec_env(self._exec_env)
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the wasm function with argument in the uint32 array, and store
|
||||
the return values back into the array */
|
||||
func (self *Instance) CallFunc(funcName string,
|
||||
argc uint32, args []uint32) error {
|
||||
_func := self._exportsCache[funcName]
|
||||
if _func == nil {
|
||||
cName := C.CString(funcName)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
|
||||
_func = C.wasm_runtime_lookup_function(self._instance,
|
||||
cName, (*C.char)(C.NULL))
|
||||
if _func == nil {
|
||||
return fmt.Errorf("CallFunc error: lookup function failed")
|
||||
}
|
||||
self._exportsCache[funcName] = _func
|
||||
}
|
||||
|
||||
thread_env_inited := Runtime().ThreadEnvInited()
|
||||
if (!thread_env_inited) {
|
||||
Runtime().InitThreadEnv()
|
||||
}
|
||||
|
||||
var args_C *C.uint32_t
|
||||
if (argc > 0) {
|
||||
args_C = (*C.uint32_t)(unsafe.Pointer(&args[0]))
|
||||
}
|
||||
if (!C.wasm_runtime_call_wasm(self._exec_env, _func,
|
||||
C.uint(argc), args_C)) {
|
||||
if (!thread_env_inited) {
|
||||
Runtime().DestroyThreadEnv()
|
||||
}
|
||||
return fmt.Errorf("CallFunc error: %s", string(self.GetException()))
|
||||
}
|
||||
|
||||
if (!thread_env_inited) {
|
||||
Runtime().DestroyThreadEnv()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* Call the wasm function with variant arguments, and store the return
|
||||
values back into the results array */
|
||||
func (self *Instance) CallFuncV(funcName string,
|
||||
num_results uint32, results []interface{},
|
||||
args ... interface{}) error {
|
||||
_func := self._exportsCache[funcName]
|
||||
if _func == nil {
|
||||
cName := C.CString(funcName)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
|
||||
_func = C.wasm_runtime_lookup_function(self._instance,
|
||||
cName, (*C.char)(C.NULL))
|
||||
if _func == nil {
|
||||
return fmt.Errorf("CallFunc error: lookup function failed")
|
||||
}
|
||||
self._exportsCache[funcName] = _func
|
||||
}
|
||||
|
||||
param_count := uint32(C.wasm_func_get_param_count(_func, self._instance))
|
||||
result_count := uint32(C.wasm_func_get_result_count(_func, self._instance))
|
||||
|
||||
if (num_results < result_count) {
|
||||
str := "CallFunc error: invalid result count %d, " +
|
||||
"must be no smaller than %d"
|
||||
return fmt.Errorf(str, num_results, result_count)
|
||||
}
|
||||
|
||||
param_types := make([]C.uchar, param_count, param_count)
|
||||
result_types := make([]C.uchar, result_count, result_count)
|
||||
if (param_count > 0) {
|
||||
C.wasm_func_get_param_types(_func, self._instance,
|
||||
(*C.uchar)(unsafe.Pointer(¶m_types[0])))
|
||||
}
|
||||
if (result_count > 0) {
|
||||
C.wasm_func_get_result_types(_func, self._instance,
|
||||
(*C.uchar)(unsafe.Pointer(&result_types[0])))
|
||||
}
|
||||
|
||||
argv_size := param_count * 2
|
||||
if (result_count > param_count) {
|
||||
argv_size = result_count * 2
|
||||
}
|
||||
argv := make([]uint32, argv_size, argv_size)
|
||||
|
||||
var i, argc uint32
|
||||
for _, arg := range args {
|
||||
if (i >= param_count) {
|
||||
break;
|
||||
}
|
||||
switch arg.(type) {
|
||||
case int32:
|
||||
if (param_types[i] != C.WASM_I32 &&
|
||||
param_types[i] != C.WASM_FUNCREF &&
|
||||
param_types[i] != C.WASM_ANYREF) {
|
||||
str := "CallFunc error: invalid param type %d, " +
|
||||
"expect i32 but got other"
|
||||
return fmt.Errorf(str, param_types[i])
|
||||
}
|
||||
argv[argc] = (uint32)(arg.(int32))
|
||||
argc++
|
||||
break
|
||||
case int64:
|
||||
if (param_types[i] != C.WASM_I64) {
|
||||
str := "CallFunc error: invalid param type %d, " +
|
||||
"expect i64 but got other"
|
||||
return fmt.Errorf(str, param_types[i])
|
||||
}
|
||||
addr := (*C.uint32_t)(unsafe.Pointer(&argv[argc]))
|
||||
C.PUT_I64_TO_ADDR(addr, (C.int64_t)(arg.(int64)))
|
||||
argc += 2
|
||||
break
|
||||
case float32:
|
||||
if (param_types[i] != C.WASM_F32) {
|
||||
str := "CallFunc error: invalid param type %d, " +
|
||||
"expect f32 but got other"
|
||||
return fmt.Errorf(str, param_types[i])
|
||||
}
|
||||
*(*C.float)(unsafe.Pointer(&argv[argc])) = (C.float)(arg.(float32))
|
||||
argc++
|
||||
break
|
||||
case float64:
|
||||
if (param_types[i] != C.WASM_F64) {
|
||||
str := "CallFunc error: invalid param type %d, " +
|
||||
"expect f64 but got other"
|
||||
return fmt.Errorf(str, param_types[i])
|
||||
}
|
||||
addr := (*C.uint32_t)(unsafe.Pointer(&argv[argc]))
|
||||
C.PUT_F64_TO_ADDR(addr, (C.double)(arg.(float64)))
|
||||
argc += 2
|
||||
break
|
||||
default:
|
||||
return fmt.Errorf("CallFunc error: unknown param type %d",
|
||||
param_types[i])
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if (i < param_count) {
|
||||
str := "CallFunc error: invalid param count, " +
|
||||
"must be no smaller than %d"
|
||||
return fmt.Errorf(str, param_count)
|
||||
}
|
||||
|
||||
err := self.CallFunc(funcName, argc, argv)
|
||||
if (err != nil) {
|
||||
return err
|
||||
}
|
||||
|
||||
argc = 0
|
||||
for i = 0; i < result_count; i++ {
|
||||
switch result_types[i] {
|
||||
case C.WASM_I32:
|
||||
case C.WASM_FUNCREF:
|
||||
case C.WASM_ANYREF:
|
||||
i32 := (int32)(argv[argc])
|
||||
results[i] = i32
|
||||
argc++
|
||||
break
|
||||
case C.WASM_I64:
|
||||
addr := (*C.uint32_t)(unsafe.Pointer(&argv[argc]))
|
||||
results[i] = (int64)(C.GET_I64_FROM_ADDR(addr))
|
||||
argc += 2
|
||||
break
|
||||
case C.WASM_F32:
|
||||
addr := (*C.float)(unsafe.Pointer(&argv[argc]))
|
||||
results[i] = (float32)(*addr)
|
||||
argc++
|
||||
break
|
||||
case C.WASM_F64:
|
||||
addr := (*C.uint32_t)(unsafe.Pointer(&argv[argc]))
|
||||
results[i] = (float64)(C.GET_F64_FROM_ADDR(addr))
|
||||
argc += 2
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/* Get exception info of the instance */
|
||||
func (self *Instance) GetException() string {
|
||||
cStr := C.wasm_runtime_get_exception(self._instance)
|
||||
goStr := C.GoString(cStr)
|
||||
return goStr
|
||||
}
|
||||
|
||||
/* Allocate memory from the heap of the instance */
|
||||
func (self Instance) ModuleMalloc(size uint32) (uint32, *uint8) {
|
||||
var offset C.uint32_t
|
||||
native_addrs := make([]*uint8, 1, 1)
|
||||
ptr := unsafe.Pointer(&native_addrs[0])
|
||||
offset = C.wasm_runtime_module_malloc(self._instance, (C.uint32_t)(size),
|
||||
(*unsafe.Pointer)(ptr))
|
||||
return (uint32)(offset), native_addrs[0]
|
||||
}
|
||||
|
||||
/* Free memory to the heap of the instance */
|
||||
func (self Instance) ModuleFree(offset uint32) {
|
||||
C.wasm_runtime_module_free(self._instance, (C.uint32_t)(offset))
|
||||
}
|
||||
|
||||
func (self Instance) ValidateAppAddr(app_offset uint32, size uint32) bool {
|
||||
ret := C.wasm_runtime_validate_app_addr(self._instance,
|
||||
(C.uint32_t)(app_offset),
|
||||
(C.uint32_t)(size))
|
||||
return (bool)(ret)
|
||||
}
|
||||
|
||||
func (self Instance) ValidateStrAddr(app_str_offset uint32) bool {
|
||||
ret := C.wasm_runtime_validate_app_str_addr(self._instance,
|
||||
(C.uint32_t)(app_str_offset))
|
||||
return (bool)(ret)
|
||||
}
|
||||
|
||||
func (self Instance) ValidateNativeAddr(native_ptr *uint8, size uint32) bool {
|
||||
native_ptr_C := (unsafe.Pointer)(native_ptr)
|
||||
ret := C.wasm_runtime_validate_native_addr(self._instance,
|
||||
native_ptr_C,
|
||||
(C.uint32_t)(size))
|
||||
return (bool)(ret)
|
||||
}
|
||||
|
||||
func (self Instance) AddrAppToNative(app_offset uint32) *uint8 {
|
||||
native_ptr := C.wasm_runtime_addr_app_to_native(self._instance,
|
||||
(C.uint32_t)(app_offset))
|
||||
return (*uint8)(native_ptr)
|
||||
}
|
||||
|
||||
func (self Instance) AddrNativeToApp(native_ptr *uint8) uint32 {
|
||||
native_ptr_C := (unsafe.Pointer)(native_ptr)
|
||||
offset := C.wasm_runtime_addr_native_to_app(self._instance,
|
||||
native_ptr_C)
|
||||
return (uint32)(offset)
|
||||
}
|
||||
|
||||
func (self Instance) GetAppAddrRange(app_offset uint32) (bool,
|
||||
uint32,
|
||||
uint32) {
|
||||
var start_offset, end_offset C.uint32_t
|
||||
ret := C.wasm_runtime_get_app_addr_range(self._instance,
|
||||
(C.uint32_t)(app_offset),
|
||||
&start_offset, &end_offset)
|
||||
return (bool)(ret), (uint32)(start_offset), (uint32)(end_offset)
|
||||
}
|
||||
|
||||
func (self Instance) GetNativeAddrRange(native_ptr *uint8) (bool,
|
||||
*uint8,
|
||||
*uint8) {
|
||||
var start_addr, end_addr *C.uint8_t
|
||||
native_ptr_C := (*C.uint8_t)((unsafe.Pointer)(native_ptr))
|
||||
ret := C.wasm_runtime_get_native_addr_range(self._instance,
|
||||
native_ptr_C,
|
||||
&start_addr, &end_addr)
|
||||
return (bool)(ret), (*uint8)(start_addr), (*uint8)(end_addr)
|
||||
}
|
||||
|
||||
func (self Instance) DumpMemoryConsumption() {
|
||||
C.wasm_runtime_dump_mem_consumption(self._exec_env)
|
||||
}
|
||||
|
||||
func (self Instance) DumpCallStack() {
|
||||
C.wasm_runtime_dump_call_stack(self._exec_env)
|
||||
}
|
19
language-bindings/go/wamr/instance_test.go
Normal file
19
language-bindings/go/wamr/instance_test.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package wamr
|
||||
|
||||
import (
|
||||
//"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestInstance(t *testing.T) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
func TestCallFunc(t *testing.T) {
|
||||
/* TODO */
|
||||
}
|
134
language-bindings/go/wamr/module.go
Normal file
134
language-bindings/go/wamr/module.go
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package wamr
|
||||
|
||||
// #include <wasm_export.h>
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
"runtime"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Module struct {
|
||||
module C.wasm_module_t
|
||||
}
|
||||
|
||||
/* Create WASM/AOT module from the memory buffer */
|
||||
func NewModule(wasmBytes []byte) (*Module, error) {
|
||||
if (wasmBytes == nil || len(wasmBytes) == 0) {
|
||||
return nil, fmt.Errorf("NewModule error: invalid input")
|
||||
}
|
||||
|
||||
wasmPtr := (*C.uint8_t)(unsafe.Pointer(&wasmBytes[0]))
|
||||
wasmLen := C.uint(len(wasmBytes))
|
||||
|
||||
errorBytes := make([]byte, 128)
|
||||
errorPtr := (*C.char)(unsafe.Pointer(&errorBytes[0]))
|
||||
errorLen := C.uint(len(errorBytes))
|
||||
|
||||
m := C.wasm_runtime_load(wasmPtr, wasmLen, errorPtr, errorLen)
|
||||
if (m == nil) {
|
||||
return nil, fmt.Errorf("NewModule error: %s", string(errorBytes))
|
||||
}
|
||||
|
||||
self := &Module{
|
||||
module: m,
|
||||
}
|
||||
|
||||
runtime.SetFinalizer(self, func(self *Module) {
|
||||
self.Destroy()
|
||||
})
|
||||
|
||||
return self, nil
|
||||
}
|
||||
|
||||
/* Destroy the module */
|
||||
func (self *Module) Destroy() {
|
||||
runtime.SetFinalizer(self, nil)
|
||||
if (self.module != nil) {
|
||||
C.wasm_runtime_unload(self.module)
|
||||
}
|
||||
}
|
||||
|
||||
/* Set module's wasi arguments */
|
||||
func (self *Module) SetWasiArgs(dirList [][]byte, mapDirList [][]byte,
|
||||
env [][]byte, argv[][]byte) {
|
||||
var dirPtr, mapDirPtr, envPtr, argvPtr **C.char
|
||||
var dirCount, mapDirCount, envCount C.uint
|
||||
var argc C.int
|
||||
|
||||
if (dirList != nil) {
|
||||
dirPtr = (**C.char)(unsafe.Pointer(&dirList[0]))
|
||||
dirCount = C.uint(len(dirList))
|
||||
}
|
||||
|
||||
if (mapDirList != nil) {
|
||||
mapDirPtr = (**C.char)(unsafe.Pointer(&mapDirList[0]))
|
||||
mapDirCount = C.uint(len(mapDirList))
|
||||
}
|
||||
|
||||
if (env != nil) {
|
||||
envPtr = (**C.char)(unsafe.Pointer(&env[0]))
|
||||
envCount = C.uint(len(env))
|
||||
}
|
||||
|
||||
if (argv != nil) {
|
||||
argvPtr = (**C.char)(unsafe.Pointer(&argv[0]))
|
||||
argc = C.int(len(argv))
|
||||
}
|
||||
|
||||
C.wasm_runtime_set_wasi_args(self.module, dirPtr, dirCount,
|
||||
mapDirPtr, mapDirCount,
|
||||
envPtr, envCount, argvPtr, argc)
|
||||
}
|
||||
|
||||
/* Set module's wasi arguments */
|
||||
func (self *Module) SetWasiArgsEx(dirList [][]byte, mapDirList [][]byte,
|
||||
env [][]byte, argv[][]byte,
|
||||
stdinfd int, stdoutfd int, stderrfd int) {
|
||||
var dirPtr, mapDirPtr, envPtr, argvPtr **C.char
|
||||
var dirCount, mapDirCount, envCount C.uint
|
||||
var argc C.int
|
||||
|
||||
if (dirList != nil) {
|
||||
dirPtr = (**C.char)(unsafe.Pointer(&dirList[0]))
|
||||
dirCount = C.uint(len(dirList))
|
||||
}
|
||||
|
||||
if (mapDirList != nil) {
|
||||
mapDirPtr = (**C.char)(unsafe.Pointer(&mapDirList[0]))
|
||||
mapDirCount = C.uint(len(mapDirList))
|
||||
}
|
||||
|
||||
if (env != nil) {
|
||||
envPtr = (**C.char)(unsafe.Pointer(&env[0]))
|
||||
envCount = C.uint(len(env))
|
||||
}
|
||||
|
||||
if (argv != nil) {
|
||||
argvPtr = (**C.char)(unsafe.Pointer(&argv[0]))
|
||||
argc = C.int(len(argv))
|
||||
}
|
||||
|
||||
C.wasm_runtime_set_wasi_args_ex(self.module, dirPtr, dirCount,
|
||||
mapDirPtr, mapDirCount,
|
||||
envPtr, envCount, argvPtr, argc,
|
||||
C.int(stdinfd), C.int(stdoutfd),
|
||||
C.int(stderrfd))
|
||||
}
|
||||
|
||||
/* Set module's wasi network address pool */
|
||||
func (self *Module) SetWasiAddrPool(addrPool [][]byte) {
|
||||
var addrPoolPtr **C.char
|
||||
var addrPoolSize C.uint
|
||||
|
||||
if (addrPool != nil) {
|
||||
addrPoolPtr = (**C.char)(unsafe.Pointer(&addrPool[0]))
|
||||
addrPoolSize = C.uint(len(addrPool))
|
||||
}
|
||||
C.wasm_runtime_set_wasi_addr_pool(self.module, addrPoolPtr, addrPoolSize)
|
||||
}
|
15
language-bindings/go/wamr/module_test.go
Normal file
15
language-bindings/go/wamr/module_test.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package wamr
|
||||
|
||||
import (
|
||||
//"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestModule(t *testing.T) {
|
||||
/* TODO */
|
||||
}
|
6
language-bindings/go/wamr/packaged/include/dummy.go
Normal file
6
language-bindings/go/wamr/packaged/include/dummy.go
Normal file
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package include
|
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package darwin_amd64
|
6
language-bindings/go/wamr/packaged/lib/dummy.go
Normal file
6
language-bindings/go/wamr/packaged/lib/dummy.go
Normal file
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package lib
|
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package linux_amd64
|
153
language-bindings/go/wamr/runtime.go
Normal file
153
language-bindings/go/wamr/runtime.go
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package wamr
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <wasm_export.h>
|
||||
|
||||
void
|
||||
bh_log_set_verbose_level(uint32_t level);
|
||||
|
||||
bool
|
||||
init_wamr_runtime(bool alloc_with_pool, uint8_t *heap_buf,
|
||||
uint32_t heap_size, uint32_t max_thread_num)
|
||||
{
|
||||
RuntimeInitArgs init_args;
|
||||
|
||||
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
||||
|
||||
if (alloc_with_pool) {
|
||||
init_args.mem_alloc_type = Alloc_With_Pool;
|
||||
init_args.mem_alloc_option.pool.heap_buf = heap_buf;
|
||||
init_args.mem_alloc_option.pool.heap_size = heap_size;
|
||||
}
|
||||
else {
|
||||
init_args.mem_alloc_type = Alloc_With_System_Allocator;
|
||||
}
|
||||
|
||||
return wasm_runtime_full_init(&init_args);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type LogLevel uint32
|
||||
const (
|
||||
LOG_LEVEL_FATAL LogLevel = 0
|
||||
LOG_LEVEL_ERROR LogLevel = 1
|
||||
LOG_LEVEL_WARNING LogLevel = 2
|
||||
LOG_LEVEL_DEBUG LogLevel = 3
|
||||
LOG_LEVEL_VERBOSE LogLevel = 4
|
||||
)
|
||||
|
||||
/*
|
||||
type NativeSymbol struct {
|
||||
symbol string
|
||||
func_ptr *uint8
|
||||
signature string
|
||||
}
|
||||
*/
|
||||
|
||||
type _Runtime struct {
|
||||
initialized bool
|
||||
}
|
||||
|
||||
var _runtime_singleton *_Runtime
|
||||
|
||||
/* Return the runtime singleton */
|
||||
func Runtime() *_Runtime {
|
||||
if (_runtime_singleton == nil) {
|
||||
self := &_Runtime{}
|
||||
_runtime_singleton = self
|
||||
}
|
||||
return _runtime_singleton;
|
||||
}
|
||||
|
||||
/* Initialize the WASM runtime environment */
|
||||
func (self *_Runtime) FullInit(alloc_with_pool bool, heap_buf []byte,
|
||||
max_thread_num uint) error {
|
||||
var heap_buf_C *C.uchar
|
||||
|
||||
if (self.initialized) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if (alloc_with_pool) {
|
||||
if (heap_buf == nil) {
|
||||
return fmt.Errorf("Failed to init WAMR runtime")
|
||||
}
|
||||
heap_buf_C = (*C.uchar)(unsafe.Pointer(&heap_buf[0]))
|
||||
}
|
||||
|
||||
if (!C.init_wamr_runtime((C.bool)(alloc_with_pool), heap_buf_C,
|
||||
(C.uint)(len(heap_buf)),
|
||||
(C.uint)(max_thread_num))) {
|
||||
return fmt.Errorf("Failed to init WAMR runtime")
|
||||
}
|
||||
|
||||
self.initialized = true
|
||||
return nil
|
||||
}
|
||||
|
||||
/* Initialize the WASM runtime environment */
|
||||
func (self *_Runtime) Init() error {
|
||||
return self.FullInit(false, nil, 1)
|
||||
}
|
||||
|
||||
/* Destroy the WASM runtime environment */
|
||||
func (self *_Runtime) Destroy() {
|
||||
if (self.initialized) {
|
||||
C.wasm_runtime_destroy()
|
||||
self.initialized = false
|
||||
}
|
||||
}
|
||||
|
||||
/* Set log verbose level (0 to 5, default is 2),
|
||||
larger level with more log */
|
||||
func (self *_Runtime) SetLogLevel(level LogLevel) {
|
||||
C.bh_log_set_verbose_level(C.uint32_t(level))
|
||||
}
|
||||
|
||||
/*
|
||||
func (self *_Runtime) RegisterNatives(moduleName string,
|
||||
nativeSymbols []NativeSymbol) {
|
||||
}
|
||||
*/ /* TODO */
|
||||
|
||||
func (self *_Runtime) InitThreadEnv() bool {
|
||||
if (!C.wasm_runtime_init_thread_env()) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *_Runtime) DestroyThreadEnv() {
|
||||
C.wasm_runtime_destroy_thread_env();
|
||||
}
|
||||
|
||||
func (self *_Runtime) ThreadEnvInited() bool {
|
||||
if (!C.wasm_runtime_thread_env_inited()) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/* Allocate memory from runtime memory environment */
|
||||
func (self *_Runtime) Malloc(size uint32) *uint8 {
|
||||
ptr := C.wasm_runtime_malloc((C.uint32_t)(size))
|
||||
return (*uint8)(ptr)
|
||||
}
|
||||
|
||||
/* Free memory to runtime memory environment */
|
||||
func (self *_Runtime) Free(ptr *uint8) {
|
||||
C.wasm_runtime_free((unsafe.Pointer)(ptr))
|
||||
}
|
42
language-bindings/go/wamr/runtime_test.go
Normal file
42
language-bindings/go/wamr/runtime_test.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
package wamr
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRuntime(t *testing.T) {
|
||||
res := false
|
||||
if (Runtime() != nil) {
|
||||
res = true;
|
||||
}
|
||||
assert.Equal(t, res, true)
|
||||
|
||||
err := Runtime().Init()
|
||||
assert.NoError(t, err)
|
||||
Runtime().Destroy()
|
||||
|
||||
err = Runtime().FullInit(false, nil, 6)
|
||||
assert.NoError(t, err)
|
||||
Runtime().Destroy()
|
||||
|
||||
err = Runtime().FullInit(false, nil, 0)
|
||||
assert.NoError(t, err)
|
||||
Runtime().Destroy()
|
||||
|
||||
heap_buf := make([]byte, 128 * 1024)
|
||||
err = Runtime().FullInit(true, heap_buf, 4)
|
||||
assert.NoError(t, err)
|
||||
Runtime().Destroy()
|
||||
|
||||
Runtime().FullInit(false, nil, 0)
|
||||
err = Runtime().FullInit(false, nil, 0)
|
||||
assert.NoError(t, err)
|
||||
Runtime().Destroy()
|
||||
Runtime().Destroy()
|
||||
}
|
160
language-bindings/python/.gitignore
vendored
Normal file
160
language-bindings/python/.gitignore
vendored
Normal file
|
@ -0,0 +1,160 @@
|
|||
# Refer to https://github.com/github/gitignore/blob/main/Python.gitignore
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# virtual environment
|
||||
Pipfile
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# VSCode settings
|
||||
.vscode/
|
||||
|
1
language-bindings/python/LICENSE
Symbolic link
1
language-bindings/python/LICENSE
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE
|
31
language-bindings/python/README.md
Normal file
31
language-bindings/python/README.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
# wamr-python
|
||||
|
||||
## Installation
|
||||
|
||||
### Installing from the source code
|
||||
|
||||
Installing from local source tree is in _development mode_. The package appears to be installed but still is editable from the source tree.
|
||||
|
||||
```bash
|
||||
$ python -m pip install -e /path/to/wamr-root/binding/python
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
import wamr.ffi as ffi
|
||||
```
|
||||
|
||||
### Preparation
|
||||
|
||||
The binding will load the shared library _libiwasm.so_ from the WAMR repo. So before running the binding, you need to build the library yourself.
|
||||
|
||||
The default compile options are good enough.
|
||||
|
||||
Please be aware that `wasm_frame_xxx` and `wasm_trap_xxx` only work well when enabling `WAMR_BUILD_DUMP_CALL_STACK`.
|
||||
|
||||
### Examples
|
||||
|
||||
There is a [simple example](./samples/hello_procedural.py) to show how to use bindings. Actually, the python binding follows C-APIs. There it should be easy if be familiar with _programming with wasm-c-api_.
|
||||
|
||||
Unit test cases under _./tests_ could be another but more complete references.
|
708
language-bindings/python/docs/design.md
Normal file
708
language-bindings/python/docs/design.md
Normal file
|
@ -0,0 +1,708 @@
|
|||
# how to implement a python binding of WAMR
|
||||
|
||||
A python language binding of Wasm runtime allows its users to call a set of APIs of
|
||||
the runtime from the python world. Those APIs maybe implemented in C, C++, or Rust.
|
||||
|
||||
In the WAMR case, a python binding allows APIs in `core/iwasm/include/wasm_c_api.h`
|
||||
to be used in the python scripts. To achieve that, we will create two kinds
|
||||
of stuff: wrappers of structured data types and wrappers of functions under the
|
||||
help of _ctypes_.
|
||||
|
||||
Cyptes is a tool in the standard library for creating Python bindings. It
|
||||
provides a low-level toolset for loading shared libraries and marshaling
|
||||
data between Python and C. Other options include _cffi_, _pybind11_,
|
||||
_cpython_ and so on. Because we tend to make the binding depending on least
|
||||
items. The built-in module, _ctypes_, is a good choice.
|
||||
|
||||
## General rules to marshal
|
||||
|
||||
The core of the idea of a language binding is how to translate different
|
||||
representations of types in different language.
|
||||
|
||||
### load libraries
|
||||
|
||||
The `ctypes` supports locating a dynamic link library in a way similar to the
|
||||
compiler does.
|
||||
|
||||
Currently, `ctypes.LoadLibrary` supports:
|
||||
|
||||
- `CDLL`. Those libraries use the standard C calling conversion.
|
||||
- `OleDLL` and `WinDLL`. Those libraries use the `stdcall` calling conversion on
|
||||
Windows only
|
||||
|
||||
### fundamental datatypes
|
||||
|
||||
_ctypes_ provides [primitive C compatiable data types](https://docs.python.org/3/library/ctypes.html#fundamental-data-types).
|
||||
Like `c_bool`, `c_byte`, `c_int`, `c_long` and so on.
|
||||
|
||||
> `c_int` represents the _C_ `signed int` datatype. On platforms where
|
||||
> `sizeof(int) == sizeof(long)` it is an alias to `c_long`.
|
||||
|
||||
| c datatypes | ctypes |
|
||||
| ------------------- | ----------------------- |
|
||||
| bool | c_bool |
|
||||
| byte_t | c_ubyte |
|
||||
| char | c_char |
|
||||
| float32_t | c_float |
|
||||
| float64_t | c_double |
|
||||
| int32_t | c_int32 |
|
||||
| int64_t | c_int64 |
|
||||
| intptr_t | c_void_p |
|
||||
| size_t | c_size_t |
|
||||
| uint8_t | c_uint8 |
|
||||
| uint32_t | c_uint32 |
|
||||
| void | None |
|
||||
| wasm_byte_t | c_ubyte |
|
||||
| wasm_externkind_t | c_uint8 |
|
||||
| wasm_memory_pages_t | c_uint32 |
|
||||
| wasm_mutability_t | c_bool |
|
||||
| wasm_table_size_t | c_uint32 |
|
||||
| wasm_valkind_t | c_uint8 |
|
||||
| wasm_data_type\* | POINTER(wasm_data_type) |
|
||||
|
||||
- `c_void_p` only represents `void *` only
|
||||
- `None` represents `void` in function parameter lists and return lists
|
||||
|
||||
### structured datatypes
|
||||
|
||||
Create a corresponding concept for every native structured data type includes
|
||||
`enum`, `struct` and `union`, in the python world.
|
||||
|
||||
#### Enum types
|
||||
|
||||
For example, if there is a `enum wams_mutability_enum` in native.
|
||||
|
||||
```c
|
||||
typedef uint8_t wams_mutability_t;
|
||||
enum wams_mutability_enum {
|
||||
WASM_CONST,
|
||||
WASM_VAR
|
||||
};
|
||||
```
|
||||
|
||||
Use `ctypes.int`(or any integer types in ctypes) to represents its value directly.
|
||||
|
||||
```python
|
||||
# represents enum wams_mutability_enum
|
||||
wasm_mutability_t = c_uint8
|
||||
|
||||
WASM_CONST = 0
|
||||
WASM_VAR = 1
|
||||
```
|
||||
|
||||
> C standard only requires "Each enumerated type shall be compatible with char,
|
||||
> a signed integer type, or an unsigned integer type. The choice of the integer
|
||||
> type is implementation-defined, but shall be capable of representing the
|
||||
> values of all the members of the enumeration.
|
||||
|
||||
#### Struct types
|
||||
|
||||
If there is a `struct wasm_byte_vec_t` in native(in C).
|
||||
|
||||
```c
|
||||
typedef struct wasm_byte_vec_t {
|
||||
size_t size;
|
||||
wasm_byte_t *data;
|
||||
size_t num_elems;
|
||||
size_t size_of_elem;
|
||||
} wasm_byte_vec_t;
|
||||
```
|
||||
|
||||
Use `ctypes.Structure` to create its corresponding data type in python.
|
||||
|
||||
```python
|
||||
class wasm_byte_vec_t(ctypes.Structure):
|
||||
_fileds_ = [
|
||||
("size", ctypes.c_size_t),
|
||||
("data", ctypes.POINTER(c_ubyte)),
|
||||
("num_elems", ctypes.c_size_t),
|
||||
("size_of_elem", ctypes.c_size_t),
|
||||
]
|
||||
```
|
||||
|
||||
a list of `Structures`
|
||||
|
||||
| name |
|
||||
| ----------------- |
|
||||
| wasm_engine_t |
|
||||
| wasm_store_t |
|
||||
| wasm_limits_t |
|
||||
| wasm_valtype_t |
|
||||
| wasm_functype_t |
|
||||
| wasm_globaltype_t |
|
||||
| wasm_tabletype_t |
|
||||
| wasm_memorytype_t |
|
||||
| wasm_externtype_t |
|
||||
| wasm_importtype_t |
|
||||
| wasm_exporttype_t |
|
||||
| wasm_ref_t |
|
||||
| wasm_ref_t |
|
||||
| wasm_frame_t |
|
||||
| wasm_trap_t |
|
||||
| wasm_foreign_t |
|
||||
| WASMModuleCommon |
|
||||
| WASMModuleCommon |
|
||||
| wasm_func_t |
|
||||
| wasm_global_t |
|
||||
| wasm_table_t |
|
||||
| wasm_memory_t |
|
||||
| wasm_extern_t |
|
||||
| wasm_instance_t |
|
||||
|
||||
not supported `struct`
|
||||
|
||||
- wasm_config_t
|
||||
|
||||
If there is an anonymous `union` in native.
|
||||
|
||||
```c
|
||||
typedef struct wasm_val_t {
|
||||
wasm_valkind_t kind;
|
||||
union {
|
||||
int32_t i32;
|
||||
int64_t i64;
|
||||
float32_t f32;
|
||||
float64_t f64;
|
||||
} of;
|
||||
} wasm_val_t;
|
||||
```
|
||||
|
||||
Use `ctypes.Union` to create its corresponding data type in python.
|
||||
|
||||
```python
|
||||
class _OF(ctypes.Union):
|
||||
_fields_ = [
|
||||
("i32", ctypes.c_int32),
|
||||
("i64", ctypes.c_int64),
|
||||
("f32", ctypes.c_float),
|
||||
("f64", ctypes.c_double),
|
||||
]
|
||||
|
||||
class wasm_val_t(ctypes.Structure):
|
||||
_anonymous_ = ("of",)
|
||||
_fields_ = [
|
||||
("kind", ctypes.c_uint8)
|
||||
("of", _OF)
|
||||
]
|
||||
```
|
||||
|
||||
### wrappers of functions
|
||||
|
||||
Foreign functions (C functions) can be accessed as attributes of loaded shared
|
||||
libraries or an instance of function prototypes. Callback functions(python
|
||||
functions) can only be accessed by instantiating function prototypes.
|
||||
|
||||
For example,
|
||||
|
||||
```c
|
||||
void wasm_name_new(wasm_name_t* out, size_t len, wasm_byte_t [] data);
|
||||
```
|
||||
|
||||
Assume there are:
|
||||
|
||||
- `class wasm_name_t` of python represents `wasm_name_t` of C
|
||||
- `libiwasm` represents loaded _libiwasm.so_
|
||||
|
||||
If to access a c function like an attribute,
|
||||
|
||||
```python
|
||||
def wasm_name_new(out, len, data):
|
||||
_wasm_name_new = libiwasm.wasm_name_new
|
||||
_wasm_name_new.argtypes = (ctypes.POINTER(wasm_name_t), ctypes.c_size_t, ctypes.POINTER(ctypes.c_ubyte))
|
||||
_wasm_name_new.restype = None
|
||||
return _wasm_name_new(out, len, data)
|
||||
```
|
||||
|
||||
Or to instantiate a function prototype,
|
||||
|
||||
```python
|
||||
def wasm_name_new(out, len, data):
|
||||
return ctypes.CFUNCTYPE(None, (ctypes.POINTER(wasm_name_t), ctypes.c_size_t, ctypes.POINTER(ctypes.c_ubyte)))(
|
||||
("wasm_name_new", libiwasm), out, len, data)
|
||||
```
|
||||
|
||||
Now it is able to create a `wasm_name_t` with `wasm_name_new()` in python.
|
||||
|
||||
Sometimes, need to create a python function as a callback of c.
|
||||
|
||||
```c
|
||||
wasm_trap_t* (*wasm_func_callback_t)(wasm_val_vec_t* args, wasm_val_vec_t *results);
|
||||
```
|
||||
|
||||
Use `cyptes.CFUNCTYPE` to create a _pointer of function_
|
||||
|
||||
```python
|
||||
def hello(args, results):
|
||||
print("hello from a callback")
|
||||
|
||||
wasm_func_callback_t = ctypes.CFUNCTYPE(c_size_t, POINTER(wasm_val_vec_t), POINTER(wasm_val_vec_t))
|
||||
hello_callback = wasm_func_callback_t(hello)
|
||||
```
|
||||
|
||||
or with a decorator
|
||||
|
||||
```python
|
||||
def wasm_func_cb_decl(func):
|
||||
return @ctypes.CFUNCTYPE(ctypes.POINTER(wasm_trap_t), (ctypes.POINTER(wasm_val_vec_t), ctypes.POINTER(wasm_val_vec_t)))(func)
|
||||
|
||||
@wasm_func_cb_decl
|
||||
def hello(args, results):
|
||||
print("hello from a callback")
|
||||
```
|
||||
|
||||
### programming tips
|
||||
|
||||
#### `struct` and `ctypes.Structure`
|
||||
|
||||
There are two kinds of `cytes.Structure` in `binding.py`.
|
||||
|
||||
- has `__field__` definition. like `class wasm_byte_vec_t(Structure)`
|
||||
- doesn't have `__field__` definition. like `class wasm_config_t(Structure)`
|
||||
|
||||
Since, `ctypes` will create its C world _mirror_ variable according to `__field__`
|
||||
information, `wasm_config_t()` will only create a python instance without binding
|
||||
to any C variable. `wasm_byte_vec_t()` will return a python instance with an internal
|
||||
C variable.
|
||||
|
||||
That is why `pointer(wasm_config_t())` is a NULL pointer which can not be dereferenced.
|
||||
|
||||
#### deal with pointers
|
||||
|
||||
`byref()` and `pointer()` are two functions can return a pointer.
|
||||
|
||||
```python
|
||||
x = ctypes.c_int(2)
|
||||
|
||||
# use pointer() to creates a new pointer instance which would later be used in Python
|
||||
x_ptr = ctypes.pointer(x)
|
||||
...
|
||||
struct_use_pointer = Mystruct()
|
||||
struct_use_pointer.ptr = x_ptr
|
||||
|
||||
# use byref() pass a pointer to an object to a foreign function call
|
||||
func(ctypes.byref(x))
|
||||
```
|
||||
|
||||
The main difference is that `pointer()` does a lot more work since it
|
||||
constructs a real pointer object. It is faster to use `byref(`) if don't need
|
||||
the pointer object in Python itself(e.g. only use it as an argument to pass
|
||||
to a function).
|
||||
|
||||
There is no doubt that `wasm_xxx_new()` which return type is `ctypes.POINTER`
|
||||
can return a pointer. Plus, the return value of `wasm_xxx_t()` can also be
|
||||
used as a pointer without casting by `byref` or `pointer`.
|
||||
|
||||
#### array
|
||||
|
||||
In [ctypes document](https://docs.python.org/3/library/ctypes.html#arrays),
|
||||
it states that "The recommended way to create array types is by multiplying a
|
||||
data type with a positive integer". So _multiplying a data type_ should be a
|
||||
better way to create arrays
|
||||
|
||||
```python
|
||||
from ctypes import *
|
||||
|
||||
class POINT(Structure):
|
||||
_fields_ = ("x", c_int), ("y", c_int)
|
||||
|
||||
# multiplying a data type
|
||||
# type(TenPointsArrayType) is <class '_ctypes.PyCArrayType'>
|
||||
TenPointsArrayType = POINT * 10
|
||||
|
||||
# Instances are created in the usual way, by calling the class:
|
||||
arr = TenPointsArrayType()
|
||||
arr[0] = POINT(3,2)
|
||||
for pt in arr:
|
||||
print(pt.x, pt.y)
|
||||
```
|
||||
|
||||
On both sides, it is OK to assign an array to a pointer.
|
||||
|
||||
```c
|
||||
char buf[128] = {0};
|
||||
char *ptr = buf;
|
||||
```
|
||||
|
||||
```python
|
||||
binary = wasm_byte_vec_t()
|
||||
binary.data = (ctypes.c_ubyte * len(wasm)).from_buffer_copy(wasm)
|
||||
```
|
||||
|
||||
#### exceptions and traps
|
||||
|
||||
Interfaces of _wasm-c-api_ have their return values to represent failures.
|
||||
The python binding should just keep and transfer them to callers instead of
|
||||
raising any additional exception.
|
||||
|
||||
The python binding should raise exceptions when the python partial is failed.
|
||||
|
||||
#### readonly buffer
|
||||
|
||||
```python
|
||||
with open("hello.wasm", "rb") as f:
|
||||
wasm = f.read()
|
||||
binary = wasm_byte_vec_t()
|
||||
wasm_byte_vec_new_uninitialized(byref(binary), len(wasm))
|
||||
# create a ctypes instance (byte[] in c) and copy the content
|
||||
# from wasm(bytearray in python)
|
||||
binary.data = (ctypes.c_ubyte * len(wasm)).from_buffer_copy(wasm)
|
||||
```
|
||||
|
||||
in the above example, `wasm` is a python-created readable buffer. It is not
|
||||
writable and needs to be copied into a ctype array.
|
||||
|
||||
#### variable arguments
|
||||
|
||||
A function with _variable arugments_ makes it hard to specify the required
|
||||
argument types for the function prototype. It leaves us one way to call it
|
||||
directly without any arguments type checking.
|
||||
|
||||
```python
|
||||
libc.printf(b"Hello, an int %d, a float %f, a string %s\n", c_int(1), c_doulbe(3.14), "World!")
|
||||
```
|
||||
|
||||
#### Use `c_bool` to represent `wasm_mutability_t `
|
||||
|
||||
- `True` for `WASM_CONST`
|
||||
- `False` for `WASM_VALUE`
|
||||
|
||||
#### customize class builtins
|
||||
|
||||
- `__eq__` for comparation.
|
||||
- `__repr__` for printing.
|
||||
|
||||
### bindgen.py
|
||||
|
||||
`bindge.py` is a tool to create WAMR python binding automatically. `binding.py`
|
||||
is generated. We should avoid modification on it. Additional helpers should go
|
||||
to `ffi.py`.
|
||||
|
||||
`bindgen.py` uses _pycparser_. Visit the AST of `core/iwasm/include/wasm_c_api.h`
|
||||
created by _gcc_ and generate necessary wrappers.
|
||||
|
||||
```python
|
||||
from pycparser import c_ast
|
||||
|
||||
class Visitor(c_ast.NodeVisitor):
|
||||
def visit_Struct(self, node):
|
||||
pass
|
||||
|
||||
def visit_Union(self, node):
|
||||
pass
|
||||
|
||||
def visit_TypeDef(self, node):
|
||||
pass
|
||||
|
||||
def visit_FuncDecl(self, node):
|
||||
pass
|
||||
|
||||
ast = parse_file(...)
|
||||
v = Visitor()
|
||||
v.visit(ast)
|
||||
```
|
||||
|
||||
Before running _bindgen.py_, the shared library _libiwasm.so_ should be generated.
|
||||
|
||||
```bash
|
||||
$ cd /path/to/wamr/repo
|
||||
$ # if it is in linux
|
||||
$ pushd product-mini/platforms/linux/
|
||||
$ cmake -S . -B build ..
|
||||
$ cmake --build build --target iwasm
|
||||
$ popd
|
||||
$ cd binding/python
|
||||
$ python utils/bindgen.py
|
||||
```
|
||||
|
||||
`wasm_frame_xxx` and `wasm_trap_xxx` only work well when enabling `WAMR_BUILD_DUMP_CALL_STACK`.
|
||||
|
||||
```bash
|
||||
$ cmake -S . -B build -DWAMR_BUILD_DUMP_CALL_STACK=1 ..
|
||||
```
|
||||
|
||||
## OOP wrappers
|
||||
|
||||
Based on the above general rules, there will be corresponding python
|
||||
APIs for every C API in `wasm_c_api.h` with same name. Users can do procedural
|
||||
programming with those.
|
||||
|
||||
In next phase, we will create OOP APIs. Almost follow the
|
||||
[C++ version of wasm_c_api](https://github.com/WebAssembly/wasm-c-api/blob/master/include/wasm.hh)
|
||||
|
||||
## A big list
|
||||
|
||||
| WASM Concept | Procedural APIs | OOP APIs | OOP APIs methods |
|
||||
| ------------ | ------------------------------ | ---------- | ---------------- |
|
||||
| XXX_vec | wasm_xxx_vec_new | | list |
|
||||
| | wasm_xxx_vec_new_uninitialized | | |
|
||||
| | wasm_xxx_vec_new_empty | | |
|
||||
| | wasm_xxx_vec_copy | | |
|
||||
| | wasm_xxx_vec_delete | | |
|
||||
| valtype | wasm_valtype_new | valtype | \_\_init\_\_ |
|
||||
| | wasm_valtype_delete | | \_\_del\_\_ |
|
||||
| | wasm_valtype_kind | | \_\_eq\_\_ |
|
||||
| | wasm_valtype_copy | | |
|
||||
| | _vector methods_ | | |
|
||||
| functype | wasm_functype_new | functype | |
|
||||
| | wasm_functype_delete | | |
|
||||
| | wasm_functype_params | | |
|
||||
| | wasm_functype_results | | |
|
||||
| | wasm_functype_copy | | |
|
||||
| | _vector methods_ | | |
|
||||
| globaltype | wasm_globaltype_new | globaltype | \_\_init\_\_ |
|
||||
| | wasm_globaltype_delete | | \_\_del\_\_ |
|
||||
| | wasm_globaltype_content | | \_\_eq\_\_ |
|
||||
| | wasm_globaltype_mutability | | |
|
||||
| | wasm_globaltype_copy | | |
|
||||
| | _vector methods_ | | |
|
||||
| tabletype | wasm_tabletype_new | tabletype | \_\_init\_\_ |
|
||||
| | wasm_tabletype_delete | | \_\_del\_\_ |
|
||||
| | wasm_tabletype_element | | \_\_eq\_\_ |
|
||||
| | wasm_tabletype_limits | | |
|
||||
| | wasm_tabletype_copy | | |
|
||||
| | _vector methods_ | | |
|
||||
| memorytype | wasm_memorytype_new | memorytype | \_\_init\_\_ |
|
||||
| | wasm_memorytype_delete | | \_\_del\_\_ |
|
||||
| | wasm_memorytype_limits | | \_\_eq\_\_ |
|
||||
| | wasm_memorytype_copy | | |
|
||||
| | _vector methods_ | | |
|
||||
| externtype | wasm_externtype_as_XXX | externtype | |
|
||||
| | wasm_XXX_as_externtype | | |
|
||||
| | wasm_externtype_copy | | |
|
||||
| | wasm_externtype_delete | | |
|
||||
| | wasm_externtype_kind | | |
|
||||
| | _vector methods_ | | |
|
||||
| importtype | wasm_importtype_new | importtype | |
|
||||
| | wasm_importtype_delete | | |
|
||||
| | wasm_importtype_module | | |
|
||||
| | wasm_importtype_name | | |
|
||||
| | wasm_importtype_type | | |
|
||||
| | wasm_importtype_copy | | |
|
||||
| | _vector methods_ | | |
|
||||
| exportype | wasm_exporttype_new | exporttype | |
|
||||
| | wasm_exporttype_delete | | |
|
||||
| | wasm_exporttype_name | | |
|
||||
| | wasm_exporttype_type | | |
|
||||
| | wasm_exporttype_copy | | |
|
||||
| | _vector methods_ | | |
|
||||
| val | wasm_val_delete | val | |
|
||||
| | wasm_val_copy | | |
|
||||
| | _vector methods_ | | |
|
||||
| frame | wasm_frame_delete | frame | |
|
||||
| | wasm_frame_instance | | |
|
||||
| | wasm_frame_func_index | | |
|
||||
| | wasm_frame_func_offset | | |
|
||||
| | wasm_frame_module_offset | | |
|
||||
| | wasm_frame_copy | | |
|
||||
| | _vector methods_ | | |
|
||||
| trap | wasm_trap_new | trap | |
|
||||
| | wasm_trap_delete | | |
|
||||
| | wasm_trap_message | | |
|
||||
| | wasm_trap_origin | | |
|
||||
| | wasm_trap_trace | | |
|
||||
| | _vector methods_ | | |
|
||||
| foreign | wasm_foreign_new | foreign | |
|
||||
| | wasm_foreign_delete | | |
|
||||
| | _vector methods_ | | |
|
||||
| engine | wasm_engine_new | engine | |
|
||||
| | wasm_engine_new_with_args\* | | |
|
||||
| | wasm_engine_new_with_config | | |
|
||||
| | wasm_engine_delete | | |
|
||||
| store | wasm_store_new | store | |
|
||||
| | wasm_store_delete | | |
|
||||
| | _vector methods_ | | |
|
||||
| module | wasm_module_new | module | |
|
||||
| | wasm_module_delete | | |
|
||||
| | wasm_module_validate | | |
|
||||
| | wasm_module_imports | | |
|
||||
| | wasm_module_exports | | |
|
||||
| instance | wasm_instance_new | instance | |
|
||||
| | wasm_instance_delete | | |
|
||||
| | wasm_instance_new_with_args\* | | |
|
||||
| | wasm_instance_exports | | |
|
||||
| | _vector methods_ | | |
|
||||
| func | wasm_func_new | func | |
|
||||
| | wasm_func_new_with_env | | |
|
||||
| | wasm_func_delete | | |
|
||||
| | wasm_func_type | | |
|
||||
| | wasm_func_call | | |
|
||||
| | wasm_func_param_arity | | |
|
||||
| | wasm_func_result_arity | | |
|
||||
| | _vector methods_ | | |
|
||||
| global | wasm_global_new | global | |
|
||||
| | wasm_global_delete | | |
|
||||
| | wasm_global_type | | |
|
||||
| | wasm_global_get | | |
|
||||
| | wasm_global_set | | |
|
||||
| | _vector methods_ | | |
|
||||
| table | wasm_table_new | table | |
|
||||
| | wasm_table_delete | | |
|
||||
| | wasm_table_type | | |
|
||||
| | wasm_table_get | | |
|
||||
| | wasm_table_set | | |
|
||||
| | wasm_table_size | | |
|
||||
| | _vector methods_ | | |
|
||||
| memory | wasm_memory_new | memory | |
|
||||
| | wasm_memory_delete | | |
|
||||
| | wasm_memory_type | | |
|
||||
| | wasm_memory_data | | |
|
||||
| | wasm_memory_data_size | | |
|
||||
| | wasm_memory_size | | |
|
||||
| | _vector methods_ | | |
|
||||
| extern | wasm_extern_delete | extern | |
|
||||
| | wasm_extern_as_XXX | | |
|
||||
| | wasm_XXX_as_extern | | |
|
||||
| | wasm_extern_kind | | |
|
||||
| | wasm_extern_type | | |
|
||||
| | _vector methods_ | | |
|
||||
|
||||
not supported _functions_
|
||||
|
||||
- wasm_config_XXX
|
||||
- wasm_module_deserialize
|
||||
- wasm_module_serialize
|
||||
- wasm_ref_XXX
|
||||
- wasm_XXX_as_ref
|
||||
- wasm_XXX_as_ref_const
|
||||
- wasm_XXX_copy
|
||||
- wasm_XXX_get_host_info
|
||||
- wasm_XXX_set_host_info
|
||||
|
||||
## test
|
||||
|
||||
there will be two kinds of tests in the project
|
||||
|
||||
- unit test. located in `./tests`. driven by _unittest_. run by
|
||||
`$ python -m unittest` or `$ make test`.
|
||||
- integration test. located in `./samples`.
|
||||
|
||||
The whole project is under test-driven development. Every wrapper function will
|
||||
have two kinds of test cases. The first kind is a positive case. It checks a
|
||||
wrapper function with expected and safe arguments combinations. Its goal is the
|
||||
function should work well with expected inputs. Another kind is a negative
|
||||
case. It feeds unexpected arguments combinations into a wrapper function. Arguments
|
||||
should include but not be limited to `None`. It ensures that the function will
|
||||
gracefully handle invalid input or unexpected behaviors.
|
||||
|
||||
## distribution
|
||||
|
||||
### package
|
||||
|
||||
Create a python package named `wamr`. Users should import it after installation
|
||||
just like any other python module.
|
||||
|
||||
```python
|
||||
from wamr import *
|
||||
```
|
||||
|
||||
### PyPI
|
||||
|
||||
Refer to [tutorial provided by PyPA](https://packaging.python.org/en/latest/tutorials/packaging-projects/).
|
||||
Steps to publish WAMR Python library:
|
||||
|
||||
1. Creating `pyproject.toml` tells build tools (like pip and build) what is
|
||||
required to build a project. An example .toml file uses _setuptools_
|
||||
|
||||
```toml
|
||||
[build-system]
|
||||
requires = [
|
||||
"setuptools>=42",
|
||||
"wheel"
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
||||
```
|
||||
|
||||
2. Configuring metadata tells build tools about a package (such as the name
|
||||
and the version), as well as which code files to include
|
||||
|
||||
- Static metadata (`setup.cfg`): guaranteed to be the same every time.
|
||||
It is simpler, easier to read, and avoids many common errors, like
|
||||
encoding errors.
|
||||
|
||||
- Dynamic metadata (`setup.py`): possibly non-deterministic. Any items that
|
||||
are dynamic or determined at install-time, as well as extension modules
|
||||
or extensions to setuptools, need to go into setup.py.
|
||||
|
||||
**_Static metadata should be preferred_**. Dynamic metadata should be used
|
||||
only as an escape hatch when necessary. setup.py used to be
|
||||
required, but can be omitted with newer versions of setuptools and pip.
|
||||
|
||||
3. Including other files in the distribution
|
||||
|
||||
- For [source distribution](https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist):
|
||||
|
||||
It's usually generated using `python setup.py sdist`, providing metadata
|
||||
and the essential source files needed for installing by a tool like pip,
|
||||
or for generating a Built Distribution.
|
||||
|
||||
It includes our Python modules, pyproject.toml, metadata, README.md,
|
||||
LICENSE. If you want to control what goes in this explicitly,
|
||||
see [Including files in source distributions with MANIFEST.in](https://packaging.python.org/en/latest/guides/using-manifest-in/#using-manifest-in).
|
||||
|
||||
- For [final built distribution](https://packaging.python.org/en/latest/glossary/#term-Built-Distribution)
|
||||
|
||||
A Distribution format containing files and metadata that only need to be
|
||||
moved to the correct location on the target system, to be installed.
|
||||
e.g. `Wheel`
|
||||
|
||||
It will have the Python files in the discovered or listed Python packages.
|
||||
If you want to control what goes here, such as to add data files,
|
||||
see [Including Data Files](https://setuptools.pypa.io/en/latest/userguide/datafiles.html) from the [setuptools docs](https://setuptools.pypa.io/en/latest/index.html).
|
||||
|
||||
4. Generating distribution archives. These are archives that are uploaded to
|
||||
the Python Package Index and can be installed by pip.
|
||||
|
||||
example using `setuptools`
|
||||
|
||||
```shell
|
||||
python3 -m pip install --upgrade build
|
||||
python3 -m build
|
||||
```
|
||||
|
||||
generated files:
|
||||
|
||||
```shell
|
||||
dist/
|
||||
WAMR-package-0.0.1-py3-none-any.whl
|
||||
WAMR-package-0.0.1.tar.gz
|
||||
```
|
||||
|
||||
The `tar.gz` file is a _source archive_ whereas the `.whl file` is a
|
||||
_built distribution_. Newer pip versions preferentially install built
|
||||
distributions but will fall back to source archives if needed. You should
|
||||
always upload a source archive and provide built archives for compatibility
|
||||
reasons.
|
||||
|
||||
5. Uploading the distribution archives
|
||||
|
||||
- Register an account on https://pypi.org.
|
||||
- To securely upload your project, you’ll need a
|
||||
[PyPI API token](https://pypi.org/help/#apitoken). It can create at
|
||||
[here](https://pypi.org/manage/account/#api-tokens), and the “Scope”
|
||||
the setting needs to be “Entire account”.
|
||||
- After registration, now twine can be used to upload the distribution packages.
|
||||
|
||||
```shell
|
||||
# install twine
|
||||
python3 -m pip install --upgrade twine
|
||||
# --repository is https://pypi.org/ by default.
|
||||
# You will be prompted for a username and password. For the username, use __token__. For the password, use the token value, including the pypi- prefix.
|
||||
twine upload dist/*
|
||||
```
|
||||
|
||||
after all, the python binding will be installed with
|
||||
|
||||
```shell
|
||||
$ pip install wamr
|
||||
```
|
||||
|
||||
PS: A example lifecycle of a python package
|
||||

|
||||
|
||||
## CI
|
||||
|
||||
There are several parts:
|
||||
|
||||
- code format check.
|
||||
- test. include running all unit test cases and examples.
|
||||
- publish built distribution.
|
Binary file not shown.
After Width: | Height: | Size: 75 KiB |
12
language-bindings/python/docs/setup_dev_env.md
Normal file
12
language-bindings/python/docs/setup_dev_env.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
Use a python virtual environment tool to create an environment for development. All necessary packages are in _../requirements.txt_.
|
||||
|
||||
python code formatter is provided by _black_.
|
||||
|
||||
python code linter is provided by _pylint_ and default configuration.
|
||||
|
||||
Unit tests are driven by _unittest_.
|
||||
|
||||
```bash
|
||||
$ python -m unittest -v tests/test_basics.py
|
||||
$ python -m unittest -v tests/test_advanced.py
|
||||
```
|
3
language-bindings/python/pyproject.toml
Normal file
3
language-bindings/python/pyproject.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
[build-system]
|
||||
requires = ["setuptools>=42"]
|
||||
build-backend = "setuptools.build_meta"
|
5
language-bindings/python/requirements.txt
Normal file
5
language-bindings/python/requirements.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
black
|
||||
nose
|
||||
pycparser
|
||||
pylint
|
||||
|
4
language-bindings/python/samples/hello.wat
Normal file
4
language-bindings/python/samples/hello.wat
Normal file
|
@ -0,0 +1,4 @@
|
|||
(module
|
||||
(func $hello (import "" "hello"))
|
||||
(func (export "run") (call $hello))
|
||||
)
|
41
language-bindings/python/samples/hello_oop.py
Normal file
41
language-bindings/python/samples/hello_oop.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
import ctypes
|
||||
from wamr import *
|
||||
|
||||
|
||||
def hello_callback():
|
||||
print("Calling back...")
|
||||
print("> Hello World!")
|
||||
|
||||
|
||||
def main():
|
||||
print("Initializing...")
|
||||
engine = Engine()
|
||||
store = Store(engine)
|
||||
|
||||
print("Loading binary...")
|
||||
print("Compiling module...")
|
||||
module = Module.from_file(engine, "./hello.wasm")
|
||||
|
||||
print("Creating callback...")
|
||||
hello = Func(store, FuncType([], []), hello_callback)
|
||||
|
||||
print("Instantiating module...")
|
||||
instance = Instance(store, module, [hello])
|
||||
|
||||
print("Extracting export...")
|
||||
run = instance.exports(store)["run"]
|
||||
|
||||
print("Calling export...")
|
||||
run(store)
|
||||
|
||||
print("Shutting down...")
|
||||
print("Done.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
93
language-bindings/python/samples/hello_procedural.py
Normal file
93
language-bindings/python/samples/hello_procedural.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
import ctypes
|
||||
import wamr.ffi as ffi
|
||||
|
||||
WAMS_BINARY_CONTENT = (
|
||||
b"\x00asm\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01`\x00\x00\x02\x8a\x80"
|
||||
b"\x80\x80\x00\x01\x00\x05hello\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00"
|
||||
b"\x07\x87\x80\x80\x80\x00\x01\x03run\x00\x01\n\x8a\x80\x80\x80\x00\x01"
|
||||
b"\x84\x80\x80\x80\x00\x00\x10\x00\x0b"
|
||||
)
|
||||
|
||||
|
||||
@ffi.wasm_func_cb_decl
|
||||
def hello_callback(args, results):
|
||||
print("Calling back...")
|
||||
print("> Hello World!")
|
||||
|
||||
|
||||
def main():
|
||||
print("Initializing...")
|
||||
engine = ffi.wasm_engine_new()
|
||||
store = ffi.wasm_store_new(engine)
|
||||
|
||||
print("Loading binary...")
|
||||
|
||||
# for convenience, use binary content instead of open file
|
||||
# with open("./hello.wasm", "rb") as f:
|
||||
# wasm = f.read()
|
||||
wasm = WAMS_BINARY_CONTENT
|
||||
binary = ffi.wasm_byte_vec_t()
|
||||
ffi.wasm_byte_vec_new_uninitialized(binary, len(wasm))
|
||||
# underlying buffer is not writable
|
||||
binary.data = (ctypes.c_ubyte * len(wasm)).from_buffer_copy(wasm)
|
||||
|
||||
print("Compiling module...")
|
||||
module = ffi.wasm_module_new(store, binary)
|
||||
if not module:
|
||||
raise RuntimeError("Compiling module failed")
|
||||
|
||||
binary.data = None
|
||||
ffi.wasm_byte_vec_delete(binary)
|
||||
|
||||
print("Creating callback...")
|
||||
hello_type = ffi.wasm_functype_new_0_0()
|
||||
hello_func = ffi.wasm_func_new(
|
||||
store,
|
||||
hello_type,
|
||||
hello_callback,
|
||||
)
|
||||
|
||||
ffi.wasm_functype_delete(hello_type)
|
||||
|
||||
print("Instantiating module...")
|
||||
|
||||
imports = ffi.wasm_extern_vec_t()
|
||||
ffi.wasm_extern_vec_new((imports), 1, ffi.wasm_func_as_extern(hello_func))
|
||||
instance = ffi.wasm_instance_new(store, module, imports, None)
|
||||
|
||||
ffi.wasm_func_delete(hello_func)
|
||||
|
||||
print("Extracting export...")
|
||||
exports = ffi.wasm_extern_vec_t()
|
||||
ffi.wasm_instance_exports(instance, exports)
|
||||
|
||||
run_func = ffi.wasm_extern_as_func(exports.data[0])
|
||||
if not run_func:
|
||||
raise RuntimeError("can not extract exported function")
|
||||
|
||||
ffi.wasm_instance_delete(instance)
|
||||
ffi.wasm_module_delete(module)
|
||||
|
||||
print("Calling export...")
|
||||
args = ffi.wasm_val_vec_t()
|
||||
results = ffi.wasm_val_vec_t()
|
||||
|
||||
ffi.wasm_val_vec_new_empty(args)
|
||||
ffi.wasm_val_vec_new_empty(results)
|
||||
ffi.wasm_func_call(run_func, args, results)
|
||||
|
||||
print("Shutting down...")
|
||||
ffi.wasm_store_delete(store)
|
||||
ffi.wasm_engine_delete(engine)
|
||||
|
||||
print("Done.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
30
language-bindings/python/setup.py
Executable file
30
language-bindings/python/setup.py
Executable file
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
# pylint: disable=missing-class-docstring
|
||||
# pylint: disable=missing-function-docstring
|
||||
# pylint: disable=missing-module-docstring
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
|
||||
with open("README.md") as f:
|
||||
readme = f.read()
|
||||
|
||||
with open("LICENSE") as f:
|
||||
license = f.read()
|
||||
|
||||
setup(
|
||||
name="wamr-python",
|
||||
version="0.1.0",
|
||||
description="A WebAssembly runtime powered by WAMR",
|
||||
long_description=readme,
|
||||
author="The WAMR Project Developers",
|
||||
author_email="hello@bytecodealliance.org",
|
||||
url="https://github.com/bytecodealliance/wamr-python",
|
||||
license=license,
|
||||
packages=["wamr"],
|
||||
)
|
7
language-bindings/python/tests/__init__.py
Normal file
7
language-bindings/python/tests/__init__.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
__all__ = ["test_basic", "test_advanced"]
|
13
language-bindings/python/tests/context.py
Normal file
13
language-bindings/python/tests/context.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||
|
||||
import wamr
|
525
language-bindings/python/tests/test_advanced.py
Normal file
525
language-bindings/python/tests/test_advanced.py
Normal file
|
@ -0,0 +1,525 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
# pylint: disable=missing-class-docstring
|
||||
# pylint: disable=missing-function-docstring
|
||||
# pylint: disable=missing-module-docstring
|
||||
|
||||
import ctypes as c
|
||||
import math
|
||||
import unittest
|
||||
|
||||
import wamr.ffi as ffi
|
||||
|
||||
|
||||
# It is a module likes:
|
||||
# (module
|
||||
# (import "mod" "g0" (global i32))
|
||||
# (import "mod" "f0" (func (param f32) (result f64)))
|
||||
#
|
||||
# (func (export "f1") (param i32 i64))
|
||||
# (global (export "g1") (mut f32) (f32.const 3.14))
|
||||
# (memory (export "m1") 1 2)
|
||||
# (table (export "t1") 1 funcref)
|
||||
#
|
||||
# (func (export "f2") (unreachable))
|
||||
# )
|
||||
MODULE_BINARY = (
|
||||
b"\x00asm\x01\x00\x00\x00\x01\x0e\x03`\x01}\x01|`\x02\x7f~\x00`\x00"
|
||||
b"\x00\x02\x14\x02\x03mod\x02g0\x03\x7f\x00\x03mod\x02f0\x00\x00\x03\x03"
|
||||
b"\x02\x01\x02\x04\x04\x01p\x00\x01\x05\x04\x01\x01\x01\x02\x06\t\x01}\x01C"
|
||||
b"\xc3\xf5H@\x0b\x07\x1a\x05\x02f1\x00\x01\x02g1\x03\x01\x02m1\x02\x00\x02t1"
|
||||
b"\x01\x00\x02f2\x00\x02\n\x08\x02\x02\x00\x0b\x03\x00\x00\x0b"
|
||||
)
|
||||
|
||||
# False -> True when testing with a library enabling WAMR_BUILD_DUMP_CALL_STACK flag
|
||||
TEST_WITH_WAMR_BUILD_DUMP_CALL_STACK = False
|
||||
|
||||
|
||||
@ffi.wasm_func_cb_decl
|
||||
def callback(args, results):
|
||||
args = ffi.dereference(args)
|
||||
results = ffi.dereference(results)
|
||||
|
||||
arg_v = args.data[0]
|
||||
|
||||
result_v = ffi.wasm_f64_val(arg_v.of.f32 * 2.0)
|
||||
ffi.wasm_val_copy(results.data[0], result_v)
|
||||
results.num_elems = 1
|
||||
|
||||
print(f"\nIn callback: {arg_v} --> {result_v}\n")
|
||||
|
||||
|
||||
@ffi.wasm_func_with_env_cb_decl
|
||||
def callback_with_env(env, args, results):
|
||||
# pylint: disable=unused-argument
|
||||
print("summer")
|
||||
|
||||
|
||||
class AdvancedTestSuite(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
print("Initializing...")
|
||||
cls._wasm_engine = ffi.wasm_engine_new()
|
||||
cls._wasm_store = ffi.wasm_store_new(cls._wasm_engine)
|
||||
|
||||
def assertIsNullPointer(self, pointer):
|
||||
# pylint: disable=invalid-name
|
||||
if not ffi.is_null_pointer(pointer):
|
||||
self.fail("not a non-null pointer")
|
||||
|
||||
def assertIsNotNullPointer(self, pointer):
|
||||
# pylint: disable=invalid-name
|
||||
if ffi.is_null_pointer(pointer):
|
||||
self.fail("not a non-null pointer")
|
||||
|
||||
def load_binary(self, binary_string):
|
||||
print("Load binary...")
|
||||
binary = ffi.load_module_file(binary_string)
|
||||
binary = c.pointer(binary)
|
||||
self.assertIsNotNullPointer(binary)
|
||||
return binary
|
||||
|
||||
def compile(self, binary):
|
||||
print("Compile...")
|
||||
module = ffi.wasm_module_new(self._wasm_store, binary)
|
||||
self.assertIsNotNullPointer(module)
|
||||
return module
|
||||
|
||||
def prepare_imports_local(self):
|
||||
print("Prepare imports...")
|
||||
func_type = ffi.wasm_functype_new_1_1(
|
||||
ffi.wasm_valtype_new(ffi.WASM_F32),
|
||||
ffi.wasm_valtype_new(ffi.WASM_F64),
|
||||
)
|
||||
func = ffi.wasm_func_new(self._wasm_store, func_type, callback)
|
||||
self.assertIsNotNullPointer(func)
|
||||
ffi.wasm_functype_delete(func_type)
|
||||
|
||||
glbl_type = ffi.wasm_globaltype_new(ffi.wasm_valtype_new(ffi.WASM_I32), True)
|
||||
init = ffi.wasm_i32_val(1024)
|
||||
glbl = ffi.wasm_global_new(self._wasm_store, glbl_type, init)
|
||||
self.assertIsNotNullPointer(glbl)
|
||||
ffi.wasm_globaltype_delete(glbl_type)
|
||||
|
||||
imports = ffi.wasm_extern_vec_t()
|
||||
data = ffi.list_to_carray(
|
||||
c.POINTER(ffi.wasm_extern_t),
|
||||
ffi.wasm_func_as_extern(func),
|
||||
ffi.wasm_global_as_extern(glbl),
|
||||
)
|
||||
ffi.wasm_extern_vec_new(imports, 2, data)
|
||||
imports = c.pointer(imports)
|
||||
self.assertIsNotNullPointer(imports)
|
||||
return imports
|
||||
|
||||
def instantiate(self, module, imports):
|
||||
print("Instantiate module...")
|
||||
instance = ffi.wasm_instance_new(
|
||||
self._wasm_store, module, imports, ffi.create_null_pointer(ffi.wasm_trap_t)
|
||||
)
|
||||
self.assertIsNotNone(instance)
|
||||
self.assertIsNotNullPointer(instance)
|
||||
return instance
|
||||
|
||||
def extract_exports(self, instance):
|
||||
print("Extracting exports...")
|
||||
exports = ffi.wasm_extern_vec_t()
|
||||
ffi.wasm_instance_exports(instance, exports)
|
||||
exports = c.pointer(exports)
|
||||
self.assertIsNotNullPointer(exports)
|
||||
return exports
|
||||
|
||||
def setUp(self):
|
||||
binary = self.load_binary(MODULE_BINARY)
|
||||
self.module = self.compile(binary)
|
||||
self.imports = self.prepare_imports_local()
|
||||
self.instance = self.instantiate(self.module, self.imports)
|
||||
self.exports = self.extract_exports(self.instance)
|
||||
|
||||
ffi.wasm_byte_vec_delete(binary)
|
||||
|
||||
def tearDown(self):
|
||||
if self.imports:
|
||||
ffi.wasm_extern_vec_delete(self.imports)
|
||||
|
||||
if self.exports:
|
||||
ffi.wasm_extern_vec_delete(self.exports)
|
||||
|
||||
ffi.wasm_instance_delete(self.instance)
|
||||
ffi.wasm_module_delete(self.module)
|
||||
|
||||
def test_wasm_func_call_wasm(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
print(export_list)
|
||||
|
||||
func = ffi.wasm_extern_as_func(export_list[0])
|
||||
self.assertIsNotNullPointer(func)
|
||||
|
||||
# make a call
|
||||
params = ffi.wasm_val_vec_t()
|
||||
data = ffi.list_to_carray(
|
||||
ffi.wasm_val_t,
|
||||
ffi.wasm_i32_val(1024),
|
||||
ffi.wasm_i64_val(1024 * 1024),
|
||||
)
|
||||
ffi.wasm_val_vec_new(params, 2, data)
|
||||
|
||||
results = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new_empty(results)
|
||||
|
||||
ffi.wasm_func_call(func, params, results)
|
||||
|
||||
def test_wasm_func_call_native(self):
|
||||
import_list = ffi.wasm_vec_to_list(self.imports)
|
||||
|
||||
func = ffi.wasm_extern_as_func(import_list[0])
|
||||
self.assertIsNotNullPointer(func)
|
||||
|
||||
params = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new(
|
||||
params, 1, ffi.list_to_carray(ffi.wasm_val_t, ffi.wasm_f32_val(3.14))
|
||||
)
|
||||
results = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new_uninitialized(results, 1)
|
||||
ffi.wasm_func_call(func, params, results)
|
||||
self.assertEqual(params.data[0].of.f32 * 2, results.data[0].of.f64)
|
||||
|
||||
def test_wasm_func_call_wrong_params(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
func = ffi.wasm_extern_as_func(export_list[0])
|
||||
# make a call
|
||||
params = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new_empty(params)
|
||||
results = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new_empty(results)
|
||||
trap = ffi.wasm_func_call(func, params, results)
|
||||
|
||||
self.assertIsNotNullPointer(trap)
|
||||
|
||||
def test_wasm_func_call_unlinked(self):
|
||||
ft = ffi.wasm_functype_new_0_0()
|
||||
func = ffi.wasm_func_new(self._wasm_store, ft, callback)
|
||||
params = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new_empty(params)
|
||||
results = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new_empty(results)
|
||||
trap = ffi.wasm_func_call(func, params, results)
|
||||
ffi.wasm_func_delete(func)
|
||||
|
||||
def test_wasm_global_get_wasm(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
glb = ffi.wasm_extern_as_global(export_list[1])
|
||||
self.assertIsNotNullPointer(glb)
|
||||
|
||||
# access the global
|
||||
val = ffi.wasm_val_t()
|
||||
ffi.wasm_global_get(glb, val)
|
||||
self.assertAlmostEqual(val.of.f32, 3.14, places=3)
|
||||
|
||||
def test_wasm_global_get_native(self):
|
||||
import_list = ffi.wasm_vec_to_list(self.imports)
|
||||
|
||||
glb = ffi.wasm_extern_as_global(import_list[1])
|
||||
self.assertIsNotNullPointer(glb)
|
||||
|
||||
val = ffi.wasm_val_t()
|
||||
ffi.wasm_global_get(glb, val)
|
||||
self.assertEqual(val.of.i32, 1024)
|
||||
|
||||
def test_wasm_global_get_unlinked(self):
|
||||
gt = ffi.wasm_globaltype_new(ffi.wasm_valtype_new(ffi.WASM_I32), True)
|
||||
init = ffi.wasm_i32_val(32)
|
||||
glbl = ffi.wasm_global_new(self._wasm_store, gt, init)
|
||||
val_ret = ffi.wasm_f32_val(3.14)
|
||||
ffi.wasm_global_get(glbl, val_ret)
|
||||
ffi.wasm_global_delete(glbl)
|
||||
|
||||
# val_ret wasn't touched, keep the original value
|
||||
self.assertAlmostEqual(val_ret.of.f32, 3.14, 3)
|
||||
|
||||
def test_wasm_global_get_null_val(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
glb = ffi.wasm_extern_as_global(export_list[1])
|
||||
ffi.wasm_global_get(glb, ffi.create_null_pointer(ffi.wasm_val_t))
|
||||
|
||||
def test_wasm_global_get_null_global(self):
|
||||
val = ffi.wasm_val_t()
|
||||
ffi.wasm_global_get(ffi.create_null_pointer(ffi.wasm_global_t), val)
|
||||
|
||||
def test_wasm_global_set_wasm(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
glb = ffi.wasm_extern_as_global(export_list[1])
|
||||
self.assertIsNotNullPointer(glb)
|
||||
|
||||
# access the global
|
||||
new_val = ffi.wasm_f32_val(math.e)
|
||||
ffi.wasm_global_set(glb, new_val)
|
||||
|
||||
val = ffi.wasm_val_t()
|
||||
ffi.wasm_global_get(glb, val)
|
||||
self.assertNotEqual(val.of.f32, 3.14)
|
||||
|
||||
def test_wasm_global_set_native(self):
|
||||
import_list = ffi.wasm_vec_to_list(self.imports)
|
||||
|
||||
glb = ffi.wasm_extern_as_global(import_list[1])
|
||||
self.assertIsNotNullPointer(glb)
|
||||
|
||||
new_val = ffi.wasm_i32_val(2048)
|
||||
ffi.wasm_global_set(glb, new_val)
|
||||
|
||||
val = ffi.wasm_val_t()
|
||||
ffi.wasm_global_get(glb, val)
|
||||
self.assertEqual(val, new_val)
|
||||
|
||||
def test_wasm_global_set_unlinked(self):
|
||||
gt = ffi.wasm_globaltype_new(ffi.wasm_valtype_new(ffi.WASM_I32), True)
|
||||
init = ffi.wasm_i32_val(32)
|
||||
glbl = ffi.wasm_global_new(self._wasm_store, gt, init)
|
||||
val_ret = ffi.wasm_f32_val(3.14)
|
||||
ffi.wasm_global_set(glbl, val_ret)
|
||||
ffi.wasm_global_delete(glbl)
|
||||
|
||||
def test_wasm_global_set_null_v(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
glb = ffi.wasm_extern_as_global(export_list[1])
|
||||
# access the global
|
||||
ffi.wasm_global_set(glb, ffi.create_null_pointer(ffi.wasm_val_t))
|
||||
|
||||
def test_wasm_global_set_null_global(self):
|
||||
# access the global
|
||||
new_val = ffi.wasm_f32_val(math.e)
|
||||
ffi.wasm_global_set(ffi.create_null_pointer(ffi.wasm_global_t), new_val)
|
||||
|
||||
def test_wasm_table_size(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
tbl = ffi.wasm_extern_as_table(export_list[3])
|
||||
self.assertIsNotNullPointer(tbl)
|
||||
|
||||
tbl_sz = ffi.wasm_table_size(tbl)
|
||||
self.assertEqual(tbl_sz, 1)
|
||||
|
||||
def test_wasm_table_size_unlink(self):
|
||||
vt = ffi.wasm_valtype_new(ffi.WASM_FUNCREF)
|
||||
limits = ffi.wasm_limits_new(10, 15)
|
||||
tt = ffi.wasm_tabletype_new(vt, limits)
|
||||
tbl = ffi.wasm_table_new(
|
||||
self._wasm_store, tt, ffi.create_null_pointer(ffi.wasm_ref_t)
|
||||
)
|
||||
tbl_sz = ffi.wasm_table_size(tbl)
|
||||
ffi.wasm_table_delete(tbl)
|
||||
|
||||
def test_wasm_table_size_null_table(self):
|
||||
ffi.wasm_table_size(ffi.create_null_pointer(ffi.wasm_table_t))
|
||||
|
||||
def test_wasm_table_get(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
tbl = ffi.wasm_extern_as_table(export_list[3])
|
||||
self.assertIsNotNullPointer(tbl)
|
||||
|
||||
ref = ffi.wasm_table_get(tbl, 0)
|
||||
self.assertIsNullPointer(ref)
|
||||
|
||||
ref = ffi.wasm_table_get(tbl, 4096)
|
||||
self.assertIsNullPointer(ref)
|
||||
|
||||
def test_wasm_table_get_unlinked(self):
|
||||
vt = ffi.wasm_valtype_new(ffi.WASM_FUNCREF)
|
||||
limits = ffi.wasm_limits_new(10, 15)
|
||||
tt = ffi.wasm_tabletype_new(vt, limits)
|
||||
tbl = ffi.wasm_table_new(
|
||||
self._wasm_store, tt, ffi.create_null_pointer(ffi.wasm_ref_t)
|
||||
)
|
||||
ffi.wasm_table_get(tbl, 0)
|
||||
ffi.wasm_table_delete(tbl)
|
||||
|
||||
def test_wasm_table_get_null_table(self):
|
||||
ffi.wasm_table_get(ffi.create_null_pointer(ffi.wasm_table_t), 0)
|
||||
|
||||
def test_wasm_table_get_out_of_bounds(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
tbl = ffi.wasm_extern_as_table(export_list[3])
|
||||
ffi.wasm_table_get(tbl, 1_000_000_000)
|
||||
|
||||
def test_wasm_ref(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
func = ffi.wasm_extern_as_func(export_list[0])
|
||||
self.assertIsNotNullPointer(func)
|
||||
|
||||
ref = ffi.wasm_func_as_ref(func)
|
||||
self.assertIsNotNullPointer(ref)
|
||||
|
||||
func_from_ref = ffi.wasm_ref_as_func(ref)
|
||||
self.assertEqual(
|
||||
ffi.dereference(ffi.wasm_func_type(func)),
|
||||
ffi.dereference(ffi.wasm_func_type(func_from_ref)),
|
||||
)
|
||||
|
||||
def test_wasm_table_set(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
tbl = ffi.wasm_extern_as_table(export_list[3])
|
||||
self.assertIsNotNullPointer(tbl)
|
||||
|
||||
func = ffi.wasm_extern_as_func(export_list[0])
|
||||
ref = ffi.wasm_func_as_ref(func)
|
||||
|
||||
ffi.wasm_table_set(tbl, 0, ref)
|
||||
|
||||
ref_ret = ffi.wasm_table_get(tbl, 0)
|
||||
self.assertIsNotNullPointer(ref_ret)
|
||||
func_ret = ffi.wasm_ref_as_func(ref_ret)
|
||||
self.assertEqual(
|
||||
ffi.dereference(ffi.wasm_func_type(func)),
|
||||
ffi.dereference(ffi.wasm_func_type(func_ret)),
|
||||
)
|
||||
|
||||
def test_wasm_table_set_unlinked(self):
|
||||
vt = ffi.wasm_valtype_new(ffi.WASM_FUNCREF)
|
||||
limits = ffi.wasm_limits_new(10, 15)
|
||||
tt = ffi.wasm_tabletype_new(vt, limits)
|
||||
tbl = ffi.wasm_table_new(
|
||||
self._wasm_store, tt, ffi.create_null_pointer(ffi.wasm_ref_t)
|
||||
)
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
func = ffi.wasm_extern_as_func(export_list[0])
|
||||
ref = ffi.wasm_func_as_ref(func)
|
||||
ffi.wasm_table_set(tbl, 0, ref)
|
||||
ffi.wasm_table_delete(tbl)
|
||||
|
||||
def test_wasm_table_set_null_table(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
func = ffi.wasm_extern_as_func(export_list[0])
|
||||
ref = ffi.wasm_func_as_ref(func)
|
||||
ffi.wasm_table_set(ffi.create_null_pointer(ffi.wasm_table_t), 0, ref)
|
||||
|
||||
def test_wasm_table_set_null_ref(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
tbl = ffi.wasm_extern_as_table(export_list[3])
|
||||
ffi.wasm_table_set(tbl, 0, ffi.create_null_pointer(ffi.wasm_ref_t))
|
||||
|
||||
def test_wasm_table_set_out_of_bounds(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
tbl = ffi.wasm_extern_as_table(export_list[3])
|
||||
func = ffi.wasm_extern_as_func(export_list[0])
|
||||
ref = ffi.wasm_func_as_ref(func)
|
||||
ffi.wasm_table_set(tbl, 1_000_000_000, ref)
|
||||
|
||||
def test_wasm_memory_size(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
mem = ffi.wasm_extern_as_memory(export_list[2])
|
||||
self.assertIsNotNullPointer(mem)
|
||||
|
||||
pg_sz = ffi.wasm_memory_size(mem)
|
||||
self.assertEqual(pg_sz, 1)
|
||||
|
||||
def test_wasm_memory_size_unlinked(self):
|
||||
limits = ffi.wasm_limits_new(10, 12)
|
||||
mt = ffi.wasm_memorytype_new(limits)
|
||||
mem = ffi.wasm_memory_new(self._wasm_store, mt)
|
||||
ffi.wasm_memory_size(mem)
|
||||
ffi.wasm_memory_delete(mem)
|
||||
|
||||
def test_wasm_memory_data(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
mem = ffi.wasm_extern_as_memory(export_list[2])
|
||||
self.assertIsNotNullPointer(mem)
|
||||
|
||||
data_base = ffi.wasm_memory_data(mem)
|
||||
self.assertIsNotNone(data_base)
|
||||
|
||||
def test_wasm_memory_data_unlinked(self):
|
||||
limits = ffi.wasm_limits_new(10, 12)
|
||||
mt = ffi.wasm_memorytype_new(limits)
|
||||
mem = ffi.wasm_memory_new(self._wasm_store, mt)
|
||||
ffi.wasm_memory_data(mem)
|
||||
ffi.wasm_memory_delete(mem)
|
||||
|
||||
def test_wasm_memory_data_size(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
mem = ffi.wasm_extern_as_memory(export_list[2])
|
||||
self.assertIsNotNullPointer(mem)
|
||||
|
||||
mem_sz = ffi.wasm_memory_data_size(mem)
|
||||
self.assertGreater(mem_sz, 0)
|
||||
|
||||
def test_wasm_memory_data_size_unlinked(self):
|
||||
limits = ffi.wasm_limits_new(10, 12)
|
||||
mt = ffi.wasm_memorytype_new(limits)
|
||||
mem = ffi.wasm_memory_new(self._wasm_store, mt)
|
||||
ffi.wasm_memory_data_size(mem)
|
||||
ffi.wasm_memory_delete(mem)
|
||||
|
||||
def test_wasm_trap(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
func = ffi.wasm_extern_as_func(export_list[0])
|
||||
# make a call
|
||||
params = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new_empty(params)
|
||||
results = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new_empty(results)
|
||||
|
||||
trap = ffi.wasm_func_call(func, params, results)
|
||||
self.assertIsNotNullPointer(trap)
|
||||
|
||||
message = ffi.wasm_message_t()
|
||||
ffi.wasm_trap_message(trap, message)
|
||||
self.assertIsNotNullPointer(c.pointer(message))
|
||||
|
||||
# not a function internal exception
|
||||
frame = ffi.wasm_trap_origin(trap)
|
||||
self.assertIsNullPointer(frame)
|
||||
|
||||
@unittest.skipUnless(
|
||||
TEST_WITH_WAMR_BUILD_DUMP_CALL_STACK,
|
||||
"need to enable WAMR_BUILD_DUMP_CALL_STACK",
|
||||
)
|
||||
# assertions only works if enabling WAMR_BUILD_DUMP_CALL_STACK
|
||||
def test_wasm_frame(self):
|
||||
export_list = ffi.wasm_vec_to_list(self.exports)
|
||||
func = ffi.wasm_extern_as_func(export_list[4])
|
||||
# make a call
|
||||
params = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new_empty(params)
|
||||
results = ffi.wasm_val_vec_t()
|
||||
ffi.wasm_val_vec_new_empty(results)
|
||||
|
||||
print("Making a call...")
|
||||
trap = ffi.wasm_func_call(func, params, results)
|
||||
|
||||
message = ffi.wasm_message_t()
|
||||
ffi.wasm_trap_message(trap, message)
|
||||
self.assertIsNotNullPointer(c.pointer(message))
|
||||
print(message)
|
||||
|
||||
frame = ffi.wasm_trap_origin(trap)
|
||||
self.assertIsNotNullPointer(frame)
|
||||
print(ffi.dereference(frame))
|
||||
|
||||
traces = ffi.wasm_frame_vec_t()
|
||||
ffi.wasm_trap_trace(trap, traces)
|
||||
self.assertIsNotNullPointer(c.pointer(frame))
|
||||
|
||||
instance = ffi.wasm_frame_instance(frame)
|
||||
self.assertIsNotNullPointer(instance)
|
||||
|
||||
module_offset = ffi.wasm_frame_module_offset(frame)
|
||||
|
||||
func_index = ffi.wasm_frame_func_index(frame)
|
||||
self.assertEqual(func_index, 2)
|
||||
|
||||
func_offset = ffi.wasm_frame_func_offset(frame)
|
||||
self.assertGreater(func_offset, 0)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
print("Shutting down...")
|
||||
ffi.wasm_store_delete(cls._wasm_store)
|
||||
ffi.wasm_engine_delete(cls._wasm_engine)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
1588
language-bindings/python/tests/test_basic.py
Normal file
1588
language-bindings/python/tests/test_basic.py
Normal file
File diff suppressed because it is too large
Load Diff
386
language-bindings/python/utils/bindgen.py
Normal file
386
language-bindings/python/utils/bindgen.py
Normal file
|
@ -0,0 +1,386 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
# pylint: disable=missing-class-docstring
|
||||
# pylint: disable=missing-function-docstring
|
||||
# pylint: disable=missing-module-docstring
|
||||
|
||||
"""
|
||||
- Need to run *download_wamr.py* firstly.
|
||||
- Parse *./wasm-micro-runtime/core/iwasm/include/wasm_c_api.h* and generate
|
||||
*wamr/binding.py*
|
||||
"""
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
from pycparser import c_ast, parse_file
|
||||
|
||||
WASM_C_API_HEADER = "core/iwasm/include/wasm_c_api.h"
|
||||
BINDING_PATH = "wamr/binding.py"
|
||||
# 4 spaces as default indent
|
||||
INDENT = " "
|
||||
|
||||
IGNORE_SYMOLS = (
|
||||
"wasm_engine_new_with_args",
|
||||
"wasm_valkind_is_num",
|
||||
"wasm_valkind_is_ref",
|
||||
"wasm_valtype_is_num",
|
||||
"wasm_valtype_is_ref",
|
||||
"wasm_valtype_new_i32",
|
||||
"wasm_valtype_new_i64",
|
||||
"wasm_valtype_new_f32",
|
||||
"wasm_valtype_new_f64",
|
||||
"wasm_valtype_new_anyref",
|
||||
"wasm_valtype_new_funcref",
|
||||
"wasm_functype_new_0_0",
|
||||
"wasm_functype_new_0_0",
|
||||
"wasm_functype_new_1_0",
|
||||
"wasm_functype_new_2_0",
|
||||
"wasm_functype_new_3_0",
|
||||
"wasm_functype_new_0_1",
|
||||
"wasm_functype_new_1_1",
|
||||
"wasm_functype_new_2_1",
|
||||
"wasm_functype_new_3_1",
|
||||
"wasm_functype_new_0_2",
|
||||
"wasm_functype_new_1_2",
|
||||
"wasm_functype_new_2_2",
|
||||
"wasm_functype_new_3_2",
|
||||
"wasm_val_init_ptr",
|
||||
"wasm_val_ptr",
|
||||
"wasm_val_t",
|
||||
"wasm_ref_t",
|
||||
"wasm_name_new_from_string",
|
||||
"wasm_name_new_from_string_nt",
|
||||
)
|
||||
|
||||
|
||||
class Visitor(c_ast.NodeVisitor):
|
||||
def __init__(self):
|
||||
self.type_map = {
|
||||
"_Bool": "c_bool",
|
||||
"byte_t": "c_ubyte",
|
||||
"char": "c_char",
|
||||
"errno_t": "c_int",
|
||||
"int": "c_int",
|
||||
"long": "c_long",
|
||||
"size_t": "c_size_t",
|
||||
"uint32_t": "c_uint32",
|
||||
"uint8_t": "c_uint8",
|
||||
"void": "None",
|
||||
}
|
||||
self.ret = (
|
||||
"# -*- coding: utf-8 -*-\n"
|
||||
"#!/usr/bin/env python3\n"
|
||||
"#\n"
|
||||
"# Copyright (C) 2019 Intel Corporation. All rights reserved.\n"
|
||||
"# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
|
||||
"#\n"
|
||||
"#It is a generated file. DO NOT EDIT.\n"
|
||||
"#\n"
|
||||
"from ctypes import *\n"
|
||||
"\n"
|
||||
"from .ffi import dereference, libiwasm, wasm_ref_t, wasm_val_t\n"
|
||||
"\n"
|
||||
"\n"
|
||||
)
|
||||
|
||||
def get_type_name(self, c_type):
|
||||
if isinstance(c_type, c_ast.TypeDecl):
|
||||
return self.get_type_name(c_type.type)
|
||||
elif isinstance(c_type, c_ast.PtrDecl):
|
||||
pointed_type = self.get_type_name(c_type.type)
|
||||
|
||||
if isinstance(c_type.type, c_ast.FuncDecl):
|
||||
# CFUCNTYPE is a pointer of function
|
||||
return pointed_type
|
||||
|
||||
if "None" == pointed_type:
|
||||
return "c_void_p"
|
||||
|
||||
return f"POINTER({pointed_type})"
|
||||
|
||||
elif isinstance(c_type, c_ast.ArrayDecl):
|
||||
return f"POINTER({self.get_type_name(c_type.type)})"
|
||||
elif isinstance(c_type, c_ast.IdentifierType):
|
||||
if len(c_type.names) > 1:
|
||||
raise RuntimeError(f"unexpected type with a long names: {c_type}")
|
||||
|
||||
type_name = c_type.names[0]
|
||||
|
||||
if type_name.startswith("wasm_"):
|
||||
return type_name
|
||||
|
||||
if not type_name in self.type_map:
|
||||
raise RuntimeError(f"a new type should be in type_map: {type_name}")
|
||||
|
||||
return self.type_map.get(type_name)
|
||||
elif isinstance(c_type, c_ast.Union):
|
||||
if not c_type.name:
|
||||
raise RuntimeError(f"found an anonymous union {c_type}")
|
||||
|
||||
return c_type.name
|
||||
elif isinstance(c_type, c_ast.Struct):
|
||||
if not c_type.name:
|
||||
raise RuntimeError(f"found an anonymous union {c_type}")
|
||||
|
||||
return c_type.name
|
||||
elif isinstance(c_type, c_ast.FuncDecl):
|
||||
content = "CFUNCTYPE("
|
||||
if isinstance(c_type.type, c_ast.PtrDecl):
|
||||
# there is a bug in CFUNCTYPE if the result type is a pointer
|
||||
content += "c_void_p"
|
||||
else:
|
||||
content += f"{self.get_type_name(c_type.type)}"
|
||||
content += f",{self.get_type_name(c_type.args)}" if c_type.args else ""
|
||||
content += ")"
|
||||
return content
|
||||
elif isinstance(c_type, c_ast.Decl):
|
||||
return self.get_type_name(c_type.type)
|
||||
elif isinstance(c_type, c_ast.ParamList):
|
||||
content = ",".join(
|
||||
[self.get_type_name(param.type) for param in c_type.params]
|
||||
)
|
||||
return content
|
||||
else:
|
||||
raise RuntimeError(f"unexpected type: {c_type.show()}")
|
||||
|
||||
def visit_Struct(self, node):
|
||||
# pylint: disable=invalid-name
|
||||
def gen_fields(info, indent):
|
||||
content = ""
|
||||
for k, v in info.items():
|
||||
content += f'{indent}("{k}", {v}),\n'
|
||||
return content[:-1]
|
||||
|
||||
def gen_equal(info, indent):
|
||||
content = f"{indent}return"
|
||||
for k, v in info.items():
|
||||
# not compare pointer value in __eq__
|
||||
if v.startswith("POINTER") or v.startswith("c_void_p"):
|
||||
continue
|
||||
|
||||
content += f" self.{k} == other.{k} and"
|
||||
return content[:-4]
|
||||
|
||||
def gen_repr(info, indent):
|
||||
content = f'{indent}return f"{{{{'
|
||||
for k, _ in info.items():
|
||||
content += f"{k}={{self.{k}}}, "
|
||||
content = content[:-2] + '}}"'
|
||||
return content
|
||||
|
||||
def gen_vector_repr(info, indent):
|
||||
content = f'{indent}ret = ""\n'
|
||||
content += f"{indent}for i in range(self.num_elems):\n"
|
||||
|
||||
if 1 == info["data"].count("POINTER"):
|
||||
# pointer
|
||||
content += f"{2*indent}ret += str(self.data[i])\n"
|
||||
else:
|
||||
# pointer of pointer
|
||||
content += f"{2*indent}ret += str(dereference(self.data[i]))\n"
|
||||
|
||||
content += f'{2*indent}ret += " "\n'
|
||||
content += f"{indent}return ret\n"
|
||||
return content
|
||||
|
||||
if not node.name or not node.name.lower().startswith("wasm"):
|
||||
return
|
||||
|
||||
if node.name in IGNORE_SYMOLS:
|
||||
return
|
||||
|
||||
name = node.name
|
||||
|
||||
info = {}
|
||||
if node.decls:
|
||||
for decl in node.decls:
|
||||
info[decl.name] = self.get_type_name(decl.type)
|
||||
|
||||
if info:
|
||||
self.ret += (
|
||||
f"class {name}(Structure):\n"
|
||||
f"{INDENT}_fields_ = [\n"
|
||||
f"{gen_fields(info, INDENT*2)}\n"
|
||||
f"{INDENT}]\n"
|
||||
f"\n"
|
||||
f"{INDENT}def __eq__(self, other):\n"
|
||||
f"{INDENT*2}if not isinstance(other, {name}):\n"
|
||||
f"{INDENT*3}return False\n"
|
||||
f"{gen_equal(info, INDENT*2)}\n"
|
||||
f"\n"
|
||||
f"{INDENT}def __repr__(self):\n"
|
||||
)
|
||||
self.ret += (
|
||||
f"{gen_vector_repr(info, INDENT*2)}\n"
|
||||
if name.endswith("_vec_t")
|
||||
else f"{gen_repr(info, INDENT*2)}\n"
|
||||
)
|
||||
self.ret += "\n"
|
||||
|
||||
else:
|
||||
self.ret += f"class {name}(Structure):\n{INDENT}pass\n"
|
||||
|
||||
self.ret += "\n"
|
||||
|
||||
def visit_Union(self, node):
|
||||
# pylint: disable=invalid-name
|
||||
print(f"Union: {node.show()}")
|
||||
|
||||
def visit_Typedef(self, node):
|
||||
# pylint: disable=invalid-name
|
||||
# system defined
|
||||
if not node.name:
|
||||
return
|
||||
|
||||
if not node.name.startswith("wasm_"):
|
||||
return
|
||||
|
||||
if node.name in IGNORE_SYMOLS:
|
||||
return
|
||||
|
||||
self.visit(node.type)
|
||||
|
||||
if node.name == self.get_type_name(node.type):
|
||||
return
|
||||
else:
|
||||
self.ret += f"{node.name} = {self.get_type_name(node.type)}\n"
|
||||
self.ret += "\n"
|
||||
|
||||
def visit_FuncDecl(self, node):
|
||||
# pylint: disable=invalid-name
|
||||
restype = self.get_type_name(node.type)
|
||||
|
||||
if isinstance(node.type, c_ast.TypeDecl):
|
||||
func_name = node.type.declname
|
||||
elif isinstance(node.type, c_ast.PtrDecl):
|
||||
func_name = node.type.type.declname
|
||||
else:
|
||||
raise RuntimeError(f"unexpected type in FuncDecl: {type}")
|
||||
|
||||
if not func_name.startswith("wasm_") or func_name.endswith("_t"):
|
||||
return
|
||||
|
||||
if func_name in IGNORE_SYMOLS:
|
||||
return
|
||||
|
||||
params_len = 0
|
||||
for arg in node.args.params:
|
||||
# ignore void but not void*
|
||||
if isinstance(arg.type, c_ast.TypeDecl):
|
||||
type_name = self.get_type_name(arg.type)
|
||||
if "None" == type_name:
|
||||
continue
|
||||
|
||||
params_len += 1
|
||||
|
||||
args = (
|
||||
"" if not params_len else ",".join([f"arg{i}" for i in range(params_len)])
|
||||
)
|
||||
argtypes = f"[{self.get_type_name(node.args)}]" if params_len else "None"
|
||||
|
||||
self.ret += (
|
||||
f"def {func_name}({args}):\n"
|
||||
f"{INDENT}_{func_name} = libiwasm.{func_name}\n"
|
||||
f"{INDENT}_{func_name}.restype = {restype}\n"
|
||||
f"{INDENT}_{func_name}.argtypes = {argtypes}\n"
|
||||
f"{INDENT}return _{func_name}({args})\n"
|
||||
)
|
||||
self.ret += "\n"
|
||||
|
||||
def visit_Enum(self, node):
|
||||
# pylint: disable=invalid-name
|
||||
elem_value = 0
|
||||
# generate enum elementes directly as consts with values
|
||||
for i, elem in enumerate(node.values.enumerators):
|
||||
self.ret += f"{elem.name}"
|
||||
|
||||
if elem.value:
|
||||
elem_value = int(elem.value.value)
|
||||
else:
|
||||
if 0 == i:
|
||||
elem_value = 0
|
||||
else:
|
||||
elem_value += 1
|
||||
|
||||
self.ret += f" = {elem_value}\n"
|
||||
|
||||
self.ret += "\n"
|
||||
|
||||
|
||||
def preflight_check(workspace):
|
||||
wamr_repo = workspace.joinpath("wasm-micro-runtime")
|
||||
file_check_list = [
|
||||
wamr_repo.exists(),
|
||||
wamr_repo.joinpath(WASM_C_API_HEADER).exists(),
|
||||
]
|
||||
|
||||
if not all(file_check_list):
|
||||
print(
|
||||
"please run utils/download_wamr.py to download the repo, or re-download the repo"
|
||||
)
|
||||
return False
|
||||
|
||||
if not shutil.which("gcc"):
|
||||
print("please install gcc")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def do_parse(workspace):
|
||||
filename = workspace.joinpath(WASM_C_API_HEADER)
|
||||
filename = str(filename)
|
||||
|
||||
ast = parse_file(
|
||||
filename,
|
||||
use_cpp=True,
|
||||
cpp_path="gcc",
|
||||
cpp_args=[
|
||||
"-E",
|
||||
"-D__attribute__(x)=",
|
||||
"-D__asm__(x)=",
|
||||
"-D__asm(x)=",
|
||||
"-D__builtin_va_list=int",
|
||||
"-D__extension__=",
|
||||
"-D__inline__=",
|
||||
"-D__restrict=",
|
||||
"-D__restrict__=",
|
||||
"-D_Static_assert(x, y)=",
|
||||
"-D__signed=",
|
||||
"-D__volatile__(x)=",
|
||||
"-Dstatic_assert(x, y)=",
|
||||
],
|
||||
)
|
||||
|
||||
ast_visitor = Visitor()
|
||||
ast_visitor.visit(ast)
|
||||
return ast_visitor.ret
|
||||
|
||||
|
||||
def main():
|
||||
current_file = pathlib.Path(__file__)
|
||||
if current_file.is_symlink():
|
||||
current_file = pathlib.Path(os.readlink(current_file))
|
||||
|
||||
current_dir = current_file.parent.resolve()
|
||||
root_dir = current_dir.joinpath("..").resolve()
|
||||
|
||||
if not preflight_check(root_dir):
|
||||
return False
|
||||
|
||||
wamr_repo = root_dir.joinpath("wasm-micro-runtime")
|
||||
binding_file_path = root_dir.joinpath(BINDING_PATH)
|
||||
with open(binding_file_path, "wt", encoding="utf-8") as binding_file:
|
||||
binding_file.write(do_parse(wamr_repo))
|
||||
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(0 if main() else 1)
|
7
language-bindings/python/wamr/__init__.py
Normal file
7
language-bindings/python/wamr/__init__.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
__all__ = ["ffi"]
|
2020
language-bindings/python/wamr/binding.py
Normal file
2020
language-bindings/python/wamr/binding.py
Normal file
File diff suppressed because it is too large
Load Diff
642
language-bindings/python/wamr/ffi.py
Normal file
642
language-bindings/python/wamr/ffi.py
Normal file
|
@ -0,0 +1,642 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
# pylint: disable=missing-class-docstring
|
||||
# pylint: disable=missing-function-docstring
|
||||
# pylint: disable=missing-module-docstring
|
||||
|
||||
import ctypes as c
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
#
|
||||
# Prologue. Dependencies of binding
|
||||
#
|
||||
|
||||
# how to open the library file of WAMR
|
||||
|
||||
if sys.platform == "linux":
|
||||
BUILDING_DIR = "product-mini/platforms/linux/build"
|
||||
LIBRARY_NAME = "libiwasm.so"
|
||||
elif sys.platform == "win32":
|
||||
BUILDING_DIR = "product-mini/platforms/windows/build"
|
||||
LIBRARY_NAME = "iwasm.dll"
|
||||
elif sys.platform == "darwin":
|
||||
BUILDING_DIR = "product-mini/platforms/darwin/build"
|
||||
LIBRARY_NAME = "libiwasm.dylib"
|
||||
else:
|
||||
raise RuntimeError(f"unsupported platform `{sys.platform}`")
|
||||
|
||||
# FIXME: should load libiwasm.so from current system library path
|
||||
current_file = Path(__file__)
|
||||
if current_file.is_symlink():
|
||||
current_file = Path(os.readlink(current_file))
|
||||
current_dir = current_file.parent.resolve()
|
||||
root_dir = current_dir.parent.parent.parent.parent.resolve()
|
||||
wamr_dir = root_dir.joinpath("wasm-micro-runtime").resolve()
|
||||
if not wamr_dir.exists():
|
||||
raise RuntimeError(f"not found the repo of wasm-micro-runtime under {root_dir}")
|
||||
|
||||
libpath = wamr_dir.joinpath(BUILDING_DIR).joinpath(LIBRARY_NAME).resolve()
|
||||
if not libpath.exists():
|
||||
raise RuntimeError(f"not found precompiled wamr library at {libpath}")
|
||||
|
||||
print(f"loading WAMR library from {libpath} ...")
|
||||
libiwasm = c.cdll.LoadLibrary(libpath)
|
||||
|
||||
|
||||
class wasm_ref_t(c.Structure):
|
||||
# pylint: disable=invalid-name
|
||||
pass
|
||||
|
||||
|
||||
class wasm_val_union(c.Union):
|
||||
# pylint: disable=invalid-name
|
||||
_fields_ = [
|
||||
("i32", c.c_int32),
|
||||
("i64", c.c_int64),
|
||||
("f32", c.c_float),
|
||||
("f64", c.c_double),
|
||||
("ref", c.POINTER(wasm_ref_t)),
|
||||
]
|
||||
|
||||
|
||||
class wasm_val_t(c.Structure):
|
||||
# pylint: disable=invalid-name
|
||||
_fields_ = [
|
||||
("kind", c.c_uint8),
|
||||
("of", wasm_val_union),
|
||||
]
|
||||
|
||||
|
||||
def dereference(p):
|
||||
# pylint: disable=protected-access
|
||||
if not isinstance(p, c._Pointer):
|
||||
raise RuntimeError("not a pointer")
|
||||
return p.contents
|
||||
|
||||
|
||||
# HELPERs
|
||||
def create_null_pointer(struct_type):
|
||||
return c.POINTER(struct_type)()
|
||||
|
||||
|
||||
def is_null_pointer(c_pointer):
|
||||
# pylint: disable=protected-access
|
||||
if isinstance(c_pointer, c._Pointer):
|
||||
return False if c_pointer else True
|
||||
else:
|
||||
raise RuntimeError("not a pointer")
|
||||
|
||||
|
||||
def wasm_vec_to_list(vec):
|
||||
"""
|
||||
Converts a vector or a POINTER(vector) to a list
|
||||
vector of type pointers -> list of type pointers
|
||||
"""
|
||||
known_vec_type = [
|
||||
wasm_byte_vec_t,
|
||||
wasm_valtype_vec_t,
|
||||
wasm_functype_vec_t,
|
||||
wasm_globaltype_vec_t,
|
||||
wasm_tabletype_vec_t,
|
||||
wasm_memorytype_vec_t,
|
||||
wasm_externtype_vec_t,
|
||||
wasm_importtype_vec_t,
|
||||
wasm_exporttype_vec_t,
|
||||
wasm_val_vec_t,
|
||||
wasm_frame_vec_t,
|
||||
wasm_extern_vec_t,
|
||||
]
|
||||
known_vec_pointer_type = [POINTER(type) for type in known_vec_type]
|
||||
|
||||
if any([isinstance(vec, type) for type in known_vec_pointer_type]):
|
||||
vec = dereference(vec)
|
||||
return [vec.data[i] for i in range(vec.num_elems)]
|
||||
elif any([isinstance(vec, type) for type in known_vec_type]):
|
||||
return [vec.data[i] for i in range(vec.num_elems)]
|
||||
else:
|
||||
raise RuntimeError("not a known vector type")
|
||||
|
||||
|
||||
def list_to_carray(elem_type, *args):
|
||||
"""
|
||||
Converts a python list into a C array
|
||||
"""
|
||||
data = (elem_type * len(args))(*args)
|
||||
return data
|
||||
|
||||
|
||||
def load_module_file(wasm_content):
|
||||
binary = wasm_byte_vec_t()
|
||||
wasm_byte_vec_new_uninitialized(binary, len(wasm_content))
|
||||
# has to use malloced memory.
|
||||
c.memmove(binary.data, wasm_content, len(wasm_content))
|
||||
binary.num_elems = len(wasm_content)
|
||||
return binary
|
||||
|
||||
|
||||
#
|
||||
# Enhancment of binding
|
||||
#
|
||||
|
||||
from .binding import *
|
||||
|
||||
# Built-in functions for Structure
|
||||
|
||||
|
||||
wasm_finalizer = CFUNCTYPE(None, c_void_p)
|
||||
|
||||
|
||||
def __repr_wasm_limits_t(self):
|
||||
return f"{self.min:#x} {self.max:#x}"
|
||||
|
||||
|
||||
# overwrite
|
||||
wasm_limits_t.__repr__ = __repr_wasm_limits_t
|
||||
|
||||
|
||||
def __compare_wasm_valtype_t(self, other):
|
||||
if not isinstance(other, wasm_valtype_t):
|
||||
return False
|
||||
|
||||
return wasm_valtype_kind(byref(self)) == wasm_valtype_kind(byref(other))
|
||||
|
||||
|
||||
def __repr_wasm_valtype_t(self):
|
||||
val_kind = wasm_valtype_kind(byref(self))
|
||||
if WASM_I32 == val_kind:
|
||||
return "i32"
|
||||
elif WASM_I64 == val_kind:
|
||||
return "i64"
|
||||
elif WASM_F32 == val_kind:
|
||||
return "f32"
|
||||
elif WASM_F64 == val_kind:
|
||||
return "f64"
|
||||
elif WASM_FUNCREF == val_kind:
|
||||
return "funcref"
|
||||
else:
|
||||
return "anyref"
|
||||
|
||||
|
||||
wasm_valtype_t.__eq__ = __compare_wasm_valtype_t
|
||||
wasm_valtype_t.__repr__ = __repr_wasm_valtype_t
|
||||
|
||||
|
||||
def __compare_wasm_byte_vec_t(self, other):
|
||||
if not isinstance(other, wasm_byte_vec_t):
|
||||
return False
|
||||
|
||||
if self.num_elems != other.num_elems:
|
||||
return False
|
||||
|
||||
self_data = bytes(self.data[: self.num_elems])
|
||||
other_data = bytes(other.data[: other.num_elems])
|
||||
return self_data.decode() == other_data.decode()
|
||||
|
||||
|
||||
def __repr_wasm_byte_vec_t(self):
|
||||
data = bytes(self.data[: self.num_elems])
|
||||
return data.decode() if self.size else ""
|
||||
|
||||
|
||||
wasm_byte_vec_t.__eq__ = __compare_wasm_byte_vec_t
|
||||
wasm_byte_vec_t.__repr__ = __repr_wasm_byte_vec_t
|
||||
|
||||
|
||||
def __compare_wasm_functype_t(self, other):
|
||||
if not isinstance(other, wasm_functype_t):
|
||||
return False
|
||||
|
||||
params1 = dereference(wasm_functype_params(byref(self)))
|
||||
params2 = dereference(wasm_functype_params(byref(other)))
|
||||
results1 = dereference(wasm_functype_results(byref(self)))
|
||||
results2 = dereference(wasm_functype_results(byref(other)))
|
||||
return params1 == params2 and results1 == results2
|
||||
|
||||
|
||||
def __repr_wasm_functype_t(self):
|
||||
params = dereference(wasm_functype_params(byref(self)))
|
||||
results = dereference(wasm_functype_results(byref(self)))
|
||||
params = f" (params {params})" if params.size else ""
|
||||
results = f" (results {results})" if results.size else ""
|
||||
return f"(func{params}{results})"
|
||||
|
||||
|
||||
wasm_functype_t.__eq__ = __compare_wasm_functype_t
|
||||
wasm_functype_t.__repr__ = __repr_wasm_functype_t
|
||||
|
||||
|
||||
def __compare_wasm_globaltype_t(self, other):
|
||||
if not isinstance(other, wasm_globaltype_t):
|
||||
return False
|
||||
|
||||
content1 = dereference(wasm_globaltype_content(byref(self)))
|
||||
content2 = dereference(wasm_globaltype_content(byref(other)))
|
||||
mutability1 = wasm_globaltype_mutability(byref(self))
|
||||
mutability2 = wasm_globaltype_mutability(byref(other))
|
||||
return content1 == content2 and mutability1 == mutability2
|
||||
|
||||
|
||||
def __repr_wasm_globaltype_t(self):
|
||||
mutability = f"{wasm_globaltype_mutability(byref(self))}"
|
||||
content = f"{dereference(wasm_globaltype_content(byref(self)))}"
|
||||
return f"(global{' mut ' if mutability else ' '}{content})"
|
||||
|
||||
|
||||
wasm_globaltype_t.__eq__ = __compare_wasm_globaltype_t
|
||||
wasm_globaltype_t.__repr__ = __repr_wasm_globaltype_t
|
||||
|
||||
|
||||
def __compare_wasm_tabletype_t(self, other):
|
||||
if not isinstance(other, wasm_tabletype_t):
|
||||
return False
|
||||
|
||||
element1 = dereference(wasm_tabletype_element(byref(self)))
|
||||
element2 = dereference(wasm_tabletype_element(byref(other)))
|
||||
limits1 = dereference(wasm_tabletype_limits(byref(self)))
|
||||
limits2 = dereference(wasm_tabletype_limits(byref(other)))
|
||||
return element1 == element2 and limits1 == limits2
|
||||
|
||||
|
||||
def __repr_wasm_tabletype_t(self):
|
||||
element = dereference(wasm_tabletype_element(byref(self)))
|
||||
limit = dereference(wasm_tabletype_limits(byref(self)))
|
||||
return f"(table {limit} {element})"
|
||||
|
||||
|
||||
wasm_tabletype_t.__eq__ = __compare_wasm_tabletype_t
|
||||
wasm_tabletype_t.__repr__ = __repr_wasm_tabletype_t
|
||||
|
||||
|
||||
def __compare_wasm_memorytype_t(self, other):
|
||||
if not isinstance(other, wasm_memorytype_t):
|
||||
return False
|
||||
|
||||
limits1 = dereference(wasm_memorytype_limits(byref(self)))
|
||||
limits2 = dereference(wasm_memorytype_limits(byref(other)))
|
||||
return limits1 == limits2
|
||||
|
||||
|
||||
def __repr_wasm_memorytype_t(self):
|
||||
limit = dereference(wasm_memorytype_limits(byref(self)))
|
||||
return f"(memory {limit})"
|
||||
|
||||
|
||||
wasm_memorytype_t.__eq__ = __compare_wasm_memorytype_t
|
||||
wasm_memorytype_t.__repr__ = __repr_wasm_memorytype_t
|
||||
|
||||
|
||||
def __compare_wasm_externtype_t(self, other):
|
||||
if not isinstance(other, wasm_externtype_t):
|
||||
return False
|
||||
|
||||
if wasm_externtype_kind(byref(self)) != wasm_externtype_kind(byref(other)):
|
||||
return False
|
||||
|
||||
extern_kind = wasm_externtype_kind(byref(self))
|
||||
if WASM_EXTERN_FUNC == extern_kind:
|
||||
return dereference(wasm_externtype_as_functype(self)) == dereference(
|
||||
wasm_externtype_as_functype(other)
|
||||
)
|
||||
elif WASM_EXTERN_GLOBAL == extern_kind:
|
||||
return dereference(wasm_externtype_as_globaltype(self)) == dereference(
|
||||
wasm_externtype_as_globaltype(other)
|
||||
)
|
||||
elif WASM_EXTERN_MEMORY == extern_kind:
|
||||
return dereference(wasm_externtype_as_memorytype(self)) == dereference(
|
||||
wasm_externtype_as_memorytype(other)
|
||||
)
|
||||
elif WASM_EXTERN_TABLE == extern_kind:
|
||||
return dereference(wasm_externtype_as_tabletype(self)) == dereference(
|
||||
wasm_externtype_as_tabletype(other)
|
||||
)
|
||||
else:
|
||||
raise RuntimeError("not a valid wasm_externtype_t")
|
||||
|
||||
|
||||
def __repr_wasm_externtype_t(self):
|
||||
extern_kind = wasm_externtype_kind(byref(self))
|
||||
if WASM_EXTERN_FUNC == extern_kind:
|
||||
return str(dereference(wasm_externtype_as_functype(byref(self))))
|
||||
elif WASM_EXTERN_GLOBAL == extern_kind:
|
||||
return str(dereference(wasm_externtype_as_globaltype(byref(self))))
|
||||
elif WASM_EXTERN_MEMORY == extern_kind:
|
||||
return str(dereference(wasm_externtype_as_memorytype(byref(self))))
|
||||
elif WASM_EXTERN_TABLE == extern_kind:
|
||||
return str(dereference(wasm_externtype_as_tabletype(byref(self))))
|
||||
else:
|
||||
raise RuntimeError("not a valid wasm_externtype_t")
|
||||
|
||||
|
||||
wasm_externtype_t.__eq__ = __compare_wasm_externtype_t
|
||||
wasm_externtype_t.__repr__ = __repr_wasm_externtype_t
|
||||
|
||||
|
||||
def __compare_wasm_importtype_t(self, other):
|
||||
if not isinstance(other, wasm_importtype_t):
|
||||
return False
|
||||
|
||||
if dereference(wasm_importtype_module(self)) != dereference(
|
||||
wasm_importtype_module(other)
|
||||
):
|
||||
return False
|
||||
|
||||
if dereference(wasm_importtype_name(self)) != dereference(
|
||||
wasm_importtype_name(other)
|
||||
):
|
||||
return False
|
||||
|
||||
self_type = dereference(wasm_importtype_type(byref(self)))
|
||||
other_type = dereference(wasm_importtype_type(byref(other)))
|
||||
return self_type == other_type
|
||||
|
||||
|
||||
def __repr_wasm_importtype_t(self):
|
||||
module = wasm_importtype_module(byref(self))
|
||||
name = wasm_importtype_name(byref(self))
|
||||
extern_type = wasm_importtype_type(byref(self))
|
||||
return f'(import "{dereference(module)}" "{dereference(name)}" {dereference(extern_type)})'
|
||||
|
||||
|
||||
wasm_importtype_t.__eq__ = __compare_wasm_importtype_t
|
||||
wasm_importtype_t.__repr__ = __repr_wasm_importtype_t
|
||||
|
||||
|
||||
def __compare_wasm_exporttype_t(self, other):
|
||||
if not isinstance(other, wasm_exporttype_t):
|
||||
return False
|
||||
|
||||
self_name = dereference(wasm_exporttype_name(byref(self)))
|
||||
other_name = dereference(wasm_exporttype_name(byref(other)))
|
||||
if self_name != other_name:
|
||||
return False
|
||||
|
||||
self_type = dereference(wasm_exporttype_type(byref(self)))
|
||||
other_type = dereference(wasm_exporttype_type(byref(other)))
|
||||
return self_type == other_type
|
||||
|
||||
|
||||
def __repr_wasm_exporttype_t(self):
|
||||
name = wasm_exporttype_name(byref(self))
|
||||
extern_type = wasm_exporttype_type(byref(self))
|
||||
return f'(export "{dereference(name)}" {dereference(extern_type)})'
|
||||
|
||||
|
||||
wasm_exporttype_t.__eq__ = __compare_wasm_exporttype_t
|
||||
wasm_exporttype_t.__repr__ = __repr_wasm_exporttype_t
|
||||
|
||||
|
||||
def __compare_wasm_val_t(self, other):
|
||||
if not isinstance(other, wasm_val_t):
|
||||
return False
|
||||
|
||||
if self.kind != other.kind:
|
||||
return False
|
||||
|
||||
if WASM_I32 == self.kind:
|
||||
return self.of.i32 == other.of.i32
|
||||
elif WASM_I64 == self.kind:
|
||||
return self.of.i64 == other.of.i64
|
||||
elif WASM_F32 == self.kind:
|
||||
return self.of.f32 == other.of.f32
|
||||
elif WASM_F64 == self.kind:
|
||||
return self.of.f64 == other.of.f63
|
||||
elif WASM_ANYREF == self.kind:
|
||||
raise RuntimeError("FIXME")
|
||||
else:
|
||||
raise RuntimeError("not a valid val kind")
|
||||
|
||||
|
||||
def __repr_wasm_val_t(self):
|
||||
if WASM_I32 == self.kind:
|
||||
return f"i32 {self.of.i32}"
|
||||
elif WASM_I64 == self.kind:
|
||||
return f"i64 {self.of.i64}"
|
||||
elif WASM_F32 == self.kind:
|
||||
return f"f32 {self.of.f32}"
|
||||
elif WASM_F64 == self.kind:
|
||||
return f"f64 {self.of.f64}"
|
||||
elif WASM_ANYREF == self.kind:
|
||||
return f"anyref {self.of.ref}"
|
||||
else:
|
||||
raise RuntimeError("not a valid val kind")
|
||||
|
||||
|
||||
wasm_val_t.__repr__ = __repr_wasm_val_t
|
||||
wasm_val_t.__eq__ = __compare_wasm_val_t
|
||||
|
||||
|
||||
def __repr_wasm_trap_t(self):
|
||||
message = wasm_message_t()
|
||||
wasm_trap_message(self, message)
|
||||
return f'(trap "{str(message)}")'
|
||||
|
||||
|
||||
wasm_trap_t.__repr__ = __repr_wasm_trap_t
|
||||
|
||||
|
||||
def __repr_wasm_frame_t(self):
|
||||
instance = wasm_frame_instance(self)
|
||||
module_offset = wasm_frame_module_offset(self)
|
||||
func_index = wasm_frame_func_index(self)
|
||||
func_offset = wasm_frame_func_offset(self)
|
||||
return f"> module:{module_offset:#x} => func#{func_index:#x}.{func_offset:#x}"
|
||||
|
||||
|
||||
wasm_frame_t.__repr__ = __repr_wasm_frame_t
|
||||
|
||||
|
||||
def __repr_wasm_module_t(self):
|
||||
imports = wasm_importtype_vec_t()
|
||||
wasm_module_imports(self, imports)
|
||||
|
||||
exports = wasm_exporttype_vec_t()
|
||||
wasm_module_exports(self, exports)
|
||||
|
||||
ret = "(module"
|
||||
ret += str(imports).replace("(import", "\n (import")
|
||||
ret += str(exports).replace("(export", "\n (export")
|
||||
ret += "\n)"
|
||||
return ret
|
||||
|
||||
|
||||
wasm_module_t.__repr__ = __repr_wasm_module_t
|
||||
|
||||
|
||||
def __repr_wasm_instance_t(self):
|
||||
exports = wasm_extern_vec_t()
|
||||
wasm_instance_exports(self, exports)
|
||||
|
||||
ret = "(instance"
|
||||
ret += str(exports).replace("(export", "\n (export")
|
||||
ret += "\n)"
|
||||
return ret
|
||||
|
||||
|
||||
wasm_instance_t.__repr__ = __repr_wasm_instance_t
|
||||
|
||||
|
||||
def __repr_wasm_func_t(self):
|
||||
ft = wasm_func_type(self)
|
||||
return f"{str(dereference(ft))[:-1]} ... )"
|
||||
|
||||
|
||||
wasm_func_t.__repr__ = __repr_wasm_func_t
|
||||
|
||||
|
||||
def __repr_wasm_global_t(self):
|
||||
gt = wasm_global_type(self)
|
||||
return f"{str(dereference(gt))[:-1]} ... )"
|
||||
|
||||
|
||||
wasm_global_t.__repr__ = __repr_wasm_global_t
|
||||
|
||||
|
||||
def __repr_wasm_table_t(self):
|
||||
tt = wasm_table_type(self)
|
||||
return f"{str(dereference(tt))[:-1]} ... )"
|
||||
|
||||
|
||||
wasm_table_t.__repr__ = __repr_wasm_table_t
|
||||
|
||||
|
||||
def __repr_wasm_memory_t(self):
|
||||
mt = wasm_memory_type(self)
|
||||
return f"{str(dereference(mt))[:-1]} ... )"
|
||||
|
||||
|
||||
wasm_memory_t.__repr__ = __repr_wasm_memory_t
|
||||
|
||||
|
||||
def __repr_wasm_extern_t(self):
|
||||
ext_type = wasm_extern_type(self)
|
||||
ext_kind = wasm_extern_kind(self)
|
||||
|
||||
ret = "(export "
|
||||
if WASM_EXTERN_FUNC == ext_kind:
|
||||
ft = wasm_externtype_as_functype(ext_type)
|
||||
ret += str(dereference(ft))
|
||||
elif WASM_EXTERN_GLOBAL == ext_kind:
|
||||
gt = wasm_externtype_as_globaltype(ext_type)
|
||||
ret += str(dereference(gt))
|
||||
elif WASM_EXTERN_MEMORY == ext_kind:
|
||||
mt = wasm_externtype_as_memorytype(ext_type)
|
||||
ret += str(dereference(mt))
|
||||
elif WASM_EXTERN_TABLE == ext_kind:
|
||||
tt = wasm_externtype_as_tabletype(ext_type)
|
||||
ret += str(dereference(tt))
|
||||
else:
|
||||
raise RuntimeError("not a valid extern kind")
|
||||
ret += ")"
|
||||
return ret
|
||||
|
||||
|
||||
wasm_extern_t.__repr__ = __repr_wasm_extern_t
|
||||
|
||||
|
||||
# Function Types construction short-hands
|
||||
def wasm_name_new_from_string(s):
|
||||
name = wasm_name_t()
|
||||
data = ((c.c_ubyte) * len(s)).from_buffer_copy(s.encode())
|
||||
wasm_byte_vec_new(byref(name), len(s), data)
|
||||
return name
|
||||
|
||||
|
||||
def __wasm_functype_new(param_list, result_list):
|
||||
def __list_to_wasm_valtype_vec(l):
|
||||
vec = wasm_valtype_vec_t()
|
||||
|
||||
if not l:
|
||||
wasm_valtype_vec_new_empty(byref(vec))
|
||||
else:
|
||||
data_type = POINTER(wasm_valtype_t) * len(l)
|
||||
data = data_type()
|
||||
for i in range(len(l)):
|
||||
data[i] = l[i]
|
||||
wasm_valtype_vec_new(byref(vec), len(l), data)
|
||||
|
||||
return vec
|
||||
|
||||
params = __list_to_wasm_valtype_vec(param_list)
|
||||
results = __list_to_wasm_valtype_vec(result_list)
|
||||
return wasm_functype_new(byref(params), byref(results))
|
||||
|
||||
|
||||
def wasm_functype_new_0_0():
|
||||
return __wasm_functype_new([], [])
|
||||
|
||||
|
||||
def wasm_functype_new_1_0(p1):
|
||||
return __wasm_functype_new([p1], [])
|
||||
|
||||
|
||||
def wasm_functype_new_2_0(p1, p2):
|
||||
return __wasm_functype_new([p1, p2], [])
|
||||
|
||||
|
||||
def wasm_functype_new_3_0(p1, p2, p3):
|
||||
return __wasm_functype_new([p1, p2, p3], [])
|
||||
|
||||
|
||||
def wasm_functype_new_0_1(r1):
|
||||
return __wasm_functype_new([], [r1])
|
||||
|
||||
|
||||
def wasm_functype_new_1_1(p1, r1):
|
||||
return __wasm_functype_new([p1], [r1])
|
||||
|
||||
|
||||
def wasm_functype_new_2_1(p1, p2, r1):
|
||||
return __wasm_functype_new([p1, p2], [r1])
|
||||
|
||||
|
||||
def wasm_functype_new_3_1(p1, p2, p3, r1):
|
||||
return __wasm_functype_new([p1, p2, p3], [r1])
|
||||
|
||||
|
||||
def wasm_limits_new(min, max):
|
||||
limit = wasm_limits_t()
|
||||
limit.min = min
|
||||
limit.max = max
|
||||
return c.pointer(limit)
|
||||
|
||||
|
||||
def wasm_i32_val(i):
|
||||
v = wasm_val_t()
|
||||
v.kind = WASM_I32
|
||||
v.of.i32 = i
|
||||
return v
|
||||
|
||||
|
||||
def wasm_i64_val(i):
|
||||
v = wasm_val_t()
|
||||
v.kind = WASM_I64
|
||||
v.of.i64 = i
|
||||
return v
|
||||
|
||||
|
||||
def wasm_f32_val(z):
|
||||
v = wasm_val_t()
|
||||
v.kind = WASM_F32
|
||||
v.of.f32 = z
|
||||
return v
|
||||
|
||||
|
||||
def wasm_f64_val(z):
|
||||
v = wasm_val_t()
|
||||
v.kind = WASM_F64
|
||||
v.of.f64 = z
|
||||
return v
|
||||
|
||||
|
||||
def wasm_func_cb_decl(func):
|
||||
return wasm_func_callback_t(func)
|
||||
|
||||
|
||||
def wasm_func_with_env_cb_decl(func):
|
||||
return wasm_func_callback_with_env_t(func)
|
|
@ -160,6 +160,12 @@ else
|
|||
CFLAGS += -DWASM_ENABLE_BULK_MEMORY=0
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_PERF_PROFILING),y)
|
||||
CFLAGS += -DWASM_ENABLE_PERF_PROFILING=1
|
||||
else
|
||||
CFLAGS += -DWASM_ENABLE_PERF_PROFILING=0
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_MEMORY_PROFILING),y)
|
||||
CFLAGS += -DWASM_ENABLE_MEMORY_PROFILING=1
|
||||
else
|
||||
|
@ -174,10 +180,27 @@ endif
|
|||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN),y)
|
||||
CFLAGS += -DWASM_ENABLE_LIBC_BUILTIN=1
|
||||
CSRCS += libc_builtin_wrapper.c
|
||||
VPATH += $(IWASM_ROOT)/libraries/libc-builtin
|
||||
else
|
||||
CFLAGS += -DWASM_ENABLE_LIBC_BUILTIN=0
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_LIBC_WASI),y)
|
||||
CFLAGS += -DWASM_ENABLE_LIBC_WASI=1
|
||||
CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src
|
||||
CFLAGS += -I$(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/include
|
||||
CSRCS += posix_socket.c
|
||||
CSRCS += libc_wasi_wrapper.c
|
||||
VPATH += $(IWASM_ROOT)/libraries/libc-wasi
|
||||
CSRCS += posix.c
|
||||
CSRCS += random.c
|
||||
CSRCS += str.c
|
||||
VPATH += $(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src
|
||||
else
|
||||
CFLAGS += -DWASM_ENABLE_LIBC_WASI=0
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_MULTI_MODULE),y)
|
||||
CFLAGS += -DWASM_ENABLE_MULTI_MODULE=1
|
||||
else
|
||||
|
@ -253,7 +276,6 @@ CSRCS += nuttx_platform.c \
|
|||
bh_vector.c \
|
||||
bh_read_file.c \
|
||||
runtime_timer.c \
|
||||
libc_builtin_wrapper.c \
|
||||
wasm_application.c \
|
||||
wasm_runtime_common.c \
|
||||
wasm_native.c \
|
||||
|
@ -272,7 +294,6 @@ VPATH += $(SHARED_ROOT)/utils/uncommon
|
|||
VPATH += $(IWASM_ROOT)/common
|
||||
VPATH += $(IWASM_ROOT)/interpreter
|
||||
VPATH += $(IWASM_ROOT)/libraries
|
||||
VPATH += $(IWASM_ROOT)/libraries/libc-builtin
|
||||
VPATH += $(IWASM_ROOT)/libraries/lib-pthread
|
||||
VPATH += $(IWASM_ROOT)/common/arch
|
||||
VPATH += $(IWASM_ROOT)/aot
|
||||
|
|
|
@ -98,7 +98,7 @@ app_instance_func(wasm_module_inst_t module_inst, const char *func_name)
|
|||
static char **
|
||||
split_string(char *str, int *count)
|
||||
{
|
||||
char **res = NULL;
|
||||
char **res = NULL, **res1;
|
||||
char *p;
|
||||
int idx = 0;
|
||||
|
||||
|
@ -106,16 +106,18 @@ split_string(char *str, int *count)
|
|||
do {
|
||||
p = strtok(str, " ");
|
||||
str = NULL;
|
||||
res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1));
|
||||
res1 = res;
|
||||
res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1));
|
||||
if (res == NULL) {
|
||||
free(res1);
|
||||
return NULL;
|
||||
}
|
||||
res[idx++] = p;
|
||||
} while (p);
|
||||
|
||||
/**
|
||||
* since the function name,
|
||||
* res[0] might be contains a '\' to indicate a space
|
||||
* Due to the function name,
|
||||
* res[0] might contain a '\' to indicate a space
|
||||
* func\name -> func name
|
||||
*/
|
||||
p = strchr(res[0], '\\');
|
||||
|
|
|
@ -84,7 +84,7 @@ app_instance_func(wasm_module_inst_t module_inst, const char *func_name)
|
|||
static char **
|
||||
split_string(char *str, int *count)
|
||||
{
|
||||
char **res = NULL;
|
||||
char **res = NULL, **res1;
|
||||
char *p, *next_token;
|
||||
int idx = 0;
|
||||
|
||||
|
@ -92,16 +92,18 @@ split_string(char *str, int *count)
|
|||
do {
|
||||
p = strtok_s(str, " ", &next_token);
|
||||
str = NULL;
|
||||
res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1));
|
||||
res1 = res;
|
||||
res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1));
|
||||
if (res == NULL) {
|
||||
free(res1);
|
||||
return NULL;
|
||||
}
|
||||
res[idx++] = p;
|
||||
} while (p);
|
||||
|
||||
/**
|
||||
* since the function name,
|
||||
* res[0] might be contains a '\' to indicate a space
|
||||
* Due to the function name,
|
||||
* res[0] might contain a '\' to indicate a space
|
||||
* func\name -> func name
|
||||
*/
|
||||
p = strchr(res[0], '\\');
|
||||
|
|
|
@ -1,387 +0,0 @@
|
|||
Copyright (C) Joel Martin <github@martintribe.org>
|
||||
|
||||
The wac project is licensed under the MPL 2.0 (Mozilla Public License
|
||||
2.0). The text of the MPL 2.0 license is included below and can be
|
||||
found at https://www.mozilla.org/MPL/2.0/
|
||||
|
||||
By default, wac and wace link with the BSD licensed editline library
|
||||
(http://www.thrysoee.dk/editline/). The wac/wace build process can be
|
||||
switched to link with the GPL license GNU readline library with the
|
||||
USE_READLINE=1 flag.
|
||||
|
||||
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
|
||||
|
|
@ -57,26 +57,25 @@ rundir = None
|
|||
|
||||
class Runner():
|
||||
def __init__(self, args, no_pty=False):
|
||||
#print "args: %s" % repr(args)
|
||||
self.no_pty = no_pty
|
||||
|
||||
# Cleanup child process on exit
|
||||
atexit.register(self.cleanup)
|
||||
|
||||
self.p = None
|
||||
self.process = None
|
||||
env = os.environ
|
||||
env['TERM'] = 'dumb'
|
||||
env['INPUTRC'] = '/dev/null'
|
||||
env['PERL_RL'] = 'false'
|
||||
if no_pty:
|
||||
self.p = Popen(args, bufsize=0,
|
||||
self.process = Popen(args, bufsize=0,
|
||||
stdin=PIPE, stdout=PIPE, stderr=STDOUT,
|
||||
preexec_fn=os.setsid,
|
||||
env=env)
|
||||
self.stdin = self.p.stdin
|
||||
self.stdout = self.p.stdout
|
||||
self.stdin = self.process.stdin
|
||||
self.stdout = self.process.stdout
|
||||
else:
|
||||
# provide tty to get 'interactive' readline to work
|
||||
# Use tty to setup an interactive environment
|
||||
master, slave = pty.openpty()
|
||||
|
||||
# Set terminal size large so that readline will not send
|
||||
|
@ -84,7 +83,7 @@ class Runner():
|
|||
buf = array.array('h', [100, 200, 0, 0])
|
||||
fcntl.ioctl(master, termios.TIOCSWINSZ, buf, True)
|
||||
|
||||
self.p = Popen(args, bufsize=0,
|
||||
self.process = Popen(args, bufsize=0,
|
||||
stdin=slave, stdout=slave, stderr=STDOUT,
|
||||
preexec_fn=os.setsid,
|
||||
env=env)
|
||||
|
@ -95,55 +94,55 @@ class Runner():
|
|||
self.stdin = os.fdopen(master, 'r+b', 0)
|
||||
self.stdout = self.stdin
|
||||
|
||||
#print "started"
|
||||
self.buf = ""
|
||||
self.last_prompt = ""
|
||||
|
||||
def read_to_prompt(self, prompts, timeout):
|
||||
end_time = time.time() + timeout
|
||||
while time.time() < end_time:
|
||||
wait_until = time.time() + timeout
|
||||
while time.time() < wait_until:
|
||||
[outs,_,_] = select([self.stdout], [], [], 1)
|
||||
if self.stdout in outs:
|
||||
new_data = self.stdout.read(1)
|
||||
if not new_data:
|
||||
read_byte = self.stdout.read(1)
|
||||
if not read_byte:
|
||||
# EOF on macOS ends up here.
|
||||
break
|
||||
new_data = new_data.decode("utf-8") if IS_PY_3 else new_data
|
||||
#print("new_data: '%s'" % new_data)
|
||||
debug(new_data)
|
||||
read_byte = read_byte.decode('utf-8') if IS_PY_3 else read_byte
|
||||
|
||||
debug(read_byte)
|
||||
if self.no_pty:
|
||||
self.buf += new_data.replace("\n", "\r\n")
|
||||
self.buf += read_byte.replace('\n', '\r\n')
|
||||
else:
|
||||
self.buf += new_data
|
||||
self.buf = self.buf.replace("\r\r", "\r")
|
||||
self.buf += read_byte
|
||||
self.buf = self.buf.replace('\r\r', '\r')
|
||||
|
||||
# filter the prompts
|
||||
for prompt in prompts:
|
||||
regexp = re.compile(prompt)
|
||||
match = regexp.search(self.buf)
|
||||
pattern = re.compile(prompt)
|
||||
match = pattern.search(self.buf)
|
||||
if match:
|
||||
end = match.end()
|
||||
buf = self.buf[0:end-len(prompt)]
|
||||
self.buf = self.buf[end:]
|
||||
self.last_prompt = prompt
|
||||
return buf
|
||||
return None
|
||||
|
||||
def writeline(self, str):
|
||||
def _to_bytes(s):
|
||||
return bytes(s, "utf-8") if IS_PY_3 else s
|
||||
str_to_write = str + '\n'
|
||||
str_to_write = bytes(
|
||||
str_to_write, 'utf-8') if IS_PY_3 else str_to_write
|
||||
|
||||
self.stdin.write(_to_bytes(str + "\n"))
|
||||
self.stdin.write(str_to_write)
|
||||
|
||||
def cleanup(self):
|
||||
if self.p:
|
||||
if self.process:
|
||||
try:
|
||||
self.writeline("__exit__")
|
||||
time.sleep(.020)
|
||||
os.killpg(self.p.pid, signal.SIGTERM)
|
||||
self.process.kill()
|
||||
except OSError:
|
||||
pass
|
||||
except IOError:
|
||||
pass
|
||||
self.p = None
|
||||
self.process = None
|
||||
self.stdin.close()
|
||||
if self.stdin != self.stdout:
|
||||
self.stdout.close()
|
||||
|
|
|
@ -35,11 +35,16 @@ add_definitions(-DWASM_ENABLE_REF_TYPES=1)
|
|||
add_definitions(-DWASM_ENABLE_CUSTOM_NAME_SECTION=1)
|
||||
add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1)
|
||||
add_definitions(-DWASM_ENABLE_PERF_PROFILING=1)
|
||||
add_definitions(-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1)
|
||||
|
||||
if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1)
|
||||
add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1)
|
||||
endif()
|
||||
|
||||
if (DEFINED WAMR_BUILD_AOT_FUNC_PREFIX)
|
||||
add_definitions(-DAOT_FUNC_PREFIX="${WAMR_BUILD_AOT_FUNC_PREFIX}")
|
||||
endif ()
|
||||
|
||||
# Set WAMR_BUILD_TARGET, currently values supported:
|
||||
# "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32"
|
||||
if (NOT WAMR_BUILD_TARGET)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "aot_export.h"
|
||||
|
||||
/* clang-format off */
|
||||
static int
|
||||
static void
|
||||
print_help()
|
||||
{
|
||||
printf("Usage: wamrc [options] -o output_file wasm_file\n");
|
||||
|
@ -58,14 +58,66 @@ print_help()
|
|||
printf(" --enable-indirect-mode Enalbe call function through symbol table but not direct call\n");
|
||||
printf(" --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n");
|
||||
printf(" --disable-llvm-lto Disable the LLVM link time optimization\n");
|
||||
printf(" --emit-custom-sections=<section names>\n");
|
||||
printf(" Emit the specified custom sections to AoT file, using comma to separate\n");
|
||||
printf(" multiple names, e.g.\n");
|
||||
printf(" --emit-custom-sections=section1,section2,sectionN\n");
|
||||
printf(" -v=n Set log verbose level (0 to 5, default is 2), larger with more log\n");
|
||||
printf("Examples: wamrc -o test.aot test.wasm\n");
|
||||
printf(" wamrc --target=i386 -o test.aot test.wasm\n");
|
||||
printf(" wamrc --target=i386 --format=object -o test.o test.wasm\n");
|
||||
return 1;
|
||||
}
|
||||
/* clang-format on */
|
||||
|
||||
#define PRINT_HELP_AND_EXIT() \
|
||||
do { \
|
||||
print_help(); \
|
||||
goto fail0; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Split a strings into an array of strings
|
||||
* Returns NULL on failure
|
||||
* Memory must be freed by caller
|
||||
* Based on: http://stackoverflow.com/a/11198630/471795
|
||||
*/
|
||||
static char **
|
||||
split_string(char *str, int *count, const char *delimer)
|
||||
{
|
||||
char **res = NULL, **res1;
|
||||
char *p;
|
||||
int idx = 0;
|
||||
|
||||
/* split string and append tokens to 'res' */
|
||||
do {
|
||||
p = strtok(str, delimer);
|
||||
str = NULL;
|
||||
res1 = res;
|
||||
res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1));
|
||||
if (res == NULL) {
|
||||
free(res1);
|
||||
return NULL;
|
||||
}
|
||||
res[idx++] = p;
|
||||
} while (p);
|
||||
|
||||
/**
|
||||
* Due to the section name,
|
||||
* res[0] might contain a '\' to indicate a space
|
||||
* func\name -> func name
|
||||
*/
|
||||
p = strchr(res[0], '\\');
|
||||
while (p) {
|
||||
*p = ' ';
|
||||
p = strchr(p, '\\');
|
||||
}
|
||||
|
||||
if (count) {
|
||||
*count = idx - 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -97,39 +149,39 @@ main(int argc, char *argv[])
|
|||
if (!strcmp(argv[0], "-o")) {
|
||||
argc--, argv++;
|
||||
if (argc < 2)
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
out_file_name = argv[0];
|
||||
}
|
||||
else if (!strncmp(argv[0], "--target=", 9)) {
|
||||
if (argv[0][9] == '\0')
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
option.target_arch = argv[0] + 9;
|
||||
}
|
||||
else if (!strncmp(argv[0], "--target-abi=", 13)) {
|
||||
if (argv[0][13] == '\0')
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
option.target_abi = argv[0] + 13;
|
||||
}
|
||||
else if (!strncmp(argv[0], "--cpu=", 6)) {
|
||||
if (argv[0][6] == '\0')
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
option.target_cpu = argv[0] + 6;
|
||||
}
|
||||
else if (!strncmp(argv[0], "--cpu-features=", 15)) {
|
||||
if (argv[0][15] == '\0')
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
option.cpu_features = argv[0] + 15;
|
||||
}
|
||||
else if (!strncmp(argv[0], "--opt-level=", 12)) {
|
||||
if (argv[0][12] == '\0')
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
option.opt_level = (uint32)atoi(argv[0] + 12);
|
||||
if (option.opt_level > 3)
|
||||
option.opt_level = 3;
|
||||
}
|
||||
else if (!strncmp(argv[0], "--size-level=", 13)) {
|
||||
if (argv[0][13] == '\0')
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
option.size_level = (uint32)atoi(argv[0] + 13);
|
||||
if (option.size_level > 3)
|
||||
option.size_level = 3;
|
||||
|
@ -143,7 +195,7 @@ main(int argc, char *argv[])
|
|||
}
|
||||
else if (!strncmp(argv[0], "--format=", 9)) {
|
||||
if (argv[0][9] == '\0')
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
if (!strcmp(argv[0] + 9, "aot"))
|
||||
option.output_format = AOT_FORMAT_FILE;
|
||||
else if (!strcmp(argv[0] + 9, "object"))
|
||||
|
@ -154,13 +206,13 @@ main(int argc, char *argv[])
|
|||
option.output_format = AOT_LLVMIR_OPT_FILE;
|
||||
else {
|
||||
printf("Invalid format %s.\n", argv[0] + 9);
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
}
|
||||
}
|
||||
else if (!strncmp(argv[0], "-v=", 3)) {
|
||||
log_verbose_level = atoi(argv[0] + 3);
|
||||
if (log_verbose_level < 0 || log_verbose_level > 5)
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
}
|
||||
else if (!strcmp(argv[0], "--disable-bulk-memory")) {
|
||||
option.enable_bulk_memory = false;
|
||||
|
@ -201,12 +253,27 @@ main(int argc, char *argv[])
|
|||
else if (!strcmp(argv[0], "--disable-llvm-lto")) {
|
||||
option.disable_llvm_lto = true;
|
||||
}
|
||||
else if (!strncmp(argv[0], "--emit-custom-sections=", 23)) {
|
||||
int len = 0;
|
||||
if (option.custom_sections) {
|
||||
free(option.custom_sections);
|
||||
}
|
||||
|
||||
option.custom_sections = split_string(argv[0] + 23, &len, ",");
|
||||
if (!option.custom_sections) {
|
||||
printf("Failed to process emit-custom-sections: alloc "
|
||||
"memory failed\n");
|
||||
PRINT_HELP_AND_EXIT();
|
||||
}
|
||||
|
||||
option.custom_sections_count = len;
|
||||
}
|
||||
else
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
}
|
||||
|
||||
if (argc == 0 || !out_file_name)
|
||||
return print_help();
|
||||
PRINT_HELP_AND_EXIT();
|
||||
|
||||
if (!size_level_set) {
|
||||
/**
|
||||
|
@ -348,6 +415,12 @@ fail1:
|
|||
/* Destroy runtime environment */
|
||||
wasm_runtime_destroy();
|
||||
|
||||
fail0:
|
||||
/* free option.custom_sections */
|
||||
if (option.custom_sections) {
|
||||
free(option.custom_sections);
|
||||
}
|
||||
|
||||
bh_print_time("wamrc return");
|
||||
return exit_status;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user