mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 15:05:19 +00:00
Merge branch 'bytecodealliance:main' into master
This commit is contained in:
commit
85c0bc2d9d
|
@ -1,32 +1,67 @@
|
|||
---
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- c
|
||||
- C
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
- h
|
||||
- hpp
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
|
||||
Language: Cpp
|
||||
BasedOnStyle: Mozilla
|
||||
IndentWidth: 4
|
||||
|
||||
---
|
||||
Language: Cpp
|
||||
AlignAfterOpenBracket: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AlignConsecutiveMacros: true
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AlwaysBreakAfterReturnType: All
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: false
|
||||
AfterEnum: true
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: true
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: true
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeElse: true
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: true
|
||||
ColumnLimit: 79
|
||||
ContinuationIndentWidth: 2
|
||||
DerivePointerAlignment: false
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
|
@ -36,20 +71,23 @@ IncludeCategories:
|
|||
Priority: 1
|
||||
- Regex: ".*"
|
||||
Priority: 3
|
||||
IndentPPDirectives: None
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
NamespaceIndentation: None
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
Standard: Cpp03
|
||||
SortIncludes: false
|
||||
Standard: Auto
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
|
||||
# AccessModifierOffset: -2
|
||||
# AlignAfterOpenBracket: Align
|
||||
# AlignConsecutiveAssignments: false
|
||||
# AlignConsecutiveDeclarations: false
|
||||
# AlignEscapedNewlines: Right
|
||||
# AlignOperands: true
|
||||
# AlignTrailingComments: true
|
||||
# AllowAllArgumentsOnNextLine: true
|
||||
# AllowAllConstructorInitializersOnNextLine: true
|
||||
# AllowAllParametersOfDeclarationOnNextLine: false
|
||||
# AllowShortCaseLabelsOnASingleLine: false
|
||||
|
@ -61,7 +99,6 @@ StatementMacros:
|
|||
# AlwaysBreakAfterReturnType: TopLevel
|
||||
# AlwaysBreakBeforeMultilineStrings: false
|
||||
# AlwaysBreakTemplateDeclarations: Yes
|
||||
# BreakBeforeBinaryOperators: None
|
||||
# BreakBeforeInheritanceComma: false
|
||||
# BreakInheritanceList: BeforeComma
|
||||
# BreakBeforeTernaryOperators: true
|
||||
|
@ -73,7 +110,6 @@ StatementMacros:
|
|||
# CompactNamespaces: false
|
||||
# ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
# ConstructorInitializerIndentWidth: 2
|
||||
# ContinuationIndentWidth: 2
|
||||
# Cpp11BracedListStyle: false
|
||||
# DisableFormat: false
|
||||
# ExperimentalAutoDetectBinPacking: false
|
||||
|
@ -84,7 +120,6 @@ StatementMacros:
|
|||
# - BOOST_FOREACH
|
||||
# IncludeIsMainRegex: '(Test)?$'
|
||||
# IndentCaseLabels: true
|
||||
# IndentPPDirectives: None
|
||||
# IndentWrappedFunctionNames: false
|
||||
# JavaScriptQuotes: Leave
|
||||
# JavaScriptWrapImports: true
|
||||
|
@ -92,7 +127,6 @@ StatementMacros:
|
|||
# MacroBlockBegin: ''
|
||||
# MacroBlockEnd: ''
|
||||
# MaxEmptyLinesToKeep: 1
|
||||
# NamespaceIndentation: None
|
||||
# ObjCBinPackProtocolList: Auto
|
||||
# ObjCBlockIndentWidth: 2
|
||||
# ObjCSpaceAfterProperty: true
|
91
.github/workflows/android.yml
vendored
Normal file
91
.github/workflows/android.yml
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: android
|
||||
|
||||
# Controls when the action will run.
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the master branch
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
build:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build iwasm [default]
|
||||
run: |
|
||||
cd product-mini/platforms/android
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [Classic interp]
|
||||
run: |
|
||||
cd product-mini/platforms/android
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_FAST_INTERP=0
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [Multi module]
|
||||
run: |
|
||||
cd product-mini/platforms/android
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_MULTI_MODULE=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [lib-pthread]
|
||||
run: |
|
||||
cd product-mini/platforms/android
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_LIB_PTHREAD=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [aot only]
|
||||
run: |
|
||||
cd product-mini/platforms/android
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [interp only]
|
||||
run: |
|
||||
cd product-mini/platforms/android
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_AOT=0
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [memory profiling]
|
||||
run: |
|
||||
cd product-mini/platforms/android
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_MEMORY_PROFILING=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [tail call]
|
||||
run: |
|
||||
cd product-mini/platforms/android
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_TAIL_CALL=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [custom name section]
|
||||
run: |
|
||||
cd product-mini/platforms/android
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1
|
||||
make
|
||||
cd .. && rm -rf build
|
133
.github/workflows/linux.yml
vendored
Normal file
133
.github/workflows/linux.yml
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
name: Linux
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the main branch
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04, ubuntu-20.04]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build iwasm [default]
|
||||
run: |
|
||||
cd product-mini/platforms/linux
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [Classic interp]
|
||||
run: |
|
||||
cd product-mini/platforms/linux
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_FAST_INTERP=0
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [Multi module]
|
||||
run: |
|
||||
cd product-mini/platforms/linux
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_MULTI_MODULE=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [lib-pthread]
|
||||
run: |
|
||||
cd product-mini/platforms/linux
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_LIB_PTHREAD=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [aot only]
|
||||
run: |
|
||||
cd product-mini/platforms/linux
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [interp only]
|
||||
run: |
|
||||
cd product-mini/platforms/linux
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_AOT=0
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [memory profiling]
|
||||
run: |
|
||||
cd product-mini/platforms/linux
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_MEMORY_PROFILING=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [tail call]
|
||||
run: |
|
||||
cd product-mini/platforms/linux
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_TAIL_CALL=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [custom name section]
|
||||
run: |
|
||||
cd product-mini/platforms/linux
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: download and install wasi-sdk
|
||||
run: |
|
||||
cd /opt
|
||||
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-8/wasi-sdk-8.0-linux.tar.gz
|
||||
tar -xzf wasi-sdk-8.0-linux.tar.gz
|
||||
mv wasi-sdk-8.0 wasi-sdk
|
||||
- name: download and install wabt
|
||||
run: |
|
||||
cd /opt
|
||||
wget https://github.com/WebAssembly/wabt/releases/download/1.0.19/wabt-1.0.19-ubuntu.tar.gz
|
||||
tar -xzf wabt-1.0.19-ubuntu.tar.gz
|
||||
mv wabt-1.0.19 wabt
|
||||
- name: Build Sample [wasm-c-api]
|
||||
run: |
|
||||
cd samples/wasm-c-api
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
./hello
|
||||
./global
|
||||
./callback
|
||||
- name: Build Sample [basic]
|
||||
run: |
|
||||
cd samples/basic
|
||||
./build.sh
|
||||
./run.sh
|
||||
- name: Build Sample [multi-thread]
|
||||
run: |
|
||||
cd samples/multi-thread
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
./iwasm wasm-apps/test.wasm
|
||||
- name: Build Sample [multi-module]
|
||||
run: |
|
||||
cd samples/multi-module
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
./multi_module
|
||||
- name: Build Sample [spawn-thread]
|
||||
run: |
|
||||
cd samples/spawn-thread
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
./spawn_thread
|
101
.github/workflows/mac.yml
vendored
Normal file
101
.github/workflows/mac.yml
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
name: Mac
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the main branch
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build iwasm [default]
|
||||
run: |
|
||||
cd product-mini/platforms/darwin
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [Classic interp]
|
||||
run: |
|
||||
cd product-mini/platforms/darwin
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_FAST_INTERP=0
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [Multi module]
|
||||
run: |
|
||||
cd product-mini/platforms/darwin
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_MULTI_MODULE=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [lib-pthread]
|
||||
run: |
|
||||
cd product-mini/platforms/darwin
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_LIB_PTHREAD=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [aot only]
|
||||
run: |
|
||||
cd product-mini/platforms/darwin
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [interp only]
|
||||
run: |
|
||||
cd product-mini/platforms/darwin
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_AOT=0
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [memory profiling]
|
||||
run: |
|
||||
cd product-mini/platforms/darwin
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_MEMORY_PROFILING=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [tail call]
|
||||
run: |
|
||||
cd product-mini/platforms/darwin
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_TAIL_CALL=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: Build iwasm [custom name section]
|
||||
run: |
|
||||
cd product-mini/platforms/darwin
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1
|
||||
make
|
||||
cd .. && rm -rf build
|
||||
- name: download and install wabt
|
||||
run: |
|
||||
cd /opt
|
||||
sudo wget https://github.com/WebAssembly/wabt/releases/download/1.0.19/wabt-1.0.19-macos.tar.gz
|
||||
sudo tar -xzf wabt-1.0.19-macos.tar.gz
|
||||
sudo mv wabt-1.0.19 wabt
|
||||
- name: Build Sample [wasm-c-api]
|
||||
run: |
|
||||
cd samples/wasm-c-api
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
./hello
|
||||
./global
|
||||
./callback
|
63
.github/workflows/windows.yml
vendored
Normal file
63
.github/workflows/windows.yml
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
name: Windows
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the main branch
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: clone uvwasi library
|
||||
run: |
|
||||
cd core/deps
|
||||
git clone https://github.com/nodejs/uvwasi.git
|
||||
- name: Build iwasm [default]
|
||||
run: |
|
||||
cd product-mini/platforms/windows
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
cd .. && rm -force -r build
|
||||
- name: Build iwasm [aot only]
|
||||
run: |
|
||||
cd product-mini/platforms/windows
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0
|
||||
cmake --build . --config Release
|
||||
cd .. && rm -force -r build
|
||||
- name: Build iwasm [interp only]
|
||||
run: |
|
||||
cd product-mini/platforms/windows
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_AOT=0
|
||||
cmake --build . --config Release
|
||||
cd .. && rm -force -r build
|
||||
- name: Build iwasm [tail call]
|
||||
run: |
|
||||
cd product-mini/platforms/windows
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_TAIL_CALL=1
|
||||
cmake --build . --config Release
|
||||
cd .. && rm -force -r build
|
||||
- name: Build iwasm [custom name section]
|
||||
run: |
|
||||
cd product-mini/platforms/windows
|
||||
mkdir build && cd build
|
||||
cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1
|
||||
cmake --build . --config Release
|
||||
cd .. && rm -force -r build
|
||||
|
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -1,10 +1,14 @@
|
|||
|
||||
.vs
|
||||
.vscode
|
||||
**/*build/
|
||||
core/deps/lv_drivers
|
||||
core/deps/llvm
|
||||
core/deps/lvgl
|
||||
core/deps/**
|
||||
core/shared/mem-alloc/tlsf
|
||||
core/app-framework/wgl
|
||||
|
||||
wamr-sdk/out/
|
||||
wamr-sdk/runtime/build_runtime_sdk/
|
||||
test-tools/host-tool/bin/
|
||||
product-mini/app-samples/hello-world/test.wasm
|
||||
|
||||
build_out
|
||||
|
|
335
ATTRIBUTIONS.md
335
ATTRIBUTIONS.md
|
@ -2,329 +2,64 @@ WebAssembly Micro Runtime Attributions
|
|||
======================================
|
||||
|
||||
WAMR project reused some components from other open source project:
|
||||
- **wasmtime**: for the wasi libc implementation
|
||||
- **cJson**: used in the host_tool for remotely managing wasm applications
|
||||
- **contiki-ng**: for the coap protocol implementation
|
||||
- **freebsd libm**: used in core/shared/platform/alios/bh_math.c
|
||||
- **littlevgl**: for the gui samples and wrapped the wasm graphic layer.
|
||||
- **littlevgl**: for the gui samples and wrapped the wasm graphic layer
|
||||
- **llvm**. for the AOT/JIT compilation
|
||||
- **wasm-c-api**. to implement the C-APIs of wasm. using headers and sameples
|
||||
- **wasmtime**: for the wasi libc implementation
|
||||
- **zephyr**. for several platform specific examples
|
||||
|
||||
The WAMR fast interpreter is a clean room development. We would acknowledge the inspirations by [WASM3](https://github.com/wasm3/wasm3) open source project for the approach of pre-calculated oprand stack location.
|
||||
The WAMR fast interpreter is a clean room development. We would acknowledge the inspirations by [WASM3](https://github.com/wasm3/wasm3) open source project for the approach of pre-calculated oprand stack location.
|
||||
|
||||
| third party components | version number | latest release | vendor pages | CVE details |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| cjson | 1.7.10 | 1.7.14 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html |
|
||||
| contiki-ng (er-coap) | unspecified | 3.0 | https://github.com/contiki-os/contiki | https://www.cvedetails.com/vendor/16528/Contiki-os.html |
|
||||
| freebsd libm | unspecified | 13.0 | https://www.freebsd.org/ | https://www.cvedetails.com/vendor/6/Freebsd.html |
|
||||
| littlevgl | 6.0.1 | 7.11.0 | https://lvgl.io/ | |
|
||||
| llvm | 11.0.1 | 12.0.0 | https://llvm.org | https://www.cvedetails.com/vendor/13260/Llvm.html |
|
||||
| wasm-c-api | ac9b509f4df86e40e56e9b01f3f49afab0100037 | c9d31284651b975f05ac27cee0bab1377560b87e | https://github.com/WebAssembly/wasm-c-api | |
|
||||
| wasmtime | unspecified | v0.26.0 | https://github.com/bytecodealliance/wasmtime | |
|
||||
| zephyr | unspecified | v2.5.0 | https://www.zephyrproject.org/ | https://www.cvedetails.com/vendor/19255/Zephyrproject.html |
|
||||
|
||||
## Licenses
|
||||
|
||||
### wasmtime
|
||||
|
||||
```
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
--- LLVM Exceptions to the Apache 2.0 License ----
|
||||
|
||||
As an exception, if, as a result of your compiling your source code, portions
|
||||
of this Software are embedded into an Object form of such source code, you
|
||||
may redistribute such embedded portions in such Object form without complying
|
||||
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||
|
||||
In addition, if you combine or link compiled forms of this Software with
|
||||
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||
court of competent jurisdiction determines that the patent provision (Section
|
||||
3), the indemnity provision (Section 9) or other Section of the License
|
||||
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||
the License, but only in their entirety and only with respect to the Combined
|
||||
Software.
|
||||
```
|
||||
|
||||
### cJson
|
||||
|
||||
```
|
||||
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
```
|
||||
[LICENSE](./test-tools/host-tool/external/cJSON/LICENSE)
|
||||
|
||||
### contiki-ng
|
||||
|
||||
```
|
||||
|
||||
|
||||
Copyright (c) (Year), (Name of copyright holder) All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
```
|
||||
[LICENSE](./core/shared/coap/er-coap/LICENSE.md)
|
||||
|
||||
### freebsd libm
|
||||
|
||||
```
|
||||
Copyright 1992-2011 The FreeBSD Project. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation
|
||||
are those of the authors and should not be interpreted as representing
|
||||
official policies, either expressed or implied, of the FreeBSD
|
||||
Project.
|
||||
```
|
||||
[COPYRIGHT](./core/shared/platform/common/math/COPYRIGHT)
|
||||
|
||||
### littlevgl
|
||||
|
||||
```
|
||||
MIT licence
|
||||
Copyright (c) 2016 Gábor Kiss-Vámosi
|
||||
[LICENCE](./samples/littlevgl/LICENCE.txt)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
[LICENSE](./core/deps/lvgl/LICENCE.txt)
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
### llvm
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
```
|
||||
[LICENSE](./core/deps/llvm/llvm/LICENCE.txt)
|
||||
|
||||
### wasm-c-api
|
||||
|
||||
[LICENSE](./samples/wasm-c-api/src/LICENSE)
|
||||
|
||||
### wasmtime
|
||||
|
||||
[LICENSE](./core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE)
|
||||
|
||||
[LICENSE](./core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE)
|
||||
|
||||
[LICENSE](./core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE)
|
||||
|
||||
### zephyr
|
||||
|
||||
[LICENSE](./samples/gui/wasm-runtime-wgl/src/platform/zephyr/LICENSE)
|
||||
|
|
139
CMakeLists.txt
Normal file
139
CMakeLists.txt
Normal file
|
@ -0,0 +1,139 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
cmake_minimum_required (VERSION 2.8...3.16)
|
||||
|
||||
project (iwasm)
|
||||
# set (CMAKE_VERBOSE_MAKEFILE 1)
|
||||
|
||||
set (WAMR_BUILD_PLATFORM "linux")
|
||||
|
||||
# Reset default linker flags
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
||||
|
||||
set (CMAKE_C_STANDARD 99)
|
||||
|
||||
# Set WAMR_BUILD_TARGET, currently values supported:
|
||||
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
|
||||
# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
|
||||
if (NOT DEFINED WAMR_BUILD_TARGET)
|
||||
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
set (WAMR_BUILD_TARGET "AARCH64")
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
|
||||
set (WAMR_BUILD_TARGET "RISCV64")
|
||||
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
# Build as X86_64 by default in 64-bit platform
|
||||
set (WAMR_BUILD_TARGET "X86_64")
|
||||
else ()
|
||||
# Build as X86_32 by default in 32-bit platform
|
||||
set (WAMR_BUILD_TARGET "X86_32")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_INTERP)
|
||||
# Enable Interpreter by default
|
||||
set (WAMR_BUILD_INTERP 1)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_AOT)
|
||||
# Enable AOT by default.
|
||||
set (WAMR_BUILD_AOT 1)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_JIT)
|
||||
# Disable JIT by default.
|
||||
set (WAMR_BUILD_JIT 0)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN)
|
||||
# Enable libc builtin support by default
|
||||
set (WAMR_BUILD_LIBC_BUILTIN 1)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_LIBC_WASI)
|
||||
# Enable libc wasi support by default
|
||||
set (WAMR_BUILD_LIBC_WASI 1)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_FAST_INTERP)
|
||||
# Enable fast interpreter
|
||||
set (WAMR_BUILD_FAST_INTERP 1)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_MULTI_MODULE)
|
||||
# Enable multiple modules
|
||||
set (WAMR_BUILD_MULTI_MODULE 0)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
|
||||
# Disable pthread library by default
|
||||
set (WAMR_BUILD_LIB_PTHREAD 0)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
|
||||
# Disable wasm mini loader by default
|
||||
set (WAMR_BUILD_MINI_LOADER 0)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_SIMD)
|
||||
# Enable SIMD by default
|
||||
set (WAMR_BUILD_SIMD 1)
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_REF_TYPES)
|
||||
# Disable reference types by default
|
||||
set (WAMR_BUILD_REF_TYPES 0)
|
||||
endif ()
|
||||
|
||||
if (COLLECT_CODE_COVERAGE EQUAL 1)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
endif ()
|
||||
|
||||
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE")
|
||||
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security")
|
||||
# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion")
|
||||
|
||||
if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
|
||||
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# The following flags are to enhance security, but it may impact performance,
|
||||
# we disable them by default.
|
||||
#if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
|
||||
# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftrapv -D_FORTIFY_SOURCE=2")
|
||||
#endif ()
|
||||
#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4")
|
||||
#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now")
|
||||
|
||||
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
||||
|
||||
# STATIC LIBRARY
|
||||
add_library(iwasm_static STATIC ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
set_target_properties (iwasm_static PROPERTIES OUTPUT_NAME vmlib)
|
||||
|
||||
install (TARGETS iwasm_static ARCHIVE DESTINATION lib)
|
||||
|
||||
# SHARED LIBRARY
|
||||
add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm)
|
||||
target_link_libraries (iwasm_shared ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread)
|
||||
|
||||
install (TARGETS iwasm_shared LIBRARY DESTINATION lib)
|
||||
|
||||
# HEADERS
|
||||
install (FILES
|
||||
${WAMR_ROOT_DIR}/core/iwasm/include/wasm_c_api.h
|
||||
${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h
|
||||
DESTINATION include)
|
21
Dockerfile
21
Dockerfile
|
@ -1,21 +0,0 @@
|
|||
# Currently supports clang-8 compiler
|
||||
# Using the "test.c" app from the README.md:
|
||||
# clang-8 --target=wasm32 -O3 -Wl,--initial-memory=131072,--allow-undefined,--export=main,--no-threads,--strip-all,--no-entry -nostdlib -o test.wasm test.c
|
||||
# Pay attention to spacing above! ^
|
||||
# iwasm test.wasm
|
||||
|
||||
FROM ubuntu:latest
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get -y upgrade && \
|
||||
apt-get install -y build-essential clang-8 cmake g++-multilib git lib32gcc-5-dev llvm-8 lld-8 nano
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
RUN git clone https://github.com/intel/wasm-micro-runtime
|
||||
|
||||
RUN cd wasm-micro-runtime/product-mini/platforms/linux/ && mkdir build && \
|
||||
cd build && cmake .. && make
|
||||
|
||||
RUN cd /usr/bin && ln -s wasm-ld-8 wasm-ld
|
||||
RUN cd /usr/bin && ln -s ~/wasm-micro-runtime/product-mini/platforms/linux/build/iwasm iwasm
|
96
README.md
96
README.md
|
@ -1,6 +1,6 @@
|
|||
WebAssembly Micro Runtime
|
||||
=========================
|
||||
[Build WAMR VM core](./doc/build_wamr.md) | [Embed WAMR](./doc/embed_wamr.md) | [Export native function](./doc/export_native_api.md) | [Build WASM applications](./doc/build_wasm_app.md) | [Samples](https://github.com/bytecodealliance/wasm-micro-runtime#samples-and-demos)
|
||||
[Build WAMR VM core](./doc/build_wamr.md) | [Embed WAMR](./doc/embed_wamr.md) | [Export native function](./doc/export_native_api.md) | [Build WASM applications](./doc/build_wasm_app.md) | [Samples](https://github.com/bytecodealliance/wasm-micro-runtime#samples)
|
||||
|
||||
**A [Bytecode Alliance][BA] project**
|
||||
|
||||
|
@ -13,8 +13,6 @@ WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with
|
|||
|
||||
- The **dynamic management** of the WASM applications
|
||||
|
||||
|
||||
|
||||
iwasm VM core
|
||||
=========================
|
||||
|
||||
|
@ -22,14 +20,24 @@ iwasm VM core
|
|||
|
||||
- 100% compliant to the W3C WASM MVP
|
||||
- Small runtime binary size (85K for interpreter and 50K for AoT) and low memory usage
|
||||
- Near to native speed by AoT
|
||||
- Near to native speed by AoT
|
||||
- Self-implemented module loader enables AoT working cross Linux, SGX and MCU systems
|
||||
- Choices of WASM application libc support: the built-in libc subset for the embedded environment or [WASI](https://github.com/WebAssembly/WASI) for standard libc
|
||||
- [Embeddable with the supporting C API's](./doc/embed_wamr.md)
|
||||
- [The mechanism for exporting native API's to WASM applications](./doc/export_native_api.md)
|
||||
- [Multiple modules as dependencies](./doc/multi_module.md), ref to [sample](samples/multi-module)
|
||||
- [Thread management and pthread library](./doc/pthread_library.md), ref to [sample](samples/multi-thread)
|
||||
|
||||
### Performance and memory usage
|
||||
The WAMR performance, footprint and memory usage data are available at the [performance](../../wiki/Performance) wiki page.
|
||||
### post-MVP features
|
||||
- [Non-trapping float-to-int conversions](https://github.com/WebAssembly/nontrapping-float-to-int-conversions)
|
||||
- [Sign-extension operators](https://github.com/WebAssembly/sign-extension-ops)
|
||||
- [Bulk memory operations](https://github.com/WebAssembly/bulk-memory-operations)
|
||||
- [Shared memory](https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#shared-linear-memory)
|
||||
- [Multi-value](https://github.com/WebAssembly/multi-value)
|
||||
- [wasm-c-api](https://github.com/WebAssembly/wasm-c-api), ref to [document](doc/wasm_c_api.md) and [sample](samples/wasm-c-api)
|
||||
- [Tail-call](https://github.com/WebAssembly/tail-call)
|
||||
- [128-bit SIMD](https://github.com/WebAssembly/simd), ref to [samples/workload](samples/workload)
|
||||
- [Reference Types](https://github.com/WebAssembly/reference-types), ref to [document](doc/ref_types.md) and [sample](samples/ref-types)
|
||||
|
||||
### Supported architectures and platforms
|
||||
|
||||
|
@ -40,31 +48,41 @@ The iwasm supports the following architectures:
|
|||
- AArch64 (Cortex-A57 and Cortex-A53 are tested)
|
||||
- MIPS
|
||||
- XTENSA
|
||||
- RISCV64, RISCV32 (interpreter only)
|
||||
|
||||
Following platforms are supported. Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform.
|
||||
|
||||
- [Linux](./doc/build_wamr.md#linux), [Zephyr](./doc/build_wamr.md#zephyr), [MacOS](./doc/build_wamr.md#macos), [VxWorks](./doc/build_wamr.md#vxworks), [AliOS-Things](./doc/build_wamr.md#alios-things), [Intel Software Guard Extention (Linux)](./doc/build_wamr.md#linux-sgx-intel-software-guard-extention), [Android](./doc/build_wamr.md#android)
|
||||
- [Linux](./doc/build_wamr.md#linux), [Linux SGX (Intel Software Guard Extension)](./doc/linux_sgx.md), [MacOS](./doc/build_wamr.md#macos), [Android](./doc/build_wamr.md#android), [Windows](./doc/build_wamr.md#windows)
|
||||
- [Zephyr](./doc/build_wamr.md#zephyr), [AliOS-Things](./doc/build_wamr.md#alios-things), [VxWorks](./doc/build_wamr.md#vxworks), [NuttX](./doc/build_wamr.md#nuttx), [RT-Thread](./doc/build_wamr.md#RT-Thread)
|
||||
|
||||
### Build iwasm VM core (mini product)
|
||||
|
||||
WAMR supports building the iwasm VM core only (no app framework) to the mini product. The WAMR mini product takes the WASM application file name or AoT file name as input and then executes it. For the detailed procedure, please see **[build WAMR VM core](./doc/build_wamr.md)** and **[build and run WASM application](./doc/build_wasm_app.md)**. Also we can click the link of each platform above to see how to build iwasm on it.
|
||||
|
||||
### Build wamrc AoT compiler
|
||||
|
||||
Execute following commands to build **wamrc** compiler:
|
||||
Both wasm binary file and AoT file are supported by iwasm. The wamrc AoT compiler is to compile wasm binary file to AoT file which can also be run by iwasm. Execute following commands to build **wamrc** compiler for Linux:
|
||||
|
||||
```shell
|
||||
cd wamr-compiler
|
||||
./build_llvm.sh (use build_llvm_xtensa.sh instead to support xtensa target)
|
||||
./build_llvm.sh (or "./build_llvm_xtensa.sh" to support xtensa target)
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake .. (or "cmake .. -DWAMR_BUILD_TARGET=darwin" for MacOS)
|
||||
make
|
||||
ln -s {current path}/wamrc /usr/bin/wamrc
|
||||
# wamrc is generated under current directory
|
||||
```
|
||||
|
||||
### Build the mini product
|
||||
|
||||
WAMR supports building the iwasm VM core only (no app framework) to the mini product. The WAMR mini product takes the WASM application file name as input and then executes it. For the detailed procedure, see **[build WAMR VM core](./doc/build_wamr.md)** and **[build and run WASM application](./doc/build_wasm_app.md)**.
|
||||
|
||||
|
||||
For **Windows**:
|
||||
```shell
|
||||
cd wamr-compiler
|
||||
python build_llvm.py
|
||||
open LLVM.sln in wasm-micro-runtime\core\deps\llvm\win32build with Visual Studio
|
||||
build LLVM.sln Release
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
# wamrc.exe is generated under .\Release directory
|
||||
```
|
||||
|
||||
Application framework
|
||||
===================================
|
||||
|
@ -77,8 +95,6 @@ The WAMR has offered a comprehensive framework for programming WASM applications
|
|||
|
||||
Browse the folder [core/app-framework](./core/app-framework) for how to extend the application framework.
|
||||
|
||||
|
||||
|
||||
# Remote application management
|
||||
|
||||
The WAMR application manager supports [remote application management](./core/app-mgr) from the host environment or the cloud through any physical communications such as TCP, UPD, UART, BLE, etc. Its modular design makes it able to support application management for different managed runtimes.
|
||||
|
@ -102,28 +118,16 @@ Samples
|
|||
|
||||
The WAMR [samples](./samples) integrate the iwasm VM core, application manager and selected application framework components.
|
||||
|
||||
- [**Basic**](./samples/basic): Demonstrating how host runtime calls WASM function as well as WASM function calls native function.
|
||||
- **[Simple](./samples/simple/README.md)**: The runtime is integrated with most of the WAMR APP libraries, and a few WASM applications are provided for testing the WAMR APP API set. It uses **built-in libc** and executes apps in **interpreter** mode by default.
|
||||
- **[littlevgl](./samples/littlevgl/README.md)**: Demonstrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application. It uses **WASI libc** and executes apps in **AoT mode** by default.
|
||||
- **[gui](./samples/gui/README.md)**: Moved the [LittlevGL](https://github.com/littlevgl/) library into the runtime and defined a WASM application interface by wrapping the littlevgl API. It uses **WASI libc** and executes apps in **interpreter** mode by default.
|
||||
|
||||
|
||||
|
||||
|
||||
Releases and acknowledgments
|
||||
============================
|
||||
|
||||
WAMR is a community effort. Since Intel Corp contributed the first release of this open source project, this project has received many good contributions from the community.
|
||||
|
||||
See the [major features releasing history and contributor names](./doc/release_ack.md)
|
||||
|
||||
|
||||
Roadmap
|
||||
=======
|
||||
|
||||
See the [roadmap](./doc/roadmap.md) to understand what major features are planned or under development.
|
||||
|
||||
Please submit issues for any new feature request or your plan for contributing new features.
|
||||
- [**basic**](./samples/basic): Demonstrating how to use runtime exposed API's to call WASM functions, how to register native functions and call them, and how to call WASM function from native function.
|
||||
- **[simple](./samples/simple/README.md)**: The runtime is integrated with most of the WAMR APP libraries, and a few WASM applications are provided for testing the WAMR APP API set. It uses **built-in libc** and executes apps in **interpreter** mode by default.
|
||||
- **[littlevgl](./samples/littlevgl/README.md)**: Demonstrating the graphic user interface application usage on WAMR. The whole [LittleVGL](https://github.com/lvgl/) 2D user graphic library and the UI application are built into WASM application. It uses **WASI libc** and executes apps in **AoT mode** by default.
|
||||
- **[gui](./samples/gui/README.md)**: Move the [LittleVGL](https://github.com/lvgl/) library into the runtime and define a WASM application interface by wrapping the littlevgl API. It uses **WASI libc** and executes apps in **interpreter** mode by default.
|
||||
- **[multi-thread](./samples/multi-thread/)**: Demonstrating how to run wasm application which creates multiple threads to execute wasm functions concurrently, and uses mutex/cond by calling pthread related API's.
|
||||
- **[spawn-thread](./samples/spawn-thread)**: Demonstrating how to execute wasm functions of the same wasm application concurrently, in threads created by host embedder or runtime, but not the wasm application itself.
|
||||
- **[multi-module](./samples/multi-module)**: Demonstrating the [multiple modules as dependencies](./doc/multi_module.md) feature which implements the [load-time dynamic linking](https://webassembly.org/docs/dynamic-linking/).
|
||||
- **[ref-types](./samples/ref-types)**: Demonstrating how to call wasm functions with argument of externref type introduced by [reference types proposal](https://github.com/WebAssembly/reference-types).
|
||||
- **[wasm-c-api](./samples/wasm-c-api/README.md)**: Demonstrating how to run some samples from [wasm-c-api proposal](https://github.com/WebAssembly/wasm-c-api) and showing the supported API's.
|
||||
- **[workload](./samples/workload/README.md)**: Demonstrating how to build and run some complex workloads, e.g. tensorflow-lite, XNNPACK, wasm-av1, meshoptimizer and bwa.
|
||||
|
||||
|
||||
License
|
||||
|
@ -134,9 +138,13 @@ use, modify, distribute and sell your own products based on WAMR.
|
|||
Any contributions you make will be under the same license.
|
||||
|
||||
|
||||
Submit issues and contact the maintainers
|
||||
=========================================
|
||||
[Click here to submit. Your feedback is always welcome!](https://github.com/intel/wasm-micro-runtime/issues/new)
|
||||
|
||||
# More resources
|
||||
|
||||
Check out the [Wiki documents ](../../wiki) for more resources:
|
||||
|
||||
- [Performance and footprint data](../../wiki/Performance)
|
||||
- Community news and events
|
||||
- Roadmap
|
||||
- Technical documents
|
||||
|
||||
Contact the maintainers: imrt-public@intel.com
|
||||
|
|
33
SConscript
Normal file
33
SConscript
Normal file
|
@ -0,0 +1,33 @@
|
|||
#
|
||||
# Copyright (c) 2021, RT-Thread Development Team
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
# for module compiling
|
||||
import os
|
||||
|
||||
from building import *
|
||||
|
||||
objs = []
|
||||
cwd = GetCurrentDir()
|
||||
list = os.listdir(cwd)
|
||||
|
||||
if GetDepend(['PKG_USING_WAMR']):
|
||||
wamr_entry_sconscript = os.path.join(cwd, "product-mini", "platforms", "rt-thread", 'SConscript')
|
||||
|
||||
if os.path.isfile(wamr_entry_sconscript):
|
||||
objs = objs + SConscript(wamr_entry_sconscript)
|
||||
else:
|
||||
print("[WAMR] entry script wrong:", wamr_entry_sconscript)
|
||||
Return('objs')
|
||||
|
||||
wamr_runlib_sconsript = os.path.join(cwd, "build-scripts", 'SConscript')
|
||||
|
||||
if os.path.isfile(wamr_runlib_sconsript):
|
||||
objs = objs + SConscript(wamr_runlib_sconsript)
|
||||
else:
|
||||
print("[WAMR] runtime lib script wrong:", wamr_runlib_sconsript)
|
||||
|
||||
Return('objs')
|
||||
|
28
SECURITY.md
28
SECURITY.md
|
@ -1,29 +1,3 @@
|
|||
# Security Policy
|
||||
|
||||
Building secure foundations for software development is at the core of what we do in the Bytecode Alliance. Contributions of external security researchers are a vital part of that.
|
||||
|
||||
## Scope
|
||||
|
||||
If you believe you've found a security issue in any website, service, or software owned or operated by the Bytecode Alliance, we encourage you to notify us.
|
||||
|
||||
## How to Submit a Report
|
||||
|
||||
To submit a vulnerability report to the Bytecode Alliance, please contact us at [security@bytecodealliance.org](mailto:security@bytecodealliance.org). Your submission will be reviewed and validated by a member of our security team.
|
||||
|
||||
## Safe Harbor
|
||||
|
||||
The Bytecode Alliance supports safe harbor for security researchers who:
|
||||
|
||||
* Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our services.
|
||||
* Only interact with accounts you own or with explicit permission of the account holder. If you do encounter Personally Identifiable Information (PII) contact us immediately, do not proceed with access, and immediately purge any local information.
|
||||
* Provide us with a reasonable amount of time to resolve vulnerabilities prior to any disclosure to the public or a third-party.
|
||||
|
||||
We will consider activities conducted consistent with this policy to constitute "authorized" conduct and will not pursue civil action or initiate a complaint to law enforcement. We will help to the extent we can if legal action is initiated by a third party against you.
|
||||
|
||||
Please submit a report to us before engaging in conduct that may be inconsistent with or unaddressed by this policy.
|
||||
|
||||
## Preferences
|
||||
|
||||
* Please provide detailed reports with reproducible steps and a clearly defined impact.
|
||||
* Submit one vulnerability per report.
|
||||
* Social engineering (e.g. phishing, vishing, smishing) is prohibited.
|
||||
Please refer to the [Bytecode Alliance security policy](https://bytecodealliance.org/security) for details on how to report security issues in WebAssembly Micro Runtime, our disclosure policy, and how to receive notifications about security issues.
|
||||
|
|
177
TSC_Charter.md
Normal file
177
TSC_Charter.md
Normal file
|
@ -0,0 +1,177 @@
|
|||
# Project Technical Steering Committee (PTSC) Charter
|
||||
|
||||
## Section 1. Guiding Principle
|
||||
|
||||
The WebAssembly Micro Runtime (WAMR) project is part of the
|
||||
|
||||
Bytecode Alliance (BA) which operates transparently, openly,
|
||||
|
||||
collaboratively, and ethically. Project proposals, timelines, and status
|
||||
|
||||
must not merely be open, but also easily visible to outsiders.
|
||||
|
||||
## Section 2. Project Governance under Bytecode Alliance
|
||||
|
||||
Technical leadership for the WAMR projects within the Bytecode Alliance
|
||||
|
||||
is delegated to the projects through the project charter. Though the BA TSC
|
||||
|
||||
will not interfere with day-to-day discussions, votes or meetings of the PTSC,
|
||||
|
||||
the BA TSC may request additional amendments to the PTSC charter when
|
||||
|
||||
there is misalignment between the project charter and the BA mission and values.
|
||||
|
||||
|
||||
|
||||
The PTSC structure described in this document may be overhauled as part of
|
||||
|
||||
establishing a BA TSC in order to adhere to constraints or requirements that
|
||||
|
||||
TSC will impose on project-level governance.
|
||||
|
||||
## Section 3. Establishment of the PTSC
|
||||
|
||||
PTSC memberships are not time-limited. There is no maximum size of the PTSC.
|
||||
The size is expected to vary in order to ensure adequate coverage of important
|
||||
areas of expertise, balanced with the ability to make decisions efficiently.
|
||||
The PTSC must have at least four members.
|
||||
|
||||
There is no specific set of requirements or qualifications for PTSC
|
||||
membership beyond these rules. The PTSC may add additional members to the
|
||||
PTSC by a standard PTSC motion and vote. A PTSC member may be removed from the
|
||||
PTSC by voluntary resignation, by a standard PTSC motion, or in accordance to the
|
||||
participation rules described below.
|
||||
|
||||
Changes to PTSC membership should be posted in the agenda, and may be suggested
|
||||
as any other agenda item.
|
||||
|
||||
The PTSC may, at its discretion, invite any number of non-voting observers to
|
||||
participate in the public portion of PTSC discussions and meetings.
|
||||
|
||||
The PTSC shall meet regularly using tools that enable participation by the
|
||||
community (e.g. weekly on a Zulip channel, or through any other
|
||||
appropriate means selected by the PTSC ). The meeting shall be directed by
|
||||
the PTSC Chairperson. Responsibility for directing individual meetings may be
|
||||
delegated by the PTSC Chairperson to any other PTSC member. Minutes or an
|
||||
appropriate recording shall be taken and made available to the community
|
||||
through accessible public postings.
|
||||
|
||||
PTSC members are expected to regularly participate in PTSC activities.
|
||||
|
||||
In the case where an individual PTSC member -- within any three month period --
|
||||
attends fewer than 25% of the regularly scheduled meetings, does not
|
||||
participate in PTSC discussions, *and* does not participate in PTSC votes, the
|
||||
member shall be automatically removed from the PTSC. The member may be invited
|
||||
to continue attending PTSC meetings as an observer.
|
||||
|
||||
## Section 4. Responsibilities of the PTSC
|
||||
|
||||
Subject to such policies as may be set by the BA TSC, the WAMR PTSC is
|
||||
responsible for all technical development within the WAMR project,
|
||||
including:
|
||||
|
||||
* Setting release dates.
|
||||
* Release quality standards.
|
||||
* Technical direction.
|
||||
* Project governance and process.
|
||||
* GitHub repository hosting.
|
||||
* Conduct guidelines.
|
||||
* Maintaining the list of additional Collaborators.
|
||||
* Development process and any coding standards.
|
||||
* Mediating technical conflicts between Collaborators or Foundation
|
||||
projects.
|
||||
|
||||
The PTSC will define WAMR project’s release vehicles.
|
||||
|
||||
## Section 5. WAMR Project Operations
|
||||
|
||||
The PTSC will establish and maintain a development process for the WAMR
|
||||
project. The development process will establish guidelines
|
||||
for how the developers and community will operate. It will, for example,
|
||||
establish appropriate timelines for PTSC review (e.g. agenda items must be
|
||||
published at least a certain number of hours in advance of a PTSC
|
||||
meeting).
|
||||
|
||||
The PTSC and entire technical community will follow any processes as may
|
||||
be specified by the Bytecode Alliance Board relating to the intake and license compliance
|
||||
review of contributions, including the Bytecode Alliance IP Policy.
|
||||
|
||||
## Section 6. Elections
|
||||
|
||||
Leadership roles in the WAMR project will be peer elected
|
||||
representatives of the community.
|
||||
|
||||
For election of persons (such as the PTSC Chairperson), a multiple-candidate
|
||||
method should be used, such as:
|
||||
|
||||
* [Condorcet][] or
|
||||
* [Single Transferable Vote][]
|
||||
|
||||
Multiple-candidate methods may be reduced to simple election by plurality
|
||||
when there are only two candidates for one position to be filled. No
|
||||
election is required if there is only one candidate and no objections to
|
||||
the candidate's election. Elections shall be done within the projects by
|
||||
the Collaborators active in the project.
|
||||
|
||||
The PTSC will elect from amongst voting PTSC members a PTSC Chairperson to
|
||||
work on building an agenda for PTSC meetings. The PTSC shall hold annual
|
||||
|
||||
elections to select a PTSC Chairperson; there are no limits on the number
|
||||
of terms a PTSC Chairperson may serve.
|
||||
|
||||
## Section 7. Voting
|
||||
|
||||
For internal project decisions, Collaborators shall operate under Lazy
|
||||
Consensus. The PTSC shall establish appropriate guidelines for
|
||||
implementing Lazy Consensus (e.g. expected notification and review time
|
||||
periods) within the development process.
|
||||
|
||||
The PTSC follows a [Consensus Seeking][] decision making model. When an agenda
|
||||
item has appeared to reach a consensus the moderator will ask "Does anyone
|
||||
object?" as a final call for dissent from the consensus.
|
||||
|
||||
If an agenda item cannot reach a consensus a PTSC member can call for
|
||||
either a closing vote or a vote to table the issue to the next meeting.
|
||||
The call for a vote must be seconded by a majority of the PTSC or else the
|
||||
discussion will continue.
|
||||
|
||||
For all votes, a simple majority of all PTSC members for, or against, the issue
|
||||
wins. A PTSC member may choose to participate in any vote through abstention.
|
||||
|
||||
## Section 8. Project Roles
|
||||
|
||||
The WAMR git repository is maintained by the PTSC and
|
||||
additional Collaborators who are added by the PTSC on an ongoing basis.
|
||||
|
||||
Individuals making significant and valuable contributions,
|
||||
“Contributor(s)”, are made Collaborators and given commit-access to the
|
||||
project. These individuals are identified by the PTSC and their addition
|
||||
as Collaborators is discussed during a PTSC meeting. Modifications of the
|
||||
contents of the git repository are made on a collaborative basis as defined in
|
||||
the development process.
|
||||
|
||||
Collaborators may opt to elevate significant or controversial
|
||||
modifications, or modifications that have not found consensus to the PTSC
|
||||
for discussion by assigning the `tsc-agenda` tag to a pull request or
|
||||
issue. The PTSC should serve as the final arbiter where required. The PTSC
|
||||
will maintain and publish a list of current Collaborators, as
|
||||
well as a development process guide for Collaborators and Contributors
|
||||
looking to participate in the development effort.
|
||||
|
||||
## Section 9. Definitions
|
||||
|
||||
* **Contributors**: contribute code or other artifacts, but do not have
|
||||
the right to commit to the code base. Contributors work with the
|
||||
project’s Collaborators to have code committed to the code base. A
|
||||
Contributor may be promoted to a Collaborator by the PTSC. Contributors should
|
||||
rarely be encumbered by the PTSC.
|
||||
|
||||
* **Project**: a technical collaboration effort, e.g. a subsystem, that
|
||||
is organized through the project creation process and approved by the
|
||||
PTSC.
|
||||
|
||||
[Consensus Seeking]: https://en.wikipedia.org/wiki/Consensus-seeking_decision-making
|
||||
[Condorcet]: https://en.wikipedia.org/wiki/Condorcet_method
|
||||
[Single Transferable Vote]: https://en.wikipedia.org/wiki/Single_transferable_vote
|
||||
|
1
assembly-script/.gitignore
vendored
Normal file
1
assembly-script/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/node_modules
|
16
assembly-script/package-lock.json
generated
16
assembly-script/package-lock.json
generated
|
@ -5,24 +5,24 @@
|
|||
"requires": true,
|
||||
"dependencies": {
|
||||
"assemblyscript": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npm.taobao.org/assemblyscript/download/assemblyscript-0.8.1.tgz",
|
||||
"integrity": "sha1-xcYnSSQG5th/QmiXs9kr0qUz9/4=",
|
||||
"version": "0.17.4",
|
||||
"resolved": "https://registry.npm.taobao.org/assemblyscript/download/assemblyscript-0.17.4.tgz",
|
||||
"integrity": "sha1-1GEduJpClDNa1H7DxmYaJqRCh3E=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"binaryen": "89.0.0-nightly.20191113",
|
||||
"binaryen": "98.0.0-nightly.20201109",
|
||||
"long": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"binaryen": {
|
||||
"version": "89.0.0-nightly.20191113",
|
||||
"resolved": "https://registry.npm.taobao.org/binaryen/download/binaryen-89.0.0-nightly.20191113.tgz",
|
||||
"integrity": "sha1-oNORTzXJKXhzQeApELf/rrfYl6k=",
|
||||
"version": "98.0.0-nightly.20201109",
|
||||
"resolved": "https://registry.npm.taobao.org/binaryen/download/binaryen-98.0.0-nightly.20201109.tgz",
|
||||
"integrity": "sha1-USv2yhXGe/dAIURzSkg25jmTqgU=",
|
||||
"dev": true
|
||||
},
|
||||
"long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/long/download/long-4.0.0.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/long/download/long-4.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flong%2Fdownload%2Flong-4.0.0.tgz",
|
||||
"integrity": "sha1-mntxz7fTYaGU6lVSQckvdGjVvyg=",
|
||||
"dev": true
|
||||
}
|
||||
|
|
|
@ -5,16 +5,16 @@
|
|||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --validate --optimize --use abort=",
|
||||
"build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --validate --optimize --use abort=",
|
||||
"build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --validate --optimize --use abort=",
|
||||
"build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --validate --optimize --use abort=",
|
||||
"build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --validate --optimize --use abort=",
|
||||
"build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --optimize --exportRuntime --use abort=",
|
||||
"build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --optimize --exportRuntime --use abort=",
|
||||
"build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --optimize --exportRuntime --use abort=",
|
||||
"build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --optimize --exportRuntime --use abort=",
|
||||
"build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --optimize --exportRuntime --use abort=",
|
||||
"build:all": "npm run build:request_handler; npm run build:request_sender; npm run build:timer; npm run build:subscriber; npm run build:publisher"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"assemblyscript": "^0.8.1"
|
||||
"assemblyscript": "^0.18.15"
|
||||
}
|
||||
}
|
||||
|
|
88
build-scripts/SConscript
Normal file
88
build-scripts/SConscript
Normal file
|
@ -0,0 +1,88 @@
|
|||
#
|
||||
# Copyright (c) 2021, RT-Thread Development Team
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
import os
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
objs = []
|
||||
|
||||
WAMR_ROOT_DIR = os.path.join(cwd, "..")
|
||||
|
||||
|
||||
SHARED_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'shared')
|
||||
|
||||
IWASM_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'iwasm')
|
||||
|
||||
APP_MGR_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'app-mgr')
|
||||
|
||||
APP_FRAMEWORK_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'app-framework')
|
||||
|
||||
DEPS_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'deps')
|
||||
|
||||
if GetDepend(['WAMR_BUILD_INTERP']):
|
||||
script_path = os.path.join(IWASM_DIR, 'interpreter', 'SConscript')
|
||||
objs += SConscript(script_path)
|
||||
|
||||
|
||||
if GetDepend(['WAMR_BUILD_AOT']):
|
||||
script_path = os.path.join(IWASM_DIR, 'aot', 'SConscript')
|
||||
objs += SConscript(script_path)
|
||||
if GetDepend(['WAMR_BUILD_JIT']):
|
||||
script_path = os.path.join(IWASM_DIR, 'compilation', 'SConscript')
|
||||
objs += SConscript(script_path)
|
||||
|
||||
|
||||
if GetDepend(['WAMR_BUILD_APP_FRAMEWORK']):
|
||||
objs += SConscript(os.path.join(APP_FRAMEWORK_DIR, 'SConscript'))
|
||||
objs += SConscript(os.path.join(SHARED_DIR, 'coap', 'SConscript'))
|
||||
objs += SConscript(os.path.join(APP_MGR_DIR, 'app-manager', 'SConscript'))
|
||||
objs += SConscript(os.path.join(APP_MGR_DIR, 'app-mgr-shared', 'SConscript'))
|
||||
|
||||
|
||||
|
||||
if GetDepend(['WAMR_BUILD_LIBC_BUILTIN']):
|
||||
objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-builtin', 'SConscript'))
|
||||
|
||||
|
||||
|
||||
if GetDepend(['WAMR_BUILD_LIBC_WASI']):
|
||||
objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-wasi', 'SConscript'))
|
||||
|
||||
|
||||
if GetDepend(['WAMR_BUILD_LIB_PTHREAD']):
|
||||
objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-pthread', 'SConscript'))
|
||||
# TODO: 这里加一下
|
||||
|
||||
|
||||
|
||||
# if (WAMR_BUILD_THREAD_MGR EQUAL 1)
|
||||
# include (${IWASM_DIR}/libraries/thread-mgr/thread_mgr.cmake)
|
||||
# endif ()
|
||||
|
||||
if GetDepend(['WAMR_BUILD_THREAD_MGR']):
|
||||
objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'thread-mgr', 'SConscript'))
|
||||
|
||||
|
||||
|
||||
# if (WAMR_BUILD_LIBC_EMCC EQUAL 1)
|
||||
# include (${IWASM_DIR}/libraries/libc-emcc/libc_emcc.cmake)
|
||||
# endif()
|
||||
|
||||
if GetDepend(['WAMR_BUILD_LIBC_EMCC']):
|
||||
objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-emmc', 'SConscript'))
|
||||
|
||||
objs += SConscript(os.path.join(cwd, 'SConscript_config'));
|
||||
|
||||
|
||||
objs += SConscript(os.path.join(SHARED_DIR, 'platform', 'rt-thread', 'SConscript'))
|
||||
objs += SConscript(os.path.join(SHARED_DIR, 'mem-alloc', 'SConscript'))
|
||||
objs += SConscript(os.path.join(IWASM_DIR, 'common', 'SConscript'))
|
||||
objs += SConscript(os.path.join(SHARED_DIR, 'utils', 'SConscript'))
|
||||
|
||||
|
||||
|
||||
Return('objs')
|
121
build-scripts/SConscript_config
Normal file
121
build-scripts/SConscript_config
Normal file
|
@ -0,0 +1,121 @@
|
|||
#
|
||||
# Copyright (c) 2021, RT-Thread Development Team
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
src = Split('''
|
||||
''')
|
||||
objs = []
|
||||
cwd = GetCurrentDir()
|
||||
|
||||
IWASM_INC_DIR = os.path.join(cwd, '..', 'core', 'iwasm', 'include')
|
||||
|
||||
# include_directories (${IWASM_DIR}/include)
|
||||
|
||||
CPPPATH = [IWASM_INC_DIR]
|
||||
|
||||
if rtconfig.BUILD == 'debug':
|
||||
CPPDEFINES = ['BH_DEBUG=1']
|
||||
else:
|
||||
CPPDEFINES = ['BH_DEBUG=0']
|
||||
|
||||
if rtconfig.ARCH == 'arm':
|
||||
if re.match('^cortex-m.*', rtconfig.CPU):
|
||||
print('[WAMR] using thumbv4t')
|
||||
CPPDEFINES += ['BUILD_TARGET_THUMB']
|
||||
CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_THUMB']
|
||||
elif re.match('^cortex-a.*', rtconfig.CPU):
|
||||
print('[WAMR] using armv7')
|
||||
CPPDEFINES += ['BUILD_TARGET_ARM']
|
||||
CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_ARMV7']
|
||||
elif re.match('^cortex-r.*', rtconfig.CPU):
|
||||
print('[WAMR] using armv7')
|
||||
CPPDEFINES += ['BUILD_TARGET_ARM']
|
||||
CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_ARMV7']
|
||||
elif rtconfig.CPU == 'armv6':
|
||||
print('[WAMR] using armv6')
|
||||
CPPDEFINES += ['BUILD_TARGET_ARM']
|
||||
CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_ARMV6']
|
||||
elif re.match('^arm9*', rtconfig.CPU):
|
||||
print('[WAMR] using armv4')
|
||||
CPPDEFINES += ['BUILD_TARGET_ARM']
|
||||
CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_ARMV4']
|
||||
else:
|
||||
print("[WAMR] unknown arch", rtconfig.ARCH)
|
||||
|
||||
|
||||
LIBS = ['m']
|
||||
|
||||
if GetDepend(['WAMR_BUILD_INTERP']):
|
||||
CPPDEFINES += ['WASM_ENABLE_INTERP=1']
|
||||
if GetDepend(['WAMR_BUILD_FAST_INTERP']):
|
||||
CPPDEFINES += ['WASM_ENABLE_FAST_INTERP=1']
|
||||
print("[WAMR] fast interpreter was enabled")
|
||||
else:
|
||||
CPPDEFINES += ['WASM_ENABLE_FAST_INTERP=0']
|
||||
print("[WAMR] fast interpreter was disabled")
|
||||
else:
|
||||
CPPDEFINES += ['WASM_ENABLE_INTERP=0']
|
||||
|
||||
CPPDEFINES += ['WASM_ENABLE_JIT=0']
|
||||
|
||||
if GetDepend(['WAMR_BUILD_MULTI_MODULE']):
|
||||
CPPDEFINES += ['WASM_ENABLE_MULTI_MODULE=1']
|
||||
else:
|
||||
CPPDEFINES += ['WASM_ENABLE_MULTI_MODULE=0']
|
||||
|
||||
if GetDepend(['WAMR_BUILD_SPEC_TEST']):
|
||||
CPPDEFINES += ['WASM_ENABLE_SPEC_TEST=1']
|
||||
print("[WAMR] spec test compatible mode was enabled")
|
||||
|
||||
if GetDepend(['WAMR_BUILD_BULK_MEMORY']):
|
||||
CPPDEFINES += ['WASM_ENABLE_BULK_MEMORY=1']
|
||||
print("[WAMR] Bulk memory feature was enabled")
|
||||
else:
|
||||
CPPDEFINES += ['WASM_ENABLE_BULK_MEMORY=0']
|
||||
|
||||
if GetDepend(['WAMR_BUILD_SHARED_MEMORY']):
|
||||
CPPDEFINES += ['WASM_ENABLE_SHARED_MEMORY=1']
|
||||
print("[WAMR] Shared memory enabled")
|
||||
else:
|
||||
CPPDEFINES += ['WASM_ENABLE_SHARED_MEMORY=0']
|
||||
|
||||
if GetDepend(['WAMR_BUILD_MINI_LOADER']):
|
||||
CPPDEFINES += ['WASM_ENABLE_MINI_LOADER=1']
|
||||
print("[WAMR] mini loader enabled")
|
||||
else:
|
||||
CPPDEFINES += ['WASM_ENABLE_MINI_LOADER=0']
|
||||
|
||||
if GetDepend(['WAMR_DISABLE_HW_BOUND_CHECK']):
|
||||
CPPDEFINES += ['WASM_DISABLE_HW_BOUND_CHECK=1']
|
||||
print("[WAMR] Hardware boundary check disabled")
|
||||
|
||||
if GetDepend(['WAMR_BUILD_SIMD']):
|
||||
CPPDEFINES += ['WASM_ENABLE_SIMD=1']
|
||||
print('[WAMR] SIMD enabled')
|
||||
|
||||
if GetDepend(['WAMR_BUILD_MEMORY_PROFILING']):
|
||||
CPPDEFINES += ['WASM_ENABLE_MEMORY_PROFILING=1']
|
||||
print('[WAMR] Memory profiling enabled')
|
||||
|
||||
if GetDepend(['WAMR_BUILD_CUSTOM_NAME_SECTION']):
|
||||
CPPDEFINES += ['WASM_ENABLE_CUSTOM_NAME_SECTION=1']
|
||||
print('[WAMR] Custom name section enabled')
|
||||
|
||||
if GetDepend(['WAMR_BUILD_TAIL_CALL']):
|
||||
CPPDEFINES += ['WASM_ENABLE_TAIL_CALL=1']
|
||||
print('[WAMR] Tail call enabledd')
|
||||
|
||||
|
||||
group = DefineGroup('wamr_config_common', src, depend = ['PKG_USING_WAMR'], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES, LIBS = LIBS)
|
||||
|
||||
Return('group')
|
||||
|
|
@ -34,8 +34,16 @@ elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
|
|||
add_definitions(-DBUILD_TARGET_MIPS)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
|
||||
add_definitions(-DBUILD_TARGET_XTENSA)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64" OR WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64D")
|
||||
add_definitions(-DBUILD_TARGET_RISCV64_LP64D)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64")
|
||||
add_definitions(-DBUILD_TARGET_RISCV64_LP64)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32D")
|
||||
add_definitions(-DBUILD_TARGET_RISCV32_ILP32D)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32")
|
||||
add_definitions(-DBUILD_TARGET_RISCV32_ILP32)
|
||||
else ()
|
||||
message (FATAL_ERROR "-- WAMR build target isn't set")
|
||||
message (FATAL_ERROR "-- WAMR build target isn't set")
|
||||
endif ()
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
|
@ -43,10 +51,12 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|||
endif ()
|
||||
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*")
|
||||
# Add -fPIC flag if build as 64-bit
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
|
||||
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*" OR WAMR_BUILD_TARGET MATCHES "RISCV64.*")
|
||||
if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||
# Add -fPIC flag if build as 64-bit
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
|
||||
endif ()
|
||||
else ()
|
||||
add_definitions (-m32)
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32")
|
||||
|
@ -55,10 +65,10 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|||
endif ()
|
||||
|
||||
if (WAMR_BUILD_TARGET MATCHES "ARM.*")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm")
|
||||
elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb")
|
||||
set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-mthumb")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb")
|
||||
set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-mthumb")
|
||||
endif ()
|
||||
|
||||
if (NOT WAMR_BUILD_INTERP EQUAL 1)
|
||||
|
@ -70,11 +80,17 @@ endif ()
|
|||
if (WAMR_BUILD_JIT EQUAL 1)
|
||||
if (WAMR_BUILD_AOT EQUAL 1)
|
||||
add_definitions("-DWASM_ENABLE_JIT=1")
|
||||
set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
|
||||
if (NOT EXISTS "${LLVM_SRC_ROOT}/build")
|
||||
message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build")
|
||||
if (NOT DEFINED LLVM_DIR)
|
||||
set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
|
||||
set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build")
|
||||
if (WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||
set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/win32build")
|
||||
endif ()
|
||||
if (NOT EXISTS "${LLVM_BUILD_ROOT}")
|
||||
message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_BUILD_ROOT}")
|
||||
endif ()
|
||||
set (CMAKE_PREFIX_PATH "${LLVM_BUILD_ROOT};${CMAKE_PREFIX_PATH}")
|
||||
endif ()
|
||||
set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}")
|
||||
find_package(LLVM REQUIRED CONFIG)
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
add_definitions(${LLVM_DEFINITIONS})
|
||||
|
@ -111,7 +127,9 @@ if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
|
|||
else ()
|
||||
message (" Libc builtin disabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_LIBC_WASI EQUAL 1)
|
||||
if (WAMR_BUILD_LIBC_UVWASI EQUAL 1)
|
||||
message (" Libc WASI enabled with uvwasi implementation")
|
||||
elseif (WAMR_BUILD_LIBC_WASI EQUAL 1)
|
||||
message (" Libc WASI enabled")
|
||||
else ()
|
||||
message (" Libc WASI disabled")
|
||||
|
@ -123,4 +141,86 @@ else ()
|
|||
add_definitions (-DWASM_ENABLE_FAST_INTERP=0)
|
||||
message (" Fast interpreter disabled")
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_MULTI_MODULE EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_MULTI_MODULE=1)
|
||||
message (" Multiple modules enabled")
|
||||
else ()
|
||||
add_definitions (-DWASM_ENABLE_MULTI_MODULE=0)
|
||||
message (" Multiple modules disabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_SPEC_TEST EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_SPEC_TEST=1)
|
||||
message (" spec test compatible mode is on")
|
||||
endif ()
|
||||
if (WAMR_BUILD_BULK_MEMORY EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_BULK_MEMORY=1)
|
||||
message (" Bulk memory feature enabled")
|
||||
else ()
|
||||
add_definitions (-DWASM_ENABLE_BULK_MEMORY=0)
|
||||
endif ()
|
||||
if (WAMR_BUILD_SHARED_MEMORY EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_SHARED_MEMORY=1)
|
||||
message (" Shared memory enabled")
|
||||
else ()
|
||||
add_definitions (-DWASM_ENABLE_SHARED_MEMORY=0)
|
||||
endif ()
|
||||
if (WAMR_BUILD_THREAD_MGR EQUAL 1)
|
||||
message (" Thread manager enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
|
||||
message (" Lib pthread enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_LIBC_EMCC EQUAL 1)
|
||||
message (" Libc emcc enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_MINI_LOADER EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_MINI_LOADER=1)
|
||||
message (" WASM mini loader enabled")
|
||||
else ()
|
||||
add_definitions (-DWASM_ENABLE_MINI_LOADER=0)
|
||||
endif ()
|
||||
if (WAMR_DISABLE_HW_BOUND_CHECK EQUAL 1)
|
||||
add_definitions (-DWASM_DISABLE_HW_BOUND_CHECK=1)
|
||||
message (" Hardware boundary check disabled")
|
||||
else ()
|
||||
add_definitions (-DWASM_DISABLE_HW_BOUND_CHECK=0)
|
||||
endif ()
|
||||
if (WAMR_BUILD_SIMD EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_SIMD=1)
|
||||
message (" SIMD enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_MEMORY_PROFILING EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_MEMORY_PROFILING=1)
|
||||
message (" Memory profiling enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_PERF_PROFILING EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_PERF_PROFILING=1)
|
||||
message (" Performance profiling enabled")
|
||||
endif ()
|
||||
if (DEFINED WAMR_APP_THREAD_STACK_SIZE_MAX)
|
||||
add_definitions (-DAPP_THREAD_STACK_SIZE_MAX=${WAMR_APP_THREAD_STACK_SIZE_MAX})
|
||||
endif ()
|
||||
if (WAMR_BUILD_CUSTOM_NAME_SECTION EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_CUSTOM_NAME_SECTION=1)
|
||||
message (" Custom name section enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_DUMP_CALL_STACK EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1)
|
||||
message (" Dump call stack enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_TAIL_CALL EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_TAIL_CALL=1)
|
||||
message (" Tail call enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_REF_TYPES EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_REF_TYPES=1)
|
||||
message (" Reference types enabled")
|
||||
else ()
|
||||
message (" Reference types disabled")
|
||||
endif ()
|
||||
if (DEFINED WAMR_BH_VPRINTF)
|
||||
add_definitions (-DBH_VPRINTF=${WAMR_BH_VPRINTF})
|
||||
endif ()
|
||||
if (WAMR_DISABLE_APP_ENTRY EQUAL 1)
|
||||
message (" WAMR application entry functions excluded")
|
||||
endif ()
|
||||
|
|
|
@ -31,9 +31,14 @@ endif ()
|
|||
# Set default options
|
||||
|
||||
# Set WAMR_BUILD_TARGET, currently values supported:
|
||||
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
|
||||
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
|
||||
# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
|
||||
if (NOT DEFINED WAMR_BUILD_TARGET)
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
set (WAMR_BUILD_TARGET "AARCH64")
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
|
||||
set (WAMR_BUILD_TARGET "RISCV64")
|
||||
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
# Build as X86_64 by default in 64-bit platform
|
||||
set (WAMR_BUILD_TARGET "X86_64")
|
||||
else ()
|
||||
|
@ -47,6 +52,11 @@ if (WAMR_BUILD_INTERP EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1)
|
|||
include (${IWASM_DIR}/interpreter/iwasm_interp.cmake)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_TARGET MATCHES "RISCV.*" AND WAMR_BUILD_AOT EQUAL 1)
|
||||
set (WAMR_BUILD_AOT 0)
|
||||
message ("-- WAMR AOT disabled as it isn't supported by riscv currently")
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_AOT EQUAL 1)
|
||||
include (${IWASM_DIR}/aot/iwasm_aot.cmake)
|
||||
if (WAMR_BUILD_JIT EQUAL 1)
|
||||
|
@ -65,22 +75,40 @@ if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
|
|||
include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_LIBC_WASI EQUAL 1)
|
||||
if (WAMR_BUILD_LIBC_UVWASI EQUAL 1)
|
||||
include (${IWASM_DIR}/libraries/libc-uvwasi/libc_uvwasi.cmake)
|
||||
elseif (WAMR_BUILD_LIBC_WASI EQUAL 1)
|
||||
include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
|
||||
include (${IWASM_DIR}/libraries/lib-pthread/lib_pthread.cmake)
|
||||
# Enable the dependent feature if lib pthread is enabled
|
||||
set (WAMR_BUILD_THREAD_MGR 1)
|
||||
set (WAMR_BUILD_BULK_MEMORY 1)
|
||||
set (WAMR_BUILD_SHARED_MEMORY 1)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_THREAD_MGR EQUAL 1)
|
||||
include (${IWASM_DIR}/libraries/thread-mgr/thread_mgr.cmake)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_LIBC_EMCC EQUAL 1)
|
||||
include (${IWASM_DIR}/libraries/libc-emcc/libc_emcc.cmake)
|
||||
endif()
|
||||
|
||||
####################### Common sources #######################
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \
|
||||
-Wall -Wno-unused-parameter -Wno-pedantic")
|
||||
if (NOT MSVC)
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \
|
||||
-Wall -Wno-unused-parameter -Wno-pedantic")
|
||||
endif ()
|
||||
|
||||
# include the build config template file
|
||||
include (${CMAKE_CURRENT_LIST_DIR}/config_common.cmake)
|
||||
|
||||
include_directories (${SHARED_DIR}/include
|
||||
${IWASM_DIR}/include)
|
||||
include_directories (${IWASM_DIR}/include)
|
||||
|
||||
file (GLOB header
|
||||
${SHARED_DIR}/include/*.h
|
||||
${IWASM_DIR}/include/*.h
|
||||
)
|
||||
LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
|
||||
|
@ -106,6 +134,9 @@ set (source_all
|
|||
${WASM_APP_LIB_SOURCE_ALL}
|
||||
${NATIVE_INTERFACE_SOURCE}
|
||||
${APP_MGR_SOURCE}
|
||||
${LIB_PTHREAD_SOURCE}
|
||||
${THREAD_MGR_SOURCE}
|
||||
${LIBC_EMCC_SOURCE}
|
||||
)
|
||||
|
||||
set (WAMR_RUNTIME_LIB_SOURCE ${source_all})
|
||||
|
|
18
ci/Dockerfile
Normal file
18
ci/Dockerfile
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt update \
|
||||
&& apt install -y apt-transport-https ca-certificates gnupg \
|
||||
software-properties-common wget lsb-release curl build-essential
|
||||
|
||||
#
|
||||
# CMAKE (https://apt.kitware.com/)
|
||||
RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null \
|
||||
&& apt purge --auto-remove cmake \
|
||||
&& apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' \
|
||||
&& apt update \
|
||||
&& apt-get install -y kitware-archive-keyring \
|
||||
&& rm /etc/apt/trusted.gpg.d/kitware.gpg \
|
||||
&& apt-get install -y cmake
|
24
ci/build_wamr.sh
Executable file
24
ci/build_wamr.sh
Executable file
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
docker build -t wamr_dev:0.1 -f Dockerfile . \
|
||||
&& docker run --rm -it \
|
||||
--name wamr_building \
|
||||
--mount type=bind,src=$(realpath .)/..,dst=/source \
|
||||
--workdir /source \
|
||||
wamr_dev:0.1 \
|
||||
/bin/bash -c "\
|
||||
pushd product-mini/platforms/linux \
|
||||
&& mkdir -p build \
|
||||
&& pushd build \
|
||||
&& rm -rf * \
|
||||
&& cmake .. \
|
||||
&& make \
|
||||
&& popd \
|
||||
&& popd \
|
||||
&& echo 'Copying binary for image build' \
|
||||
&& mkdir -p build_out \
|
||||
&& rm build_out/* \
|
||||
&& cp -f product-mini/platforms/linux/build/iwasm build_out/iwasm"
|
|
@ -106,13 +106,13 @@ attr_container_get_attr_begin(const attr_container_t *attr_cont,
|
|||
|
||||
/* tag content */
|
||||
p += str_len;
|
||||
if (p - attr_cont->buf >= total_length)
|
||||
if ((uint32_t)(p - attr_cont->buf) >= total_length)
|
||||
return NULL;
|
||||
|
||||
/* attribute num */
|
||||
attr_num = get_uint16(p);
|
||||
p += sizeof(uint16_t);
|
||||
if (p - attr_cont->buf >= total_length)
|
||||
if ((uint32_t)(p - attr_cont->buf) >= total_length)
|
||||
return NULL;
|
||||
|
||||
if (p_total_length)
|
||||
|
@ -174,7 +174,8 @@ attr_container_find_attr(const attr_container_t *attr_cont, const char *key)
|
|||
|
||||
if (str_len == strlen(key) + 1
|
||||
&& memcmp(p + sizeof(uint16_t), key, str_len) == 0) {
|
||||
if (p + sizeof(uint16_t) + str_len - attr_cont->buf >= total_length)
|
||||
if ((uint32_t)(p + sizeof(uint16_t) + str_len
|
||||
- attr_cont->buf) >= total_length)
|
||||
return NULL;
|
||||
return p;
|
||||
}
|
||||
|
@ -337,7 +338,7 @@ bool attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
|
|||
}
|
||||
|
||||
/* Set the attr buf */
|
||||
str_len = strlen(key) + 1;
|
||||
str_len = (uint16_t)(strlen(key) + 1);
|
||||
set_uint16(p, str_len);
|
||||
p += sizeof(uint16_t);
|
||||
bh_memcpy_s(p, str_len, key, str_len);
|
||||
|
@ -366,7 +367,7 @@ bool attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (p1 - p + msg_end - attr_end >= attr_len) {
|
||||
if ((uint32_t)(p1 - p + msg_end - attr_end) >= attr_len) {
|
||||
memmove(p, p1, attr_end - p1);
|
||||
bh_memcpy_s(p + (attr_end - p1), attr_len, attr_buf, attr_len);
|
||||
attr_container_free(attr_buf);
|
||||
|
@ -399,7 +400,7 @@ bool attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
|
|||
return true;
|
||||
} else {
|
||||
/* key not found */
|
||||
if (msg_end - attr_end >= attr_len) {
|
||||
if ((uint32_t)(msg_end - attr_end) >= attr_len) {
|
||||
bh_memcpy_s(attr_end, msg_end - attr_end, attr_buf, attr_len);
|
||||
attr_container_inc_attr_num(attr_cont);
|
||||
attr_container_free(attr_buf);
|
||||
|
@ -564,6 +565,9 @@ attr_container_get_attr(const attr_container_t *attr_cont, const char *key)
|
|||
bh_memcpy_s(&val.var_name, sizeof(val.var_name), addr, len); \
|
||||
break; \
|
||||
} \
|
||||
default: \
|
||||
bh_assert(0); \
|
||||
break; \
|
||||
} \
|
||||
return val.var_name; \
|
||||
} while (0)
|
||||
|
@ -819,6 +823,9 @@ void attr_container_dump(const attr_container_t *attr_cont)
|
|||
get_uint32(p));
|
||||
p += sizeof(uint32_t) + get_uint32(p);
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef _ATTR_CONTAINER_H_
|
||||
#define _ATTR_CONTAINER_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -71,23 +71,18 @@ void free_req_resp_packet(char * packet)
|
|||
request_t * unpack_request(char * packet, int size, request_t * request)
|
||||
{
|
||||
if (*packet != REQUES_PACKET_VER) {
|
||||
printf("version fail\n");
|
||||
return NULL;
|
||||
}
|
||||
if (size < REQUEST_PACKET_FIX_PART_LEN) {
|
||||
printf("size error: %d\n", size);
|
||||
return NULL;
|
||||
}
|
||||
uint16 url_len = ntohs(*((uint16*) (packet + 12)));
|
||||
uint32 payload_len = ntohl(*((uint32*) (packet + 14)));
|
||||
|
||||
if (size != ( REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len)) {
|
||||
printf("size error: %d, expect: %d\n", size,
|
||||
REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len);
|
||||
return NULL;
|
||||
}
|
||||
if (*(packet + REQUEST_PACKET_FIX_PART_LEN + url_len - 1) != 0) {
|
||||
printf("url not end with 0\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,4 +45,18 @@ uint16 ntohs(uint16 value);
|
|||
// We are not worried for the WASM world since the sandbox will catch it.
|
||||
#define bh_memcpy_s(dst, dst_len, src, src_len) memcpy(dst, src, src_len)
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define bh_assert(v) (void)0
|
||||
#else
|
||||
#define bh_assert(v) do { \
|
||||
if (!(v)) { \
|
||||
int _count; \
|
||||
printf("ASSERTION FAILED: %s, at %s, line %d",\
|
||||
#v, __FILE__, __LINE__); \
|
||||
_count = printf("\n"); \
|
||||
printf("%d\n", _count / (_count - 1)); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_ */
|
||||
|
|
|
@ -5,20 +5,22 @@
|
|||
|
||||
#include "bh_platform.h"
|
||||
#include "app_manager_export.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "../app-manager/module_wasm_app.h"
|
||||
#include "timer_native_api.h"
|
||||
|
||||
static bool timer_thread_run = true;
|
||||
|
||||
bh_list g_timer_ctx_list;
|
||||
korp_cond g_timer_ctx_list_cond;
|
||||
korp_mutex g_timer_ctx_list_mutex;
|
||||
typedef struct {
|
||||
bh_list_link l;
|
||||
timer_ctx_t timer_ctx;
|
||||
} timer_ctx_node_t;
|
||||
|
||||
void wasm_timer_callback(timer_id_t id, unsigned int mod_id)
|
||||
static bool timer_thread_run = true;
|
||||
|
||||
static bh_list g_timer_ctx_list;
|
||||
static korp_cond g_timer_ctx_list_cond;
|
||||
static korp_mutex g_timer_ctx_list_mutex;
|
||||
|
||||
void
|
||||
wasm_timer_callback(timer_id_t id, unsigned int mod_id)
|
||||
{
|
||||
module_data* module = module_data_list_lookup_id(mod_id);
|
||||
if (module == NULL)
|
||||
|
@ -29,27 +31,29 @@ void wasm_timer_callback(timer_id_t id, unsigned int mod_id)
|
|||
bh_post_msg(module->queue, TIMER_EVENT_WASM, (char *)(uintptr_t)id, 0);
|
||||
}
|
||||
|
||||
///
|
||||
/// why we create a separate link for module timer contexts
|
||||
/// rather than traverse the module list?
|
||||
/// It helps to reduce the lock frequency for the module list.
|
||||
/// Also when we lock the module list and then call the callback for
|
||||
/// timer expire, the callback is request the list lock again for lookup
|
||||
/// the module from module id. It is for avoiding that situation.
|
||||
/**
|
||||
* why we create a separate link for module timer contexts
|
||||
* rather than traverse the module list?
|
||||
* It helps to reduce the lock frequency for the module list.
|
||||
* Also when we lock the module list and then call the callback for
|
||||
* timer expire, the callback is request the list lock again for lookup
|
||||
* the module from module id. It is for avoiding that situation.
|
||||
*/
|
||||
|
||||
void * thread_modulers_timer_check(void * arg)
|
||||
{
|
||||
int ms_to_expiry;
|
||||
uint32 ms_to_expiry;
|
||||
uint64 us_to_wait;
|
||||
|
||||
while (timer_thread_run) {
|
||||
ms_to_expiry = -1;
|
||||
ms_to_expiry = (uint32)-1;
|
||||
os_mutex_lock(&g_timer_ctx_list_mutex);
|
||||
timer_ctx_node_t* elem = (timer_ctx_node_t*)
|
||||
bh_list_first_elem(&g_timer_ctx_list);
|
||||
while (elem) {
|
||||
int next = check_app_timers(elem->timer_ctx);
|
||||
if (next != -1) {
|
||||
if (ms_to_expiry == -1 || ms_to_expiry > next)
|
||||
uint32 next = check_app_timers(elem->timer_ctx);
|
||||
if (next != (uint32)-1) {
|
||||
if (ms_to_expiry == (uint32)-1 || ms_to_expiry > next)
|
||||
ms_to_expiry = next;
|
||||
}
|
||||
|
||||
|
@ -57,48 +61,54 @@ void * thread_modulers_timer_check(void * arg)
|
|||
}
|
||||
os_mutex_unlock(&g_timer_ctx_list_mutex);
|
||||
|
||||
if (ms_to_expiry == -1)
|
||||
ms_to_expiry = 60 * 1000;
|
||||
if (ms_to_expiry == (uint32)-1)
|
||||
us_to_wait = BHT_WAIT_FOREVER;
|
||||
else
|
||||
us_to_wait = (uint64)ms_to_expiry * 1000;
|
||||
os_mutex_lock(&g_timer_ctx_list_mutex);
|
||||
os_cond_reltimedwait(&g_timer_ctx_list_cond, &g_timer_ctx_list_mutex,
|
||||
ms_to_expiry * 1000);
|
||||
us_to_wait);
|
||||
os_mutex_unlock(&g_timer_ctx_list_mutex);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void wakeup_modules_timer_thread(timer_ctx_t ctx)
|
||||
void
|
||||
wakeup_modules_timer_thread(timer_ctx_t ctx)
|
||||
{
|
||||
os_mutex_lock(&g_timer_ctx_list_mutex);
|
||||
os_cond_signal(&g_timer_ctx_list_cond);
|
||||
os_mutex_unlock(&g_timer_ctx_list_mutex);
|
||||
}
|
||||
|
||||
void init_wasm_timer()
|
||||
void
|
||||
init_wasm_timer()
|
||||
{
|
||||
korp_tid tm_tid;
|
||||
bh_list_init(&g_timer_ctx_list);
|
||||
|
||||
os_cond_init(&g_timer_ctx_list_cond);
|
||||
/* temp solution for: thread_modulers_timer_check thread would recursive lock the mutex */
|
||||
/* temp solution for: thread_modulers_timer_check thread
|
||||
would recursive lock the mutex */
|
||||
os_recursive_mutex_init(&g_timer_ctx_list_mutex);
|
||||
|
||||
os_thread_create(&tm_tid, thread_modulers_timer_check,
|
||||
NULL, BH_APPLET_PRESERVED_STACK_SIZE);
|
||||
}
|
||||
|
||||
void exit_wasm_timer()
|
||||
void
|
||||
exit_wasm_timer()
|
||||
{
|
||||
timer_thread_run = false;
|
||||
}
|
||||
|
||||
timer_ctx_t create_wasm_timer_ctx(unsigned int module_id, int prealloc_num)
|
||||
timer_ctx_t
|
||||
create_wasm_timer_ctx(unsigned int module_id, int prealloc_num)
|
||||
{
|
||||
timer_ctx_t ctx = create_timer_ctx(wasm_timer_callback,
|
||||
wakeup_modules_timer_thread,
|
||||
prealloc_num,
|
||||
module_id);
|
||||
prealloc_num, module_id);
|
||||
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
@ -119,11 +129,14 @@ timer_ctx_t create_wasm_timer_ctx(unsigned int module_id, int prealloc_num)
|
|||
return ctx;
|
||||
}
|
||||
|
||||
void destroy_module_timer_ctx(unsigned int module_id)
|
||||
void
|
||||
destroy_module_timer_ctx(unsigned int module_id)
|
||||
{
|
||||
timer_ctx_node_t* elem;
|
||||
|
||||
os_mutex_lock(&g_timer_ctx_list_mutex);
|
||||
timer_ctx_node_t* elem = (timer_ctx_node_t*)
|
||||
bh_list_first_elem(&g_timer_ctx_list);
|
||||
elem = (timer_ctx_node_t*)
|
||||
bh_list_first_elem(&g_timer_ctx_list);
|
||||
while (elem) {
|
||||
if (timer_ctx_get_owner(elem->timer_ctx) == module_id) {
|
||||
bh_list_remove(&g_timer_ctx_list, elem);
|
||||
|
@ -137,7 +150,8 @@ void destroy_module_timer_ctx(unsigned int module_id)
|
|||
os_mutex_unlock(&g_timer_ctx_list_mutex);
|
||||
}
|
||||
|
||||
timer_ctx_t get_wasm_timer_ctx(wasm_module_inst_t module_inst)
|
||||
timer_ctx_t
|
||||
get_wasm_timer_ctx(wasm_module_inst_t module_inst)
|
||||
{
|
||||
module_data * m = app_manager_get_module_data(Module_WASM_App,
|
||||
module_inst);
|
||||
|
@ -184,8 +198,6 @@ wasm_timer_restart(wasm_exec_env_t exec_env,
|
|||
sys_timer_restart(timer_ctx, timer_id, interval);
|
||||
}
|
||||
|
||||
extern uint32 get_sys_tick_ms();
|
||||
|
||||
uint32
|
||||
wasm_get_sys_tick_ms(wasm_exec_env_t exec_env)
|
||||
{
|
||||
|
|
|
@ -32,8 +32,8 @@ void app_manager_post_applets_update_event()
|
|||
return;
|
||||
|
||||
if (!(attr_cont = attr_container_create("All Applets"))) {
|
||||
app_manager_printf(
|
||||
"Post applets update event failed: allocate memory failed.");
|
||||
app_manager_printf("Post applets update event failed: "
|
||||
"allocate memory failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,8 @@ void app_manager_post_applets_update_event()
|
|||
}
|
||||
|
||||
if (!(attr_container_set_int(&attr_cont, "num", num))) {
|
||||
app_manager_printf(
|
||||
"Post applets update event failed: set attr container key failed.");
|
||||
app_manager_printf("Post applets update event failed: "
|
||||
"set attr container key failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -57,14 +57,14 @@ void app_manager_post_applets_update_event()
|
|||
i++;
|
||||
snprintf(buf, sizeof(buf), "%s%d", "applet", i);
|
||||
if (!(attr_container_set_string(&attr_cont, buf, m_data->module_name))) {
|
||||
app_manager_printf(
|
||||
"Post applets update event failed: set attr applet name key failed.");
|
||||
app_manager_printf("Post applets update event failed: "
|
||||
"set attr applet name key failed.");
|
||||
goto fail;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s%d", "heap", i);
|
||||
if (!(attr_container_set_int(&attr_cont, buf, m_data->heap_size))) {
|
||||
app_manager_printf(
|
||||
"Post applets update event failed: set attr heap key failed.");
|
||||
app_manager_printf("Post applets update event failed: "
|
||||
"set attr heap key failed.");
|
||||
goto fail;
|
||||
}
|
||||
m_data = m_data->next;
|
||||
|
@ -114,7 +114,7 @@ static bool app_manager_query_applets(request_t *msg, const char *name)
|
|||
attr_cont = attr_container_create("Applets Info");
|
||||
if (!attr_cont) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applets failed: allocate memory failed.");
|
||||
"Query Applets failed: allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ static bool app_manager_query_applets(request_t *msg, const char *name)
|
|||
|
||||
if (name == NULL && !(attr_container_set_int(&attr_cont, "num", num))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applets failed: set attr container key failed.");
|
||||
"Query Applets failed: set attr container key failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -142,26 +142,31 @@ static bool app_manager_query_applets(request_t *msg, const char *name)
|
|||
if (!(attr_container_set_string(&attr_cont, buf,
|
||||
m_data->module_name))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applets failed: set attr container key failed.");
|
||||
"Query Applets failed: "
|
||||
"set attr container key failed.");
|
||||
goto fail;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s%d", "heap", i);
|
||||
if (!(attr_container_set_int(&attr_cont, buf, m_data->heap_size))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applets failed: set attr container heap key failed.");
|
||||
"Query Applets failed: "
|
||||
"set attr container heap key failed.");
|
||||
goto fail;
|
||||
}
|
||||
} else if (!strcmp(name, m_data->module_name)) {
|
||||
}
|
||||
else if (!strcmp(name, m_data->module_name)) {
|
||||
found = true;
|
||||
if (!(attr_container_set_string(&attr_cont, "name",
|
||||
m_data->module_name))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applet failed: set attr container key failed.");
|
||||
"Query Applet failed: "
|
||||
"set attr container key failed.");
|
||||
goto fail;
|
||||
}
|
||||
if (!(attr_container_set_int(&attr_cont, "heap", m_data->heap_size))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applet failed: set attr container heap key failed.");
|
||||
"Query Applet failed: "
|
||||
"set attr container heap key failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +271,7 @@ static void app_manager_queue_callback(void *message, void *arg)
|
|||
goto fail;
|
||||
}
|
||||
if (g_module_interfaces[module_type]
|
||||
&& g_module_interfaces[module_type]->module_install) {
|
||||
&& g_module_interfaces[module_type]->module_install) {
|
||||
if (!g_module_interfaces[module_type]->module_install(request))
|
||||
goto fail;
|
||||
}
|
||||
|
@ -276,14 +281,13 @@ static void app_manager_queue_callback(void *message, void *arg)
|
|||
module_type = get_module_type(request->url + offset);
|
||||
if (module_type == -1) {
|
||||
SEND_ERR_RESPONSE(mid,
|
||||
"Uninstall Applet failed: invalid module type.");
|
||||
"Uninstall Applet failed: invalid module type.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (g_module_interfaces[module_type]
|
||||
&& g_module_interfaces[module_type]->module_uninstall) {
|
||||
if (!g_module_interfaces[module_type]->module_uninstall(
|
||||
request))
|
||||
if (!g_module_interfaces[module_type]->module_uninstall(request))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -292,18 +296,19 @@ static void app_manager_queue_callback(void *message, void *arg)
|
|||
char name[APP_NAME_MAX_LEN] = { 0 };
|
||||
char *properties = request->url + offset;
|
||||
find_key_value(properties, strlen(properties), "name", name,
|
||||
sizeof(name) - 1, '&');
|
||||
sizeof(name) - 1, '&');
|
||||
if (strlen(name) > 0)
|
||||
app_manager_query_applets(request, name);
|
||||
else
|
||||
app_manager_query_applets(request, NULL);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
SEND_ERR_RESPONSE(mid, "Invalid request of applet: invalid action");
|
||||
}
|
||||
}
|
||||
/* Event Register/Unregister */
|
||||
else if ((offset = check_url_start(request->url, strlen(request->url),
|
||||
"/event/")) > 0) {
|
||||
"/event/")) > 0) {
|
||||
char url_buf[256] = { 0 };
|
||||
|
||||
strncpy(url_buf, request->url + offset, sizeof(url_buf) - 1);
|
||||
|
@ -313,11 +318,12 @@ static void app_manager_queue_callback(void *message, void *arg)
|
|||
goto fail;
|
||||
}
|
||||
send_error_response_to_host(mid, CONTENT_2_05, NULL); /* OK */
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
for (i = 0; i < Module_Max; i++) {
|
||||
if (g_module_interfaces[i]
|
||||
&& g_module_interfaces[i]->module_handle_host_url) {
|
||||
&& g_module_interfaces[i]->module_handle_host_url) {
|
||||
if (g_module_interfaces[i]->module_handle_host_url(request))
|
||||
break;
|
||||
}
|
||||
|
@ -325,10 +331,8 @@ static void app_manager_queue_callback(void *message, void *arg)
|
|||
|
||||
}
|
||||
|
||||
fail:
|
||||
|
||||
fail:
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static void module_interfaces_init()
|
||||
|
@ -360,7 +364,7 @@ void app_manager_startup(host_interface *interface)
|
|||
|
||||
am_register_resource("/app/", targeted_app_request_handler, ID_APP_MGR);
|
||||
|
||||
/*/app/ and /event/ are both processed by applet_mgt_reqeust_handler*/
|
||||
/* /app/ and /event/ are both processed by applet_mgt_reqeust_handler */
|
||||
am_register_resource("/applet", applet_mgt_reqeust_handler, ID_APP_MGR);
|
||||
am_register_resource("/event/", applet_mgt_reqeust_handler, ID_APP_MGR);
|
||||
|
||||
|
@ -369,6 +373,12 @@ void app_manager_startup(host_interface *interface)
|
|||
/* Enter loop run */
|
||||
bh_queue_enter_loop_run(g_app_mgr_queue, app_manager_queue_callback, NULL);
|
||||
|
||||
/* Destroy registered resources */
|
||||
am_cleanup_registeration(ID_APP_MGR);
|
||||
|
||||
/* Destroy watchdog */
|
||||
watchdog_destroy();
|
||||
|
||||
fail2:
|
||||
module_data_list_destroy();
|
||||
|
||||
|
@ -396,4 +406,5 @@ module_interface *g_module_interfaces[Module_Max] = {
|
|||
#else
|
||||
NULL
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -13,11 +13,19 @@
|
|||
static host_interface host_commu;
|
||||
|
||||
/* IMRTLink Two leading bytes */
|
||||
static unsigned char leadings[] = { (unsigned char) 0x12, (unsigned char) 0x34 };
|
||||
static unsigned char leadings[] = {
|
||||
(unsigned char)0x12,
|
||||
(unsigned char)0x34
|
||||
};
|
||||
|
||||
/* IMRTLink Receiving Phase */
|
||||
typedef enum recv_phase_t {
|
||||
Phase_Non_Start, Phase_Leading, Phase_Type, Phase_Size, Phase_Payload
|
||||
Phase_Non_Start,
|
||||
Phase_Leading,
|
||||
Phase_Type,
|
||||
Phase_Size,
|
||||
Phase_Payload,
|
||||
Phase_Ignoring
|
||||
} recv_phase_t;
|
||||
|
||||
/* IMRTLink Receive Context */
|
||||
|
@ -74,7 +82,8 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
|
|||
}
|
||||
|
||||
return 0;
|
||||
} else if (ctx->phase == Phase_Leading) {
|
||||
}
|
||||
else if (ctx->phase == Phase_Leading) {
|
||||
if (ch == leadings[1]) {
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: got leading 1\n");
|
||||
|
@ -83,12 +92,14 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
|
|||
ctx->phase = Phase_Non_Start;
|
||||
|
||||
return 0;
|
||||
} else if (ctx->phase == Phase_Type) {
|
||||
}
|
||||
else if (ctx->phase == Phase_Type) {
|
||||
if (ctx->size_in_phase++ == 0) {
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: got type 0\n");
|
||||
ctx->message.message_type = ch;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: got type 1\n");
|
||||
ctx->message.message_type |= (ch << 8);
|
||||
|
@ -98,12 +109,13 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
|
|||
}
|
||||
|
||||
return 0;
|
||||
} else if (ctx->phase == Phase_Size) {
|
||||
}
|
||||
else if (ctx->phase == Phase_Size) {
|
||||
unsigned char *p = (unsigned char *) &ctx->message.payload_size;
|
||||
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: got payload_size, byte %d\n",
|
||||
ctx->size_in_phase);
|
||||
ctx->size_in_phase);
|
||||
p[ctx->size_in_phase++] = ch;
|
||||
|
||||
if (ctx->size_in_phase == sizeof(ctx->message.payload_size)) {
|
||||
|
@ -112,7 +124,7 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
|
|||
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: payload_size: %d\n",
|
||||
ctx->message.payload_size);
|
||||
ctx->message.payload_size);
|
||||
if (ctx->message.payload) {
|
||||
APP_MGR_FREE(ctx->message.payload);
|
||||
ctx->message.payload = NULL;
|
||||
|
@ -122,16 +134,11 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
|
|||
if (ctx->message.payload_size == 0) {
|
||||
ctx->phase = Phase_Non_Start;
|
||||
if (enable_log)
|
||||
app_manager_printf(
|
||||
"##On byte arrive: receive end, payload_size is 0.\n");
|
||||
app_manager_printf("##On byte arrive: receive end, "
|
||||
"payload_size is 0.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ctx->message.payload_size > 1024 * 1024) {
|
||||
ctx->phase = Phase_Non_Start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->message.message_type != INSTALL_WASM_APP) {
|
||||
ctx->message.payload =
|
||||
(char *) APP_MGR_MALLOC(ctx->message.payload_size);
|
||||
|
@ -146,7 +153,8 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
|
|||
}
|
||||
|
||||
return 0;
|
||||
} else if (ctx->phase == Phase_Payload) {
|
||||
}
|
||||
else if (ctx->phase == Phase_Payload) {
|
||||
if (ctx->message.message_type == INSTALL_WASM_APP) {
|
||||
int received_size;
|
||||
module_on_install_request_byte_arrive_func module_on_install =
|
||||
|
@ -162,36 +170,53 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
|
|||
ctx->phase = Phase_Non_Start;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
/* receive or handle fail */
|
||||
ctx->phase = Phase_Non_Start;
|
||||
ctx->size_in_phase = 0;
|
||||
if (ctx->size_in_phase < ctx->message.payload_size) {
|
||||
ctx->phase = Phase_Ignoring;
|
||||
}
|
||||
else {
|
||||
ctx->phase = Phase_Non_Start;
|
||||
ctx->size_in_phase = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ctx->phase = Phase_Non_Start;
|
||||
ctx->size_in_phase = 0;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ctx->message.payload[ctx->size_in_phase++] = ch;
|
||||
|
||||
if (ctx->size_in_phase == ctx->message.payload_size) {
|
||||
ctx->phase = Phase_Non_Start;
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: receive end, payload_size is %d.\n",
|
||||
app_manager_printf("##On byte arrive: receive end, "
|
||||
"payload_size is %d.\n",
|
||||
ctx->message.payload_size);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (ctx->phase == Phase_Ignoring) {
|
||||
ctx->size_in_phase++;
|
||||
if (ctx->size_in_phase == ctx->message.payload_size) {
|
||||
if (ctx->message.payload)
|
||||
APP_MGR_FREE(ctx->message.payload);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aee_host_msg_callback(void *msg, uint16_t msg_len)
|
||||
int aee_host_msg_callback(void *msg, uint32_t msg_len)
|
||||
{
|
||||
unsigned char *p = msg, *p_end = p + msg_len;
|
||||
|
||||
|
@ -209,14 +234,15 @@ int aee_host_msg_callback(void *msg, uint16_t msg_len)
|
|||
memset(&request, 0, sizeof(request));
|
||||
|
||||
if (!unpack_request(recv_ctx.message.payload,
|
||||
recv_ctx.message.payload_size, &request))
|
||||
recv_ctx.message.payload_size, &request))
|
||||
continue;
|
||||
|
||||
request.sender = ID_HOST;
|
||||
|
||||
am_dispatch_request(&request);
|
||||
} else {
|
||||
printf("unexpected host msg type: %d\n", msg_type);
|
||||
}
|
||||
else {
|
||||
app_manager_printf("unexpected host msg type: %d\n", msg_type);
|
||||
}
|
||||
|
||||
APP_MGR_FREE(recv_ctx.message.payload);
|
||||
|
@ -246,7 +272,7 @@ bool app_manager_host_init(host_interface *interface)
|
|||
return true;
|
||||
}
|
||||
|
||||
int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size)
|
||||
int app_manager_host_send_msg(int msg_type, const char *buf, int size)
|
||||
{
|
||||
/* send an IMRT LINK message contains the buf as payload */
|
||||
if (host_commu.send != NULL) {
|
||||
|
@ -258,8 +284,8 @@ int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size)
|
|||
bh_memcpy_s(header, 2, leadings, 2);
|
||||
|
||||
/* message type */
|
||||
// todo: check if use network byte order!!!
|
||||
*((uint16*) (header + 2)) = htons(msg_type);
|
||||
/* TODO: check if use network byte order!!! */
|
||||
*((uint16*)(header + 2)) = htons(msg_type);
|
||||
|
||||
/* payload length */
|
||||
if (is_little_endian())
|
||||
|
@ -276,10 +302,11 @@ int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size)
|
|||
n = host_commu.send(NULL, buf, size);
|
||||
os_mutex_unlock(&host_lock);
|
||||
|
||||
printf("sent %d bytes to host\n", n);
|
||||
app_manager_printf("sent %d bytes to host\n", n);
|
||||
return n;
|
||||
} else {
|
||||
printf("no send api provided\n");
|
||||
}
|
||||
else {
|
||||
app_manager_printf("no send api provided\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ bool send_error_response_to_host(int mid, int status, const char *msg)
|
|||
}
|
||||
}
|
||||
|
||||
set_response(response, status,
|
||||
FMT_ATTR_CONTAINER, (const char *)payload, payload_len);
|
||||
set_response(response, status, FMT_ATTR_CONTAINER,
|
||||
(const char *)payload, payload_len);
|
||||
response->mid = mid;
|
||||
|
||||
send_response_to_host(response);
|
||||
|
|
|
@ -198,17 +198,16 @@ void release_module(module_data *m_data)
|
|||
APP_MGR_FREE(m_data);
|
||||
}
|
||||
|
||||
int check_modules_timer_expiry()
|
||||
uint32 check_modules_timer_expiry()
|
||||
{
|
||||
os_mutex_lock(&module_data_list_lock);
|
||||
module_data *p = module_data_list;
|
||||
int ms_to_expiry = -1;
|
||||
uint32 ms_to_expiry = (uint32)-1;
|
||||
|
||||
while (p) {
|
||||
|
||||
int next = get_expiry_ms(p->timer_ctx);
|
||||
if (next != -1) {
|
||||
if (ms_to_expiry == -1 || ms_to_expiry > next)
|
||||
uint32 next = get_expiry_ms(p->timer_ctx);
|
||||
if (next != (uint32)-1) {
|
||||
if (ms_to_expiry == (uint32)-1 || ms_to_expiry > next)
|
||||
ms_to_expiry = next;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
#include "event.h"
|
||||
#include "watchdog.h"
|
||||
#include "runtime_lib.h"
|
||||
#include "wasm.h"
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
#include "aot_export.h"
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
|
||||
/* Wasm bytecode file 4 version bytes */
|
||||
static uint8 wasm_bytecode_version[] = {
|
||||
static uint8 wasm_bytecode_version[4] = {
|
||||
(uint8) 0x01,
|
||||
(uint8) 0x00,
|
||||
(uint8) 0x00,
|
||||
|
@ -29,12 +30,13 @@ static uint8 wasm_bytecode_version[] = {
|
|||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
/* Wasm aot file 4 version bytes */
|
||||
static uint8 wasm_aot_version[] = {
|
||||
(uint8) 0x01,
|
||||
static uint8 wasm_aot_version[4] = {
|
||||
(uint8) 0x02,
|
||||
(uint8) 0x00,
|
||||
(uint8) 0x00,
|
||||
(uint8) 0x00
|
||||
};
|
||||
#endif
|
||||
|
||||
static union {
|
||||
int a;
|
||||
|
@ -42,8 +44,6 @@ static union {
|
|||
} __ue = { .a = 1 };
|
||||
|
||||
#define is_little_endian() (__ue.b == 1)
|
||||
#endif
|
||||
|
||||
/* Wasm App Install Request Receiving Phase */
|
||||
typedef enum wasm_app_install_req_recv_phase_t {
|
||||
Phase_Req_Ver,
|
||||
|
@ -163,14 +163,6 @@ module_interface wasm_app_module_interface = {
|
|||
wasm_app_module_on_install_request_byte_arrive
|
||||
};
|
||||
|
||||
static unsigned
|
||||
align_uint(unsigned v, unsigned b)
|
||||
{
|
||||
unsigned m = b - 1;
|
||||
return (v + m) & ~m;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
static void
|
||||
exchange_uint32(uint8 *p_data)
|
||||
{
|
||||
|
@ -182,7 +174,6 @@ exchange_uint32(uint8 *p_data)
|
|||
*(p_data + 1) = *(p_data + 2);
|
||||
*(p_data + 2) = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
static wasm_function_inst_t
|
||||
app_manager_lookup_function(const wasm_module_inst_t module_inst,
|
||||
|
@ -445,7 +436,7 @@ wasm_app_routine(void *arg)
|
|||
0, NULL)) {
|
||||
const char *exception = wasm_runtime_get_exception(inst);
|
||||
bh_assert(exception);
|
||||
printf("Got exception running wasi start function: %s\n",
|
||||
app_manager_printf("Got exception running wasi start function: %s\n",
|
||||
exception);
|
||||
wasm_runtime_clear_exception(inst);
|
||||
goto fail1;
|
||||
|
@ -467,7 +458,7 @@ wasm_app_routine(void *arg)
|
|||
0, NULL)) {
|
||||
const char *exception = wasm_runtime_get_exception(inst);
|
||||
bh_assert(exception);
|
||||
printf("Got exception running WASM code: %s\n",
|
||||
app_manager_printf("Got exception running WASM code: %s\n",
|
||||
exception);
|
||||
wasm_runtime_clear_exception(inst);
|
||||
/* call on_destroy() in case some resources are opened in on_init()
|
||||
|
@ -513,18 +504,20 @@ cleanup_app_resource(module_data *m_data)
|
|||
|
||||
/* Destroy remain sections (i.e. data segment section for bytecode file
|
||||
* or text section of aot file) from app file's section list. */
|
||||
if (is_bytecode)
|
||||
if (is_bytecode) {
|
||||
#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
|
||||
destroy_all_wasm_sections((wasm_section_list_t)(wasm_app_data->sections));
|
||||
#else
|
||||
bh_assert(0);
|
||||
#endif
|
||||
else
|
||||
}
|
||||
else {
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
destroy_all_aot_sections((aot_section_list_t)(wasm_app_data->sections));
|
||||
#else
|
||||
bh_assert(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (wasm_app_data->wasm_module)
|
||||
wasm_runtime_unload(wasm_app_data->wasm_module);
|
||||
|
@ -546,7 +539,21 @@ cleanup_app_resource(module_data *m_data)
|
|||
static bool
|
||||
wasm_app_module_init(void)
|
||||
{
|
||||
/* wasm runtime is already initialized by main func */
|
||||
uint32 version;
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
|
||||
version = WASM_CURRENT_VERSION;
|
||||
if (!is_little_endian())
|
||||
exchange_uint32((uint8 *)&version);
|
||||
bh_memcpy_s(wasm_bytecode_version, 4, &version, 4);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
version = AOT_CURRENT_VERSION;
|
||||
if (!is_little_endian())
|
||||
exchange_uint32((uint8 *)&version);
|
||||
bh_memcpy_s(wasm_aot_version, 4, &version, 4);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -556,14 +563,14 @@ wasm_app_module_init(void)
|
|||
static bool
|
||||
wasm_app_module_install(request_t * msg)
|
||||
{
|
||||
unsigned int m_data_size, heap_size;
|
||||
unsigned int m_data_size, heap_size, stack_size;
|
||||
unsigned int timeout, timers, err_size;
|
||||
char *properties;
|
||||
int properties_offset;
|
||||
wasm_app_file_t *wasm_app_file;
|
||||
wasm_data *wasm_app_data;
|
||||
package_type_t package_type;
|
||||
module_data *m_data;
|
||||
module_data *m_data = NULL;
|
||||
wasm_module_t module = NULL;
|
||||
wasm_module_inst_t inst = NULL;
|
||||
wasm_exec_env_t exec_env = NULL;
|
||||
|
@ -584,23 +591,30 @@ wasm_app_module_install(request_t * msg)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Judge the app type is AOTed or not */
|
||||
package_type = get_package_type((uint8 *)msg->payload, msg->payload_len);
|
||||
wasm_app_file = (wasm_app_file_t *)msg->payload;
|
||||
|
||||
/* Check app name */
|
||||
properties_offset = check_url_start(msg->url, strlen(msg->url), "/applet");
|
||||
bh_assert(properties_offset > 0);
|
||||
if (properties_offset <= 0)
|
||||
return false;
|
||||
if (properties_offset <= 0) {
|
||||
SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: invalid app name.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
properties = msg->url + properties_offset;
|
||||
find_key_value(properties, strlen(properties), "name", m_name,
|
||||
sizeof(m_name) - 1, '&');
|
||||
|
||||
if (strlen(m_name) == 0) {
|
||||
SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: invalid app name.");
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (app_manager_lookup_module_data(m_name)) {
|
||||
SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: app already installed.");
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Parse heap size */
|
||||
|
@ -615,9 +629,6 @@ wasm_app_module_install(request_t * msg)
|
|||
heap_size = APP_HEAP_SIZE_MAX;
|
||||
}
|
||||
|
||||
/* Judge the app type is AOTed or not */
|
||||
package_type = get_package_type((uint8 *) msg->payload, msg->payload_len);
|
||||
|
||||
/* Load WASM file and instantiate*/
|
||||
switch (package_type) {
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
|
@ -634,8 +645,6 @@ wasm_app_module_install(request_t * msg)
|
|||
AOT_SECTION_TYPE_SIGANATURE
|
||||
};
|
||||
|
||||
wasm_app_file = (wasm_app_file_t *) msg->payload;
|
||||
bh_assert(wasm_app_file);
|
||||
aot_file = &wasm_app_file->u.aot;
|
||||
|
||||
/* Load AOT module from sections */
|
||||
|
@ -644,9 +653,7 @@ wasm_app_module_install(request_t * msg)
|
|||
if (!module) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: load WASM file failed.");
|
||||
printf("error: %s\n", err);
|
||||
destroy_all_aot_sections(aot_file->sections);
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
/* Destroy useless sections from list after load */
|
||||
destroy_part_aot_sections(&aot_file->sections,
|
||||
|
@ -658,9 +665,7 @@ wasm_app_module_install(request_t * msg)
|
|||
wasi_dir_buf, sizeof(wasi_dir_buf))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: prepare wasi env failed.");
|
||||
wasm_runtime_unload(module);
|
||||
destroy_all_aot_sections(aot_file->sections);
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
wasm_runtime_set_wasi_args(module,
|
||||
wasi_dir_list, 1,
|
||||
|
@ -674,10 +679,7 @@ wasm_app_module_install(request_t * msg)
|
|||
if (!inst) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: instantiate wasm runtime failed.");
|
||||
printf("error: %s\n", err);
|
||||
wasm_runtime_unload(module);
|
||||
destroy_all_aot_sections(aot_file->sections);
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -698,13 +700,15 @@ wasm_app_module_install(request_t * msg)
|
|||
SECTION_TYPE_GLOBAL,
|
||||
SECTION_TYPE_EXPORT,
|
||||
SECTION_TYPE_START,
|
||||
SECTION_TYPE_ELEM
|
||||
SECTION_TYPE_ELEM,
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
SECTION_TYPE_DATACOUNT
|
||||
#endif
|
||||
|
||||
};
|
||||
/* Sections to be released after instantiating */
|
||||
uint8 sections2[] = { SECTION_TYPE_DATA };
|
||||
|
||||
wasm_app_file = (wasm_app_file_t *) msg->payload;
|
||||
bh_assert(wasm_app_file);
|
||||
bytecode_file = &wasm_app_file->u.bytecode;
|
||||
|
||||
/* Load wasm module from sections */
|
||||
|
@ -713,9 +717,7 @@ wasm_app_module_install(request_t * msg)
|
|||
if (!module) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: load WASM file failed.");
|
||||
printf("error: %s\n", err);
|
||||
destroy_all_wasm_sections(bytecode_file->sections);
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Destroy useless sections from list after load */
|
||||
|
@ -728,9 +730,7 @@ wasm_app_module_install(request_t * msg)
|
|||
wasi_dir_buf, sizeof(wasi_dir_buf))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: prepare wasi env failed.");
|
||||
wasm_runtime_unload(module);
|
||||
destroy_all_wasm_sections(bytecode_file->sections);
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
wasm_runtime_set_wasi_args(module,
|
||||
wasi_dir_list, 1,
|
||||
|
@ -744,10 +744,7 @@ wasm_app_module_install(request_t * msg)
|
|||
if (!inst) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: instantiate wasm runtime failed.");
|
||||
printf("error: %s\n", err);
|
||||
wasm_runtime_unload(module);
|
||||
destroy_all_wasm_sections(bytecode_file->sections);
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Destroy useless sections from list after instantiate */
|
||||
|
@ -760,7 +757,7 @@ wasm_app_module_install(request_t * msg)
|
|||
default:
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: invalid wasm package type.");
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Create module data including the wasm_app_data as its internal_data*/
|
||||
|
@ -842,12 +839,16 @@ wasm_app_module_install(request_t * msg)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
stack_size = APP_THREAD_STACK_SIZE_DEFAULT;
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
stack_size += 4 * BH_KB;
|
||||
#endif
|
||||
/* Create WASM app thread. */
|
||||
if (os_thread_create(&wasm_app_data->thread_id, wasm_app_routine,
|
||||
(void*) m_data, APP_THREAD_STACK_SIZE_DEFAULT) != 0) {
|
||||
(void*) m_data, stack_size) != 0) {
|
||||
module_data_list_remove(m_data);
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: create app threadf failed.");
|
||||
"Install WASM app failed: create app thread failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -862,8 +863,13 @@ wasm_app_module_install(request_t * msg)
|
|||
fail:
|
||||
if (m_data)
|
||||
release_module(m_data);
|
||||
wasm_runtime_deinstantiate(inst);
|
||||
wasm_runtime_unload(module);
|
||||
|
||||
if (inst)
|
||||
wasm_runtime_deinstantiate(inst);
|
||||
|
||||
if (module)
|
||||
wasm_runtime_unload(module);
|
||||
|
||||
if (exec_env)
|
||||
wasm_runtime_destroy_exec_env(exec_env);
|
||||
|
||||
|
@ -956,7 +962,7 @@ wasm_app_module_uninstall(request_t *msg)
|
|||
static bool
|
||||
wasm_app_module_handle_host_url(void *queue_msg)
|
||||
{
|
||||
//todo: implement in future
|
||||
/* TODO: implement in future */
|
||||
app_manager_printf("App handles host url address %d\n",
|
||||
(int)(uintptr_t)queue_msg);
|
||||
return false;
|
||||
|
@ -972,7 +978,7 @@ wasm_app_module_get_module_data(void *inst)
|
|||
static void
|
||||
wasm_app_module_watchdog_kill(module_data *m_data)
|
||||
{
|
||||
//todo: implement in future
|
||||
/* TODO: implement in future */
|
||||
app_manager_printf("Watchdog kills app: %s\n", m_data->module_name);
|
||||
return;
|
||||
}
|
||||
|
@ -984,7 +990,7 @@ wasm_register_msg_callback(int message_type,
|
|||
int i;
|
||||
int freeslot = -1;
|
||||
for (i = 0; i < Max_Msg_Callback; i++) {
|
||||
// replace handler for the same event registered
|
||||
/* replace handler for the same event registered */
|
||||
if (g_msg_type[i] == message_type)
|
||||
break;
|
||||
|
||||
|
@ -1042,6 +1048,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
int *received_size)
|
||||
{
|
||||
uint8 *p;
|
||||
int magic;
|
||||
package_type_t package_type = Package_Type_Unknown;
|
||||
|
||||
if (recv_ctx.phase == Phase_Req_Ver) {
|
||||
|
@ -1089,6 +1096,9 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
APP_MGR_MALLOC(recv_ctx.message.request_url_len + 1);
|
||||
if (NULL == recv_ctx.message.request_url) {
|
||||
app_manager_printf("Allocate memory failed!\n");
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: "
|
||||
"allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
memset(recv_ctx.message.request_url, 0,
|
||||
|
@ -1118,7 +1128,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
|
||||
if (recv_ctx.size_in_phase ==
|
||||
sizeof(recv_ctx.message.app_file_magic)) {
|
||||
int magic = recv_ctx.message.app_file_magic;
|
||||
magic = recv_ctx.message.app_file_magic;
|
||||
package_type = get_package_type((uint8 *)&magic, sizeof(magic) + 1);
|
||||
switch (package_type) {
|
||||
#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
|
||||
|
@ -1139,7 +1149,8 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
#endif
|
||||
default:
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: invalid file format.");
|
||||
"Install WASM app failed: "
|
||||
"invalid file format.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -1153,6 +1164,8 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
p[recv_ctx.size_in_phase++] = ch;
|
||||
else {
|
||||
app_manager_printf("Invalid WASM version!\n");
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: invalid WASM version.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1165,10 +1178,19 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
}
|
||||
else if (recv_ctx.phase == Phase_Wasm_Section_Type) {
|
||||
uint8 section_type = ch;
|
||||
if (section_type <= SECTION_TYPE_DATA) {
|
||||
#if WASM_ENABLE_BULK_MEMORY == 0
|
||||
uint8 section_type_max = SECTION_TYPE_DATA;
|
||||
#else
|
||||
uint8 section_type_max = SECTION_TYPE_DATACOUNT;
|
||||
#endif
|
||||
if (section_type <= section_type_max) {
|
||||
wasm_section_t *new_section;
|
||||
if (!(new_section = (wasm_section_t *) APP_MGR_MALLOC(sizeof(wasm_section_t)))) {
|
||||
if (!(new_section = (wasm_section_t *)
|
||||
APP_MGR_MALLOC(sizeof(wasm_section_t)))) {
|
||||
app_manager_printf("Allocate memory failed!\n");
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: "
|
||||
"allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
memset(new_section, 0, sizeof(wasm_section_t));
|
||||
|
@ -1191,7 +1213,13 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
return true;
|
||||
}
|
||||
else {
|
||||
char error_buf[128];
|
||||
|
||||
app_manager_printf("Invalid wasm section type: %d\n", section_type);
|
||||
snprintf(error_buf, sizeof(error_buf),
|
||||
"Install WASM app failed: invalid wasm section type %d",
|
||||
section_type);
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid, error_buf);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -1210,7 +1238,10 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
/* check leab128 overflow for uint32 value */
|
||||
if (recv_ctx.size_in_phase >
|
||||
(sizeof(section->section_body_size) * 8 + 7 - 1) / 7) {
|
||||
app_manager_printf(" LEB overflow when parsing section size\n");
|
||||
app_manager_printf("LEB overflow when parsing section size\n");
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: "
|
||||
"LEB overflow when parsing section size");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1218,6 +1249,8 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
/* leb128 encoded section size parsed done */
|
||||
if (!(section->section_body = APP_MGR_MALLOC(section->section_body_size))) {
|
||||
app_manager_printf("Allocate memory failed!\n");
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: allocate memory failed");
|
||||
goto fail;
|
||||
}
|
||||
recv_ctx.phase = Phase_Wasm_Section_Content;
|
||||
|
@ -1245,7 +1278,15 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
}
|
||||
else {
|
||||
app_manager_printf("Handle install message failed!\n");
|
||||
goto fail;
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: "
|
||||
"handle install message failed");
|
||||
/**
|
||||
* The sections were destroyed inside
|
||||
* module_wasm_app_handle_install_msg(),
|
||||
* no need to destroy again.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1265,7 +1306,9 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
if (ch == wasm_aot_version[recv_ctx.size_in_phase])
|
||||
p[recv_ctx.size_in_phase++] = ch;
|
||||
else {
|
||||
app_manager_printf("Invalid WASM AOT version!\n");
|
||||
app_manager_printf("Invalid AOT version!\n");
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: invalid AOT version");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1287,8 +1330,12 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
if (aot_file_cur_offset % 4)
|
||||
return true;
|
||||
|
||||
if (!(cur_section = (aot_section_t *) APP_MGR_MALLOC(sizeof(aot_section_t)))) {
|
||||
if (!(cur_section = (aot_section_t *)
|
||||
APP_MGR_MALLOC(sizeof(aot_section_t)))) {
|
||||
app_manager_printf("Allocate memory failed!\n");
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: "
|
||||
"allocate memory failed");
|
||||
goto fail;
|
||||
}
|
||||
memset(cur_section, 0, sizeof(aot_section_t));
|
||||
|
@ -1318,8 +1365,14 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
recv_ctx.size_in_phase = 0;
|
||||
}
|
||||
else {
|
||||
char error_buf[128];
|
||||
|
||||
app_manager_printf("Invalid AOT section id: %d\n",
|
||||
cur_section->section_type);
|
||||
snprintf(error_buf, sizeof(error_buf),
|
||||
"Install WASM app failed: invalid AOT section id %d",
|
||||
cur_section->section_type);
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid, error_buf);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -1357,6 +1410,9 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
os_mmap(NULL, (uint32)total_size,
|
||||
map_prot, map_flags))) {
|
||||
app_manager_printf("Allocate executable memory failed!\n");
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: "
|
||||
"allocate memory failed");
|
||||
goto fail;
|
||||
}
|
||||
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
|
||||
|
@ -1369,6 +1425,9 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
if (!(section->section_body =
|
||||
APP_MGR_MALLOC(section->section_body_size))) {
|
||||
app_manager_printf("Allocate memory failed!\n");
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: "
|
||||
"allocate memory failed");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -1408,7 +1467,15 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
}
|
||||
else {
|
||||
app_manager_printf("Handle install message failed!\n");
|
||||
goto fail;
|
||||
SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
|
||||
"Install WASM app failed: "
|
||||
"handle install message failed");
|
||||
/**
|
||||
* The sections were destroyed inside
|
||||
* module_wasm_app_handle_install_msg(),
|
||||
* no need to destroy again.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1423,6 +1490,9 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
|
|||
#endif /* end of WASM_ENABLE_AOT != 0 */
|
||||
|
||||
fail:
|
||||
/* Restore the package type */
|
||||
magic = recv_ctx.message.app_file_magic;
|
||||
package_type = get_package_type((uint8 *)&magic, sizeof(magic) + 1);
|
||||
switch (package_type) {
|
||||
#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
|
||||
case Wasm_Module_Bytecode:
|
||||
|
@ -1443,10 +1513,7 @@ fail:
|
|||
recv_ctx.message.request_url = NULL;
|
||||
}
|
||||
|
||||
recv_ctx.phase = Phase_Req_Ver;
|
||||
recv_ctx.size_in_phase = 0;
|
||||
recv_ctx.total_received_size = 0;
|
||||
|
||||
memset(&recv_ctx, 0, sizeof(recv_ctx));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ void targeted_app_request_handler(request_t *request, void *unused)
|
|||
}
|
||||
|
||||
strncpy(applet_name, request->url + offset, sizeof(applet_name) - 1);
|
||||
char *p = strrchr(applet_name, '/');
|
||||
char *p = strchr(applet_name, '/');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
} else
|
||||
|
@ -136,7 +136,8 @@ void * am_dispatch_request(request_t *request)
|
|||
}
|
||||
|
||||
bool am_register_resource(const char *url,
|
||||
void (*request_handler)(request_t *, void *), uint32 register_id)
|
||||
void (*request_handler)(request_t *, void *),
|
||||
uint32 register_id)
|
||||
{
|
||||
app_res_register_t * r = g_resources;
|
||||
int register_num = 0;
|
||||
|
@ -158,7 +159,7 @@ bool am_register_resource(const char *url,
|
|||
if (register_num >= RESOURCE_REGISTRATION_NUM_MAX)
|
||||
return false;
|
||||
|
||||
r = (app_res_register_t *) APP_MGR_MALLOC(sizeof(app_res_register_t));
|
||||
r = (app_res_register_t *)APP_MGR_MALLOC(sizeof(app_res_register_t));
|
||||
if (r == NULL)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -124,3 +124,9 @@ bool watchdog_startup()
|
|||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void watchdog_destroy()
|
||||
{
|
||||
bh_queue_exit_loop_run(watchdog_queue);
|
||||
bh_queue_destroy(watchdog_queue);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,9 @@ app_manager_get_watchdog_timer(void *timer);
|
|||
bool
|
||||
watchdog_startup();
|
||||
|
||||
void
|
||||
watchdog_destroy();
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -173,20 +173,11 @@ typedef struct host_interface {
|
|||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool
|
||||
app_manager_host_init(host_interface *interface);
|
||||
|
||||
/**
|
||||
* Send message to Host
|
||||
*
|
||||
* @param buf buffer to send
|
||||
* @param size size of buffer
|
||||
*
|
||||
* @return size of buffer sent
|
||||
*/
|
||||
app_manager_host_init(host_interface *intf);
|
||||
|
||||
/* Startup app manager */
|
||||
void
|
||||
app_manager_startup(host_interface *interface);
|
||||
app_manager_startup(host_interface *intf);
|
||||
|
||||
/* Get queue of current applet */
|
||||
void *
|
||||
|
@ -284,8 +275,16 @@ send_error_response_to_host(int mid, int code, const char *msg);
|
|||
bool
|
||||
bh_applet_check_permission(const char *perm);
|
||||
|
||||
/**
|
||||
* Send message to Host
|
||||
*
|
||||
* @param buf buffer to send
|
||||
* @param size size of buffer
|
||||
*
|
||||
* @return size of buffer sent
|
||||
*/
|
||||
int
|
||||
app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size);
|
||||
app_manager_host_send_msg(int msg_type, const char *buf, int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
|
|
159
core/config.h
159
core/config.h
|
@ -15,7 +15,11 @@
|
|||
&& !defined(BUILD_TARGET_THUMB) \
|
||||
&& !defined(BUILD_TARGET_THUMB_VFP) \
|
||||
&& !defined(BUILD_TARGET_MIPS) \
|
||||
&& !defined(BUILD_TARGET_XTENSA)
|
||||
&& !defined(BUILD_TARGET_XTENSA) \
|
||||
&& !defined(BUILD_TARGET_RISCV64_LP64D) \
|
||||
&& !defined(BUILD_TARGET_RISCV64_LP64) \
|
||||
&& !defined(BUILD_TARGET_RISCV32_ILP32D) \
|
||||
&& !defined(BUILD_TARGET_RISCV32_ILP32)
|
||||
#if defined(__x86_64__) || defined(__x86_64)
|
||||
#define BUILD_TARGET_X86_64
|
||||
#elif defined(__amd64__) || defined(__amd64)
|
||||
|
@ -34,6 +38,10 @@
|
|||
#define BUILD_TARGET_MIPS
|
||||
#elif defined(__XTENSA__)
|
||||
#define BUILD_TARGET_XTENSA
|
||||
#elif defined(__riscv) && (__riscv_xlen == 64)
|
||||
#define BUILD_TARGET_RISCV64_LP64D
|
||||
#elif defined(__riscv) && (__riscv_xlen == 32)
|
||||
#define BUILD_TARGET_RISCV32_ILP32D
|
||||
#else
|
||||
#error "Build target isn't set"
|
||||
#endif
|
||||
|
@ -43,12 +51,8 @@
|
|||
#define BH_DEBUG 0
|
||||
#endif
|
||||
|
||||
enum {
|
||||
/* Memory allocator ems */
|
||||
MEM_ALLOCATOR_EMS = 0,
|
||||
/* Memory allocator tlsf */
|
||||
MEM_ALLOCATOR_TLSF
|
||||
};
|
||||
#define MEM_ALLOCATOR_EMS 0
|
||||
#define MEM_ALLOCATOR_TLSF 1
|
||||
|
||||
/* Default memory allocator */
|
||||
#define DEFAULT_MEM_ALLOCATOR MEM_ALLOCATOR_EMS
|
||||
|
@ -62,7 +66,7 @@ enum {
|
|||
#endif
|
||||
|
||||
#define AOT_MAGIC_NUMBER 0x746f6100
|
||||
#define AOT_CURRENT_VERSION 1
|
||||
#define AOT_CURRENT_VERSION 3
|
||||
|
||||
#ifndef WASM_ENABLE_JIT
|
||||
#define WASM_ENABLE_JIT 0
|
||||
|
@ -86,6 +90,19 @@ enum {
|
|||
#define WASM_ENABLE_LIBC_WASI 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_UVWASI
|
||||
#define WASM_ENABLE_UVWASI 0
|
||||
#endif
|
||||
|
||||
/* Default disable libc emcc */
|
||||
#ifndef WASM_ENABLE_LIBC_EMCC
|
||||
#define WASM_ENABLE_LIBC_EMCC 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_LIB_PTHREAD
|
||||
#define WASM_ENABLE_LIB_PTHREAD 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_BASE_LIB
|
||||
#define WASM_ENABLE_BASE_LIB 0
|
||||
#endif
|
||||
|
@ -94,25 +111,51 @@ enum {
|
|||
#define WASM_ENABLE_APP_FRAMEWORK 0
|
||||
#endif
|
||||
|
||||
/* Bulk memory operation */
|
||||
#ifndef WASM_ENABLE_BULK_MEMORY
|
||||
#define WASM_ENABLE_BULK_MEMORY 0
|
||||
#endif
|
||||
|
||||
/* Shared memory */
|
||||
#ifndef WASM_ENABLE_SHARED_MEMORY
|
||||
#define WASM_ENABLE_SHARED_MEMORY 0
|
||||
#endif
|
||||
|
||||
/* Thread manager */
|
||||
#ifndef WASM_ENABLE_THREAD_MGR
|
||||
#define WASM_ENABLE_THREAD_MGR 0
|
||||
#endif
|
||||
|
||||
/* WASM log system */
|
||||
#ifndef WASM_ENABLE_LOG
|
||||
#define WASM_ENABLE_LOG 1
|
||||
#endif
|
||||
|
||||
#if defined(BUILD_TARGET_X86_32) || defined(BUILD_TARGET_X86_64)
|
||||
#define WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS 1
|
||||
#ifndef WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS
|
||||
#if defined(BUILD_TARGET_X86_32) || defined(BUILD_TARGET_X86_64) \
|
||||
|| defined(BUILD_TARGET_AARCH64)
|
||||
#define WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS 1
|
||||
#else
|
||||
#define WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS 0
|
||||
#define WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* WASM Interpreter labels-as-values feature */
|
||||
#ifndef WASM_ENABLE_LABELS_AS_VALUES
|
||||
#ifdef __GNUC__
|
||||
#define WASM_ENABLE_LABELS_AS_VALUES 1
|
||||
#else
|
||||
#define WASM_ENABLE_LABELS_AS_VALUES 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Enable fast interpreter or not */
|
||||
#ifndef WASM_ENABLE_FAST_INTERP
|
||||
#define WASM_ENABLE_FAST_INTERP 0
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
#define WASM_ENABLE_ABS_LABEL_ADDR 1
|
||||
#define WASM_DEBUG_PREPROCESSOR 0
|
||||
#else
|
||||
#define WASM_ENABLE_ABS_LABEL_ADDR 0
|
||||
#endif
|
||||
|
||||
/* Enable opcode counter or not */
|
||||
|
@ -120,11 +163,51 @@ enum {
|
|||
#define WASM_ENABLE_OPCODE_COUNTER 0
|
||||
#endif
|
||||
|
||||
/* Heap and stack profiling */
|
||||
#define BH_ENABLE_MEMORY_PROFILING 0
|
||||
/* Support a module with dependency, other modules */
|
||||
#ifndef WASM_ENABLE_MULTI_MODULE
|
||||
#define WASM_ENABLE_MULTI_MODULE 0
|
||||
#endif
|
||||
|
||||
/* Enable wasm mini loader or not */
|
||||
#ifndef WASM_ENABLE_MINI_LOADER
|
||||
#define WASM_ENABLE_MINI_LOADER 0
|
||||
#endif
|
||||
|
||||
/* Disable boundary check with hardware trap or not,
|
||||
* enable it by default if it is supported */
|
||||
#ifndef WASM_DISABLE_HW_BOUND_CHECK
|
||||
#define WASM_DISABLE_HW_BOUND_CHECK 0
|
||||
#endif
|
||||
|
||||
/* Disable SIMD unless it is manualy enabled somewhere */
|
||||
#ifndef WASM_ENABLE_SIMD
|
||||
#define WASM_ENABLE_SIMD 0
|
||||
#endif
|
||||
|
||||
/* Memory profiling */
|
||||
#ifndef WASM_ENABLE_MEMORY_PROFILING
|
||||
#define WASM_ENABLE_MEMORY_PROFILING 0
|
||||
#endif
|
||||
|
||||
/* Memory tracing */
|
||||
#ifndef WASM_ENABLE_MEMORY_TRACING
|
||||
#define WASM_ENABLE_MEMORY_TRACING 0
|
||||
#endif
|
||||
|
||||
/* Performance profiling */
|
||||
#ifndef WASM_ENABLE_PERF_PROFILING
|
||||
#define WASM_ENABLE_PERF_PROFILING 0
|
||||
#endif
|
||||
|
||||
/* Dump call stack */
|
||||
#ifndef WASM_ENABLE_DUMP_CALL_STACK
|
||||
#define WASM_ENABLE_DUMP_CALL_STACK 0
|
||||
#endif
|
||||
|
||||
/* Heap verification */
|
||||
#ifndef BH_ENABLE_GC_VERIFY
|
||||
#define BH_ENABLE_GC_VERIFY 0
|
||||
#endif
|
||||
|
||||
/* Max app number of all modules */
|
||||
#define MAX_APP_INSTALLATIONS 3
|
||||
|
@ -153,12 +236,9 @@ enum {
|
|||
/* The max percentage of global heap that app memory space can grow */
|
||||
#define APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT 1 / 3
|
||||
|
||||
/* Default base offset of app heap space */
|
||||
#define DEFAULT_APP_HEAP_BASE_OFFSET (1 * BH_GB)
|
||||
|
||||
/* Default min/max heap size of each app */
|
||||
#define APP_HEAP_SIZE_DEFAULT (8 * 1024)
|
||||
#define APP_HEAP_SIZE_MIN (2 * 1024)
|
||||
#define APP_HEAP_SIZE_MIN (256)
|
||||
#define APP_HEAP_SIZE_MAX (512 * 1024 * 1024)
|
||||
|
||||
/* Default wasm stack size of each app */
|
||||
|
@ -167,25 +247,54 @@ enum {
|
|||
#else
|
||||
#define DEFAULT_WASM_STACK_SIZE (12 * 1024)
|
||||
#endif
|
||||
/* Min auxilliary stack size of each wasm thread */
|
||||
#define WASM_THREAD_AUX_STACK_SIZE_MIN (256)
|
||||
|
||||
/* Default/min/max stack size of each app thread */
|
||||
#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS)
|
||||
#define APP_THREAD_STACK_SIZE_DEFAULT (20 * 1024)
|
||||
#define APP_THREAD_STACK_SIZE_MIN (16 * 1024)
|
||||
#define APP_THREAD_STACK_SIZE_MAX (256 * 1024)
|
||||
#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \
|
||||
&& !defined(BH_PLATFORM_ESP_IDF) && !defined(BH_PLATFORM_OPENRTOS)
|
||||
#define APP_THREAD_STACK_SIZE_DEFAULT (32 * 1024)
|
||||
#define APP_THREAD_STACK_SIZE_MIN (24 * 1024)
|
||||
#else
|
||||
#define APP_THREAD_STACK_SIZE_DEFAULT (6 * 1024)
|
||||
#define APP_THREAD_STACK_SIZE_MIN (4 * 1024)
|
||||
#define APP_THREAD_STACK_SIZE_MAX (256 * 1024)
|
||||
#endif
|
||||
#if !defined(APP_THREAD_STACK_SIZE_MAX)
|
||||
#define APP_THREAD_STACK_SIZE_MAX (8 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
/* Reserved bytes to the native thread stack boundary, throw native
|
||||
stack overflow exception if the guard boudary is reached */
|
||||
#define RESERVED_BYTES_TO_NATIVE_STACK_BOUNDARY (512)
|
||||
|
||||
/* Guard page count for stack overflow check with hardware trap */
|
||||
#define STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT 3
|
||||
|
||||
/* Default wasm block address cache size and conflict list size */
|
||||
#ifndef BLOCK_ADDR_CACHE_SIZE
|
||||
#define BLOCK_ADDR_CACHE_SIZE 64
|
||||
#endif
|
||||
#define BLOCK_ADDR_CONFLICT_SIZE 2
|
||||
|
||||
#ifndef WASM_ENABLE_SPEC_TEST
|
||||
#define WASM_ENABLE_SPEC_TEST 0
|
||||
#endif
|
||||
|
||||
/* Default max thread num per cluster. Can be overwrite by
|
||||
wasm_runtime_set_max_thread_num */
|
||||
#define CLUSTER_MAX_THREAD_NUM 4
|
||||
|
||||
#ifndef WASM_ENABLE_TAIL_CALL
|
||||
#define WASM_ENABLE_TAIL_CALL 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_CUSTOM_NAME_SECTION
|
||||
#define WASM_ENABLE_CUSTOM_NAME_SECTION 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_ENABLE_REF_TYPES
|
||||
#define WASM_ENABLE_REF_TYPES 0
|
||||
#endif
|
||||
|
||||
#endif /* end of _CONFIG_H_ */
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ if [ ! -d "lvgl" ]; then
|
|||
fi
|
||||
if [ ! -d "lv_drivers" ]; then
|
||||
echo "git pull lv_drivers..."
|
||||
git clone https://github.com/littlevgl/lv_drivers.git
|
||||
git clone https://github.com/littlevgl/lv_drivers.git --branch v6.0.1
|
||||
[ $? -eq 0 ] || exit $?
|
||||
fi
|
||||
|
||||
|
|
31
core/iwasm/aot/SConscript
Normal file
31
core/iwasm/aot/SConscript
Normal file
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# Copyright (c) 2021, RT-Thread Development Team
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
from building import *
|
||||
import re
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
|
||||
src = Split('''
|
||||
aot_loader.c
|
||||
aot_runtime.c
|
||||
''')
|
||||
|
||||
if rtconfig.ARCH == 'arm':
|
||||
if re.match('^cortex-m.*', rtconfig.CPU):
|
||||
src += ['arch/aot_reloc_thumb.c']
|
||||
elif re.match('^cortex-a.*', rtconfig.CPU):
|
||||
src += ['arch/aot_reloc_arm.c']
|
||||
|
||||
|
||||
CPPPATH = [cwd, cwd + '/../include']
|
||||
|
||||
CPPDEFINES = ['WASM_ENABLE_AOT=1']
|
||||
|
||||
group = DefineGroup('iwasm_aot', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
|
||||
|
||||
Return('group')
|
File diff suppressed because it is too large
Load Diff
|
@ -12,12 +12,50 @@ typedef struct {
|
|||
|
||||
#define REG_SYM(symbol) { #symbol, (void*)symbol }
|
||||
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
#define REG_BULK_MEMORY_SYM() \
|
||||
REG_SYM(aot_memory_init), \
|
||||
REG_SYM(aot_data_drop),
|
||||
#else
|
||||
#define REG_BULK_MEMORY_SYM()
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
#include "wasm_shared_memory.h"
|
||||
#define REG_ATOMIC_WAIT_SYM() \
|
||||
REG_SYM(wasm_runtime_atomic_wait), \
|
||||
REG_SYM(wasm_runtime_atomic_notify),
|
||||
#else
|
||||
#define REG_ATOMIC_WAIT_SYM()
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
#define REG_REF_TYPES_SYM() \
|
||||
REG_SYM(aot_drop_table_seg), \
|
||||
REG_SYM(aot_table_init), \
|
||||
REG_SYM(aot_table_copy), \
|
||||
REG_SYM(aot_table_fill), \
|
||||
REG_SYM(aot_table_grow),
|
||||
#else
|
||||
#define REG_REF_TYPES_SYM()
|
||||
#endif
|
||||
|
||||
#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
|
||||
#define REG_AOT_TRACE_SYM() \
|
||||
REG_SYM(aot_alloc_frame), \
|
||||
REG_SYM(aot_free_frame),
|
||||
#else
|
||||
#define REG_AOT_TRACE_SYM()
|
||||
#endif
|
||||
|
||||
#define REG_COMMON_SYMBOLS \
|
||||
REG_SYM(aot_set_exception_with_id), \
|
||||
REG_SYM(aot_invoke_native), \
|
||||
REG_SYM(aot_call_indirect), \
|
||||
REG_SYM(wasm_runtime_enlarge_memory), \
|
||||
REG_SYM(wasm_runtime_set_exception), \
|
||||
REG_SYM(aot_enlarge_memory), \
|
||||
REG_SYM(aot_set_exception), \
|
||||
{"memset", (void*)aot_memset}, \
|
||||
{"memmove", (void*)aot_memmove}, \
|
||||
REG_SYM(fmin), \
|
||||
REG_SYM(fminf), \
|
||||
REG_SYM(fmax), \
|
||||
|
@ -29,7 +67,11 @@ typedef struct {
|
|||
REG_SYM(trunc), \
|
||||
REG_SYM(truncf), \
|
||||
REG_SYM(rint), \
|
||||
REG_SYM(rintf)
|
||||
REG_SYM(rintf), \
|
||||
REG_BULK_MEMORY_SYM() \
|
||||
REG_ATOMIC_WAIT_SYM() \
|
||||
REG_REF_TYPES_SYM() \
|
||||
REG_AOT_TRACE_SYM()
|
||||
|
||||
#define CHECK_RELOC_OFFSET(data_size) do { \
|
||||
if (!check_reloc_offset(target_section_size, reloc_offset, data_size, \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,6 +30,11 @@ typedef enum AOTExceptionID {
|
|||
EXCE_UNDEFINED_ELEMENT,
|
||||
EXCE_UNINITIALIZED_ELEMENT,
|
||||
EXCE_CALL_UNLINKED_IMPORT_FUNC,
|
||||
EXCE_NATIVE_STACK_OVERFLOW,
|
||||
EXCE_UNALIGNED_ATOMIC,
|
||||
EXCE_AUX_STACK_OVERFLOW,
|
||||
EXCE_AUX_STACK_UNDERFLOW,
|
||||
EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
|
||||
EXCE_NUM,
|
||||
} AOTExceptionID;
|
||||
|
||||
|
@ -68,18 +73,67 @@ typedef struct AOTRelocationGroup {
|
|||
AOTRelocation *relocations;
|
||||
} AOTRelocationGroup;
|
||||
|
||||
/* AOT function instance */
|
||||
typedef struct AOTFunctionInstance {
|
||||
char *func_name;
|
||||
uint32 func_index;
|
||||
bool is_import_func;
|
||||
union {
|
||||
struct {
|
||||
AOTFuncType *func_type;
|
||||
/* function pointer linked */
|
||||
void *func_ptr;
|
||||
} func;
|
||||
AOTImportFunc *func_import;
|
||||
} u;
|
||||
} AOTFunctionInstance;
|
||||
|
||||
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
|
||||
typedef struct AOTUnwindInfo {
|
||||
uint8 Version : 3;
|
||||
uint8 Flags : 5;
|
||||
uint8 SizeOfProlog;
|
||||
uint8 CountOfCodes;
|
||||
uint8 FrameRegister : 4;
|
||||
uint8 FrameOffset : 4;
|
||||
struct {
|
||||
struct {
|
||||
uint8 CodeOffset;
|
||||
uint8 UnwindOp : 4;
|
||||
uint8 OpInfo : 4;
|
||||
};
|
||||
uint16 FrameOffset;
|
||||
} UnwindCode[1];
|
||||
} AOTUnwindInfo;
|
||||
|
||||
/* size of mov instruction and jmp instruction */
|
||||
#define PLT_ITEM_SIZE 12
|
||||
#endif
|
||||
|
||||
typedef struct AOTModule {
|
||||
uint32 module_type;
|
||||
|
||||
/* import memories */
|
||||
uint32 import_memory_count;
|
||||
AOTImportMemory *import_memories;
|
||||
|
||||
/* memory info */
|
||||
uint32 num_bytes_per_page;
|
||||
uint32 mem_init_page_count;
|
||||
uint32 mem_max_page_count;
|
||||
uint32 memory_count;
|
||||
AOTMemory *memories;
|
||||
|
||||
/* init data */
|
||||
uint32 mem_init_data_count;
|
||||
AOTMemInitData **mem_init_data_list;
|
||||
|
||||
/* table info */
|
||||
uint32 table_size;
|
||||
/* import tables */
|
||||
uint32 import_table_count;
|
||||
AOTImportTable *import_tables;
|
||||
|
||||
/* tables */
|
||||
uint32 table_count;
|
||||
AOTTable *tables;
|
||||
|
||||
/* table init data info */
|
||||
uint32 table_init_data_count;
|
||||
AOTTableInitData **table_init_data_list;
|
||||
|
||||
|
@ -109,15 +163,19 @@ typedef struct AOTModule {
|
|||
/* function type indexes */
|
||||
uint32 *func_type_indexes;
|
||||
|
||||
/* export function info */
|
||||
uint32 export_func_count;
|
||||
AOTExportFunc *export_funcs;
|
||||
/* export info */
|
||||
uint32 export_count;
|
||||
AOTExport *exports;
|
||||
|
||||
/* start function index, -1 denotes no start function */
|
||||
uint32 start_func_index;
|
||||
/* start function, point to AOTed/JITed function */
|
||||
void *start_function;
|
||||
|
||||
uint32 malloc_func_index;
|
||||
uint32 free_func_index;
|
||||
uint32 retain_func_index;
|
||||
|
||||
/* AOTed code, NULL for JIT mode */
|
||||
void *code;
|
||||
uint32 code_size;
|
||||
|
@ -126,6 +184,25 @@ typedef struct AOTModule {
|
|||
uint8 *literal;
|
||||
uint32 literal_size;
|
||||
|
||||
#if (defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)) \
|
||||
&& defined(BH_PLATFORM_WINDOWS)
|
||||
/* extra plt data area for __xmm and __real constants
|
||||
in Windows platform, NULL for JIT mode */
|
||||
uint8 *extra_plt_data;
|
||||
uint32 extra_plt_data_size;
|
||||
uint32 xmm_plt_count;
|
||||
uint32 real_plt_count;
|
||||
uint32 float_plt_count;
|
||||
#endif
|
||||
|
||||
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
|
||||
/* dynamic function table to be added by RtlAddFunctionTable(),
|
||||
used to unwind the call stack and register exception handler
|
||||
for AOT functions */
|
||||
RUNTIME_FUNCTION *rtl_func_table;
|
||||
bool rtl_func_table_registered;
|
||||
#endif
|
||||
|
||||
/* data sections in AOT object file, including .data, .rodata
|
||||
* and .rodata.cstN. NULL for JIT mode. */
|
||||
AOTObjectDataSection *data_sections;
|
||||
|
@ -134,10 +211,25 @@ typedef struct AOTModule {
|
|||
/* constant string set */
|
||||
HashMap *const_str_set;
|
||||
|
||||
uint32 llvm_aux_data_end;
|
||||
uint32 llvm_aux_stack_bottom;
|
||||
uint32 llvm_aux_stack_size;
|
||||
uint32 llvm_aux_stack_global_index;
|
||||
/* the index of auxiliary __data_end global,
|
||||
-1 means unexported */
|
||||
uint32 aux_data_end_global_index;
|
||||
/* auxiliary __data_end exported by wasm app */
|
||||
uint32 aux_data_end;
|
||||
|
||||
/* the index of auxiliary __heap_base global,
|
||||
-1 means unexported */
|
||||
uint32 aux_heap_base_global_index;
|
||||
/* auxiliary __heap_base exported by wasm app */
|
||||
uint32 aux_heap_base;
|
||||
|
||||
/* the index of auxiliary stack top global,
|
||||
-1 means unexported */
|
||||
uint32 aux_stack_top_global_index;
|
||||
/* auxiliary stack bottom resolved */
|
||||
uint32 aux_stack_bottom;
|
||||
/* auxiliary stack size resolved */
|
||||
uint32 aux_stack_size;
|
||||
|
||||
/* is jit mode or not */
|
||||
bool is_jit_mode;
|
||||
|
@ -159,34 +251,89 @@ typedef union {
|
|||
void *ptr;
|
||||
} AOTPointer;
|
||||
|
||||
typedef struct AOTModuleInstance {
|
||||
typedef union {
|
||||
uint64 u64;
|
||||
uint32 u32[2];
|
||||
} MemBound;
|
||||
|
||||
typedef struct AOTMemoryInstance {
|
||||
uint32 module_type;
|
||||
/* shared memory flag */
|
||||
bool is_shared;
|
||||
|
||||
/* memory space info */
|
||||
uint32 mem_cur_page_count;
|
||||
uint32 mem_max_page_count;
|
||||
uint32 num_bytes_per_page;
|
||||
uint32 cur_page_count;
|
||||
uint32 max_page_count;
|
||||
uint32 memory_data_size;
|
||||
AOTPointer memory_data;
|
||||
AOTPointer memory_data_end;
|
||||
|
||||
/* heap space info */
|
||||
int32 heap_base_offset;
|
||||
uint32 heap_data_size;
|
||||
AOTPointer heap_data;
|
||||
AOTPointer heap_data_end;
|
||||
AOTPointer heap_handle;
|
||||
|
||||
/* boundary check constants for aot code */
|
||||
MemBound mem_bound_check_1byte;
|
||||
MemBound mem_bound_check_2bytes;
|
||||
MemBound mem_bound_check_4bytes;
|
||||
MemBound mem_bound_check_8bytes;
|
||||
MemBound mem_bound_check_16bytes;
|
||||
} AOTMemoryInstance;
|
||||
|
||||
typedef struct AOTTableInstance {
|
||||
uint32 cur_size;
|
||||
/*
|
||||
* only grow in the range of [:max_size)
|
||||
* if the table is growable, max_size equals to its declared maximum size
|
||||
* otherwise, max_size equals to its declared minimum size
|
||||
*/
|
||||
uint32 max_size;
|
||||
/*
|
||||
* +------------------------------+ <--- data
|
||||
* | ref.func[] or ref.extern[]
|
||||
* +------------------------------+
|
||||
*/
|
||||
uint32 data[1];
|
||||
} AOTTableInstance;
|
||||
|
||||
typedef struct AOTModuleInstance {
|
||||
uint32 module_type;
|
||||
|
||||
/* memories */
|
||||
uint32 memory_count;
|
||||
AOTPointer memories;
|
||||
|
||||
/* global and table info */
|
||||
uint32 global_data_size;
|
||||
uint32 table_size;
|
||||
/*
|
||||
* the count of AOTTableInstance.
|
||||
* it includes imported tables and local tables.
|
||||
*
|
||||
* TODO: for now we treate imported table like a local table
|
||||
*/
|
||||
uint32 table_count;
|
||||
/* points to global_data */
|
||||
AOTPointer global_data;
|
||||
AOTPointer table_data;
|
||||
/* points to AOTTableInstance[] */
|
||||
AOTPointer tables;
|
||||
|
||||
/* funciton pointer array */
|
||||
AOTPointer func_ptrs;
|
||||
/* function type indexes */
|
||||
AOTPointer func_type_indexes;
|
||||
|
||||
/* export info */
|
||||
uint32 export_func_count;
|
||||
uint32 export_global_count;
|
||||
uint32 export_mem_count;
|
||||
uint32 export_tab_count;
|
||||
AOTPointer export_funcs;
|
||||
AOTPointer export_globals;
|
||||
AOTPointer export_memories;
|
||||
AOTPointer export_tables;
|
||||
|
||||
/* The exception buffer for current thread. */
|
||||
char cur_exception[128];
|
||||
/* The custom data that can be set/get by
|
||||
|
@ -196,32 +343,35 @@ typedef struct AOTModuleInstance {
|
|||
AOTPointer aot_module;
|
||||
/* WASI context */
|
||||
AOTPointer wasi_ctx;
|
||||
/* function performance profiling info list */
|
||||
AOTPointer func_perf_profilings;
|
||||
|
||||
/* total memory size: heap and linear memory */
|
||||
uint32 total_mem_size;
|
||||
|
||||
/* boundary check constants for aot code */
|
||||
uint32 mem_bound_check_1byte;
|
||||
uint32 mem_bound_check_2bytes;
|
||||
uint32 mem_bound_check_4bytes;
|
||||
uint32 mem_bound_check_8bytes;
|
||||
AOTPointer exec_env_singleton;
|
||||
|
||||
/* others */
|
||||
int32 temp_ret;
|
||||
uint32 temp_ret;
|
||||
uint32 llvm_stack;
|
||||
uint32 default_wasm_stack_size;
|
||||
|
||||
/* reserved */
|
||||
uint32 reserved[12];
|
||||
uint32 reserved[9];
|
||||
|
||||
/*
|
||||
* +------------------------------+ <-- memories.ptr
|
||||
* | #0 AOTMemoryInstance
|
||||
* +------------------------------+ <-- global_data.ptr
|
||||
* | global data
|
||||
* +------------------------------+ <-- tables.ptr
|
||||
* | AOTTableInstance[table_count]
|
||||
* +------------------------------+
|
||||
*/
|
||||
union {
|
||||
uint64 _make_it_8_byte_aligned_;
|
||||
AOTMemoryInstance memory_instances[1];
|
||||
uint8 bytes[1];
|
||||
} global_table_data;
|
||||
} AOTModuleInstance;
|
||||
|
||||
typedef AOTExportFunc AOTFunctionInstance;
|
||||
|
||||
/* Target info, read from ELF header of object file */
|
||||
typedef struct AOTTargetInfo {
|
||||
/* Binary type, elf32l/elf32b/elf64l/elf64b */
|
||||
|
@ -242,6 +392,24 @@ typedef struct AOTTargetInfo {
|
|||
char arch[16];
|
||||
} AOTTargetInfo;
|
||||
|
||||
typedef struct AOTFuncPerfProfInfo
|
||||
{
|
||||
/* total execution time */
|
||||
uint64 total_exec_time;
|
||||
/* total execution count */
|
||||
uint32 total_exec_cnt;
|
||||
} AOTFuncPerfProfInfo;
|
||||
|
||||
/* AOT auxiliary call stack */
|
||||
typedef struct AOTFrame {
|
||||
struct AOTFrame *prev_frame;
|
||||
uint32 func_index;
|
||||
#if WASM_ENABLE_PERF_PROFILING != 0
|
||||
uint64 time_started;
|
||||
AOTFuncPerfProfInfo *func_perf_prof_info;
|
||||
#endif
|
||||
} AOTFrame;
|
||||
|
||||
/**
|
||||
* Load a AOT module from aot file buffer
|
||||
* @param buf the byte buffer which contains the AOT file data
|
||||
|
@ -295,6 +463,7 @@ aot_unload(AOTModule *module);
|
|||
* Instantiate a AOT module.
|
||||
*
|
||||
* @param module the AOT module to instantiate
|
||||
* @param is_sub_inst the flag of sub instance
|
||||
* @param heap_size the default heap size of the module instance, a heap will
|
||||
* be created besides the app memory space. Both wasm app and native
|
||||
* function can allocate memory from the heap. If heap_size is 0, the
|
||||
|
@ -305,7 +474,7 @@ aot_unload(AOTModule *module);
|
|||
* @return return the instantiated AOT module instance, NULL if failed
|
||||
*/
|
||||
AOTModuleInstance*
|
||||
aot_instantiate(AOTModule *module,
|
||||
aot_instantiate(AOTModule *module, bool is_sub_inst,
|
||||
uint32 stack_size, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
|
@ -313,9 +482,10 @@ aot_instantiate(AOTModule *module,
|
|||
* Deinstantiate a AOT module instance, destroy the resources.
|
||||
*
|
||||
* @param module_inst the AOT module instance to destroy
|
||||
* @param is_sub_inst the flag of sub instance
|
||||
*/
|
||||
void
|
||||
aot_deinstantiate(AOTModuleInstance *module_inst);
|
||||
aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst);
|
||||
|
||||
/**
|
||||
* Lookup an exported function in the AOT module instance.
|
||||
|
@ -354,6 +524,10 @@ bool
|
|||
aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
|
||||
AOTFunctionInstance *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
|
||||
bool
|
||||
aot_create_exec_env_singleton(AOTModuleInstance *module_inst);
|
||||
|
||||
/**
|
||||
* Set AOT module instance exception with exception string
|
||||
*
|
||||
|
@ -387,20 +561,24 @@ aot_get_exception(AOTModuleInstance *module_inst);
|
|||
void
|
||||
aot_clear_exception(AOTModuleInstance *module_inst);
|
||||
|
||||
int32
|
||||
uint32
|
||||
aot_module_malloc(AOTModuleInstance *module_inst, uint32 size,
|
||||
void **p_native_addr);
|
||||
|
||||
void
|
||||
aot_module_free(AOTModuleInstance *module_inst, int32 ptr);
|
||||
uint32
|
||||
aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr,
|
||||
uint32 size, void **p_native_addr);
|
||||
|
||||
int32
|
||||
void
|
||||
aot_module_free(AOTModuleInstance *module_inst, uint32 ptr);
|
||||
|
||||
uint32
|
||||
aot_module_dup_data(AOTModuleInstance *module_inst,
|
||||
const char *src, uint32 size);
|
||||
|
||||
bool
|
||||
aot_validate_app_addr(AOTModuleInstance *module_inst,
|
||||
int32 app_offset, uint32 size);
|
||||
uint32 app_offset, uint32 size);
|
||||
|
||||
|
||||
bool
|
||||
|
@ -408,16 +586,16 @@ aot_validate_native_addr(AOTModuleInstance *module_inst,
|
|||
void *native_ptr, uint32 size);
|
||||
|
||||
void *
|
||||
aot_addr_app_to_native(AOTModuleInstance *module_inst, int32 app_offset);
|
||||
aot_addr_app_to_native(AOTModuleInstance *module_inst, uint32 app_offset);
|
||||
|
||||
int32
|
||||
uint32
|
||||
aot_addr_native_to_app(AOTModuleInstance *module_inst, void *native_ptr);
|
||||
|
||||
bool
|
||||
aot_get_app_addr_range(AOTModuleInstance *module_inst,
|
||||
int32 app_offset,
|
||||
int32 *p_app_start_offset,
|
||||
int32 *p_app_end_offset);
|
||||
uint32 app_offset,
|
||||
uint32 *p_app_start_offset,
|
||||
uint32 *p_app_end_offset);
|
||||
|
||||
bool
|
||||
aot_get_native_addr_range(AOTModuleInstance *module_inst,
|
||||
|
@ -450,13 +628,91 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
|
|||
|
||||
bool
|
||||
aot_call_indirect(WASMExecEnv *exec_env,
|
||||
bool check_func_type, uint32 func_type_idx,
|
||||
uint32 table_elem_idx,
|
||||
uint32 tbl_idx, uint32 table_elem_idx,
|
||||
uint32 argc, uint32 *argv);
|
||||
|
||||
uint32
|
||||
aot_get_plt_table_size();
|
||||
|
||||
void *
|
||||
aot_memmove(void *dest, const void *src, size_t n);
|
||||
|
||||
void *
|
||||
aot_memset(void *s, int c, size_t n);
|
||||
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
bool
|
||||
aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index,
|
||||
uint32 offset, uint32 len, uint32 dst);
|
||||
|
||||
bool
|
||||
aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
bool
|
||||
aot_set_aux_stack(WASMExecEnv *exec_env,
|
||||
uint32 start_offset, uint32 size);
|
||||
|
||||
bool
|
||||
aot_get_aux_stack(WASMExecEnv *exec_env,
|
||||
uint32 *start_offset, uint32 *size);
|
||||
#endif
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
bool
|
||||
aot_signal_init();
|
||||
|
||||
void
|
||||
aot_signal_destroy();
|
||||
#endif
|
||||
|
||||
void
|
||||
aot_get_module_mem_consumption(const AOTModule *module,
|
||||
WASMModuleMemConsumption *mem_conspn);
|
||||
|
||||
void
|
||||
aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst,
|
||||
WASMModuleInstMemConsumption *mem_conspn);
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
void
|
||||
aot_drop_table_seg(AOTModuleInstance *module_inst, uint32 tbl_seg_idx);
|
||||
|
||||
void
|
||||
aot_table_init(AOTModuleInstance *module_inst,
|
||||
uint32 tbl_idx, uint32 tbl_seg_idx,
|
||||
uint32 length, uint32 src_offset, uint32 dst_offset);
|
||||
|
||||
void
|
||||
aot_table_copy(AOTModuleInstance *module_inst,
|
||||
uint32 src_tbl_idx, uint32 dst_tbl_idx,
|
||||
uint32 length, uint32 src_offset, uint32 dst_offset);
|
||||
|
||||
void
|
||||
aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx,
|
||||
uint32 length, uint32 val, uint32 data_offset);
|
||||
|
||||
uint32
|
||||
aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx,
|
||||
uint32 inc_entries, uint32 init_val);
|
||||
#endif
|
||||
|
||||
AOTTableInstance *
|
||||
aot_next_tbl_inst(const AOTTableInstance *tbl_inst);
|
||||
|
||||
bool
|
||||
aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index);
|
||||
|
||||
void
|
||||
aot_free_frame(WASMExecEnv *exec_env);
|
||||
|
||||
void
|
||||
aot_dump_call_stack(WASMExecEnv *exec_env);
|
||||
|
||||
void
|
||||
aot_dump_perf_profiling(const AOTModuleInstance *module_inst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -1,12 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2020 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_reloc.h"
|
||||
|
||||
#define R_AARCH64_MOVW_UABS_G0 263
|
||||
#define R_AARCH64_MOVW_UABS_G0_NC 264
|
||||
#define R_AARCH64_MOVW_UABS_G1 265
|
||||
#define R_AARCH64_MOVW_UABS_G1_NC 266
|
||||
#define R_AARCH64_MOVW_UABS_G2 267
|
||||
#define R_AARCH64_MOVW_UABS_G2_NC 268
|
||||
#define R_AARCH64_MOVW_UABS_G3 269
|
||||
|
||||
#define R_AARCH64_MOVW_SABS_G0 270
|
||||
#define R_AARCH64_MOVW_SABS_G1 271
|
||||
#define R_AARCH64_MOVW_SABS_G2 272
|
||||
|
||||
#define R_AARCH64_ADR_PREL_LO19 273
|
||||
#define R_AARCH64_ADR_PREL_LO21 274
|
||||
#define R_AARCH64_ADR_PREL_PG_HI21 275
|
||||
#define R_AARCH64_ADR_PREL_PG_HI21_NC 276
|
||||
|
||||
#define R_AARCH64_ADD_ABS_LO12_NC 277
|
||||
|
||||
#define R_AARCH64_LDST8_ABS_LO12_NC 278
|
||||
#define R_AARCH64_LDST16_ABS_LO12_NC 284
|
||||
#define R_AARCH64_LDST32_ABS_LO12_NC 285
|
||||
#define R_AARCH64_LDST64_ABS_LO12_NC 286
|
||||
#define R_AARCH64_LDST128_ABS_LO12_NC 299
|
||||
|
||||
#define R_AARCH64_JUMP26 282
|
||||
#define R_AARCH64_CALL26 283
|
||||
|
||||
static SymbolMap target_sym_map[] = {
|
||||
|
@ -27,28 +51,38 @@ get_target_symbol_map(uint32 *sym_num)
|
|||
return target_sym_map;
|
||||
}
|
||||
|
||||
#define BUILD_TARGET_AARCH64_DEFAULT "aarch64v8"
|
||||
void
|
||||
get_current_target(char *target_buf, uint32 target_buf_size)
|
||||
{
|
||||
char *build_target = BUILD_TARGET;
|
||||
char *p = target_buf, *p_end;
|
||||
snprintf(target_buf, target_buf_size, "%s", build_target);
|
||||
p_end = p + strlen(target_buf);
|
||||
while (p < p_end) {
|
||||
if (*p >= 'A' && *p <= 'Z')
|
||||
*p++ += 'a' - 'A';
|
||||
else
|
||||
p++;
|
||||
const char * s = BUILD_TARGET;
|
||||
size_t s_size = sizeof(BUILD_TARGET);
|
||||
char *d = target_buf;
|
||||
|
||||
/* Set to "aarch64v8" by default if sub version isn't specified */
|
||||
if (strcmp(s, "AARCH64") == 0) {
|
||||
s = BUILD_TARGET_AARCH64_DEFAULT;
|
||||
s_size = sizeof(BUILD_TARGET_AARCH64_DEFAULT);
|
||||
}
|
||||
if (!strcmp(target_buf, "aarch64"))
|
||||
snprintf(target_buf, target_buf_size, "aarch64v8");
|
||||
if(target_buf_size < s_size){
|
||||
s_size = target_buf_size;
|
||||
}
|
||||
while (--s_size) {
|
||||
if (*s >= 'A' && *s <= 'Z')
|
||||
*d++ = *s++ + 'a' - 'A';
|
||||
else
|
||||
*d++ = *s++ ;
|
||||
}
|
||||
/* Ensure the string is null byte ('\0') terminated */
|
||||
*d = '\0';
|
||||
}
|
||||
#undef BUILD_TARGET_AARCH64_DEFAULT
|
||||
|
||||
static uint32
|
||||
get_plt_item_size()
|
||||
{
|
||||
/* 8*4 bytes instructions and 8 bytes symbol address */
|
||||
return 40;
|
||||
/* 6*4 bytes instructions and 8 bytes symbol address */
|
||||
return 32;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -57,13 +91,11 @@ init_plt_table(uint8 *plt)
|
|||
uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
|
||||
for (i = 0; i < num; i++) {
|
||||
uint32 *p = (uint32*)plt;
|
||||
*p++ = 0xd10023ff; /* sub sp, sp, #0x8 */
|
||||
*p++ = 0xf90003fe; /* str x30, [sp] */
|
||||
*p++ = 0x100000de; /* adr x30, #24 */
|
||||
*p++ = 0xf81f0ffe; /* str x30, [sp, #-16]! */
|
||||
*p++ = 0x100000be; /* adr x30, #20 ;symbol addr is PC + 5 instructions below */
|
||||
*p++ = 0xf94003de; /* ldr x30, [x30] */
|
||||
*p++ = 0xd63f03c0; /* blr x30 */
|
||||
*p++ = 0xf94003fe; /* ldr x30, [sp] */
|
||||
*p++ = 0x910023ff; /* add sp, sp, #0x8 */
|
||||
*p++ = 0xf84107fe; /* ldr x30, [sp], #16 */
|
||||
*p++ = 0xd61f03c0; /* br x30 */
|
||||
/* symbol addr */
|
||||
*(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr;
|
||||
|
@ -163,7 +195,74 @@ apply_relocation(AOTModule *module,
|
|||
break;
|
||||
}
|
||||
|
||||
case R_AARCH64_MOVW_UABS_G0:
|
||||
case R_AARCH64_MOVW_UABS_G0_NC:
|
||||
case R_AARCH64_MOVW_UABS_G1:
|
||||
case R_AARCH64_MOVW_UABS_G1_NC:
|
||||
case R_AARCH64_MOVW_UABS_G2:
|
||||
case R_AARCH64_MOVW_UABS_G2_NC:
|
||||
case R_AARCH64_MOVW_UABS_G3:
|
||||
{
|
||||
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
|
||||
int64 X, A, initial_addend;
|
||||
int32 insn, imm16;
|
||||
|
||||
CHECK_RELOC_OFFSET(sizeof(int32));
|
||||
|
||||
insn = *(int32*)P;
|
||||
imm16 = (insn >> 5) & 0xFFFF;
|
||||
|
||||
SIGN_EXTEND_TO_INT64(imm16, 16, initial_addend);
|
||||
A = initial_addend;
|
||||
A += (int64)reloc_addend;
|
||||
|
||||
/* S + A */
|
||||
X = (int64)S + A;
|
||||
|
||||
/* No need to check overflow for this reloction type */
|
||||
switch (reloc_type) {
|
||||
case R_AARCH64_MOVW_UABS_G0:
|
||||
if (X < 0 || X >= (1LL << 16))
|
||||
goto overflow_check_fail;
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G1:
|
||||
if (X < 0 || X >= (1LL << 32))
|
||||
goto overflow_check_fail;
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G2:
|
||||
if (X < 0 || X >= (1LL << 48))
|
||||
goto overflow_check_fail;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* write the imm16 back to bits[5:20] of instruction */
|
||||
switch (reloc_type) {
|
||||
case R_AARCH64_MOVW_UABS_G0:
|
||||
case R_AARCH64_MOVW_UABS_G0_NC:
|
||||
*(int32*)P = (insn & 0xFFE0001F) | ((int32)((X & 0xFFFF) << 5));
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G1:
|
||||
case R_AARCH64_MOVW_UABS_G1_NC:
|
||||
*(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 16) & 0xFFFF) << 5));
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G2:
|
||||
case R_AARCH64_MOVW_UABS_G2_NC:
|
||||
*(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 32) & 0xFFFF) << 5));
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G3:
|
||||
*(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 48) & 0xFFFF) << 5));
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||
case R_AARCH64_ADR_PREL_PG_HI21_NC:
|
||||
{
|
||||
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
|
||||
int64 X, A, initial_addend;
|
||||
|
@ -184,12 +283,9 @@ apply_relocation(AOTModule *module,
|
|||
X = Page((int64)S + A) - Page((int64)P);
|
||||
|
||||
/* Check overflow: +-4GB */
|
||||
if (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module load failed: "
|
||||
"target address out of range.");
|
||||
return false;
|
||||
}
|
||||
if (reloc_type == R_AARCH64_ADR_PREL_PG_HI21
|
||||
&& (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)))
|
||||
goto overflow_check_fail;
|
||||
|
||||
/* write the imm21 back to instruction */
|
||||
immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF);
|
||||
|
@ -224,6 +320,54 @@ apply_relocation(AOTModule *module,
|
|||
break;
|
||||
}
|
||||
|
||||
case R_AARCH64_LDST8_ABS_LO12_NC:
|
||||
case R_AARCH64_LDST16_ABS_LO12_NC:
|
||||
case R_AARCH64_LDST32_ABS_LO12_NC:
|
||||
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||
case R_AARCH64_LDST128_ABS_LO12_NC:
|
||||
{
|
||||
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
|
||||
int64 X, A, initial_addend;
|
||||
int32 insn, imm12;
|
||||
|
||||
CHECK_RELOC_OFFSET(sizeof(int32));
|
||||
|
||||
insn = *(int32*)P;
|
||||
imm12 = (insn >> 10) & 0xFFF;
|
||||
|
||||
SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend);
|
||||
A = initial_addend;
|
||||
A += (int64)reloc_addend;
|
||||
|
||||
/* S + A */
|
||||
X = (int64)S + A;
|
||||
|
||||
/* No need to check overflow for this reloction type */
|
||||
|
||||
/* write the imm12 back to instruction */
|
||||
switch (reloc_type) {
|
||||
case R_AARCH64_LDST8_ABS_LO12_NC:
|
||||
*(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10));
|
||||
break;
|
||||
case R_AARCH64_LDST16_ABS_LO12_NC:
|
||||
*(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 1) << 10));
|
||||
break;
|
||||
case R_AARCH64_LDST32_ABS_LO12_NC:
|
||||
*(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 2) << 10));
|
||||
break;
|
||||
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||
*(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 3) << 10));
|
||||
break;
|
||||
case R_AARCH64_LDST128_ABS_LO12_NC:
|
||||
*(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 4) << 10));
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (error_buf != NULL)
|
||||
snprintf(error_buf, error_buf_size,
|
||||
|
@ -234,5 +378,10 @@ apply_relocation(AOTModule *module,
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
overflow_check_fail:
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module load failed: "
|
||||
"target address out of range.");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ void __aeabi_f2iz();
|
|||
void __aeabi_f2d();
|
||||
|
||||
static SymbolMap target_sym_map[] = {
|
||||
REG_COMMON_SYMBOLS,
|
||||
REG_COMMON_SYMBOLS
|
||||
/* compiler-rt symbols that come from compiler(e.g. gcc) */
|
||||
REG_SYM(__divdi3),
|
||||
REG_SYM(__udivdi3),
|
||||
|
@ -118,22 +118,32 @@ get_target_symbol_map(uint32 *sym_num)
|
|||
return target_sym_map;
|
||||
}
|
||||
|
||||
#define BUILD_TARGET_ARM_DEFAULT "armv4"
|
||||
void
|
||||
get_current_target(char *target_buf, uint32 target_buf_size)
|
||||
{
|
||||
char *build_target = BUILD_TARGET;
|
||||
char *p = target_buf, *p_end;
|
||||
snprintf(target_buf, target_buf_size, "%s", build_target);
|
||||
p_end = p + strlen(target_buf);
|
||||
while (p < p_end) {
|
||||
if (*p >= 'A' && *p <= 'Z')
|
||||
*p++ += 'a' - 'A';
|
||||
else
|
||||
p++;
|
||||
const char * s = BUILD_TARGET;
|
||||
size_t s_size = sizeof(BUILD_TARGET);
|
||||
char *d = target_buf;
|
||||
|
||||
/* Set to "armv4" by default if sub version isn't specified */
|
||||
if (strcmp(s, "ARM") == 0) {
|
||||
s = BUILD_TARGET_ARM_DEFAULT;
|
||||
s_size = sizeof(BUILD_TARGET_ARM_DEFAULT);
|
||||
}
|
||||
if (!strcmp(target_buf, "arm"))
|
||||
snprintf(target_buf, target_buf_size, "armv4");
|
||||
if(target_buf_size < s_size){
|
||||
s_size = target_buf_size;
|
||||
}
|
||||
while (--s_size) {
|
||||
if (*s >= 'A' && *s <= 'Z')
|
||||
*d++ = *s++ + 'a' - 'A';
|
||||
else
|
||||
*d++ = *s++ ;
|
||||
}
|
||||
/* Ensure the string is null byte ('\0') terminated */
|
||||
*d = '\0';
|
||||
}
|
||||
#undef BUILD_TARGET_ARM_DEFAULT
|
||||
|
||||
uint32
|
||||
get_plt_item_size()
|
||||
|
|
|
@ -8,6 +8,19 @@
|
|||
#define R_ARM_THM_CALL 10 /* PC relative (Thumb BL and ARMv5 Thumb BLX). */
|
||||
#define R_ARM_THM_JMP24 30 /* B.W */
|
||||
|
||||
void __ltdf2();
|
||||
void __adddf3();
|
||||
void __eqdf2();
|
||||
void __unorddf2();
|
||||
void __muldf3();
|
||||
void __subdf3();
|
||||
void __gedf2();
|
||||
void __ledf2();
|
||||
void __fixunsdfsi();
|
||||
void __floatunsidf();
|
||||
void __fixdfsi();
|
||||
void __nedf2();
|
||||
void __floatsidf();
|
||||
void __divdi3();
|
||||
void __udivdi3();
|
||||
void __moddi3();
|
||||
|
@ -55,8 +68,21 @@ void __aeabi_f2iz();
|
|||
void __aeabi_f2d();
|
||||
|
||||
static SymbolMap target_sym_map[] = {
|
||||
REG_COMMON_SYMBOLS,
|
||||
REG_COMMON_SYMBOLS
|
||||
/* compiler-rt symbols that come from compiler(e.g. gcc) */
|
||||
REG_SYM(__ltdf2),
|
||||
REG_SYM(__adddf3),
|
||||
REG_SYM(__eqdf2),
|
||||
REG_SYM(__unorddf2),
|
||||
REG_SYM(__muldf3),
|
||||
REG_SYM(__subdf3),
|
||||
REG_SYM(__gedf2),
|
||||
REG_SYM(__ledf2),
|
||||
REG_SYM(__fixunsdfsi),
|
||||
REG_SYM(__floatunsidf),
|
||||
REG_SYM(__fixdfsi),
|
||||
REG_SYM(__nedf2),
|
||||
REG_SYM(__floatsidf),
|
||||
REG_SYM(__divdi3),
|
||||
REG_SYM(__udivdi3),
|
||||
REG_SYM(__umoddi3),
|
||||
|
@ -117,22 +143,32 @@ get_target_symbol_map(uint32 *sym_num)
|
|||
return target_sym_map;
|
||||
}
|
||||
|
||||
#define BUILD_TARGET_THUMB_V4T "thumbv4t"
|
||||
void
|
||||
get_current_target(char *target_buf, uint32 target_buf_size)
|
||||
{
|
||||
char *build_target = BUILD_TARGET;
|
||||
char *p = target_buf, *p_end;
|
||||
snprintf(target_buf, target_buf_size, "%s", build_target);
|
||||
p_end = p + strlen(target_buf);
|
||||
while (p < p_end) {
|
||||
if (*p >= 'A' && *p <= 'Z')
|
||||
*p++ += 'a' - 'A';
|
||||
else
|
||||
p++;
|
||||
const char * s = BUILD_TARGET;
|
||||
size_t s_size = sizeof(BUILD_TARGET);
|
||||
char *d = target_buf;
|
||||
|
||||
/* Set to "thumbv4t" by default if sub version isn't specified */
|
||||
if (strcmp(s, "THUMB") == 0) {
|
||||
s = BUILD_TARGET_THUMB_V4T;
|
||||
s_size = sizeof(BUILD_TARGET_THUMB_V4T);
|
||||
}
|
||||
if (!strcmp(target_buf, "thumb"))
|
||||
snprintf(target_buf, target_buf_size, "thumbv4t");
|
||||
if(target_buf_size < s_size){
|
||||
s_size = target_buf_size;
|
||||
}
|
||||
while (--s_size) {
|
||||
if (*s >= 'A' && *s <= 'Z')
|
||||
*d++ = *s++ + 'a' - 'A';
|
||||
else
|
||||
*d++ = *s++ ;
|
||||
}
|
||||
/* Ensure the string is null byte ('\0') terminated */
|
||||
*d = '\0';
|
||||
}
|
||||
#undef BUILD_TARGET_THUMB_V4T
|
||||
|
||||
uint32
|
||||
get_plt_item_size()
|
||||
|
|
|
@ -8,13 +8,42 @@
|
|||
#define R_386_32 1 /* Direct 32 bit */
|
||||
#define R_386_PC32 2 /* PC relative 32 bit */
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN32_)
|
||||
void __divdi3();
|
||||
void __udivdi3();
|
||||
void __moddi3();
|
||||
void __umoddi3();
|
||||
#else
|
||||
#pragma function (floor)
|
||||
#pragma function (ceil)
|
||||
|
||||
static int64
|
||||
__divdi3(int64 a, int64 b)
|
||||
{
|
||||
return a / b;
|
||||
}
|
||||
|
||||
static uint64
|
||||
__udivdi3(uint64 a, uint64 b)
|
||||
{
|
||||
return a / b;
|
||||
}
|
||||
|
||||
static int64
|
||||
__moddi3(int64 a, int64 b)
|
||||
{
|
||||
return a % b;
|
||||
}
|
||||
|
||||
static uint64
|
||||
__umoddi3(uint64 a, uint64 b)
|
||||
{
|
||||
return a % b;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SymbolMap target_sym_map[] = {
|
||||
REG_COMMON_SYMBOLS,
|
||||
REG_COMMON_SYMBOLS
|
||||
/* compiler-rt symbols that come from compiler(e.g. gcc) */
|
||||
REG_SYM(__divdi3),
|
||||
REG_SYM(__udivdi3),
|
||||
|
|
|
@ -5,16 +5,27 @@
|
|||
|
||||
#include "aot_reloc.h"
|
||||
|
||||
#define R_X86_64_64 1 /* Direct 64 bit */
|
||||
#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
|
||||
#define R_X86_64_PLT32 4 /* 32 bit PLT address */
|
||||
#define R_X86_64_32 10 /* Direct 32 bit zero extended */
|
||||
#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
|
||||
#if !defined(BH_PLATFORM_WINDOWS)
|
||||
#define R_X86_64_64 1 /* Direct 64 bit */
|
||||
#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
|
||||
#define R_X86_64_PLT32 4 /* 32 bit PLT address */
|
||||
#define R_X86_64_32 10 /* Direct 32 bit zero extended */
|
||||
#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
|
||||
#else
|
||||
#ifndef IMAGE_REL_AMD64_ADDR64
|
||||
#define IMAGE_REL_AMD64_ADDR64 1 /* The 64-bit VA of the relocation target */
|
||||
#define IMAGE_REL_AMD64_ADDR32 2 /* The 32-bit VA of the relocation target */
|
||||
#define IMAGE_REL_AMD64_REL32 4 /* The 32-bit relative address from
|
||||
the byte following the relocation*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void __divdi3();
|
||||
void __udivdi3();
|
||||
void __moddi3();
|
||||
void __umoddi3();
|
||||
#if defined(BH_PLATFORM_WINDOWS)
|
||||
#pragma function (floor)
|
||||
#pragma function (ceil)
|
||||
#pragma function (floorf)
|
||||
#pragma function (ceilf)
|
||||
#endif
|
||||
|
||||
static SymbolMap target_sym_map[] = {
|
||||
REG_COMMON_SYMBOLS
|
||||
|
@ -50,15 +61,22 @@ get_plt_item_size()
|
|||
uint32
|
||||
get_plt_table_size()
|
||||
{
|
||||
return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
|
||||
uint32 size = get_plt_item_size()
|
||||
* (sizeof(target_sym_map) / sizeof(SymbolMap));
|
||||
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
|
||||
size += get_plt_item_size() + sizeof(AOTUnwindInfo);
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
|
||||
void
|
||||
init_plt_table(uint8 *plt)
|
||||
{
|
||||
uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
|
||||
uint8 *p;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
uint8 *p = plt;
|
||||
p = plt;
|
||||
/* mov symbol_addr, rax */
|
||||
*p++ = 0x48;
|
||||
*p++ = 0xB8;
|
||||
|
@ -69,6 +87,18 @@ init_plt_table(uint8 *plt)
|
|||
*p++ = 0xE0;
|
||||
plt += get_plt_item_size();
|
||||
}
|
||||
|
||||
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
|
||||
p = plt;
|
||||
/* mov exception_handler, rax */
|
||||
*p++ = 0x48;
|
||||
*p++ = 0xB8;
|
||||
*(uint64*)p = 0;/*(uint64)(uintptr_t)aot_exception_handler;*/
|
||||
p += sizeof(uint64);
|
||||
/* jmp rax */
|
||||
*p++ = 0xFF;
|
||||
*p++ = 0xE0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -93,7 +123,11 @@ apply_relocation(AOTModule *module,
|
|||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
#if !defined(BH_PLATFORM_WINDOWS)
|
||||
case R_X86_64_64:
|
||||
#else
|
||||
case IMAGE_REL_AMD64_ADDR64:
|
||||
#endif
|
||||
{
|
||||
intptr_t value;
|
||||
|
||||
|
@ -103,6 +137,29 @@ apply_relocation(AOTModule *module,
|
|||
= (uint8*)symbol_addr + reloc_addend + value; /* S + A */
|
||||
break;
|
||||
}
|
||||
#if defined(BH_PLATFORM_WINDOWS)
|
||||
case IMAGE_REL_AMD64_ADDR32:
|
||||
{
|
||||
int32 value;
|
||||
uintptr_t target_addr;
|
||||
|
||||
CHECK_RELOC_OFFSET(sizeof(void *));
|
||||
value = *(int32*)(target_section_addr + (uint32)reloc_offset);
|
||||
target_addr = (uintptr_t)symbol_addr + reloc_addend + value;
|
||||
if ((int32)target_addr != target_addr) {
|
||||
set_error_buf(
|
||||
error_buf, error_buf_size,
|
||||
"AOT module load failed: "
|
||||
"relocation truncated to fit IMAGE_REL_AMD64_ADDR32 failed. "
|
||||
"Try using wamrc with --size-level=1 option.");
|
||||
return false;
|
||||
}
|
||||
|
||||
*(int32 *)(target_section_addr + reloc_offset) = (int32)target_addr;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if !defined(BH_PLATFORM_WINDOWS)
|
||||
case R_X86_64_PC32:
|
||||
{
|
||||
intptr_t target_addr = (intptr_t) /* S + A - P */
|
||||
|
@ -147,7 +204,12 @@ apply_relocation(AOTModule *module,
|
|||
*(int32*)(target_section_addr + reloc_offset) = (int32)target_addr;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if !defined(BH_PLATFORM_WINDOWS)
|
||||
case R_X86_64_PLT32:
|
||||
#else
|
||||
case IMAGE_REL_AMD64_REL32:
|
||||
#endif
|
||||
{
|
||||
uint8 *plt;
|
||||
intptr_t target_addr = 0;
|
||||
|
@ -167,14 +229,21 @@ apply_relocation(AOTModule *module,
|
|||
- (target_section_addr + reloc_offset));
|
||||
}
|
||||
|
||||
#if defined(BH_PLATFORM_WINDOWS)
|
||||
target_addr -= sizeof(int32);
|
||||
#endif
|
||||
if ((int32)target_addr != target_addr) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"AOT module load failed: "
|
||||
"relocation truncated to fit R_X86_64_PC32 failed. "
|
||||
"relocation truncated to fit "
|
||||
#if !defined(BH_PLATFORM_WINDOWS)
|
||||
"R_X86_64_PLT32 failed. "
|
||||
#else
|
||||
"IMAGE_REL_AMD64_32 failed."
|
||||
#endif
|
||||
"Try using wamrc with --size-level=1 option.");
|
||||
return false;
|
||||
}
|
||||
|
||||
*(int32*)(target_section_addr + reloc_offset) = (int32)target_addr;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ void __modsi3();
|
|||
void __divdi3();
|
||||
|
||||
static SymbolMap target_sym_map[] = {
|
||||
REG_COMMON_SYMBOLS,
|
||||
REG_COMMON_SYMBOLS
|
||||
|
||||
/* API's for soft-float */
|
||||
/* TODO: only register these symbols when Floating-Point Coprocessor
|
||||
|
|
26
core/iwasm/common/SConscript
Normal file
26
core/iwasm/common/SConscript
Normal file
|
@ -0,0 +1,26 @@
|
|||
#
|
||||
# Copyright (c) 2021, RT-Thread Development Team
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
from building import *
|
||||
import re
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
|
||||
src = Glob('*.c')
|
||||
|
||||
if rtconfig.ARCH == 'arm':
|
||||
if re.match('^cortex-m.*', rtconfig.CPU):
|
||||
src += ['arch/invokeNative_thumb.s']
|
||||
elif re.match('^cortex-a.*', rtconfig.CPU):
|
||||
src += ['arch/invokeNative_arm.s']
|
||||
|
||||
CPPPATH = [cwd, cwd + '/../include']
|
||||
|
||||
group = DefineGroup('iwasm_common', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
|
@ -4,8 +4,14 @@
|
|||
*/
|
||||
.text
|
||||
.align 2
|
||||
.global invokeNative
|
||||
.type invokeNative,function
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
|
@ -15,7 +21,6 @@
|
|||
* x2 nstacks
|
||||
*/
|
||||
|
||||
invokeNative:
|
||||
sub sp, sp, #0x30
|
||||
stp x19, x20, [sp, #0x20] /* save the registers */
|
||||
stp x21, x22, [sp, #0x10]
|
||||
|
@ -32,7 +37,7 @@ invokeNative:
|
|||
ldp d4, d5, [x20], #16 /* d4 = argv[4], d5 = argv[5] */
|
||||
ldp d6, d7, [x20], #16 /* d6 = argv[6], d7 = argv[7] */
|
||||
|
||||
/* Fill inteter registers */
|
||||
/* Fill integer registers */
|
||||
ldp x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */
|
||||
ldp x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */
|
||||
ldp x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */
|
||||
|
@ -44,7 +49,7 @@ invokeNative:
|
|||
cmp x21, #0
|
||||
beq call_func
|
||||
|
||||
/* Fill all stack args: reserve stack space and fill ony by one */
|
||||
/* Fill all stack args: reserve stack space and fill one by one */
|
||||
mov x23, sp
|
||||
bic sp, x23, #15 /* Ensure stack is 16 bytes aligned */
|
||||
lsl x23, x21, #3 /* x23 = nstacks * 8 */
|
||||
|
|
79
core/iwasm/common/arch/invokeNative_aarch64_simd.s
Normal file
79
core/iwasm/common/arch/invokeNative_aarch64_simd.s
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (C) 2020 Intel Corporation Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
.text
|
||||
.align 2
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
*
|
||||
* x0 function ptr
|
||||
* x1 argv
|
||||
* x2 nstacks
|
||||
*/
|
||||
|
||||
sub sp, sp, #0x30
|
||||
stp x19, x20, [sp, #0x20] /* save the registers */
|
||||
stp x21, x22, [sp, #0x10]
|
||||
stp x23, x24, [sp, #0x0]
|
||||
|
||||
mov x19, x0 /* x19 = function ptr */
|
||||
mov x20, x1 /* x20 = argv */
|
||||
mov x21, x2 /* x21 = nstacks */
|
||||
mov x22, sp /* save the sp before call function */
|
||||
|
||||
/* Fill in float-point registers */
|
||||
ld1 {v0.2D, v1.2D, v2.2D, v3.2D}, [x20], #64 /* v0 = argv[0], v1 = argv[1], v2 = argv[2], v3 = argv[3]*/
|
||||
ld1 {v4.2D, v5.2D, v6.2D, v7.2D}, [x20], #64 /* v4 = argv[4], v5 = argv[5], v6 = argv[6], v7 = argv[7]*/
|
||||
|
||||
/* Fill inteter registers */
|
||||
ldp x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */
|
||||
ldp x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */
|
||||
ldp x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */
|
||||
ldp x6, x7, [x20], #16 /* x6 = argv[14], x7 = argv[15] */
|
||||
|
||||
/* Now x20 points to stack args */
|
||||
|
||||
/* Directly call the fucntion if no args in stack */
|
||||
cmp x21, #0
|
||||
beq call_func
|
||||
|
||||
/* Fill all stack args: reserve stack space and fill one by one */
|
||||
mov x23, sp
|
||||
bic sp, x23, #15 /* Ensure stack is 16 bytes aligned */
|
||||
lsl x23, x21, #3 /* x23 = nstacks * 8 */
|
||||
add x23, x23, #15 /* x23 = (x23 + 15) & ~15 */
|
||||
bic x23, x23, #15
|
||||
sub sp, sp, x23 /* reserved stack space for stack arguments */
|
||||
mov x23, sp
|
||||
|
||||
loop_stack_args: /* copy stack arguments to stack */
|
||||
cmp x21, #0
|
||||
beq call_func
|
||||
ldr x24, [x20], #8
|
||||
str x24, [x23], #8
|
||||
sub x21, x21, #1
|
||||
b loop_stack_args
|
||||
|
||||
call_func:
|
||||
mov x20, x30 /* save x30(lr) */
|
||||
blr x19
|
||||
mov sp, x22 /* restore sp which is saved before calling fuction*/
|
||||
|
||||
return:
|
||||
mov x30, x20 /* restore x30(lr) */
|
||||
ldp x19, x20, [sp, #0x20] /* restore the registers in stack */
|
||||
ldp x21, x22, [sp, #0x10]
|
||||
ldp x23, x24, [sp, #0x0]
|
||||
add sp, sp, #0x30 /* restore sp */
|
||||
ret
|
||||
|
|
@ -4,8 +4,14 @@
|
|||
*/
|
||||
.text
|
||||
.align 2
|
||||
.global invokeNative
|
||||
.type invokeNative,function
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
|
@ -15,8 +21,8 @@
|
|||
* r2 argc
|
||||
*/
|
||||
|
||||
invokeNative:
|
||||
stmfd sp!, {r4, r5, r6, r7, lr}
|
||||
sub sp, sp, #4 /* make sp 8 byte aligned */
|
||||
mov ip, r0 /* ip = function ptr */
|
||||
mov r4, r1 /* r4 = argv */
|
||||
mov r5, r2 /* r5 = argc */
|
||||
|
@ -48,7 +54,6 @@ invokeNative:
|
|||
mov r6, r5, lsl#2 /* r6 = argc * 4 */
|
||||
add r6, r6, #7 /* r6 = (r6 + 7) & ~7 */
|
||||
bic r6, r6, #7
|
||||
add r6, r6, #4 /* +4 because odd(5) registers are in stack */
|
||||
sub sp, sp, r6 /* reserved stack space for left arguments */
|
||||
mov r7, sp
|
||||
|
||||
|
@ -65,5 +70,6 @@ call_func:
|
|||
add sp, sp, r6 /* restore sp */
|
||||
|
||||
return:
|
||||
add sp, sp, #4
|
||||
ldmfd sp!, {r4, r5, r6, r7, lr}
|
||||
bx lr
|
||||
|
|
|
@ -4,8 +4,14 @@
|
|||
*/
|
||||
.text
|
||||
.align 2
|
||||
.global invokeNative
|
||||
.type invokeNative,function
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
|
@ -15,7 +21,6 @@
|
|||
* r2 nstacks
|
||||
*/
|
||||
|
||||
invokeNative:
|
||||
stmfd sp!, {r4, r5, r6, r7, lr}
|
||||
mov ip, r0 /* ip = function ptr */
|
||||
mov r4, r1 /* r4 = argv */
|
||||
|
@ -52,7 +57,7 @@ invokeNative:
|
|||
beq call_func
|
||||
|
||||
|
||||
/* Fill all stack args: reserve stack space and fill ony by one */
|
||||
/* Fill all stack args: reserve stack space and fill one by one */
|
||||
add r4, r4, #64 /* r4 points to stack args */
|
||||
bic sp, sp, #7 /* Ensure stack is 8 byte aligned */
|
||||
mov r7, r5, lsl#2 /* r7 = nstacks * 4 */
|
||||
|
|
62
core/iwasm/common/arch/invokeNative_em64.asm
Normal file
62
core/iwasm/common/arch/invokeNative_em64.asm
Normal file
|
@ -0,0 +1,62 @@
|
|||
;
|
||||
; Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
;
|
||||
|
||||
_TEXT SEGMENT
|
||||
; rcx func_ptr
|
||||
; rdx argv
|
||||
; r8 n_stacks
|
||||
|
||||
invokeNative PROC
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
mov r10, rcx ; func_ptr
|
||||
mov rax, rdx ; argv
|
||||
mov rcx, r8 ; n_stacks
|
||||
|
||||
; fill all fp args
|
||||
movsd xmm0, qword ptr [rax + 0]
|
||||
movsd xmm1, qword ptr [rax + 8]
|
||||
movsd xmm2, qword ptr [rax + 16]
|
||||
movsd xmm3, qword ptr [rax + 24]
|
||||
|
||||
; check for stack args
|
||||
cmp rcx, 0
|
||||
jz cycle_end
|
||||
|
||||
mov rdx, rsp
|
||||
and rdx, 15
|
||||
jz no_abort
|
||||
int 3
|
||||
no_abort:
|
||||
mov rdx, rcx
|
||||
and rdx, 1
|
||||
shl rdx, 3
|
||||
sub rsp, rdx
|
||||
|
||||
; store stack args
|
||||
lea r9, qword ptr [rax + rcx * 8 + 56]
|
||||
sub r9, rsp ; offset
|
||||
cycle:
|
||||
push qword ptr [rsp + r9]
|
||||
loop cycle
|
||||
|
||||
cycle_end:
|
||||
mov rcx, [rax + 32]
|
||||
mov rdx, [rax + 40]
|
||||
mov r8, [rax + 48]
|
||||
mov r9, [rax + 56]
|
||||
|
||||
sub rsp, 32 ; shadow space
|
||||
|
||||
call r10
|
||||
leave
|
||||
ret
|
||||
|
||||
invokeNative ENDP
|
||||
|
||||
_TEXT ENDS
|
||||
|
||||
END
|
62
core/iwasm/common/arch/invokeNative_em64_simd.asm
Normal file
62
core/iwasm/common/arch/invokeNative_em64_simd.asm
Normal file
|
@ -0,0 +1,62 @@
|
|||
;
|
||||
; Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
;
|
||||
|
||||
_TEXT SEGMENT
|
||||
; rcx func_ptr
|
||||
; rdx argv
|
||||
; r8 n_stacks
|
||||
|
||||
invokeNative PROC
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
mov r10, rcx ; func_ptr
|
||||
mov rax, rdx ; argv
|
||||
mov rcx, r8 ; n_stacks
|
||||
|
||||
; fill all fp args
|
||||
movdqu xmm0, xmmword ptr [rax + 0]
|
||||
movdqu xmm1, xmmword ptr [rax + 16]
|
||||
movdqu xmm2, xmmword ptr [rax + 32]
|
||||
movdqu xmm3, xmmword ptr [rax + 48]
|
||||
|
||||
; check for stack args
|
||||
cmp rcx, 0
|
||||
jz cycle_end
|
||||
|
||||
mov rdx, rsp
|
||||
and rdx, 15
|
||||
jz no_abort
|
||||
int 3
|
||||
no_abort:
|
||||
mov rdx, rcx
|
||||
and rdx, 1
|
||||
shl rdx, 3
|
||||
sub rsp, rdx
|
||||
|
||||
; store stack args
|
||||
lea r9, qword ptr [rax + rcx * 8 + 88]
|
||||
sub r9, rsp ; offset
|
||||
cycle:
|
||||
push qword ptr [rsp + r9]
|
||||
loop cycle
|
||||
|
||||
cycle_end:
|
||||
mov rcx, [rax + 64]
|
||||
mov rdx, [rax + 72]
|
||||
mov r8, [rax + 80]
|
||||
mov r9, [rax + 88]
|
||||
|
||||
sub rsp, 32 ; shadow space
|
||||
|
||||
call r10
|
||||
leave
|
||||
ret
|
||||
|
||||
invokeNative ENDP
|
||||
|
||||
_TEXT ENDS
|
||||
|
||||
END
|
64
core/iwasm/common/arch/invokeNative_em64_simd.s
Normal file
64
core/iwasm/common/arch/invokeNative_em64_simd.s
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
.text
|
||||
.align 2
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, @function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
/* rdi - function ptr */
|
||||
/* rsi - argv */
|
||||
/* rdx - n_stacks */
|
||||
|
||||
push %rbp
|
||||
mov %rsp, %rbp
|
||||
|
||||
mov %rdx, %r10
|
||||
mov %rsp, %r11 /* Check that stack is aligned on */
|
||||
and $8, %r11 /* 16 bytes. This code may be removed */
|
||||
je check_stack_succ /* when we are sure that compiler always */
|
||||
int3 /* calls us with aligned stack */
|
||||
check_stack_succ:
|
||||
mov %r10, %r11 /* Align stack on 16 bytes before pushing */
|
||||
and $1, %r11 /* stack arguments in case we have an odd */
|
||||
shl $3, %r11 /* number of stack arguments */
|
||||
sub %r11, %rsp
|
||||
/* store memory args */
|
||||
movq %rdi, %r11 /* func ptr */
|
||||
movq %r10, %rcx /* counter */
|
||||
lea 128+48-8(%rsi,%rcx,8), %r10
|
||||
sub %rsp, %r10
|
||||
cmpq $0, %rcx
|
||||
je push_args_end
|
||||
push_args:
|
||||
push 0(%rsp,%r10)
|
||||
loop push_args
|
||||
push_args_end:
|
||||
/* fill all fp args */
|
||||
movdqu 0x00(%rsi), %xmm0
|
||||
movdqu 0x10(%rsi), %xmm1
|
||||
movdqu 0x20(%rsi), %xmm2
|
||||
movdqu 0x30(%rsi), %xmm3
|
||||
movdqu 0x40(%rsi), %xmm4
|
||||
movdqu 0x50(%rsi), %xmm5
|
||||
movdqu 0x60(%rsi), %xmm6
|
||||
movdqu 0x70(%rsi), %xmm7
|
||||
|
||||
/* fill all int args */
|
||||
movq 0x80(%rsi), %rdi
|
||||
movq 0x90(%rsi), %rdx
|
||||
movq 0x98(%rsi), %rcx
|
||||
movq 0xa0(%rsi), %r8
|
||||
movq 0xa8(%rsi), %r9
|
||||
movq 0x88(%rsi), %rsi
|
||||
|
||||
call *%r11
|
||||
leave
|
||||
ret
|
||||
|
27
core/iwasm/common/arch/invokeNative_ia32.asm
Normal file
27
core/iwasm/common/arch/invokeNative_ia32.asm
Normal file
|
@ -0,0 +1,27 @@
|
|||
;
|
||||
; Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
;
|
||||
|
||||
.386
|
||||
.model flat
|
||||
.code
|
||||
_invokeNative PROC
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
mov ecx, [ebp+16] ; ecx = argc */
|
||||
mov edx, [ebp+12] ; edx = argv */
|
||||
test ecx, ecx
|
||||
jz skip_push_args ; if ecx == 0, skip pushing arguments */
|
||||
lea edx, [edx+ecx*4-4] ; edx = edx + ecx * 4 - 4 */
|
||||
sub edx,esp ; edx = edx - esp */
|
||||
loop_push:
|
||||
push [esp+edx]
|
||||
loop loop_push ; loop ecx counts */
|
||||
skip_push_args:
|
||||
mov edx, [ebp+8] ; edx = func_ptr */
|
||||
call edx
|
||||
leave
|
||||
ret
|
||||
_invokeNative ENDP
|
||||
END
|
95
core/iwasm/common/arch/invokeNative_riscv32_ilp32.s
Normal file
95
core/iwasm/common/arch/invokeNative_riscv32_ilp32.s
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
.text
|
||||
.align 2
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
*
|
||||
* a0 function ptr
|
||||
* a1 argv
|
||||
* a2 nstacks
|
||||
*/
|
||||
|
||||
/*
|
||||
* sp (stack pointer)
|
||||
* |- sw to store 32-bit values from register to memory
|
||||
* |- lw to load from stack to register
|
||||
* fp/s0 (frame pointer)
|
||||
* a0-a7 (8 integer arguments)
|
||||
* |- sw to store
|
||||
* |- lw to load
|
||||
* t0-t6 (temporaries regisgers)
|
||||
* |- caller saved
|
||||
*/
|
||||
|
||||
/* reserve space on stack to save return address and frame pointer */
|
||||
addi sp, sp, -8
|
||||
sw fp, 0(sp) /* save frame pointer */
|
||||
sw ra, 4(sp) /* save return address */
|
||||
|
||||
mv fp, sp /* set frame pointer to bottom of fixed frame */
|
||||
|
||||
/* save function ptr, argv & nstacks */
|
||||
mv t0, a0 /* t0 = function ptr */
|
||||
mv t1, a1 /* t1 = argv array address */
|
||||
mv t2, a2 /* t2 = nstack */
|
||||
|
||||
/* fill in a0-7 integer-registers */
|
||||
lw a0, 0(t1) /* a0 = argv[0] */
|
||||
lw a1, 4(t1) /* a1 = argv[1] */
|
||||
lw a2, 8(t1) /* a2 = argv[2] */
|
||||
lw a3, 12(t1) /* a3 = argv[3] */
|
||||
lw a4, 16(t1) /* a4 = argv[4] */
|
||||
lw a5, 20(t1) /* a5 = argv[5] */
|
||||
lw a6, 24(t1) /* a6 = argv[6] */
|
||||
lw a7, 28(t1) /* a7 = argv[7] */
|
||||
|
||||
addi t1, t1, 32 /* t1 points to stack args */
|
||||
|
||||
/* directly call the function if no args in stack,
|
||||
x0 always holds 0 */
|
||||
beq t2, x0, call_func
|
||||
|
||||
/* reserve enough stack space for function arguments */
|
||||
sll t3, t2, 2 /* shift left 2 bits. t3 = n_stacks * 4 */
|
||||
sub sp, sp, t3
|
||||
|
||||
/* make 16-byte aligned */
|
||||
and sp, sp, ~15
|
||||
|
||||
/* save sp in t4 register */
|
||||
mv t4, sp
|
||||
|
||||
/* copy left arguments from caller stack to own frame stack */
|
||||
loop_stack_args:
|
||||
beq t2, x0, call_func
|
||||
lw t5, 0(t1) /* load stack argument, t5 = argv[i] */
|
||||
sw t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */
|
||||
addi t1, t1, 4 /* move to next stack argument */
|
||||
addi t4, t4, 4 /* move to next stack pointer */
|
||||
addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */
|
||||
j loop_stack_args
|
||||
|
||||
call_func:
|
||||
jalr t0
|
||||
|
||||
/* restore registers pushed in stack or saved in another register */
|
||||
return:
|
||||
mv sp, fp /* restore sp saved in fp before function call */
|
||||
lw fp, 0(sp) /* load previous frame poniter to fp register */
|
||||
lw ra, 4(sp) /* load previous return address to ra register */
|
||||
addi sp, sp, 8 /* pop frame, restore sp */
|
||||
jr ra
|
||||
|
104
core/iwasm/common/arch/invokeNative_riscv32_ilp32d.s
Normal file
104
core/iwasm/common/arch/invokeNative_riscv32_ilp32d.s
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
.text
|
||||
.align 2
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
*
|
||||
* a0 function ptr
|
||||
* a1 argv
|
||||
* a2 nstacks
|
||||
*/
|
||||
|
||||
/*
|
||||
* sp (stack pointer)
|
||||
* |- sw to store 32-bit values from register to memory
|
||||
* |- lw to load from stack to register
|
||||
* fp/s0 (frame pointer)
|
||||
* a0-a7 (8 integer arguments)
|
||||
* |- sw to store
|
||||
* |- lw to load
|
||||
* t0-t6 (temporaries regisgers)
|
||||
* |- caller saved
|
||||
*/
|
||||
|
||||
/* reserve space on stack to save return address and frame pointer */
|
||||
addi sp, sp, -8
|
||||
sw fp, 0(sp) /* save frame pointer */
|
||||
sw ra, 4(sp) /* save return address */
|
||||
|
||||
mv fp, sp /* set frame pointer to bottom of fixed frame */
|
||||
|
||||
/* save function ptr, argv & nstacks */
|
||||
mv t0, a0 /* t0 = function ptr */
|
||||
mv t1, a1 /* t1 = argv array address */
|
||||
mv t2, a2 /* t2 = nstack */
|
||||
|
||||
/* fill in a0-7 integer-registers */
|
||||
lw a0, 0(t1) /* a0 = argv[0] */
|
||||
lw a1, 4(t1) /* a1 = argv[1] */
|
||||
lw a2, 8(t1) /* a2 = argv[2] */
|
||||
lw a3, 12(t1) /* a3 = argv[3] */
|
||||
lw a4, 16(t1) /* a4 = argv[4] */
|
||||
lw a5, 20(t1) /* a5 = argv[5] */
|
||||
lw a6, 24(t1) /* a6 = argv[6] */
|
||||
lw a7, 28(t1) /* a7 = argv[7] */
|
||||
|
||||
/* fill in fa0-7 float-registers*/
|
||||
fld fa0, 32(t1) /* fa0 = argv[8] */
|
||||
fld fa1, 40(t1) /* fa1 = argv[9] */
|
||||
fld fa2, 48(t1) /* fa2 = argv[10] */
|
||||
fld fa3, 56(t1) /* fa3 = argv[11] */
|
||||
fld fa4, 64(t1) /* fa4 = argv[12] */
|
||||
fld fa5, 72(t1) /* fa5 = argv[13] */
|
||||
fld fa6, 80(t1) /* fa6 = argv[14] */
|
||||
fld fa7, 88(t1) /* fa7 = argv[15] */
|
||||
|
||||
addi t1, t1, 96 /* t1 points to stack args */
|
||||
|
||||
/* directly call the function if no args in stack,
|
||||
x0 always holds 0 */
|
||||
beq t2, x0, call_func
|
||||
|
||||
/* reserve enough stack space for function arguments */
|
||||
sll t3, t2, 2 /* shift left 2 bits. t3 = n_stacks * 4 */
|
||||
sub sp, sp, t3
|
||||
|
||||
/* make 16-byte aligned */
|
||||
and sp, sp, ~15
|
||||
|
||||
/* save sp in t4 register */
|
||||
mv t4, sp
|
||||
|
||||
/* copy left arguments from caller stack to own frame stack */
|
||||
loop_stack_args:
|
||||
beq t2, x0, call_func
|
||||
lw t5, 0(t1) /* load stack argument, t5 = argv[i] */
|
||||
sw t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */
|
||||
addi t1, t1, 4 /* move to next stack argument */
|
||||
addi t4, t4, 4 /* move to next stack pointer */
|
||||
addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */
|
||||
j loop_stack_args
|
||||
|
||||
call_func:
|
||||
jalr t0
|
||||
|
||||
/* restore registers pushed in stack or saved in another register */
|
||||
return:
|
||||
mv sp, fp /* restore sp saved in fp before function call */
|
||||
lw fp, 0(sp) /* load previous frame poniter to fp register */
|
||||
lw ra, 4(sp) /* load previous return address to ra register */
|
||||
addi sp, sp, 8 /* pop frame, restore sp */
|
||||
jr ra
|
95
core/iwasm/common/arch/invokeNative_riscv64_lp64.s
Normal file
95
core/iwasm/common/arch/invokeNative_riscv64_lp64.s
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
.text
|
||||
.align 2
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
*
|
||||
* a0 function ptr
|
||||
* a1 argv
|
||||
* a2 nstacks
|
||||
*/
|
||||
|
||||
/*
|
||||
* sp (stack pointer)
|
||||
* |- sd to store 64-bit values from register to memory
|
||||
* |- ld to load from stack to register
|
||||
* fp/s0 (frame pointer)
|
||||
* a0-a7 (8 integer arguments)
|
||||
* |- sd to store
|
||||
* |- ld to load
|
||||
* t0-t6 (temporaries regisgers)
|
||||
* |- caller saved
|
||||
*/
|
||||
|
||||
/* reserve space on stack to save return address and frame pointer */
|
||||
addi sp, sp, -16
|
||||
sd fp, 0(sp) /* save frame pointer */
|
||||
sd ra, 8(sp) /* save return address */
|
||||
|
||||
mv fp, sp /* set frame pointer to bottom of fixed frame */
|
||||
|
||||
/* save function ptr, argv & nstacks */
|
||||
mv t0, a0 /* t0 = function ptr */
|
||||
mv t1, a1 /* t1 = argv array address */
|
||||
mv t2, a2 /* t2 = nstack */
|
||||
|
||||
/* fill in a0-7 integer-registers*/
|
||||
ld a0, 0(t1) /* a0 = argv[0] */
|
||||
ld a1, 8(t1) /* a1 = argv[1] */
|
||||
ld a2, 16(t1) /* a2 = argv[2] */
|
||||
ld a3, 24(t1) /* a3 = argv[3] */
|
||||
ld a4, 32(t1) /* a4 = argv[4] */
|
||||
ld a5, 40(t1) /* a5 = argv[5] */
|
||||
ld a6, 48(t1) /* a6 = argv[6] */
|
||||
ld a7, 56(t1) /* a7 = argv[7] */
|
||||
|
||||
addi t1, t1, 64 /* t1 points to stack args */
|
||||
|
||||
/* directly call the function if no args in stack,
|
||||
x0 always holds 0 */
|
||||
beq t2, x0, call_func
|
||||
|
||||
/* reserve enough stack space for function arguments */
|
||||
sll t3, t2, 3 /* shift left 3 bits. t3 = n_stacks * 8 */
|
||||
sub sp, sp, t3
|
||||
|
||||
/* make 16-byte aligned */
|
||||
and sp, sp, ~(15LL)
|
||||
|
||||
/* save sp in t4 register */
|
||||
mv t4, sp
|
||||
|
||||
/* copy left arguments from caller stack to own frame stack */
|
||||
loop_stack_args:
|
||||
beq t2, x0, call_func
|
||||
ld t5, 0(t1) /* load stack argument, t5 = argv[i] */
|
||||
sd t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */
|
||||
addi t1, t1, 8 /* move to next stack argument */
|
||||
addi t4, t4, 8 /* move to next stack pointer */
|
||||
addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */
|
||||
j loop_stack_args
|
||||
|
||||
call_func:
|
||||
jalr t0
|
||||
|
||||
/* restore registers pushed in stack or saved in another register */
|
||||
return:
|
||||
mv sp, fp /* restore sp saved in fp before function call */
|
||||
ld fp, 0(sp) /* load previous frame poniter to fp register */
|
||||
ld ra, 8(sp) /* load previous return address to ra register */
|
||||
addi sp, sp, 16 /* pop frame, restore sp */
|
||||
jr ra
|
||||
|
108
core/iwasm/common/arch/invokeNative_riscv64_lp64d.s
Normal file
108
core/iwasm/common/arch/invokeNative_riscv64_lp64d.s
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
.text
|
||||
.align 2
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
*
|
||||
* a0 function ptr
|
||||
* a1 argv
|
||||
* a2 nstacks
|
||||
*/
|
||||
|
||||
/*
|
||||
* sp (stack pointer)
|
||||
* |- sd to store 64-bit values from register to memory
|
||||
* |- ld to load from stack to register
|
||||
* fp/s0 (frame pointer)
|
||||
* a0-a7 (8 integer arguments)
|
||||
* |- sd to store
|
||||
* |- ld to load
|
||||
* fa0-a7 (8 float arguments)
|
||||
* |- fsd to store
|
||||
* |- fld to load
|
||||
* t0-t6 (temporaries regisgers)
|
||||
* |- caller saved
|
||||
*/
|
||||
|
||||
/* reserve space on stack to save return address and frame pointer */
|
||||
addi sp, sp, -16
|
||||
sd fp, 0(sp) /* save frame pointer */
|
||||
sd ra, 8(sp) /* save return address */
|
||||
|
||||
mv fp, sp /* set frame pointer to bottom of fixed frame */
|
||||
|
||||
/* save function ptr, argv & nstacks */
|
||||
mv t0, a0 /* t0 = function ptr */
|
||||
mv t1, a1 /* t1 = argv array address */
|
||||
mv t2, a2 /* t2 = nstack */
|
||||
|
||||
/* fill in fa0-7 float-registers*/
|
||||
fld fa0, 0(t1) /* fa0 = argv[0] */
|
||||
fld fa1, 8(t1) /* fa1 = argv[1] */
|
||||
fld fa2, 16(t1) /* fa2 = argv[2] */
|
||||
fld fa3, 24(t1) /* fa3 = argv[3] */
|
||||
fld fa4, 32(t1) /* fa4 = argv[4] */
|
||||
fld fa5, 40(t1) /* fa5 = argv[5] */
|
||||
fld fa6, 48(t1) /* fa6 = argv[6] */
|
||||
fld fa7, 56(t1) /* fa7 = argv[7] */
|
||||
|
||||
/* fill in a0-7 integer-registers*/
|
||||
ld a0, 64(t1) /* a0 = argv[8] */
|
||||
ld a1, 72(t1) /* a1 = argv[9] */
|
||||
ld a2, 80(t1) /* a2 = argv[10] */
|
||||
ld a3, 88(t1) /* a3 = argv[11] */
|
||||
ld a4, 96(t1) /* a4 = argv[12] */
|
||||
ld a5, 104(t1) /* a5 = argv[13] */
|
||||
ld a6, 112(t1) /* a6 = argv[14] */
|
||||
ld a7, 120(t1) /* a7 = argv[15] */
|
||||
|
||||
addi t1, t1, 128 /* t1 points to stack args */
|
||||
|
||||
/* directly call the function if no args in stack,
|
||||
x0 always holds 0 */
|
||||
beq t2, x0, call_func
|
||||
|
||||
/* reserve enough stack space for function arguments */
|
||||
sll t3, t2, 3 /* shift left 3 bits. t3 = n_stacks * 8 */
|
||||
sub sp, sp, t3
|
||||
|
||||
/* make 16-byte aligned */
|
||||
and sp, sp, ~(15LL)
|
||||
|
||||
/* save sp in t4 register */
|
||||
mv t4, sp
|
||||
|
||||
/* copy left arguments from caller stack to own frame stack */
|
||||
loop_stack_args:
|
||||
beq t2, x0, call_func
|
||||
ld t5, 0(t1) /* load stack argument, t5 = argv[i] */
|
||||
sd t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */
|
||||
addi t1, t1, 8 /* move to next stack argument */
|
||||
addi t4, t4, 8 /* move to next stack pointer */
|
||||
addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */
|
||||
j loop_stack_args
|
||||
|
||||
call_func:
|
||||
jalr t0
|
||||
|
||||
/* restore registers pushed in stack or saved in another register */
|
||||
return:
|
||||
mv sp, fp /* restore sp saved in fp before function call */
|
||||
ld fp, 0(sp) /* load previous frame poniter to fp register */
|
||||
ld ra, 8(sp) /* load previous return address to ra register */
|
||||
addi sp, sp, 16 /* pop frame, restore sp */
|
||||
jr ra
|
||||
|
||||
|
|
@ -4,8 +4,14 @@
|
|||
*/
|
||||
.text
|
||||
.align 2
|
||||
.global invokeNative
|
||||
.type invokeNative,function
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
|
@ -15,7 +21,6 @@
|
|||
* r2 argc
|
||||
*/
|
||||
|
||||
invokeNative:
|
||||
push {r4, r5, r6, r7}
|
||||
push {lr}
|
||||
mov ip, r0 /* ip = function ptr */
|
||||
|
|
|
@ -4,8 +4,14 @@
|
|||
*/
|
||||
.text
|
||||
.align 2
|
||||
.global invokeNative
|
||||
.type invokeNative,function
|
||||
#ifndef BH_PLATFORM_DARWIN
|
||||
.globl invokeNative
|
||||
.type invokeNative, function
|
||||
invokeNative:
|
||||
#else
|
||||
.globl _invokeNative
|
||||
_invokeNative:
|
||||
#endif /* end of BH_PLATFORM_DARWIN */
|
||||
|
||||
/*
|
||||
* Arguments passed in:
|
||||
|
@ -15,7 +21,6 @@
|
|||
* r2 nstacks
|
||||
*/
|
||||
|
||||
invokeNative:
|
||||
push {r4, r5, r6, r7}
|
||||
push {lr}
|
||||
mov ip, r0 /* ip = function ptr */
|
||||
|
|
|
@ -10,10 +10,40 @@ add_definitions(-DBH_FREE=wasm_runtime_free)
|
|||
|
||||
file (GLOB c_source_all ${IWASM_COMMON_DIR}/*.c)
|
||||
|
||||
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s)
|
||||
if (WAMR_DISABLE_APP_ENTRY EQUAL 1)
|
||||
list(REMOVE_ITEM c_source_all "${IWASM_COMMON_DIR}/wasm_application.c")
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_INVOKE_NATIVE_GENERAL EQUAL 1)
|
||||
# Use invokeNative C version instead of asm code version
|
||||
# if WAMR_BUILD_INVOKE_NATIVE_GENERAL is explicitly set.
|
||||
# Note:
|
||||
# the maximum number of native arguments is limited to 20,
|
||||
# and there are possible issues when passing arguments to
|
||||
# native function for some cpus, e.g. int64 and double arguments
|
||||
# in arm and mips need to be 8-bytes aligned, and some arguments
|
||||
# of x86_64 are passed by registers but not stack
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_general.c)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
|
||||
if (NOT WAMR_BUILD_SIMD EQUAL 1)
|
||||
if (WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.asm)
|
||||
else ()
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s)
|
||||
endif ()
|
||||
else ()
|
||||
if (WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64_simd.asm)
|
||||
else()
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64_simd.s)
|
||||
endif()
|
||||
endif ()
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "X86_32")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s)
|
||||
if (WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.asm)
|
||||
else ()
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s)
|
||||
endif ()
|
||||
elseif (WAMR_BUILD_TARGET MATCHES "ARM.*")
|
||||
if (WAMR_BUILD_TARGET MATCHES "ARM.*_VFP")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm_vfp.s)
|
||||
|
@ -27,19 +57,23 @@ elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
|
|||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb.s)
|
||||
endif ()
|
||||
elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s)
|
||||
if (NOT WAMR_BUILD_SIMD EQUAL 1)
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s)
|
||||
else()
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64_simd.s)
|
||||
endif()
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_xtensa.s)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "GENERAL")
|
||||
# Use invokeNative_general.c instead of assembly code,
|
||||
# but the maximum number of native arguments is limited to 20,
|
||||
# and there are possible issues when passing arguments to
|
||||
# native function for some cpus, e.g. int64 and double arguments
|
||||
# in arm and mips need to be 8-bytes aligned, and some arguments
|
||||
# of x86_64 are passed by registers but not stack
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_general.c)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64" OR WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64D")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv64_lp64d.s)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv64_lp64.s)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32D")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv32_ilp32d.s)
|
||||
elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32")
|
||||
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv32_ilp32.s)
|
||||
else ()
|
||||
message (FATAL_ERROR "Build target isn't set")
|
||||
endif ()
|
||||
|
|
676
core/iwasm/common/wasm_application.c
Normal file
676
core/iwasm/common/wasm_application.c
Normal file
|
@ -0,0 +1,676 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "bh_platform.h"
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
#include "../aot/aot_runtime.h"
|
||||
#endif
|
||||
|
||||
static void
|
||||
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
||||
{
|
||||
if (error_buf != NULL)
|
||||
snprintf(error_buf, error_buf_size, "%s", string);
|
||||
}
|
||||
|
||||
static void *
|
||||
runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
if (size >= UINT32_MAX
|
||||
|| !(mem = wasm_runtime_malloc((uint32)size))) {
|
||||
if (module_inst != NULL) {
|
||||
wasm_runtime_set_exception(module_inst,
|
||||
"allocate memory failed");
|
||||
}
|
||||
else if (error_buf != NULL) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"allocate memory failed");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(mem, 0, (uint32)size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
static union {
|
||||
int a;
|
||||
char b;
|
||||
} __ue = { .a = 1 };
|
||||
|
||||
#define is_little_endian() (__ue.b == 1)
|
||||
|
||||
/**
|
||||
* Implementation of wasm_application_execute_main()
|
||||
*/
|
||||
|
||||
static WASMFunctionInstanceCommon*
|
||||
resolve_function(const WASMModuleInstanceCommon *module_inst,
|
||||
const char *name);
|
||||
|
||||
static bool
|
||||
check_main_func_type(const WASMType *type)
|
||||
{
|
||||
if (!(type->param_count == 0 || type->param_count == 2)
|
||||
||type->result_count > 1) {
|
||||
LOG_ERROR("WASM execute application failed: invalid main function type.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type->param_count == 2
|
||||
&& !(type->types[0] == VALUE_TYPE_I32
|
||||
&& type->types[1] == VALUE_TYPE_I32)) {
|
||||
LOG_ERROR("WASM execute application failed: invalid main function type.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type->result_count
|
||||
&& type->types[type->param_count] != VALUE_TYPE_I32) {
|
||||
LOG_ERROR("WASM execute application failed: invalid main function type.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_application_execute_main(WASMModuleInstanceCommon *module_inst,
|
||||
int32 argc, char *argv[])
|
||||
{
|
||||
WASMFunctionInstanceCommon *func;
|
||||
WASMType *func_type = NULL;
|
||||
uint32 argc1 = 0, argv1[2] = { 0 };
|
||||
uint32 total_argv_size = 0;
|
||||
uint64 total_size;
|
||||
uint32 argv_buf_offset = 0;
|
||||
int32 i;
|
||||
char *argv_buf, *p, *p_end;
|
||||
uint32 *argv_offsets, module_type;
|
||||
bool ret, is_import_func = true;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
if (wasm_runtime_is_wasi_mode(module_inst)) {
|
||||
/* In wasi mode, we should call function named "_start"
|
||||
which initializes the wasi envrionment and then calls
|
||||
the actual main function. Directly call main function
|
||||
may cause exception thrown. */
|
||||
if ((func = wasm_runtime_lookup_wasi_start_function(module_inst)))
|
||||
return wasm_runtime_create_exec_env_and_call_wasm(
|
||||
module_inst, func, 0, NULL);
|
||||
/* if no start function is found, we execute
|
||||
the main function as normal */
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LIBC_WASI */
|
||||
|
||||
if (!(func = resolve_function(module_inst, "main"))
|
||||
&& !(func = resolve_function(module_inst, "__main_argc_argv"))
|
||||
&& !(func = resolve_function(module_inst, "_main"))) {
|
||||
wasm_runtime_set_exception(module_inst,
|
||||
"lookup main function failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
is_import_func = ((WASMFunctionInstance*)func)->is_import_func;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
is_import_func = ((AOTFunctionInstance*)func)->is_import_func;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is_import_func) {
|
||||
wasm_runtime_set_exception(module_inst,
|
||||
"lookup main function failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
module_type = module_inst->module_type;
|
||||
func_type = wasm_runtime_get_function_type(func, module_type);
|
||||
|
||||
if (!func_type) {
|
||||
LOG_ERROR("invalid module instance type");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_main_func_type(func_type)) {
|
||||
wasm_runtime_set_exception(module_inst,
|
||||
"invalid function type of main function");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (func_type->param_count) {
|
||||
for (i = 0; i < argc; i++)
|
||||
total_argv_size += (uint32)(strlen(argv[i]) + 1);
|
||||
total_argv_size = align_uint(total_argv_size, 4);
|
||||
|
||||
total_size = (uint64)total_argv_size + sizeof(int32) * (uint64)argc;
|
||||
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(argv_buf_offset =
|
||||
wasm_runtime_module_malloc(module_inst, (uint32)total_size,
|
||||
(void**)&argv_buf))) {
|
||||
wasm_runtime_set_exception(module_inst,
|
||||
"allocate memory failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
p = argv_buf;
|
||||
argv_offsets = (uint32*)(p + total_argv_size);
|
||||
p_end = p + total_size;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
bh_memcpy_s(p, (uint32)(p_end - p), argv[i], (uint32)(strlen(argv[i]) + 1));
|
||||
argv_offsets[i] = argv_buf_offset + (uint32)(p - argv_buf);
|
||||
p += strlen(argv[i]) + 1;
|
||||
}
|
||||
|
||||
argc1 = 2;
|
||||
argv1[0] = (uint32)argc;
|
||||
argv1[1] = (uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets);
|
||||
}
|
||||
|
||||
ret = wasm_runtime_create_exec_env_and_call_wasm(module_inst, func,
|
||||
argc1, argv1);
|
||||
if (ret && func_type->result_count > 0 && argc > 0 && argv)
|
||||
/* copy the return value */
|
||||
*(int*)argv = (int)argv1[0];
|
||||
|
||||
if (argv_buf_offset)
|
||||
wasm_runtime_module_free(module_inst, argv_buf_offset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
static WASMModuleInstance *
|
||||
get_sub_module_inst(const WASMModuleInstance *parent_module_inst,
|
||||
const char *sub_module_name)
|
||||
{
|
||||
WASMSubModInstNode *node =
|
||||
bh_list_first_elem(parent_module_inst->sub_module_inst_list);
|
||||
|
||||
while (node && strcmp(node->module_name, sub_module_name)) {
|
||||
node = bh_list_elem_next(node);
|
||||
}
|
||||
return node ? node->module_inst : NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_function_name(char *orig_function_name, char **p_module_name,
|
||||
char **p_function_name)
|
||||
{
|
||||
if (orig_function_name[0] != '$') {
|
||||
*p_module_name = NULL;
|
||||
*p_function_name = orig_function_name;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* $module_name$function_name\0
|
||||
* ===>
|
||||
* module_name\0function_name\0
|
||||
* ===>
|
||||
* module_name
|
||||
* function_name
|
||||
*/
|
||||
char *p1 = orig_function_name;
|
||||
char *p2 = strchr(p1 + 1, '$');
|
||||
if (!p2) {
|
||||
LOG_DEBUG("can not parse the incoming function name");
|
||||
return false;
|
||||
}
|
||||
|
||||
*p_module_name = p1 + 1;
|
||||
*p2 = '\0';
|
||||
*p_function_name = p2 + 1;
|
||||
return strlen(*p_module_name) && strlen(*p_function_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Implementation of wasm_application_execute_func()
|
||||
*/
|
||||
|
||||
static WASMFunctionInstanceCommon*
|
||||
resolve_function(const WASMModuleInstanceCommon *module_inst,
|
||||
const char *name)
|
||||
{
|
||||
uint32 i = 0;
|
||||
WASMFunctionInstanceCommon *ret = NULL;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMModuleInstance *sub_module_inst = NULL;
|
||||
char *orig_name = NULL;
|
||||
char *sub_module_name = NULL;
|
||||
char *function_name = NULL;
|
||||
uint32 length = (uint32)(strlen(name) + 1);
|
||||
|
||||
orig_name = runtime_malloc(sizeof(char) * length, NULL, NULL, 0);
|
||||
if (!orig_name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(orig_name, name, length);
|
||||
|
||||
if (!parse_function_name(orig_name, &sub_module_name, &function_name)) {
|
||||
goto LEAVE;
|
||||
}
|
||||
|
||||
LOG_DEBUG("%s -> %s and %s", name, sub_module_name, function_name);
|
||||
|
||||
if (sub_module_name) {
|
||||
sub_module_inst = get_sub_module_inst(
|
||||
(WASMModuleInstance *)module_inst, sub_module_name);
|
||||
if (!sub_module_inst) {
|
||||
LOG_DEBUG("can not find a sub module named %s", sub_module_name);
|
||||
goto LEAVE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
const char *function_name = name;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstance *wasm_inst = (WASMModuleInstance*)module_inst;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
wasm_inst = sub_module_inst ? sub_module_inst : wasm_inst;
|
||||
#endif /* WASM_ENABLE_MULTI_MODULE */
|
||||
|
||||
for (i = 0; i < wasm_inst->export_func_count; i++) {
|
||||
if (!strcmp(wasm_inst->export_functions[i].name, function_name)) {
|
||||
ret = wasm_inst->export_functions[i].function;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WASM_ENABLE_INTERP */
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *aot_inst = (AOTModuleInstance*)module_inst;
|
||||
AOTFunctionInstance *export_funcs = (AOTFunctionInstance *)
|
||||
aot_inst->export_funcs.ptr;
|
||||
for (i = 0; i < aot_inst->export_func_count; i++) {
|
||||
if (!strcmp(export_funcs[i].func_name, function_name)) {
|
||||
ret = &export_funcs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
LEAVE:
|
||||
wasm_runtime_free(orig_name);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
union ieee754_float {
|
||||
float f;
|
||||
|
||||
/* This is the IEEE 754 single-precision format. */
|
||||
union {
|
||||
struct {
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:8;
|
||||
unsigned int mantissa:23;
|
||||
} ieee_big_endian;
|
||||
struct {
|
||||
unsigned int mantissa:23;
|
||||
unsigned int exponent:8;
|
||||
unsigned int negative:1;
|
||||
} ieee_little_endian;
|
||||
} ieee;
|
||||
};
|
||||
|
||||
union ieee754_double {
|
||||
double d;
|
||||
|
||||
/* This is the IEEE 754 double-precision format. */
|
||||
union {
|
||||
struct {
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:11;
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int mantissa1:32;
|
||||
} ieee_big_endian;
|
||||
|
||||
struct {
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
} ieee_little_endian;
|
||||
} ieee;
|
||||
};
|
||||
|
||||
bool
|
||||
wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||
const char *name, int32 argc, char *argv[])
|
||||
{
|
||||
WASMFunctionInstanceCommon *func;
|
||||
WASMType *type = NULL;
|
||||
uint32 argc1, *argv1 = NULL, cell_num = 0, j, k = 0;
|
||||
int32 i, p, module_type;
|
||||
uint64 total_size;
|
||||
const char *exception;
|
||||
char buf[128];
|
||||
|
||||
bh_assert(argc >= 0);
|
||||
LOG_DEBUG("call a function \"%s\" with %d arguments", name, argc);
|
||||
func = resolve_function(module_inst, name);
|
||||
|
||||
if (!func) {
|
||||
snprintf(buf, sizeof(buf), "lookup function %s failed", name);
|
||||
wasm_runtime_set_exception(module_inst, buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMFunctionInstance *wasm_func = (WASMFunctionInstance*)func;
|
||||
if (wasm_func->is_import_func
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
&& !wasm_func->import_func_inst
|
||||
#endif
|
||||
) {
|
||||
snprintf(buf, sizeof(buf), "lookup function %s failed", name);
|
||||
wasm_runtime_set_exception(module_inst, buf);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
module_type = module_inst->module_type;
|
||||
type = wasm_runtime_get_function_type(func, module_type);
|
||||
|
||||
if (!type) {
|
||||
LOG_ERROR("invalid module instance type");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type->param_count != (uint32)argc) {
|
||||
wasm_runtime_set_exception(module_inst,
|
||||
"invalid input argument count");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
argc1 = type->param_cell_num;
|
||||
cell_num = (argc1 > type->ret_cell_num) ? argc1 : type->ret_cell_num;
|
||||
|
||||
total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2);
|
||||
if ((!(argv1 = runtime_malloc((uint32)total_size, module_inst,
|
||||
NULL, 0)))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Parse arguments */
|
||||
for (i = 0, p = 0; i < argc; i++) {
|
||||
char *endptr = NULL;
|
||||
bh_assert(argv[i] != NULL);
|
||||
if (argv[i][0] == '\0') {
|
||||
snprintf(buf, sizeof(buf), "invalid input argument %d", i);
|
||||
wasm_runtime_set_exception(module_inst, buf);
|
||||
goto fail;
|
||||
}
|
||||
switch (type->types[i]) {
|
||||
case VALUE_TYPE_I32:
|
||||
argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
{
|
||||
union { uint64 val; uint32 parts[2]; } u;
|
||||
u.val = strtoull(argv[i], &endptr, 0);
|
||||
argv1[p++] = u.parts[0];
|
||||
argv1[p++] = u.parts[1];
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F32:
|
||||
{
|
||||
float32 f32 = strtof(argv[i], &endptr);
|
||||
if (isnan(f32)) {
|
||||
if (argv[i][0] == '-') {
|
||||
union ieee754_float u;
|
||||
u.f = f32;
|
||||
if (is_little_endian())
|
||||
u.ieee.ieee_little_endian.negative = 1;
|
||||
else
|
||||
u.ieee.ieee_big_endian.negative = 1;
|
||||
memcpy(&f32, &u.f, sizeof(float));
|
||||
}
|
||||
if (endptr[0] == ':') {
|
||||
uint32 sig;
|
||||
union ieee754_float u;
|
||||
sig = (uint32)strtoul(endptr + 1, &endptr, 0);
|
||||
u.f = f32;
|
||||
if (is_little_endian())
|
||||
u.ieee.ieee_little_endian.mantissa = sig;
|
||||
else
|
||||
u.ieee.ieee_big_endian.mantissa = sig;
|
||||
memcpy(&f32, &u.f, sizeof(float));
|
||||
}
|
||||
}
|
||||
memcpy(&argv1[p++], &f32, sizeof(float));
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F64:
|
||||
{
|
||||
union { float64 val; uint32 parts[2]; } u;
|
||||
u.val = strtod(argv[i], &endptr);
|
||||
if (isnan(u.val)) {
|
||||
if (argv[i][0] == '-') {
|
||||
union ieee754_double ud;
|
||||
ud.d = u.val;
|
||||
if (is_little_endian())
|
||||
ud.ieee.ieee_little_endian.negative = 1;
|
||||
else
|
||||
ud.ieee.ieee_big_endian.negative = 1;
|
||||
memcpy(&u.val, &ud.d, sizeof(double));
|
||||
}
|
||||
if (endptr[0] == ':') {
|
||||
uint64 sig;
|
||||
union ieee754_double ud;
|
||||
sig = strtoull(endptr + 1, &endptr, 0);
|
||||
ud.d = u.val;
|
||||
if (is_little_endian()) {
|
||||
ud.ieee.ieee_little_endian.mantissa0 = sig >> 32;
|
||||
ud.ieee.ieee_little_endian.mantissa1 = (uint32)sig;
|
||||
}
|
||||
else {
|
||||
ud.ieee.ieee_big_endian.mantissa0 = sig >> 32;
|
||||
ud.ieee.ieee_big_endian.mantissa1 = (uint32)sig;
|
||||
}
|
||||
memcpy(&u.val, &ud.d, sizeof(double));
|
||||
}
|
||||
}
|
||||
argv1[p++] = u.parts[0];
|
||||
argv1[p++] = u.parts[1];
|
||||
break;
|
||||
}
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
case VALUE_TYPE_V128:
|
||||
{
|
||||
/* it likes 0x123\0x234 or 123\234 */
|
||||
/* retrive first i64 */
|
||||
*(uint64*)(argv1 + p) = strtoull(argv[i], &endptr, 0);
|
||||
/* skip \ */
|
||||
endptr++;
|
||||
/* retrive second i64 */
|
||||
*(uint64*)(argv1 + p + 2) = strtoull(endptr, &endptr, 0);
|
||||
p += 4;
|
||||
break;
|
||||
}
|
||||
#endif /* WASM_ENABLE_SIMD != 0 */
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
{
|
||||
if (strncmp(argv[i], "null", 4) == 0
|
||||
|| strncmp(argv[i], "NULL", 4) == 0) {
|
||||
argv1[p++] = NULL_REF;
|
||||
}
|
||||
else {
|
||||
argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
{
|
||||
if (strncmp(argv[i], "null", 4) == 0
|
||||
|| strncmp(argv[i], "NULL", 4) == 0) {
|
||||
argv1[p++] = NULL_REF;
|
||||
}
|
||||
else {
|
||||
uint64 val = strtoull(argv[i], &endptr, 0);
|
||||
void *extern_obj = (void *)(uintptr_t)val;
|
||||
uint32 externref_idx;
|
||||
|
||||
if (!wasm_externref_obj2ref(module_inst, extern_obj,
|
||||
&externref_idx)) {
|
||||
wasm_runtime_set_exception(
|
||||
module_inst, "map extern object to ref failed");
|
||||
goto fail;
|
||||
}
|
||||
argv1[p++] = externref_idx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* WASM_ENABLE_REF_TYPES */
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
if (endptr && *endptr != '\0' && *endptr != '_') {
|
||||
snprintf(buf, sizeof(buf), "invalid input argument %d: %s",
|
||||
i, argv[i]);
|
||||
wasm_runtime_set_exception(module_inst, buf);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
bh_assert(p == (int32)argc1);
|
||||
|
||||
wasm_runtime_set_exception(module_inst, NULL);
|
||||
if (!wasm_runtime_create_exec_env_and_call_wasm(module_inst, func,
|
||||
argc1, argv1)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* print return value */
|
||||
for (j = 0; j < type->result_count; j++) {
|
||||
switch (type->types[type->param_count + j]) {
|
||||
case VALUE_TYPE_I32:
|
||||
{
|
||||
os_printf("0x%x:i32", argv1[k]);
|
||||
k++;
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_I64:
|
||||
{
|
||||
union { uint64 val; uint32 parts[2]; } u;
|
||||
u.parts[0] = argv1[k];
|
||||
u.parts[1] = argv1[k + 1];
|
||||
k += 2;
|
||||
#ifdef PRIx64
|
||||
os_printf("0x%"PRIx64":i64", u.val);
|
||||
#else
|
||||
char buf[16];
|
||||
if (sizeof(long) == 4)
|
||||
snprintf(buf, sizeof(buf), "%s", "0x%llx:i64");
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%s", "0x%lx:i64");
|
||||
os_printf(buf, u.val);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F32:
|
||||
{
|
||||
os_printf("%.7g:f32", *(float32*)(argv1 + k));
|
||||
k++;
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_F64:
|
||||
{
|
||||
union { float64 val; uint32 parts[2]; } u;
|
||||
u.parts[0] = argv1[k];
|
||||
u.parts[1] = argv1[k + 1];
|
||||
k += 2;
|
||||
os_printf("%.7g:f64", u.val);
|
||||
break;
|
||||
}
|
||||
#if WASM_ENABLE_REF_TYPES
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
{
|
||||
if (argv1[k] != NULL_REF)
|
||||
os_printf("%u:ref.func", argv1[k]);
|
||||
else
|
||||
os_printf("func:ref.null");
|
||||
k++;
|
||||
break;
|
||||
}
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
{
|
||||
if (argv1[k] != NULL_REF) {
|
||||
void *extern_obj = NULL;
|
||||
bool ret = wasm_externref_ref2obj(argv1[k], &extern_obj);
|
||||
bh_assert(ret);
|
||||
(void)ret;
|
||||
os_printf("%p:ref.extern", extern_obj);
|
||||
}
|
||||
else
|
||||
os_printf("extern:ref.null");
|
||||
k++;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
case VALUE_TYPE_V128:
|
||||
{
|
||||
uint64 *v = (uint64*)(argv1 + k);
|
||||
#if defined(PRIx64)
|
||||
os_printf("<0x%016"PRIx64" 0x%016"PRIx64">:v128", *v, *(v + 1));
|
||||
#else
|
||||
if (4 == sizeof(long)) {
|
||||
os_printf("<0x%016llx 0x%016llx>:v128", *v, *(v + 1));
|
||||
}
|
||||
else {
|
||||
os_printf("<0x%016lx 0x%016lx>:v128", *v, *(v + 1));
|
||||
}
|
||||
#endif /* PRIx64 */
|
||||
k += 4;
|
||||
break;
|
||||
}
|
||||
#endif /* WASM_ENABLE_SIMD != 0 */
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
if (j < (uint32)(type->result_count - 1))
|
||||
os_printf(",");
|
||||
}
|
||||
os_printf("\n");
|
||||
|
||||
wasm_runtime_free(argv1);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
if (argv1)
|
||||
wasm_runtime_free(argv1);
|
||||
|
||||
exception = wasm_runtime_get_exception(module_inst);
|
||||
bh_assert(exception);
|
||||
os_printf("%s\n", exception);
|
||||
return false;
|
||||
}
|
3784
core/iwasm/common/wasm_c_api.c
Normal file
3784
core/iwasm/common/wasm_c_api.c
Normal file
File diff suppressed because it is too large
Load Diff
174
core/iwasm/common/wasm_c_api_internal.h
Normal file
174
core/iwasm/common/wasm_c_api_internal.h
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _WASM_C_API_INTERNAL_H
|
||||
#define _WASM_C_API_INTERNAL_H
|
||||
|
||||
#include "wasm_c_api.h"
|
||||
#include "wasm_runtime_common.h"
|
||||
|
||||
#ifndef own
|
||||
#define own
|
||||
#endif
|
||||
|
||||
/* Vectors */
|
||||
/* we will malloc resource for the vector's data field */
|
||||
/* we will release resource of data */
|
||||
/* caller needs to take care resource for the vector itself */
|
||||
#define DEFAULT_VECTOR_INIT_LENGTH (64)
|
||||
|
||||
WASM_DECLARE_VEC(store, *)
|
||||
WASM_DECLARE_VEC(module, *)
|
||||
WASM_DECLARE_VEC(instance, *)
|
||||
|
||||
/* Runtime Environment */
|
||||
struct wasm_engine_t {
|
||||
/* support one store for now */
|
||||
wasm_store_vec_t *stores;
|
||||
};
|
||||
|
||||
struct wasm_store_t {
|
||||
wasm_module_vec_t *modules;
|
||||
wasm_instance_vec_t *instances;
|
||||
};
|
||||
|
||||
/* Type Representations */
|
||||
struct wasm_valtype_t {
|
||||
wasm_valkind_t kind;
|
||||
};
|
||||
|
||||
struct wasm_functype_t {
|
||||
uint32 extern_kind;
|
||||
/* gona to new and delete own */
|
||||
wasm_valtype_vec_t *params;
|
||||
wasm_valtype_vec_t *results;
|
||||
};
|
||||
|
||||
struct wasm_globaltype_t {
|
||||
uint32 extern_kind;
|
||||
/* gona to new and delete own */
|
||||
wasm_valtype_t *val_type;
|
||||
wasm_mutability_t mutability;
|
||||
};
|
||||
|
||||
struct wasm_tabletype_t {
|
||||
uint32 extern_kind;
|
||||
/* always be WASM_FUNCREF */
|
||||
wasm_valtype_t *val_type;
|
||||
wasm_limits_t limits;
|
||||
};
|
||||
|
||||
struct wasm_memorytype_t {
|
||||
uint32 extern_kind;
|
||||
wasm_limits_t limits;
|
||||
};
|
||||
|
||||
struct wasm_externtype_t {
|
||||
uint32 extern_kind;
|
||||
uint8 data[1];
|
||||
};
|
||||
|
||||
struct wasm_importtype_t {
|
||||
wasm_name_t *module_name;
|
||||
wasm_name_t *name;
|
||||
wasm_externtype_t *extern_type;
|
||||
};
|
||||
|
||||
struct wasm_exporttype_t {
|
||||
wasm_name_t *name;
|
||||
wasm_externtype_t *extern_type;
|
||||
};
|
||||
|
||||
/* Runtime Objects */
|
||||
struct wasm_ref_t {
|
||||
uint32 obj;
|
||||
};
|
||||
|
||||
struct wasm_trap_t {
|
||||
wasm_byte_vec_t *message;
|
||||
};
|
||||
|
||||
struct wasm_func_t {
|
||||
wasm_name_t *module_name;
|
||||
wasm_name_t *name;
|
||||
uint16 kind;
|
||||
|
||||
wasm_functype_t *type;
|
||||
|
||||
bool with_env;
|
||||
union {
|
||||
wasm_func_callback_t cb;
|
||||
struct callback_ext {
|
||||
void *env;
|
||||
wasm_func_callback_with_env_t cb;
|
||||
void (*finalizer)(void *);
|
||||
} cb_env;
|
||||
} u;
|
||||
/*
|
||||
* an index in both functions runtime instance lists
|
||||
* of interpreter mode and aot mode
|
||||
*/
|
||||
uint16 func_idx_rt;
|
||||
WASMModuleInstanceCommon *inst_comm_rt;
|
||||
WASMFunctionInstanceCommon *func_comm_rt;
|
||||
};
|
||||
|
||||
struct wasm_global_t {
|
||||
wasm_name_t *module_name;
|
||||
wasm_name_t *name;
|
||||
uint16 kind;
|
||||
|
||||
wasm_globaltype_t *type;
|
||||
wasm_val_t *init;
|
||||
/*
|
||||
* an index in both global runtime instance lists
|
||||
* of interpreter mode and aot mode
|
||||
*/
|
||||
uint16 global_idx_rt;
|
||||
WASMModuleInstanceCommon *inst_comm_rt;
|
||||
};
|
||||
|
||||
struct wasm_memory_t {
|
||||
wasm_name_t *module_name;
|
||||
wasm_name_t *name;
|
||||
uint16 kind;
|
||||
|
||||
wasm_memorytype_t *type;
|
||||
/*
|
||||
* an index in both memory runtime instance lists
|
||||
* of interpreter mode and aot mode
|
||||
*/
|
||||
uint16 memory_idx_rt;
|
||||
WASMModuleInstanceCommon *inst_comm_rt;
|
||||
};
|
||||
|
||||
struct wasm_table_t {
|
||||
wasm_name_t *module_name;
|
||||
wasm_name_t *name;
|
||||
uint16 kind;
|
||||
|
||||
wasm_tabletype_t *type;
|
||||
/*
|
||||
* an index in both table runtime instance lists
|
||||
* of interpreter mode and aot mode
|
||||
*/
|
||||
uint16 table_idx_rt;
|
||||
WASMModuleInstanceCommon *inst_comm_rt;
|
||||
};
|
||||
|
||||
struct wasm_extern_t {
|
||||
wasm_name_t *module_name;
|
||||
wasm_name_t *name;
|
||||
wasm_externkind_t kind;
|
||||
uint8 data[1];
|
||||
};
|
||||
|
||||
struct wasm_instance_t {
|
||||
wasm_extern_vec_t *imports;
|
||||
wasm_extern_vec_t *exports;
|
||||
WASMModuleInstanceCommon *inst_comm_rt;
|
||||
};
|
||||
|
||||
#endif /* _WASM_C_API_INTERNAL_H */
|
|
@ -5,10 +5,20 @@
|
|||
|
||||
#include "wasm_exec_env.h"
|
||||
#include "wasm_runtime_common.h"
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
#include "../aot/aot_runtime.h"
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
#include "../libraries/thread-mgr/thread_manager.h"
|
||||
#endif
|
||||
|
||||
WASMExecEnv *
|
||||
wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size)
|
||||
wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size)
|
||||
{
|
||||
uint64 total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom)
|
||||
+ (uint64)stack_size;
|
||||
|
@ -22,26 +32,109 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
|
|||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (!(exec_env->argv_buf = wasm_runtime_malloc(sizeof(uint32) * 64))) {
|
||||
wasm_runtime_free(exec_env);
|
||||
return NULL;
|
||||
goto fail1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
if (os_mutex_init(&exec_env->wait_lock) != 0)
|
||||
goto fail2;
|
||||
|
||||
if (os_cond_init(&exec_env->wait_cond) != 0)
|
||||
goto fail3;
|
||||
#endif
|
||||
|
||||
exec_env->module_inst = module_inst;
|
||||
exec_env->wasm_stack_size = stack_size;
|
||||
exec_env->wasm_stack.s.top_boundary =
|
||||
exec_env->wasm_stack.s.bottom + stack_size;
|
||||
exec_env->wasm_stack.s.top = exec_env->wasm_stack.s.bottom;
|
||||
|
||||
#if WASM_ENABLE_MEMORY_TRACING != 0
|
||||
wasm_runtime_dump_exec_env_mem_consumption(exec_env);
|
||||
#endif
|
||||
return exec_env;
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
fail3:
|
||||
os_mutex_destroy(&exec_env->wait_lock);
|
||||
fail2:
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
wasm_runtime_free(exec_env->argv_buf);
|
||||
fail1:
|
||||
#endif
|
||||
wasm_runtime_free(exec_env);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_exec_env_destroy_internal(WASMExecEnv *exec_env)
|
||||
{
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
os_mutex_destroy(&exec_env->wait_lock);
|
||||
os_cond_destroy(&exec_env->wait_cond);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
wasm_runtime_free(exec_env->argv_buf);
|
||||
#endif
|
||||
wasm_runtime_free(exec_env);
|
||||
}
|
||||
|
||||
WASMExecEnv *
|
||||
wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size)
|
||||
{
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
WASMCluster *cluster;
|
||||
#endif
|
||||
WASMExecEnv *exec_env =
|
||||
wasm_exec_env_create_internal(module_inst, stack_size);
|
||||
|
||||
if (!exec_env)
|
||||
return NULL;
|
||||
|
||||
/* Set the aux_stack_boundary and aux_stack_bottom */
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModule *module = ((WASMModuleInstance *)module_inst)->module;
|
||||
exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom;
|
||||
exec_env->aux_stack_boundary.boundary = module->aux_stack_bottom
|
||||
- module->aux_stack_size;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModule *module =
|
||||
(AOTModule *)(((AOTModuleInstance *)module_inst)->aot_module.ptr);
|
||||
exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom;
|
||||
exec_env->aux_stack_boundary.boundary = module->aux_stack_bottom
|
||||
- module->aux_stack_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
/* Create a new cluster for this exec_env */
|
||||
if (!(cluster = wasm_cluster_create(exec_env))) {
|
||||
wasm_exec_env_destroy_internal(exec_env);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return exec_env;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_exec_env_destroy(WASMExecEnv *exec_env)
|
||||
{
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
wasm_runtime_free(exec_env->argv_buf);
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
/* Terminate all sub-threads */
|
||||
WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
|
||||
if (cluster) {
|
||||
wasm_cluster_terminate_all_except_self(cluster, exec_env);
|
||||
wasm_cluster_del_exec_env(cluster, exec_env);
|
||||
}
|
||||
#endif
|
||||
wasm_runtime_free(exec_env);
|
||||
wasm_exec_env_destroy_internal(exec_env);
|
||||
}
|
||||
|
||||
WASMModuleInstanceCommon *
|
||||
|
@ -50,3 +143,47 @@ wasm_exec_env_get_module_inst(WASMExecEnv *exec_env)
|
|||
return exec_env->module_inst;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
|
||||
{
|
||||
exec_env->handle = os_self_thread();
|
||||
exec_env->native_stack_boundary = os_thread_get_stack_boundary()
|
||||
+ RESERVED_BYTES_TO_NATIVE_STACK_BOUNDARY;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
void *
|
||||
wasm_exec_env_get_thread_arg(WASMExecEnv *exec_env)
|
||||
{
|
||||
return exec_env->thread_arg;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg)
|
||||
{
|
||||
exec_env->thread_arg = thread_arg;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
void
|
||||
wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf)
|
||||
{
|
||||
jmpbuf->prev = exec_env->jmpbuf_stack_top;
|
||||
exec_env->jmpbuf_stack_top = jmpbuf;
|
||||
}
|
||||
|
||||
WASMJmpBuf *
|
||||
wasm_exec_env_pop_jmpbuf(WASMExecEnv *exec_env)
|
||||
{
|
||||
WASMJmpBuf *stack_top = exec_env->jmpbuf_stack_top;
|
||||
|
||||
if (stack_top) {
|
||||
exec_env->jmpbuf_stack_top = stack_top->prev;
|
||||
return stack_top;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -18,14 +18,30 @@ extern "C" {
|
|||
struct WASMModuleInstanceCommon;
|
||||
struct WASMInterpFrame;
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
typedef struct WASMCluster WASMCluster;
|
||||
#endif
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
typedef struct WASMJmpBuf {
|
||||
struct WASMJmpBuf *prev;
|
||||
korp_jmpbuf jmpbuf;
|
||||
} WASMJmpBuf;
|
||||
#endif
|
||||
|
||||
/* Execution environment */
|
||||
typedef struct WASMExecEnv {
|
||||
/* Next thread's exec env of a WASM module instance. */
|
||||
/* Next thread's exec env of a WASM module instance. */
|
||||
struct WASMExecEnv *next;
|
||||
|
||||
/* Previous thread's exec env of a WASM module instance. */
|
||||
/* Previous thread's exec env of a WASM module instance. */
|
||||
struct WASMExecEnv *prev;
|
||||
|
||||
/* Note: field module_inst, argv_buf, native_stack_boundary,
|
||||
suspend_flags, aux_stack_boundary, aux_stack_bottom, and
|
||||
native_symbol are used by AOTed code, don't change the
|
||||
places of them */
|
||||
|
||||
/* The WASM module instance of current thread */
|
||||
struct WASMModuleInstanceCommon *module_inst;
|
||||
|
||||
|
@ -33,6 +49,54 @@ typedef struct WASMExecEnv {
|
|||
uint32 *argv_buf;
|
||||
#endif
|
||||
|
||||
/* The boundary of native stack. When runtime detects that native
|
||||
frame may overrun this boundary, it throws stack overflow
|
||||
exception. */
|
||||
uint8 *native_stack_boundary;
|
||||
|
||||
/* Used to terminate or suspend current thread
|
||||
bit 0: need to terminate
|
||||
bit 1: need to suspend
|
||||
bit 2: need to go into breakpoint
|
||||
bit 3: return from pthread_exit */
|
||||
union {
|
||||
uint32 flags;
|
||||
uintptr_t __padding__;
|
||||
} suspend_flags;
|
||||
|
||||
/* Auxiliary stack boundary */
|
||||
union {
|
||||
uint32 boundary;
|
||||
uintptr_t __padding__;
|
||||
} aux_stack_boundary;
|
||||
|
||||
/* Auxiliary stack bottom */
|
||||
union {
|
||||
uint32 bottom;
|
||||
uintptr_t __padding__;
|
||||
} aux_stack_bottom;
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
/* Native symbol list, reserved */
|
||||
void **native_symbol;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
/* thread return value */
|
||||
void *thread_ret_value;
|
||||
|
||||
/* Must be provided by thread library */
|
||||
void* (*thread_start_routine)(void *);
|
||||
void *thread_arg;
|
||||
|
||||
/* pointer to the cluster */
|
||||
WASMCluster *cluster;
|
||||
|
||||
/* used to support debugger */
|
||||
korp_mutex wait_lock;
|
||||
korp_cond wait_cond;
|
||||
#endif
|
||||
|
||||
/* attachment for native function */
|
||||
void *attachment;
|
||||
|
||||
|
@ -44,14 +108,21 @@ typedef struct WASMExecEnv {
|
|||
/* The native thread handle of current thread */
|
||||
korp_tid handle;
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
#if WASM_ENABLE_INTERP != 0 && WASM_ENABLE_FAST_INTERP == 0
|
||||
BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
|
||||
#endif
|
||||
|
||||
/* The boundary of native stack. When interpreter detects that native
|
||||
frame may overrun this boundary, it throws a stack overflow
|
||||
exception. */
|
||||
void *native_stack_boundary;
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
WASMJmpBuf *jmpbuf_stack_top;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
uint16 nested_calling_depth;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
uint32 max_wasm_stack_used;
|
||||
#endif
|
||||
|
||||
/* The WASM stack size */
|
||||
uint32 wasm_stack_size;
|
||||
|
@ -61,18 +132,25 @@ typedef struct WASMExecEnv {
|
|||
uint64 __make_it_8_byte_aligned_;
|
||||
|
||||
struct {
|
||||
/* The top boundary of the stack. */
|
||||
/* The top boundary of the stack. */
|
||||
uint8 *top_boundary;
|
||||
|
||||
/* Top cell index which is free. */
|
||||
/* Top cell index which is free. */
|
||||
uint8 *top;
|
||||
|
||||
/* The Java stack. */
|
||||
/* The WASM stack. */
|
||||
uint8 bottom[1];
|
||||
} s;
|
||||
} wasm_stack;
|
||||
} WASMExecEnv;
|
||||
|
||||
WASMExecEnv *
|
||||
wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size);
|
||||
|
||||
void
|
||||
wasm_exec_env_destroy_internal(WASMExecEnv *exec_env);
|
||||
|
||||
WASMExecEnv *
|
||||
wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size);
|
||||
|
@ -100,13 +178,19 @@ wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size)
|
|||
multiplying by 2 is enough. */
|
||||
if (addr + size * 2 > exec_env->wasm_stack.s.top_boundary) {
|
||||
/* WASM stack overflow. */
|
||||
/* When throwing SOE, the preserved space must be enough. */
|
||||
/* bh_assert(!exec_env->throwing_soe);*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
exec_env->wasm_stack.s.top += size;
|
||||
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
{
|
||||
uint32 wasm_stack_used = exec_env->wasm_stack.s.top
|
||||
- exec_env->wasm_stack.s.bottom;
|
||||
if (wasm_stack_used > exec_env->max_wasm_stack_used)
|
||||
exec_env->max_wasm_stack_used = wasm_stack_used;
|
||||
}
|
||||
#endif
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
@ -159,6 +243,26 @@ wasm_exec_env_get_cur_frame(WASMExecEnv *exec_env)
|
|||
struct WASMModuleInstanceCommon *
|
||||
wasm_exec_env_get_module_inst(WASMExecEnv *exec_env);
|
||||
|
||||
void
|
||||
wasm_exec_env_set_thread_info(WASMExecEnv *exec_env);
|
||||
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
void *
|
||||
wasm_exec_env_get_thread_arg(WASMExecEnv *exec_env);
|
||||
|
||||
void
|
||||
wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg);
|
||||
#endif
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
void
|
||||
wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf);
|
||||
|
||||
WASMJmpBuf *
|
||||
wasm_exec_env_pop_jmpbuf(WASMExecEnv *exec_env);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -7,33 +7,6 @@
|
|||
#include "bh_platform.h"
|
||||
#include "mem_alloc.h"
|
||||
|
||||
#if BH_ENABLE_MEMORY_PROFILING != 0
|
||||
|
||||
/* Memory profile data of a function */
|
||||
typedef struct memory_profile {
|
||||
struct memory_profile *next;
|
||||
const char *function_name;
|
||||
const char *file_name;
|
||||
int line_in_file;
|
||||
int malloc_num;
|
||||
int free_num;
|
||||
int total_malloc;
|
||||
int total_free;
|
||||
} memory_profile_t;
|
||||
|
||||
/* Memory in use which grows when BH_MALLOC was called
|
||||
* and decreases when bh_free was called */
|
||||
static unsigned int memory_in_use = 0;
|
||||
|
||||
/* Memory profile data list */
|
||||
static memory_profile_t *memory_profiles_list = NULL;
|
||||
|
||||
/* Lock of the memory profile list */
|
||||
static korp_mutex profile_lock;
|
||||
#endif /* end of BH_ENABLE_MEMORY_PROFILING */
|
||||
|
||||
#ifndef MALLOC_MEMORY_FROM_SYSTEM
|
||||
|
||||
typedef enum Memory_Mode {
|
||||
MEMORY_MODE_UNKNOWN = 0,
|
||||
MEMORY_MODE_POOL,
|
||||
|
@ -58,9 +31,6 @@ wasm_memory_init_with_pool(void *mem, unsigned int bytes)
|
|||
if (_allocator) {
|
||||
memory_mode = MEMORY_MODE_POOL;
|
||||
pool_allocator = _allocator;
|
||||
#if BH_ENABLE_MEMORY_PROFILING != 0
|
||||
os_mutex_init(&profile_lock);
|
||||
#endif
|
||||
global_pool_size = bytes;
|
||||
return true;
|
||||
}
|
||||
|
@ -78,9 +48,6 @@ wasm_memory_init_with_allocator(void *_malloc_func,
|
|||
malloc_func = _malloc_func;
|
||||
realloc_func = _realloc_func;
|
||||
free_func = _free_func;
|
||||
#if BH_ENABLE_MEMORY_PROFILING != 0
|
||||
os_mutex_init(&profile_lock);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n",
|
||||
|
@ -108,9 +75,6 @@ wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
|
|||
void
|
||||
wasm_runtime_memory_destroy()
|
||||
{
|
||||
#if BH_ENABLE_MEMORY_PROFILING != 0
|
||||
os_mutex_destroy(&profile_lock);
|
||||
#endif
|
||||
if (memory_mode == MEMORY_MODE_POOL)
|
||||
mem_allocator_destroy(pool_allocator);
|
||||
memory_mode = MEMORY_MODE_UNKNOWN;
|
||||
|
@ -125,28 +89,32 @@ wasm_runtime_memory_pool_size()
|
|||
return 1 * BH_GB;
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_malloc(unsigned int size)
|
||||
static inline void *
|
||||
wasm_runtime_malloc_internal(unsigned int size)
|
||||
{
|
||||
if (memory_mode == MEMORY_MODE_UNKNOWN) {
|
||||
LOG_WARNING("wasm_runtime_malloc failed: memory hasn't been initialize.\n");
|
||||
return NULL;
|
||||
} else if (memory_mode == MEMORY_MODE_POOL) {
|
||||
}
|
||||
else if (memory_mode == MEMORY_MODE_POOL) {
|
||||
return mem_allocator_malloc(pool_allocator, size);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return malloc_func(size);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_realloc(void *ptr, unsigned int size)
|
||||
static inline void *
|
||||
wasm_runtime_realloc_internal(void *ptr, unsigned int size)
|
||||
{
|
||||
if (memory_mode == MEMORY_MODE_UNKNOWN) {
|
||||
LOG_WARNING("wasm_runtime_realloc failed: memory hasn't been initialize.\n");
|
||||
return NULL;
|
||||
} else if (memory_mode == MEMORY_MODE_POOL) {
|
||||
}
|
||||
else if (memory_mode == MEMORY_MODE_POOL) {
|
||||
return mem_allocator_realloc(pool_allocator, ptr, size);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (realloc_func)
|
||||
return realloc_func(ptr, size);
|
||||
else
|
||||
|
@ -154,219 +122,46 @@ wasm_runtime_realloc(void *ptr, unsigned int size)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_free(void *ptr)
|
||||
static inline void
|
||||
wasm_runtime_free_internal(void *ptr)
|
||||
{
|
||||
if (!ptr) {
|
||||
LOG_WARNING("warning: wasm_runtime_free with NULL pointer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (memory_mode == MEMORY_MODE_UNKNOWN) {
|
||||
LOG_WARNING("wasm_runtime_free failed: memory hasn't been initialize.\n");
|
||||
} else if (memory_mode == MEMORY_MODE_POOL) {
|
||||
LOG_WARNING("warning: wasm_runtime_free failed: "
|
||||
"memory hasn't been initialize.\n");
|
||||
}
|
||||
else if (memory_mode == MEMORY_MODE_POOL) {
|
||||
mem_allocator_free(pool_allocator, ptr);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
free_func(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
#if BH_ENABLE_MEMORY_PROFILING != 0
|
||||
|
||||
void
|
||||
memory_profile_print(const char *file, int line,
|
||||
const char *func, int alloc)
|
||||
{
|
||||
os_printf("location:%s@%d:used:%d:contribution:%d\n",
|
||||
func, line, memory_in_use, alloc);
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_malloc_profile(const char *file, int line,
|
||||
const char *func, unsigned int size)
|
||||
{
|
||||
void *p = wasm_runtime_malloc(size + 8);
|
||||
|
||||
if (p) {
|
||||
memory_profile_t *profile;
|
||||
|
||||
os_mutex_lock(&profile_lock);
|
||||
|
||||
profile = memory_profiles_list;
|
||||
while (profile) {
|
||||
if (strcmp(profile->function_name, func) == 0
|
||||
&& strcmp(profile->file_name, file) == 0) {
|
||||
break;
|
||||
}
|
||||
profile = profile->next;
|
||||
}
|
||||
|
||||
if (profile) {
|
||||
profile->total_malloc += size;/* TODO: overflow check */
|
||||
profile->malloc_num++;
|
||||
} else {
|
||||
profile = wasm_runtime_malloc(sizeof(memory_profile_t));
|
||||
if (!profile) {
|
||||
os_mutex_unlock(&profile_lock);
|
||||
bh_memcpy_s(p, size + 8, &size, sizeof(size));
|
||||
return (char *)p + 8;
|
||||
}
|
||||
|
||||
memset(profile, 0, sizeof(memory_profile_t));
|
||||
profile->file_name = file;
|
||||
profile->line_in_file = line;
|
||||
profile->function_name = func;
|
||||
profile->malloc_num = 1;
|
||||
profile->total_malloc = size;
|
||||
profile->next = memory_profiles_list;
|
||||
memory_profiles_list = profile;
|
||||
}
|
||||
|
||||
os_mutex_unlock(&profile_lock);
|
||||
|
||||
bh_memcpy_s(p, size + 8, &size, sizeof(size));
|
||||
memory_in_use += size;
|
||||
|
||||
memory_profile_print(file, line, func, size);
|
||||
|
||||
return (char *)p + 8;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_free_profile(const char *file, int line,
|
||||
const char *func, void *ptr)
|
||||
{
|
||||
unsigned int size = *(unsigned int *)((char *)ptr - 8);
|
||||
memory_profile_t *profile;
|
||||
|
||||
wasm_runtime_free((char *)ptr - 8);
|
||||
|
||||
if (memory_in_use >= size)
|
||||
memory_in_use -= size;
|
||||
|
||||
os_mutex_lock(&profile_lock);
|
||||
|
||||
profile = memory_profiles_list;
|
||||
while (profile) {
|
||||
if (strcmp(profile->function_name, func) == 0
|
||||
&& strcmp(profile->file_name, file) == 0) {
|
||||
break;
|
||||
}
|
||||
profile = profile->next;
|
||||
}
|
||||
|
||||
if (profile) {
|
||||
profile->total_free += size;/* TODO: overflow check */
|
||||
profile->free_num++;
|
||||
} else {
|
||||
profile = wasm_runtime_malloc(sizeof(memory_profile_t));
|
||||
if (!profile) {
|
||||
os_mutex_unlock(&profile_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(profile, 0, sizeof(memory_profile_t));
|
||||
profile->file_name = file;
|
||||
profile->line_in_file = line;
|
||||
profile->function_name = func;
|
||||
profile->free_num = 1;
|
||||
profile->total_free = size;
|
||||
profile->next = memory_profiles_list;
|
||||
memory_profiles_list = profile;
|
||||
}
|
||||
|
||||
os_mutex_unlock(&profile_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarize memory usage and print it out
|
||||
* Can use awk to analyze the output like below:
|
||||
* awk -F: '{print $2,$4,$6,$8,$9}' OFS="\t" ./out.txt | sort -n -r -k 1
|
||||
*/
|
||||
void memory_usage_summarize()
|
||||
{
|
||||
memory_profile_t *profile;
|
||||
|
||||
os_mutex_lock(&profile_lock);
|
||||
|
||||
profile = memory_profiles_list;
|
||||
while (profile) {
|
||||
os_printf("malloc:%d:malloc_num:%d:free:%d:free_num:%d:%s\n",
|
||||
profile->total_malloc,
|
||||
profile->malloc_num,
|
||||
profile->total_free,
|
||||
profile->free_num,
|
||||
profile->function_name);
|
||||
profile = profile->next;
|
||||
}
|
||||
|
||||
os_mutex_unlock(&profile_lock);
|
||||
}
|
||||
|
||||
#endif /* end of BH_ENABLE_MEMORY_PROFILING */
|
||||
|
||||
#else /* else of MALLOC_MEMORY_FROM_SYSTEM */
|
||||
|
||||
|
||||
void *
|
||||
wasm_runtime_malloc(unsigned int size)
|
||||
{
|
||||
return malloc(size);
|
||||
if (size == 0) {
|
||||
LOG_WARNING("warning: wasm_runtime_malloc with size zero\n");
|
||||
/* At lease alloc 1 byte to avoid malloc failed */
|
||||
size = 1;
|
||||
}
|
||||
|
||||
return wasm_runtime_malloc_internal(size);
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_realloc(void *ptr, unsigned int size)
|
||||
{
|
||||
return realloc(ptr, size);
|
||||
return wasm_runtime_realloc_internal(ptr, size);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_free(void *ptr)
|
||||
{
|
||||
if (ptr)
|
||||
free(ptr);
|
||||
wasm_runtime_free_internal(ptr);
|
||||
}
|
||||
|
||||
#if BH_ENABLE_MEMORY_PROFILING != 0
|
||||
void *
|
||||
wasm_runtime_malloc_profile(const char *file, int line,
|
||||
const char *func, unsigned int size)
|
||||
{
|
||||
(void)file;
|
||||
(void)line;
|
||||
(void)func;
|
||||
|
||||
(void)memory_profiles_list;
|
||||
(void)profile_lock;
|
||||
(void)memory_in_use;
|
||||
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_realloc_profile(const char *file, int line,
|
||||
const char *func, void *ptr, unsigned int size)
|
||||
{
|
||||
(void)file;
|
||||
(void)line;
|
||||
(void)func;
|
||||
|
||||
(void)memory_profiles_list;
|
||||
(void)profile_lock;
|
||||
(void)memory_in_use;
|
||||
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_free_profile(const char *file, int line,
|
||||
const char *func, void *ptr)
|
||||
{
|
||||
(void)file;
|
||||
(void)line;
|
||||
(void)func;
|
||||
|
||||
if (ptr)
|
||||
free(ptr);
|
||||
}
|
||||
#endif /* end of BH_ENABLE_MEMORY_PROFILING */
|
||||
#endif /* end of MALLOC_MEMORY_FROM_SYSTEM*/
|
||||
|
||||
|
|
|
@ -7,15 +7,28 @@
|
|||
#include "wasm_runtime_common.h"
|
||||
#include "bh_log.h"
|
||||
|
||||
#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \
|
||||
&& !defined(BH_PLATFORM_OPENRTOS) && !defined(BH_PLATFORM_ESP_IDF)
|
||||
#define ENABLE_QUICKSORT 1
|
||||
#else
|
||||
#define ENABLE_QUICKSORT 0
|
||||
#endif
|
||||
|
||||
#define ENABLE_SORT_DEBUG 0
|
||||
|
||||
#if ENABLE_SORT_DEBUG != 0
|
||||
#include<sys/time.h>
|
||||
#endif
|
||||
|
||||
static NativeSymbolsList g_native_symbols_list = NULL;
|
||||
static NativeSymbolsList g_native_symbols_list_end = NULL;
|
||||
|
||||
uint32
|
||||
get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
|
||||
|
||||
#if WASM_ENABLE_SPEC_TEST != 0
|
||||
uint32
|
||||
get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis);
|
||||
#endif
|
||||
|
||||
uint32
|
||||
get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis);
|
||||
|
@ -26,6 +39,20 @@ get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
|
|||
uint32
|
||||
get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis);
|
||||
|
||||
#if WASM_ENABLE_LIB_PTHREAD != 0
|
||||
bool
|
||||
lib_pthread_init();
|
||||
|
||||
void
|
||||
lib_pthread_destroy();
|
||||
|
||||
uint32
|
||||
get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
|
||||
#endif
|
||||
|
||||
uint32
|
||||
get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis);
|
||||
|
||||
static bool
|
||||
check_symbol_signature(const WASMType *type, const char *signature)
|
||||
{
|
||||
|
@ -41,13 +68,19 @@ check_symbol_signature(const WASMType *type, const char *signature)
|
|||
if (*p++ != '(')
|
||||
return false;
|
||||
|
||||
if ((uint32)(p_end - p) < type->param_count + 1)
|
||||
if ((uint32)(p_end - p) < (uint32)(type->param_count + 1))
|
||||
/* signatures of parameters, and ')' */
|
||||
return false;
|
||||
|
||||
for (i = 0; i < type->param_count; i++) {
|
||||
sig = *p++;
|
||||
if (sig == sig_map[type->types[i] - VALUE_TYPE_F64])
|
||||
if ((type->types[i] >= VALUE_TYPE_F64
|
||||
&& type->types[i] <= VALUE_TYPE_I32
|
||||
&& sig == sig_map[type->types[i] - VALUE_TYPE_F64])
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
|| (sig == 'i' && type->types[i] == VALUE_TYPE_EXTERNREF)
|
||||
#endif
|
||||
)
|
||||
/* normal parameter */
|
||||
continue;
|
||||
|
||||
|
@ -90,6 +123,7 @@ check_symbol_signature(const WASMType *type, const char *signature)
|
|||
return true;
|
||||
}
|
||||
|
||||
#if ENABLE_QUICKSORT == 0
|
||||
static void
|
||||
sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols)
|
||||
{
|
||||
|
@ -107,13 +141,63 @@ sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols)
|
|||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void
|
||||
swap_symbol(NativeSymbol* left, NativeSymbol* right)
|
||||
{
|
||||
NativeSymbol temp = *left;
|
||||
*left = *right;
|
||||
*right = temp;
|
||||
}
|
||||
|
||||
static void
|
||||
quick_sort_symbols(NativeSymbol* native_symbols, int left, int right)
|
||||
{
|
||||
NativeSymbol base_symbol;
|
||||
int pin_left = left;
|
||||
int pin_right = right;
|
||||
|
||||
if (left >= right) {
|
||||
return;
|
||||
}
|
||||
|
||||
base_symbol = native_symbols[left];
|
||||
while (left < right) {
|
||||
while (left < right
|
||||
&& strcmp(native_symbols[right].symbol,
|
||||
base_symbol.symbol) > 0) {
|
||||
right--;
|
||||
}
|
||||
|
||||
if (left < right) {
|
||||
swap_symbol(&native_symbols[left], &native_symbols[right]);
|
||||
left++;
|
||||
}
|
||||
|
||||
while (left < right
|
||||
&& strcmp(native_symbols[left].symbol,
|
||||
base_symbol.symbol) < 0) {
|
||||
left++;
|
||||
}
|
||||
|
||||
if (left < right) {
|
||||
swap_symbol(&native_symbols[left], &native_symbols[right]);
|
||||
right--;
|
||||
}
|
||||
}
|
||||
native_symbols[left] = base_symbol;
|
||||
|
||||
quick_sort_symbols(native_symbols, pin_left, left - 1);
|
||||
quick_sort_symbols(native_symbols, left + 1, pin_right);
|
||||
}
|
||||
#endif /* end of ENABLE_QUICKSORT */
|
||||
|
||||
static void *
|
||||
lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
|
||||
const char *symbol, const char **p_signature, void **p_attachment)
|
||||
{
|
||||
int low = 0, mid, ret;
|
||||
int high = n_native_symbols - 1;
|
||||
int high = (int32)n_native_symbols - 1;
|
||||
|
||||
while (low <= high) {
|
||||
mid = (low + high) / 2;
|
||||
|
@ -192,25 +276,44 @@ register_natives(const char *module_name,
|
|||
bool call_conv_raw)
|
||||
{
|
||||
NativeSymbolsNode *node;
|
||||
#if ENABLE_SORT_DEBUG != 0
|
||||
struct timeval start;
|
||||
struct timeval end;
|
||||
unsigned long timer;
|
||||
#endif
|
||||
|
||||
if (!(node = wasm_runtime_malloc(sizeof(NativeSymbolsNode))))
|
||||
return false;
|
||||
#if WASM_ENABLE_MEMORY_TRACING != 0
|
||||
os_printf("Register native, size: %u\n", sizeof(NativeSymbolsNode));
|
||||
#endif
|
||||
|
||||
node->module_name = module_name;
|
||||
node->native_symbols = native_symbols;
|
||||
node->n_native_symbols = n_native_symbols;
|
||||
node->call_conv_raw = call_conv_raw;
|
||||
node->next = NULL;
|
||||
|
||||
if (g_native_symbols_list_end) {
|
||||
g_native_symbols_list_end->next = node;
|
||||
g_native_symbols_list_end = node;
|
||||
}
|
||||
else {
|
||||
g_native_symbols_list = g_native_symbols_list_end = node;
|
||||
}
|
||||
/* Add to list head */
|
||||
node->next = g_native_symbols_list;
|
||||
g_native_symbols_list = node;
|
||||
|
||||
#if ENABLE_SORT_DEBUG != 0
|
||||
gettimeofday(&start, NULL);
|
||||
#endif
|
||||
|
||||
#if ENABLE_QUICKSORT == 0
|
||||
sort_symbol_ptr(native_symbols, n_native_symbols);
|
||||
#else
|
||||
quick_sort_symbols(native_symbols, 0, (int)(n_native_symbols - 1));
|
||||
#endif
|
||||
|
||||
#if ENABLE_SORT_DEBUG != 0
|
||||
gettimeofday(&end, NULL);
|
||||
timer = 1000000 * (end.tv_sec - start.tv_sec)
|
||||
+ (end.tv_usec - start.tv_usec);
|
||||
LOG_ERROR("module_name: %s, nums: %d, sorted used: %ld us",
|
||||
module_name, n_native_symbols, timer);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -239,14 +342,16 @@ wasm_native_init()
|
|||
#if WASM_ENABLE_LIBC_BUILTIN != 0
|
||||
n_native_symbols = get_libc_builtin_export_apis(&native_symbols);
|
||||
if (!wasm_native_register_natives("env",
|
||||
native_symbols, n_native_symbols))
|
||||
native_symbols, n_native_symbols))
|
||||
return false;
|
||||
#endif /* WASM_ENABLE_LIBC_BUILTIN */
|
||||
|
||||
#if WASM_ENABLE_SPEC_TEST
|
||||
n_native_symbols = get_spectest_export_apis(&native_symbols);
|
||||
if (!wasm_native_register_natives("spectest",
|
||||
native_symbols, n_native_symbols))
|
||||
native_symbols, n_native_symbols))
|
||||
return false;
|
||||
#endif
|
||||
#endif /* WASM_ENABLE_SPEC_TEST */
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
|
||||
|
@ -274,6 +379,25 @@ wasm_native_init()
|
|||
return false;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIB_PTHREAD != 0
|
||||
if (!lib_pthread_init())
|
||||
return false;
|
||||
|
||||
n_native_symbols = get_lib_pthread_export_apis(&native_symbols);
|
||||
if (n_native_symbols > 0
|
||||
&& !wasm_native_register_natives("env",
|
||||
native_symbols, n_native_symbols))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_EMCC != 0
|
||||
n_native_symbols = get_libc_emcc_export_apis(&native_symbols);
|
||||
if (n_native_symbols > 0
|
||||
&& !wasm_native_register_natives("env",
|
||||
native_symbols, n_native_symbols))
|
||||
return false;
|
||||
#endif /* WASM_ENABLE_LIBC_EMCC */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -282,6 +406,10 @@ wasm_native_destroy()
|
|||
{
|
||||
NativeSymbolsNode *node, *node_next;
|
||||
|
||||
#if WASM_ENABLE_LIB_PTHREAD != 0
|
||||
lib_pthread_destroy();
|
||||
#endif
|
||||
|
||||
node = g_native_symbols_list;
|
||||
while (node) {
|
||||
node_next = node->next;
|
||||
|
@ -289,6 +417,5 @@ wasm_native_destroy()
|
|||
node = node_next;
|
||||
}
|
||||
|
||||
g_native_symbols_list = g_native_symbols_list_end = NULL;
|
||||
g_native_symbols_list = NULL;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -13,14 +13,241 @@
|
|||
#include "../include/wasm_export.h"
|
||||
#include "../interpreter/wasm.h"
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
#if WASM_ENABLE_UVWASI == 0
|
||||
#include "wasmtime_ssp.h"
|
||||
#include "posix.h"
|
||||
#else
|
||||
#include "uvwasi.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
|
||||
|
||||
#define PUT_I64_TO_ADDR(addr, value) do { \
|
||||
*(int64*)(addr) = (int64)(value); \
|
||||
} while (0)
|
||||
#define PUT_F64_TO_ADDR(addr, value) do { \
|
||||
*(float64*)(addr) = (float64)(value); \
|
||||
} while (0)
|
||||
|
||||
#define GET_I64_FROM_ADDR(addr) (*(int64*)(addr))
|
||||
#define GET_F64_FROM_ADDR(addr) (*(float64*)(addr))
|
||||
|
||||
/* For STORE opcodes */
|
||||
#define STORE_I64 PUT_I64_TO_ADDR
|
||||
#define STORE_U32(addr, value) do { \
|
||||
*(uint32*)(addr) = (uint32)(value); \
|
||||
} while (0)
|
||||
#define STORE_U16(addr, value) do { \
|
||||
*(uint16*)(addr) = (uint16)(value); \
|
||||
} while (0)
|
||||
|
||||
/* For LOAD opcodes */
|
||||
#define LOAD_I64(addr) (*(int64*)(addr))
|
||||
#define LOAD_F64(addr) (*(float64*)(addr))
|
||||
#define LOAD_I32(addr) (*(int32*)(addr))
|
||||
#define LOAD_U32(addr) (*(uint32*)(addr))
|
||||
#define LOAD_I16(addr) (*(int16*)(addr))
|
||||
#define LOAD_U16(addr) (*(uint16*)(addr))
|
||||
|
||||
#define STORE_PTR(addr, ptr) do { \
|
||||
*(void**)addr = (void*)ptr; \
|
||||
} while (0)
|
||||
#define LOAD_PTR(addr) (*(void**)(addr))
|
||||
|
||||
#else /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */
|
||||
|
||||
#define PUT_I64_TO_ADDR(addr, value) do { \
|
||||
uint32 *addr_u32 = (uint32*)(addr); \
|
||||
union { int64 val; uint32 parts[2]; } u; \
|
||||
u.val = (int64)(value); \
|
||||
addr_u32[0] = u.parts[0]; \
|
||||
addr_u32[1] = u.parts[1]; \
|
||||
} while (0)
|
||||
#define PUT_F64_TO_ADDR(addr, value) do { \
|
||||
uint32 *addr_u32 = (uint32*)(addr); \
|
||||
union { float64 val; uint32 parts[2]; } u; \
|
||||
u.val = (value); \
|
||||
addr_u32[0] = u.parts[0]; \
|
||||
addr_u32[1] = u.parts[1]; \
|
||||
} while (0)
|
||||
|
||||
static inline int64
|
||||
GET_I64_FROM_ADDR(uint32 *addr)
|
||||
{
|
||||
union { int64 val; uint32 parts[2]; } u;
|
||||
u.parts[0] = addr[0];
|
||||
u.parts[1] = addr[1];
|
||||
return u.val;
|
||||
}
|
||||
|
||||
static inline float64
|
||||
GET_F64_FROM_ADDR (uint32 *addr)
|
||||
{
|
||||
union { float64 val; uint32 parts[2]; } u;
|
||||
u.parts[0] = addr[0];
|
||||
u.parts[1] = addr[1];
|
||||
return u.val;
|
||||
}
|
||||
|
||||
/* For STORE opcodes */
|
||||
#define STORE_I64(addr, value) do { \
|
||||
uintptr_t addr1 = (uintptr_t)(addr); \
|
||||
union { int64 val; uint32 u32[2]; \
|
||||
uint16 u16[4]; uint8 u8[8]; } u; \
|
||||
if ((addr1 & (uintptr_t)7) == 0) \
|
||||
*(int64*)(addr) = (int64)(value); \
|
||||
else { \
|
||||
u.val = (int64)(value); \
|
||||
if ((addr1 & (uintptr_t)3) == 0) { \
|
||||
((uint32*)(addr))[0] = u.u32[0]; \
|
||||
((uint32*)(addr))[1] = u.u32[1]; \
|
||||
} \
|
||||
else if ((addr1 & (uintptr_t)1) == 0) { \
|
||||
((uint16*)(addr))[0] = u.u16[0]; \
|
||||
((uint16*)(addr))[1] = u.u16[1]; \
|
||||
((uint16*)(addr))[2] = u.u16[2]; \
|
||||
((uint16*)(addr))[3] = u.u16[3]; \
|
||||
} \
|
||||
else { \
|
||||
int32 t; \
|
||||
for (t = 0; t < 8; t++) \
|
||||
((uint8*)(addr))[t] = u.u8[t]; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STORE_U32(addr, value) do { \
|
||||
uintptr_t addr1 = (uintptr_t)(addr); \
|
||||
union { uint32 val; \
|
||||
uint16 u16[2]; uint8 u8[4]; } u; \
|
||||
if ((addr1 & (uintptr_t)3) == 0) \
|
||||
*(uint32*)(addr) = (uint32)(value); \
|
||||
else { \
|
||||
u.val = (uint32)(value); \
|
||||
if ((addr1 & (uintptr_t)1) == 0) { \
|
||||
((uint16*)(addr))[0] = u.u16[0]; \
|
||||
((uint16*)(addr))[1] = u.u16[1]; \
|
||||
} \
|
||||
else { \
|
||||
((uint8*)(addr))[0] = u.u8[0]; \
|
||||
((uint8*)(addr))[1] = u.u8[1]; \
|
||||
((uint8*)(addr))[2] = u.u8[2]; \
|
||||
((uint8*)(addr))[3] = u.u8[3]; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STORE_U16(addr, value) do { \
|
||||
union { uint16 val; uint8 u8[2]; } u; \
|
||||
u.val = (uint16)(value); \
|
||||
((uint8*)(addr))[0] = u.u8[0]; \
|
||||
((uint8*)(addr))[1] = u.u8[1]; \
|
||||
} while (0)
|
||||
|
||||
/* For LOAD opcodes */
|
||||
static inline int64
|
||||
LOAD_I64(void *addr)
|
||||
{
|
||||
uintptr_t addr1 = (uintptr_t)addr;
|
||||
union { int64 val; uint32 u32[2];
|
||||
uint16 u16[4]; uint8 u8[8]; } u;
|
||||
if ((addr1 & (uintptr_t)7) == 0)
|
||||
return *(int64*)addr;
|
||||
|
||||
if ((addr1 & (uintptr_t)3) == 0) {
|
||||
u.u32[0] = ((uint32*)addr)[0];
|
||||
u.u32[1] = ((uint32*)addr)[1];
|
||||
}
|
||||
else if ((addr1 & (uintptr_t)1) == 0) {
|
||||
u.u16[0] = ((uint16*)addr)[0];
|
||||
u.u16[1] = ((uint16*)addr)[1];
|
||||
u.u16[2] = ((uint16*)addr)[2];
|
||||
u.u16[3] = ((uint16*)addr)[3];
|
||||
}
|
||||
else {
|
||||
int32 t;
|
||||
for (t = 0; t < 8; t++)
|
||||
u.u8[t] = ((uint8*)addr)[t];
|
||||
}
|
||||
return u.val;
|
||||
}
|
||||
|
||||
static inline float64
|
||||
LOAD_F64(void *addr)
|
||||
{
|
||||
uintptr_t addr1 = (uintptr_t)addr;
|
||||
union { float64 val; uint32 u32[2];
|
||||
uint16 u16[4]; uint8 u8[8]; } u;
|
||||
if ((addr1 & (uintptr_t)7) == 0)
|
||||
return *(float64*)addr;
|
||||
|
||||
if ((addr1 & (uintptr_t)3) == 0) {
|
||||
u.u32[0] = ((uint32*)addr)[0];
|
||||
u.u32[1] = ((uint32*)addr)[1];
|
||||
}
|
||||
else if ((addr1 & (uintptr_t)1) == 0) {
|
||||
u.u16[0] = ((uint16*)addr)[0];
|
||||
u.u16[1] = ((uint16*)addr)[1];
|
||||
u.u16[2] = ((uint16*)addr)[2];
|
||||
u.u16[3] = ((uint16*)addr)[3];
|
||||
}
|
||||
else {
|
||||
int32 t;
|
||||
for (t = 0; t < 8; t++)
|
||||
u.u8[t] = ((uint8*)addr)[t];
|
||||
}
|
||||
return u.val;
|
||||
}
|
||||
|
||||
static inline int32
|
||||
LOAD_I32(void *addr)
|
||||
{
|
||||
uintptr_t addr1 = (uintptr_t)addr;
|
||||
union { int32 val; uint16 u16[2]; uint8 u8[4]; } u;
|
||||
if ((addr1 & (uintptr_t)3) == 0)
|
||||
return *(int32*)addr;
|
||||
|
||||
if ((addr1 & (uintptr_t)1) == 0) {
|
||||
u.u16[0] = ((uint16*)addr)[0];
|
||||
u.u16[1] = ((uint16*)addr)[1];
|
||||
}
|
||||
else {
|
||||
u.u8[0] = ((uint8*)addr)[0];
|
||||
u.u8[1] = ((uint8*)addr)[1];
|
||||
u.u8[2] = ((uint8*)addr)[2];
|
||||
u.u8[3] = ((uint8*)addr)[3];
|
||||
}
|
||||
return u.val;
|
||||
}
|
||||
|
||||
static inline int16
|
||||
LOAD_I16(void *addr)
|
||||
{
|
||||
uintptr_t addr1 = (uintptr_t)addr;
|
||||
union { int16 val; uint8 u8[2]; } u;
|
||||
if ((addr1 & (uintptr_t)1)) {
|
||||
u.u8[0] = ((uint8*)addr)[0];
|
||||
u.u8[1] = ((uint8*)addr)[1];
|
||||
return u.val;
|
||||
}
|
||||
return *(int16*)addr;
|
||||
}
|
||||
|
||||
#define LOAD_U32(addr) ((uint32)LOAD_I32(addr))
|
||||
#define LOAD_U16(addr) ((uint16)LOAD_I16(addr))
|
||||
|
||||
#if UINTPTR_MAX == UINT32_MAX
|
||||
#define STORE_PTR(addr, ptr) STORE_U32(addr, (uintptr_t)ptr)
|
||||
#elif UINTPTR_MAX == UINT64_MAX
|
||||
#define STORE_PTR(addr, ptr) STORE_I64(addr, (uintptr_t)ptr)
|
||||
#endif
|
||||
|
||||
#endif /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */
|
||||
|
||||
typedef struct WASMModuleCommon {
|
||||
/* Module type, for module loaded from WASM bytecode binary,
|
||||
|
@ -44,96 +271,174 @@ typedef struct WASMModuleInstanceCommon {
|
|||
uint8 module_inst_data[1];
|
||||
} WASMModuleInstanceCommon;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
typedef struct WASIContext {
|
||||
/* Use offset but not native address, since these fields are
|
||||
allocated from app's heap, and the heap space may be re-allocated
|
||||
after memory.grow opcode is executed, the original native address
|
||||
cannot be accessed again. */
|
||||
int32 curfds_offset;
|
||||
int32 prestats_offset;
|
||||
int32 argv_environ_offset;
|
||||
} WASIContext;
|
||||
typedef struct WASMModuleMemConsumption {
|
||||
uint32 total_size;
|
||||
uint32 module_struct_size;
|
||||
uint32 types_size;
|
||||
uint32 imports_size;
|
||||
uint32 functions_size;
|
||||
uint32 tables_size;
|
||||
uint32 memories_size;
|
||||
uint32 globals_size;
|
||||
uint32 exports_size;
|
||||
uint32 table_segs_size;
|
||||
uint32 data_segs_size;
|
||||
uint32 const_strs_size;
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
uint32 aot_code_size;
|
||||
#endif
|
||||
} WASMModuleMemConsumption;
|
||||
|
||||
typedef struct WASMModuleInstMemConsumption {
|
||||
uint32 total_size;
|
||||
uint32 module_inst_struct_size;
|
||||
uint32 memories_size;
|
||||
uint32 app_heap_size;
|
||||
uint32 tables_size;
|
||||
uint32 globals_size;
|
||||
uint32 functions_size;
|
||||
uint32 exports_size;
|
||||
} WASMModuleInstMemConsumption;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
#if WASM_ENABLE_UVWASI == 0
|
||||
typedef struct WASIContext {
|
||||
struct fd_table *curfds;
|
||||
struct fd_prestats *prestats;
|
||||
struct argv_environ_values *argv_environ;
|
||||
char *argv_buf;
|
||||
char **argv_list;
|
||||
char *env_buf;
|
||||
char **env_list;
|
||||
} WASIContext;
|
||||
#else
|
||||
typedef uvwasi_t WASIContext;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
typedef struct WASMRegisteredModule {
|
||||
bh_list_link l;
|
||||
/* point to a string pool */
|
||||
const char *module_name;
|
||||
WASMModuleCommon *module;
|
||||
/* to store the original module file buffer address */
|
||||
uint8 *orig_file_buf;
|
||||
uint32 orig_file_buf_size;
|
||||
} WASMRegisteredModule;
|
||||
#endif
|
||||
|
||||
typedef struct WASMMemoryInstanceCommon {
|
||||
uint32 module_type;
|
||||
uint8 memory_inst_data[1];
|
||||
} WASMMemoryInstanceCommon;
|
||||
|
||||
typedef package_type_t PackageType;
|
||||
typedef wasm_section_t WASMSection, AOTSection;
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
wasm_runtime_init();
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_init(void);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_full_init(RuntimeInitArgs *init_args);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_destroy();
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_destroy(void);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
PackageType
|
||||
WASM_RUNTIME_API_EXTERN PackageType
|
||||
get_package_type(const uint8 *buf, uint32 size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMModuleCommon *
|
||||
WASM_RUNTIME_API_EXTERN WASMModuleCommon *
|
||||
wasm_runtime_load(const uint8 *buf, uint32 size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMModuleCommon *
|
||||
WASM_RUNTIME_API_EXTERN 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);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_unload(WASMModuleCommon *module);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
/* Internal API */
|
||||
WASMModuleInstanceCommon *
|
||||
wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
|
||||
uint32 stack_size, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
/* Internal API */
|
||||
void
|
||||
wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
|
||||
bool is_sub_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon *
|
||||
wasm_runtime_instantiate(WASMModuleCommon *module,
|
||||
uint32 stack_size, uint32 heap_size,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMFunctionInstanceCommon *
|
||||
WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon *
|
||||
wasm_runtime_lookup_function(WASMModuleInstanceCommon * const module_inst,
|
||||
const char *name, const char *signature);
|
||||
|
||||
/* Internal API */
|
||||
WASMType *
|
||||
wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function,
|
||||
uint32 module_type);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMExecEnv *
|
||||
WASM_RUNTIME_API_EXTERN WASMExecEnv *
|
||||
wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMModuleInstanceCommon *
|
||||
WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon *
|
||||
wasm_runtime_get_module_inst(WASMExecEnv *exec_env);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void *
|
||||
wasm_runtime_get_function_attachment(wasm_exec_env_t exec_env);
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_runtime_get_function_attachment(WASMExecEnv *exec_env);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_set_user_data(wasm_exec_env_t exec_env, void *user_data);
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void *
|
||||
wasm_runtime_get_user_data(wasm_exec_env_t exec_env);
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_runtime_get_user_data(WASMExecEnv *exec_env);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_call_wasm(WASMExecEnv *exec_env,
|
||||
WASMFunctionInstanceCommon *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
uint32 argc, uint32 argv[]);
|
||||
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
|
||||
WASMFunctionInstanceCommon *function,
|
||||
uint32 num_results, wasm_val_t *results,
|
||||
uint32 num_args, wasm_val_t *args);
|
||||
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_call_wasm_v(WASMExecEnv *exec_env,
|
||||
WASMFunctionInstanceCommon *function,
|
||||
uint32 num_results, wasm_val_t *results,
|
||||
uint32 num_args, ...);
|
||||
|
||||
/**
|
||||
* Call a function reference of a given WASM runtime instance with
|
||||
|
@ -154,94 +459,105 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
|
|||
*/
|
||||
bool
|
||||
wasm_runtime_call_indirect(WASMExecEnv *exec_env,
|
||||
uint32_t element_indices,
|
||||
uint32_t argc, uint32_t argv[]);
|
||||
uint32 element_indices,
|
||||
uint32 argc, uint32 argv[]);
|
||||
|
||||
bool
|
||||
wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst,
|
||||
WASMFunctionInstanceCommon *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
uint32 argc, uint32 argv[]);
|
||||
|
||||
bool
|
||||
wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
WASMExecEnv *
|
||||
wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_application_execute_main(WASMModuleInstanceCommon *module_inst,
|
||||
int argc, char *argv[]);
|
||||
int32 argc, char *argv[]);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
||||
const char *name, int argc, char *argv[]);
|
||||
const char *name, int32 argc, char *argv[]);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_exception(WASMModuleInstanceCommon *module,
|
||||
const char *exception);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
const char *
|
||||
WASM_RUNTIME_API_EXTERN const char *
|
||||
wasm_runtime_get_exception(WASMModuleInstanceCommon *module);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
/* Internal API */
|
||||
void
|
||||
wasm_runtime_set_custom_data_internal(WASMModuleInstanceCommon *module_inst,
|
||||
void *custom_data);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_custom_data(WASMModuleInstanceCommon *module_inst,
|
||||
void *custom_data);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void *
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
int32
|
||||
WASM_RUNTIME_API_EXTERN uint32
|
||||
wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size,
|
||||
void **p_native_addr);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void
|
||||
wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, int32 ptr);
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, uint32 ptr);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
int32
|
||||
WASM_RUNTIME_API_EXTERN uint32
|
||||
wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst,
|
||||
const char *src, uint32 size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst,
|
||||
int32 app_offset, uint32 size);
|
||||
uint32 app_offset, uint32 size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst,
|
||||
int32 app_str_offset);
|
||||
uint32 app_str_offset);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst,
|
||||
void *native_ptr, uint32 size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
void *
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst,
|
||||
int32 app_offset);
|
||||
uint32 app_offset);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
int32
|
||||
WASM_RUNTIME_API_EXTERN uint32
|
||||
wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst,
|
||||
void *native_ptr);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst,
|
||||
int32 app_offset,
|
||||
int32 *p_app_start_offset,
|
||||
int32 *p_app_end_offset);
|
||||
uint32 app_offset,
|
||||
uint32 *p_app_start_offset,
|
||||
uint32 *p_app_end_offset);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst,
|
||||
uint8 *native_ptr,
|
||||
uint8 **p_native_start_addr,
|
||||
|
@ -261,9 +577,69 @@ void
|
|||
wasm_runtime_set_llvm_stack(WASMModuleInstanceCommon *module_inst,
|
||||
uint32 llvm_stack);
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
/* See wasm_export.h for description */
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_module_reader(const module_reader reader,
|
||||
const module_destroyer destroyer);
|
||||
|
||||
module_reader
|
||||
wasm_runtime_get_module_reader();
|
||||
|
||||
module_destroyer
|
||||
wasm_runtime_get_module_destroyer();
|
||||
|
||||
bool
|
||||
wasm_runtime_register_module_internal(const char *module_name,
|
||||
WASMModuleCommon *module,
|
||||
uint8 *orig_file_buf,
|
||||
uint32 orig_file_buf_size,
|
||||
char *error_buf,
|
||||
uint32 error_buf_size);
|
||||
|
||||
void
|
||||
wasm_runtime_unregister_module(const WASMModuleCommon *module);
|
||||
|
||||
bool
|
||||
wasm_runtime_is_module_registered(const char *module_name);
|
||||
|
||||
bool
|
||||
wasm_runtime_add_loading_module(const char *module_name,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
void
|
||||
wasm_runtime_delete_loading_module(const char *module_name);
|
||||
|
||||
bool
|
||||
wasm_runtime_is_loading_module(const char *module_name);
|
||||
|
||||
void
|
||||
wasm_runtime_destroy_loading_module_list();
|
||||
#endif /* WASM_ENALBE_MULTI_MODULE */
|
||||
|
||||
bool
|
||||
wasm_runtime_is_built_in_module(const char *module_name);
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
bool
|
||||
wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env,
|
||||
uint32 *start_offset, uint32 *size);
|
||||
|
||||
bool
|
||||
wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env,
|
||||
uint32 start_offset, uint32 size);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module,
|
||||
const char *dir_list[], uint32 dir_count,
|
||||
const char *map_dir_list[], uint32 map_dir_count,
|
||||
const char *env_list[], uint32 env_count,
|
||||
char *argv[], int argc,
|
||||
int stdinfd, int stdoutfd, int stderrfd);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_wasi_args(WASMModuleCommon *module,
|
||||
const char *dir_list[], uint32 dir_count,
|
||||
const char *map_dir_list[], uint32 map_dir_count,
|
||||
|
@ -271,11 +647,11 @@ wasm_runtime_set_wasi_args(WASMModuleCommon *module,
|
|||
char *argv[], int argc);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_is_wasi_mode(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASMFunctionInstanceCommon *
|
||||
WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon *
|
||||
wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
bool
|
||||
|
@ -284,6 +660,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
|
|||
const char *map_dir_list[], uint32 map_dir_count,
|
||||
const char *env[], uint32 env_count,
|
||||
char *argv[], uint32 argc,
|
||||
int stdinfd, int stdoutfd, int stderrfd,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
void
|
||||
|
@ -298,6 +675,38 @@ wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst);
|
|||
|
||||
#endif /* end of WASM_ENABLE_LIBC_WASI */
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst,
|
||||
void *extern_obj, uint32 *p_externref_idx);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_externref_ref2obj(uint32 externref_idx, void **p_extern_obj);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_externref_retain(uint32 externref_idx);
|
||||
|
||||
/**
|
||||
* Reclaim the externref objects/indexes which are not used by
|
||||
* module instance
|
||||
*/
|
||||
void
|
||||
wasm_externref_reclaim(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
/**
|
||||
* Cleanup the externref objects/indexes of the module instance
|
||||
*/
|
||||
void
|
||||
wasm_externref_cleanup(WASMModuleInstanceCommon *module_inst);
|
||||
#endif /* end of WASM_ENABLE_REF_TYPES */
|
||||
|
||||
/* Get module of the current exec_env */
|
||||
WASMModuleCommon*
|
||||
wasm_exec_env_get_module(WASMExecEnv *exec_env);
|
||||
|
||||
/**
|
||||
* Enlarge wasm memory data space.
|
||||
*
|
||||
|
@ -309,13 +718,13 @@ bool
|
|||
wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, uint32 inc_page_count);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_register_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
bool
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_register_natives_raw(const char *module_name,
|
||||
NativeSymbol *native_symbols,
|
||||
uint32 n_native_symbols);
|
||||
|
@ -332,6 +741,67 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
|
|||
void *attachment,
|
||||
uint32 *argv, uint32 argc, uint32 *ret);
|
||||
|
||||
void
|
||||
wasm_runtime_read_v128(const uint8 *bytes, uint64 *ret1, uint64 *ret2);
|
||||
|
||||
void
|
||||
wasm_runtime_dump_module_mem_consumption(const WASMModuleCommon *module);
|
||||
|
||||
void
|
||||
wasm_runtime_dump_module_inst_mem_consumption(const WASMModuleInstanceCommon
|
||||
*module_inst);
|
||||
|
||||
void
|
||||
wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env);
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
void
|
||||
wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
|
||||
WASMFunctionInstanceCommon *function);
|
||||
void
|
||||
wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
|
||||
WASMFunctionInstanceCommon *function,
|
||||
bool ret, uint32 *argv);
|
||||
#endif
|
||||
|
||||
bool
|
||||
wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
|
||||
const WASMExport *export,
|
||||
WASMType **out);
|
||||
|
||||
bool
|
||||
wasm_runtime_get_export_global_type(const WASMModuleCommon *module_comm,
|
||||
const WASMExport *export,
|
||||
uint8 *out_val_type,
|
||||
bool *out_mutability);
|
||||
|
||||
bool
|
||||
wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm,
|
||||
const WASMExport *export,
|
||||
uint32 *out_min_page,
|
||||
uint32 *out_max_page);
|
||||
|
||||
bool
|
||||
wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm,
|
||||
const WASMExport *export,
|
||||
uint8 *out_elem_type,
|
||||
uint32 *out_min_size,
|
||||
uint32 *out_max_size);
|
||||
|
||||
uint8 *
|
||||
wasm_runtime_get_memory_data(const WASMModuleInstanceCommon *module_inst_comm,
|
||||
uint32 memory_inst_idx);
|
||||
|
||||
uint32
|
||||
wasm_runtime_get_memory_data_size(const WASMModuleInstanceCommon *module_inst_comm,
|
||||
uint32 memory_inst_idx);
|
||||
|
||||
bool
|
||||
wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
|
||||
void *func_ptr, WASMType *func_type,
|
||||
uint32 argc, uint32 *argv,
|
||||
bool with_env, void *wasm_c_api_env);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
421
core/iwasm/common/wasm_shared_memory.c
Normal file
421
core/iwasm/common/wasm_shared_memory.c
Normal file
|
@ -0,0 +1,421 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "bh_log.h"
|
||||
#include "wasm_shared_memory.h"
|
||||
|
||||
static bh_list shared_memory_list_head;
|
||||
static bh_list *const shared_memory_list = &shared_memory_list_head;
|
||||
static korp_mutex shared_memory_list_lock;
|
||||
|
||||
enum {
|
||||
S_WAITING, S_NOTIFIED
|
||||
};
|
||||
|
||||
typedef struct AtomicWaitInfo {
|
||||
korp_mutex wait_list_lock;
|
||||
bh_list wait_list_head;
|
||||
bh_list *wait_list;
|
||||
} AtomicWaitInfo;
|
||||
|
||||
typedef struct AtomicWaitNode {
|
||||
bh_list_link l;
|
||||
uint8 status;
|
||||
korp_mutex wait_lock;
|
||||
korp_cond wait_cond;
|
||||
} AtomicWaitNode;
|
||||
|
||||
/* Atomic wait map */
|
||||
static HashMap *wait_map;
|
||||
|
||||
static uint32
|
||||
wait_address_hash(void *address);
|
||||
|
||||
static bool
|
||||
wait_address_equal(void *h1, void *h2);
|
||||
|
||||
static void
|
||||
destroy_wait_info(void *wait_info);
|
||||
|
||||
bool
|
||||
wasm_shared_memory_init()
|
||||
{
|
||||
if (os_mutex_init(&shared_memory_list_lock) != 0)
|
||||
return false;
|
||||
/* wait map not exists, create new map */
|
||||
if (!(wait_map =
|
||||
bh_hash_map_create(32, true,
|
||||
(HashFunc)wait_address_hash,
|
||||
(KeyEqualFunc)wait_address_equal,
|
||||
NULL, destroy_wait_info))) {
|
||||
os_mutex_destroy(&shared_memory_list_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_shared_memory_destroy()
|
||||
{
|
||||
os_mutex_destroy(&shared_memory_list_lock);
|
||||
if (wait_map) {
|
||||
bh_hash_map_destroy(wait_map);
|
||||
}
|
||||
}
|
||||
|
||||
static WASMSharedMemNode*
|
||||
search_module(WASMModuleCommon *module)
|
||||
{
|
||||
WASMSharedMemNode *node;
|
||||
|
||||
os_mutex_lock(&shared_memory_list_lock);
|
||||
node = bh_list_first_elem(shared_memory_list);
|
||||
|
||||
while (node) {
|
||||
if (module == node->module) {
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
return node;
|
||||
}
|
||||
node = bh_list_elem_next(node);
|
||||
}
|
||||
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WASMSharedMemNode*
|
||||
wasm_module_get_shared_memory(WASMModuleCommon *module)
|
||||
{
|
||||
return search_module(module);
|
||||
}
|
||||
|
||||
int32
|
||||
shared_memory_inc_reference(WASMModuleCommon *module)
|
||||
{
|
||||
WASMSharedMemNode *node = search_module(module);
|
||||
if (node) {
|
||||
os_mutex_lock(&node->lock);
|
||||
node->ref_count++;
|
||||
os_mutex_unlock(&node->lock);
|
||||
return node->ref_count;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32
|
||||
shared_memory_dec_reference(WASMModuleCommon *module)
|
||||
{
|
||||
WASMSharedMemNode *node = search_module(module);
|
||||
uint32 ref_count = 0;
|
||||
if (node) {
|
||||
os_mutex_lock(&node->lock);
|
||||
ref_count = --node->ref_count;
|
||||
os_mutex_unlock(&node->lock);
|
||||
if (ref_count == 0) {
|
||||
os_mutex_lock(&shared_memory_list_lock);
|
||||
bh_list_remove(shared_memory_list, node);
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
|
||||
os_mutex_destroy(&node->lock);
|
||||
wasm_runtime_free(node);
|
||||
}
|
||||
return ref_count;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
WASMMemoryInstanceCommon*
|
||||
shared_memory_get_memory_inst(WASMSharedMemNode *node)
|
||||
{
|
||||
return node->memory_inst;
|
||||
}
|
||||
|
||||
WASMSharedMemNode*
|
||||
shared_memory_set_memory_inst(WASMModuleCommon *module,
|
||||
WASMMemoryInstanceCommon *memory)
|
||||
{
|
||||
WASMSharedMemNode *node;
|
||||
bh_list_status ret;
|
||||
|
||||
if (!(node = wasm_runtime_malloc(sizeof(WASMSharedMemNode))))
|
||||
return NULL;
|
||||
|
||||
node->module = module;
|
||||
node->memory_inst = memory;
|
||||
node->ref_count = 1;
|
||||
if (os_mutex_init(&node->lock) != 0) {
|
||||
wasm_runtime_free(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_mutex_lock(&shared_memory_list_lock);
|
||||
ret = bh_list_insert(shared_memory_list, node);
|
||||
bh_assert(ret == BH_LIST_SUCCESS);
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
|
||||
(void)ret;
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Atomics wait && notify APIs */
|
||||
static uint32
|
||||
wait_address_hash(void *address)
|
||||
{
|
||||
return (uint32)(uintptr_t)address;
|
||||
}
|
||||
|
||||
static bool
|
||||
wait_address_equal(void *h1, void *h2)
|
||||
{
|
||||
return h1 == h2 ? true : false;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_wait_node_exists(bh_list *wait_list, AtomicWaitNode *node)
|
||||
{
|
||||
AtomicWaitNode *curr;
|
||||
curr = bh_list_first_elem(wait_list);
|
||||
|
||||
while (curr) {
|
||||
if (curr == node) {
|
||||
return true;
|
||||
}
|
||||
curr = bh_list_elem_next(curr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32
|
||||
notify_wait_list(bh_list *wait_list, uint32 count)
|
||||
{
|
||||
AtomicWaitNode *node, *next;
|
||||
uint32 i, notify_count = count;
|
||||
|
||||
if ((count == UINT32_MAX) || (count > wait_list->len))
|
||||
notify_count = wait_list->len;
|
||||
|
||||
node = bh_list_first_elem(wait_list);
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < notify_count; i++) {
|
||||
bh_assert(node);
|
||||
next = bh_list_elem_next(node);
|
||||
|
||||
node->status = S_NOTIFIED;
|
||||
/* wakeup */
|
||||
os_cond_signal(&node->wait_cond);
|
||||
|
||||
node = next;
|
||||
}
|
||||
|
||||
return notify_count;
|
||||
}
|
||||
|
||||
static AtomicWaitInfo *
|
||||
acquire_wait_info(void *address, bool create)
|
||||
{
|
||||
AtomicWaitInfo *wait_info = NULL;
|
||||
bh_list_status ret;
|
||||
|
||||
wait_info = (AtomicWaitInfo *)
|
||||
bh_hash_map_find(wait_map, address);
|
||||
|
||||
if (!create)
|
||||
return wait_info;
|
||||
|
||||
/* No wait info on this address, create new info */
|
||||
if (!wait_info) {
|
||||
if (!(wait_info =
|
||||
(AtomicWaitInfo *)wasm_runtime_malloc(sizeof(AtomicWaitInfo))))
|
||||
return NULL;
|
||||
memset(wait_info, 0, sizeof(AtomicWaitInfo));
|
||||
|
||||
/* init wait list */
|
||||
wait_info->wait_list = &wait_info->wait_list_head;
|
||||
ret = bh_list_init(wait_info->wait_list);
|
||||
bh_assert(ret == BH_LIST_SUCCESS);
|
||||
|
||||
/* init wait list lock */
|
||||
if (0 != os_mutex_init(&wait_info->wait_list_lock)) {
|
||||
wasm_runtime_free(wait_info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!bh_hash_map_insert(wait_map, address,
|
||||
(void *)wait_info)) {
|
||||
os_mutex_destroy(&wait_info->wait_list_lock);
|
||||
wasm_runtime_free(wait_info);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bh_assert(wait_info);
|
||||
(void)ret;
|
||||
return wait_info;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_wait_info(void *wait_info)
|
||||
{
|
||||
AtomicWaitNode *node, *next;
|
||||
|
||||
if (wait_info) {
|
||||
|
||||
node = bh_list_first_elem(((AtomicWaitInfo *)wait_info)->wait_list);
|
||||
|
||||
while (node) {
|
||||
next = bh_list_elem_next(node);
|
||||
os_mutex_destroy(&node->wait_lock);
|
||||
os_cond_destroy(&node->wait_cond);
|
||||
wasm_runtime_free(node);
|
||||
node = next;
|
||||
}
|
||||
|
||||
os_mutex_destroy(&((AtomicWaitInfo *)wait_info)->wait_list_lock);
|
||||
wasm_runtime_free(wait_info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
release_wait_info(HashMap *wait_map,
|
||||
AtomicWaitInfo *wait_info, void *address)
|
||||
{
|
||||
if (wait_info->wait_list->len == 0) {
|
||||
bh_hash_map_remove(wait_map, address, NULL, NULL);
|
||||
destroy_wait_info(wait_info);
|
||||
}
|
||||
}
|
||||
|
||||
uint32
|
||||
wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
uint64 expect, int64 timeout, bool wait64)
|
||||
{
|
||||
AtomicWaitInfo *wait_info;
|
||||
AtomicWaitNode *wait_node;
|
||||
bool check_ret, is_timeout;
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
|
||||
/* Currently we have only one memory instance */
|
||||
if (!module_inst->memories[0]->is_shared) {
|
||||
wasm_runtime_set_exception(module, "wait on unshared memory");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *aot_inst = (AOTModuleInstance *)module;
|
||||
AOTMemoryInstance *aot_memory =
|
||||
((AOTMemoryInstance **)aot_inst->memories.ptr)[0];
|
||||
/* Currently we have only one memory instance */
|
||||
if (!aot_memory->is_shared) {
|
||||
wasm_runtime_set_exception(module, "wait on unshared memory");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* acquire the wait info, create new one if not exists */
|
||||
wait_info = acquire_wait_info(address, true);
|
||||
|
||||
if (!wait_info) {
|
||||
wasm_runtime_set_exception(module, "failed to acquire wait_info");
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_mutex_lock(&wait_info->wait_list_lock);
|
||||
|
||||
if ((!wait64 && *(uint32*)address != (uint32)expect)
|
||||
|| (wait64 && *(uint64*)address != expect)) {
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
bh_list_status ret;
|
||||
|
||||
if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) {
|
||||
wasm_runtime_set_exception(module, "failed to create wait node");
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
return -1;
|
||||
}
|
||||
memset(wait_node, 0, sizeof(AtomicWaitNode));
|
||||
|
||||
if (0 != os_mutex_init(&wait_node->wait_lock)) {
|
||||
wasm_runtime_free(wait_node);
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != os_cond_init(&wait_node->wait_cond)) {
|
||||
os_mutex_destroy(&wait_node->wait_lock);
|
||||
wasm_runtime_free(wait_node);
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wait_node->status = S_WAITING;
|
||||
|
||||
ret = bh_list_insert(wait_info->wait_list, wait_node);
|
||||
bh_assert(ret == BH_LIST_SUCCESS);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
|
||||
/* condition wait start */
|
||||
os_mutex_lock(&wait_node->wait_lock);
|
||||
|
||||
if (timeout < 0)
|
||||
timeout = BHT_WAIT_FOREVER;
|
||||
os_cond_reltimedwait(&wait_node->wait_cond,
|
||||
&wait_node->wait_lock, timeout);
|
||||
|
||||
os_mutex_unlock(&wait_node->wait_lock);
|
||||
|
||||
/* Check the wait node status */
|
||||
os_mutex_lock(&wait_info->wait_list_lock);
|
||||
check_ret = is_wait_node_exists(wait_info->wait_list, wait_node);
|
||||
bh_assert(check_ret);
|
||||
|
||||
is_timeout = wait_node->status == S_WAITING ? true : false;
|
||||
|
||||
bh_list_remove(wait_info->wait_list, wait_node);
|
||||
os_mutex_destroy(&wait_node->wait_lock);
|
||||
os_cond_destroy(&wait_node->wait_cond);
|
||||
wasm_runtime_free(wait_node);
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
|
||||
release_wait_info(wait_map, wait_info, address);
|
||||
|
||||
(void)check_ret;
|
||||
return is_timeout ? 2 : 0;
|
||||
}
|
||||
|
||||
uint32
|
||||
wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module,
|
||||
void *address, uint32 count)
|
||||
{
|
||||
uint32 notify_result;
|
||||
AtomicWaitInfo *wait_info;
|
||||
|
||||
/* Nobody wait on this address */
|
||||
wait_info = acquire_wait_info(address, false);
|
||||
if (!wait_info)
|
||||
return 0;
|
||||
|
||||
os_mutex_lock(&wait_info->wait_list_lock);
|
||||
notify_result = notify_wait_list(wait_info->wait_list, count);
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
|
||||
release_wait_info(wait_map, wait_info, address);
|
||||
|
||||
return notify_result;
|
||||
}
|
68
core/iwasm/common/wasm_shared_memory.h
Normal file
68
core/iwasm/common/wasm_shared_memory.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _WASM_SHARED_MEMORY_H
|
||||
#define _WASM_SHARED_MEMORY_H
|
||||
|
||||
#include "bh_common.h"
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
#include "wasm_runtime.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
#include "aot_runtime.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct WASMSharedMemNode {
|
||||
bh_list_link l;
|
||||
/* Lock */
|
||||
korp_mutex lock;
|
||||
/* The module reference */
|
||||
WASMModuleCommon *module;
|
||||
/* The memory information */
|
||||
WASMMemoryInstanceCommon *memory_inst;
|
||||
|
||||
/* reference count */
|
||||
uint32 ref_count;
|
||||
} WASMSharedMemNode;
|
||||
|
||||
bool
|
||||
wasm_shared_memory_init();
|
||||
|
||||
void
|
||||
wasm_shared_memory_destroy();
|
||||
|
||||
WASMSharedMemNode*
|
||||
wasm_module_get_shared_memory(WASMModuleCommon *module);
|
||||
|
||||
int32
|
||||
shared_memory_inc_reference(WASMModuleCommon *module);
|
||||
|
||||
int32
|
||||
shared_memory_dec_reference(WASMModuleCommon *module);
|
||||
|
||||
WASMMemoryInstanceCommon*
|
||||
shared_memory_get_memory_inst(WASMSharedMemNode *node);
|
||||
|
||||
WASMSharedMemNode*
|
||||
shared_memory_set_memory_inst(WASMModuleCommon *module,
|
||||
WASMMemoryInstanceCommon *memory);
|
||||
|
||||
uint32
|
||||
wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
uint64 expect, int64 timeout, bool wait64);
|
||||
|
||||
uint32
|
||||
wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module,
|
||||
void *address, uint32 count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _WASM_SHARED_MEMORY_H */
|
|
@ -14,6 +14,15 @@ aot_get_last_error()
|
|||
return aot_error[0] == '\0' ? "" : aot_error;
|
||||
}
|
||||
|
||||
void
|
||||
aot_set_last_error_v(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(aot_error, sizeof(aot_error), format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
aot_set_last_error(const char *error)
|
||||
{
|
||||
|
@ -60,6 +69,10 @@ aot_create_mem_init_data_list(const WASMModule *module)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
data_list[i]->is_passive = module->data_segments[i]->is_passive;
|
||||
data_list[i]->memory_index = module->data_segments[i]->memory_index;
|
||||
#endif
|
||||
data_list[i]->offset = module->data_segments[i]->base_offset;
|
||||
data_list[i]->byte_count = module->data_segments[i]->data_length;
|
||||
memcpy(data_list[i]->bytes, module->data_segments[i]->data,
|
||||
|
@ -112,8 +125,18 @@ aot_create_table_init_data_list(const WASMModule *module)
|
|||
|
||||
data_list[i]->offset = module->table_segments[i].base_offset;
|
||||
data_list[i]->func_index_count = module->table_segments[i].function_count;
|
||||
memcpy(data_list[i]->func_indexes, module->table_segments[i].func_indexes,
|
||||
sizeof(uint32) * module->table_segments[i].function_count);
|
||||
data_list[i]->mode = module->table_segments[i].mode;
|
||||
data_list[i]->elem_type = module->table_segments[i].elem_type;
|
||||
/* runtime control it */
|
||||
data_list[i]->is_dropped = false;
|
||||
data_list[i]->table_index = module->table_segments[i].table_index;
|
||||
bh_memcpy_s(&data_list[i]->offset, sizeof(AOTInitExpr),
|
||||
&module->table_segments[i].base_offset, sizeof(AOTInitExpr));
|
||||
data_list[i]->func_index_count = module->table_segments[i].function_count;
|
||||
bh_memcpy_s(data_list[i]->func_indexes,
|
||||
sizeof(uint32) * module->table_segments[i].function_count,
|
||||
module->table_segments[i].func_indexes,
|
||||
sizeof(uint32) * module->table_segments[i].function_count);
|
||||
}
|
||||
|
||||
return data_list;
|
||||
|
@ -267,6 +290,7 @@ aot_create_import_funcs(const WASMModule *module)
|
|||
import_funcs[i].signature = import_func->signature;
|
||||
import_funcs[i].attachment = import_func->attachment;
|
||||
import_funcs[i].call_conv_raw = import_func->call_conv_raw;
|
||||
import_funcs[i].call_conv_wasm_c_api = false;
|
||||
/* Resolve function type index */
|
||||
for (j = 0; j < module->type_count; j++)
|
||||
if (import_func->func_type == module->types[j]) {
|
||||
|
@ -327,6 +351,8 @@ aot_create_funcs(const WASMModule *module)
|
|||
/* Resolve local variable info and code info */
|
||||
funcs[i]->local_count = func->local_count;
|
||||
funcs[i]->local_types = func->local_types;
|
||||
funcs[i]->param_cell_num = func->param_cell_num;
|
||||
funcs[i]->local_cell_num = func->local_cell_num;
|
||||
funcs[i]->code = func->code;
|
||||
funcs[i]->code_size = func->code_size;
|
||||
}
|
||||
|
@ -338,43 +364,12 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static AOTExportFunc *
|
||||
aot_create_export_funcs(const WASMModule *module,
|
||||
uint32 export_func_count)
|
||||
{
|
||||
AOTExportFunc *export_funcs;
|
||||
uint64 size;
|
||||
uint32 i, j = 0;
|
||||
|
||||
/* Allocate memory */
|
||||
size = sizeof(AOTExportFunc) * (uint64)export_func_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(export_funcs = wasm_runtime_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create each export function */
|
||||
for (i = 0; i < module->export_count; i++) {
|
||||
if (module->exports[i].kind == EXPORT_KIND_FUNC) {
|
||||
export_funcs[j].func_name = module->exports[i].name;
|
||||
export_funcs[j].func_index = module->exports[i].index;
|
||||
export_funcs[j].func_type =
|
||||
module->functions[module->exports[i].index
|
||||
- module->import_function_count]->func_type;
|
||||
/* Function pointer to be linked in JIT mode */
|
||||
export_funcs[j].func_ptr = NULL;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return export_funcs;
|
||||
}
|
||||
|
||||
AOTCompData*
|
||||
aot_create_comp_data(WASMModule *module)
|
||||
{
|
||||
AOTCompData *comp_data;
|
||||
uint32 import_global_data_size = 0, global_data_size = 0, i;
|
||||
uint32 import_global_data_size = 0, global_data_size = 0, i, j;
|
||||
uint64 size;
|
||||
|
||||
/* Allocate memory */
|
||||
if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) {
|
||||
|
@ -384,22 +379,53 @@ aot_create_comp_data(WASMModule *module)
|
|||
|
||||
memset(comp_data, 0, sizeof(AOTCompData));
|
||||
|
||||
/* Set memory page count */
|
||||
if (module->import_memory_count) {
|
||||
comp_data->num_bytes_per_page =
|
||||
module->import_memories[0].u.memory.num_bytes_per_page;
|
||||
comp_data->mem_init_page_count =
|
||||
module->import_memories[0].u.memory.init_page_count;
|
||||
comp_data->mem_max_page_count =
|
||||
module->import_memories[0].u.memory.max_page_count;
|
||||
comp_data->memory_count = module->import_memory_count + module->memory_count;
|
||||
|
||||
/* TODO: create import memories */
|
||||
|
||||
/* Allocate memory for memory array, reserve one AOTMemory space at least */
|
||||
if (!comp_data->memory_count)
|
||||
comp_data->memory_count = 1;
|
||||
|
||||
size = (uint64)comp_data->memory_count * sizeof(AOTMemory);
|
||||
if (size >= UINT32_MAX
|
||||
|| !(comp_data->memories = wasm_runtime_malloc((uint32)size))) {
|
||||
aot_set_last_error("create memories array failed.\n");
|
||||
goto fail;
|
||||
}
|
||||
else if (module->memory_count) {
|
||||
comp_data->num_bytes_per_page =
|
||||
module->memories[0].num_bytes_per_page;
|
||||
comp_data->mem_init_page_count =
|
||||
module->memories[0].init_page_count;
|
||||
comp_data->mem_max_page_count =
|
||||
module->memories[0].max_page_count;
|
||||
memset(comp_data->memories, 0, size);
|
||||
|
||||
if (!(module->import_memory_count + module->memory_count)) {
|
||||
comp_data->memories[0].num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
|
||||
}
|
||||
|
||||
/* Set memory page count */
|
||||
for (i = 0; i < module->import_memory_count + module->memory_count; i++) {
|
||||
if (i < module->import_memory_count) {
|
||||
comp_data->memories[i].memory_flags =
|
||||
module->import_memories[i].u.memory.flags;
|
||||
comp_data->memories[i].num_bytes_per_page =
|
||||
module->import_memories[i].u.memory.num_bytes_per_page;
|
||||
comp_data->memories[i].mem_init_page_count =
|
||||
module->import_memories[i].u.memory.init_page_count;
|
||||
comp_data->memories[i].mem_max_page_count =
|
||||
module->import_memories[i].u.memory.max_page_count;
|
||||
comp_data->memories[i].num_bytes_per_page =
|
||||
module->import_memories[i].u.memory.num_bytes_per_page;
|
||||
}
|
||||
else {
|
||||
j = i - module->import_memory_count;
|
||||
comp_data->memories[i].memory_flags =
|
||||
module->memories[j].flags;
|
||||
comp_data->memories[i].num_bytes_per_page =
|
||||
module->memories[j].num_bytes_per_page;
|
||||
comp_data->memories[i].mem_init_page_count =
|
||||
module->memories[j].init_page_count;
|
||||
comp_data->memories[i].mem_max_page_count =
|
||||
module->memories[j].max_page_count;
|
||||
comp_data->memories[i].num_bytes_per_page =
|
||||
module->memories[j].num_bytes_per_page;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create memory data segments */
|
||||
|
@ -409,11 +435,40 @@ aot_create_comp_data(WASMModule *module)
|
|||
aot_create_mem_init_data_list(module)))
|
||||
goto fail;
|
||||
|
||||
/* Set table size */
|
||||
if (module->import_table_count)
|
||||
comp_data->table_size = module->import_tables[0].u.table.init_size;
|
||||
else if (module->table_count)
|
||||
comp_data->table_size = module->tables[0].init_size;
|
||||
/* Create tables */
|
||||
comp_data->table_count = module->import_table_count + module->table_count;
|
||||
|
||||
if (comp_data->table_count > 0) {
|
||||
size = sizeof(AOTTable) * (uint64)comp_data->table_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(comp_data->tables = wasm_runtime_malloc((uint32)size))) {
|
||||
aot_set_last_error("create memories array failed.\n");
|
||||
goto fail;
|
||||
}
|
||||
memset(comp_data->tables, 0, size);
|
||||
for (i = 0; i < comp_data->table_count; i++) {
|
||||
if (i < module->import_table_count) {
|
||||
comp_data->tables[i].elem_type =
|
||||
module->import_tables[i].u.table.elem_type;
|
||||
comp_data->tables[i].table_flags =
|
||||
module->import_tables[i].u.table.flags;
|
||||
comp_data->tables[i].table_init_size =
|
||||
module->import_tables[i].u.table.init_size;
|
||||
comp_data->tables[i].table_max_size =
|
||||
module->import_tables[i].u.table.max_size;
|
||||
comp_data->tables[i].possible_grow =
|
||||
module->import_tables[i].u.table.possible_grow;
|
||||
}
|
||||
else {
|
||||
j = i - module->import_table_count;
|
||||
comp_data->tables[i].elem_type = module->tables[i].elem_type;
|
||||
comp_data->tables[i].table_flags = module->tables[i].flags;
|
||||
comp_data->tables[i].table_init_size = module->tables[i].init_size;
|
||||
comp_data->tables[i].table_max_size = module->tables[i].max_size;
|
||||
comp_data->tables[i].possible_grow = module->tables[i].possible_grow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create table data segments */
|
||||
comp_data->table_init_data_count = module->table_seg_count;
|
||||
|
@ -457,17 +512,20 @@ aot_create_comp_data(WASMModule *module)
|
|||
&& !(comp_data->funcs = aot_create_funcs(module)))
|
||||
goto fail;
|
||||
|
||||
/* Create export functions */
|
||||
for (i = 0; i < module->export_count; i++)
|
||||
if (module->exports[i].kind == EXPORT_KIND_FUNC)
|
||||
comp_data->export_func_count++;
|
||||
|
||||
if (comp_data->export_func_count
|
||||
&& !(comp_data->export_funcs = aot_create_export_funcs
|
||||
(module, comp_data->export_func_count)))
|
||||
goto fail;
|
||||
/* Create aux data/heap/stack information */
|
||||
comp_data->aux_data_end_global_index = module->aux_data_end_global_index;
|
||||
comp_data->aux_data_end = module->aux_data_end;
|
||||
comp_data->aux_heap_base_global_index = module->aux_heap_base_global_index;
|
||||
comp_data->aux_heap_base = module->aux_heap_base;
|
||||
comp_data->aux_stack_top_global_index = module->aux_stack_top_global_index;
|
||||
comp_data->aux_stack_bottom = module->aux_stack_bottom;
|
||||
comp_data->aux_stack_size = module->aux_stack_size;
|
||||
|
||||
comp_data->start_func_index = module->start_function;
|
||||
comp_data->malloc_func_index = module->malloc_function;
|
||||
comp_data->free_func_index = module->free_function;
|
||||
comp_data->retain_func_index = module->retain_function;
|
||||
|
||||
comp_data->wasm_module = module;
|
||||
|
||||
return comp_data;
|
||||
|
@ -484,10 +542,22 @@ aot_destroy_comp_data(AOTCompData *comp_data)
|
|||
if (!comp_data)
|
||||
return;
|
||||
|
||||
if (comp_data->import_memories)
|
||||
wasm_runtime_free(comp_data->import_memories);
|
||||
|
||||
if (comp_data->memories)
|
||||
wasm_runtime_free(comp_data->memories);
|
||||
|
||||
if (comp_data->mem_init_data_list)
|
||||
aot_destroy_mem_init_data_list(comp_data->mem_init_data_list,
|
||||
comp_data->mem_init_data_count);
|
||||
|
||||
if (comp_data->import_tables)
|
||||
wasm_runtime_free(comp_data->import_tables);
|
||||
|
||||
if (comp_data->tables)
|
||||
wasm_runtime_free(comp_data->tables);
|
||||
|
||||
if (comp_data->table_init_data_list)
|
||||
aot_destroy_table_init_data_list(comp_data->table_init_data_list,
|
||||
comp_data->table_init_data_count);
|
||||
|
@ -508,9 +578,6 @@ aot_destroy_comp_data(AOTCompData *comp_data)
|
|||
if (comp_data->funcs)
|
||||
aot_destroy_funcs(comp_data->funcs, comp_data->func_count);
|
||||
|
||||
if (comp_data->export_funcs)
|
||||
wasm_runtime_free(comp_data->export_funcs);
|
||||
|
||||
wasm_runtime_free(comp_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,11 +19,41 @@ extern "C" {
|
|||
|
||||
typedef InitializerExpression AOTInitExpr;
|
||||
typedef WASMType AOTFuncType;
|
||||
typedef WASMExport AOTExport;
|
||||
|
||||
/**
|
||||
* Import memory
|
||||
*/
|
||||
typedef struct AOTImportMemory {
|
||||
char *module_name;
|
||||
char *memory_name;
|
||||
uint32 memory_flags;
|
||||
uint32 num_bytes_per_page;
|
||||
uint32 mem_init_page_count;
|
||||
uint32 mem_max_page_count;
|
||||
} AOTImportMemory;
|
||||
|
||||
/**
|
||||
* Memory information
|
||||
*/
|
||||
typedef struct AOTMemory {
|
||||
/* memory info */
|
||||
uint32 memory_flags;
|
||||
uint32 num_bytes_per_page;
|
||||
uint32 mem_init_page_count;
|
||||
uint32 mem_max_page_count;
|
||||
} AOTMemory;
|
||||
|
||||
/**
|
||||
* A segment of memory init data
|
||||
*/
|
||||
typedef struct AOTMemInitData {
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
/* Passive flag */
|
||||
bool is_passive;
|
||||
/* memory index */
|
||||
uint32 memory_index;
|
||||
#endif
|
||||
/* Start address of init data */
|
||||
AOTInitExpr offset;
|
||||
/* Byte count */
|
||||
|
@ -32,10 +62,40 @@ typedef struct AOTMemInitData {
|
|||
uint8 bytes[1];
|
||||
} AOTMemInitData;
|
||||
|
||||
/**
|
||||
* Import table
|
||||
*/
|
||||
typedef struct AOTImportTable {
|
||||
char *module_name;
|
||||
char *table_name;
|
||||
uint32 table_flags;
|
||||
uint32 table_init_size;
|
||||
uint32 table_max_size;
|
||||
bool possible_grow;
|
||||
} AOTImportTable;
|
||||
|
||||
/**
|
||||
* Table
|
||||
*/
|
||||
typedef struct AOTTable {
|
||||
uint32 elem_type;
|
||||
uint32 table_flags;
|
||||
uint32 table_init_size;
|
||||
uint32 table_max_size;
|
||||
bool possible_grow;
|
||||
} AOTTable;
|
||||
|
||||
/**
|
||||
* A segment of table init data
|
||||
*/
|
||||
typedef struct AOTTableInitData {
|
||||
/* 0 to 7 */
|
||||
uint32 mode;
|
||||
/* funcref or externref, elemkind will be considered as funcref */
|
||||
uint32 elem_type;
|
||||
bool is_dropped;
|
||||
/* optional, only for active */
|
||||
uint32 table_index;
|
||||
/* Start address of init data */
|
||||
AOTInitExpr offset;
|
||||
/* Function index count */
|
||||
|
@ -88,6 +148,8 @@ typedef struct AOTImportFunc {
|
|||
/* attachment */
|
||||
void *attachment;
|
||||
bool call_conv_raw;
|
||||
bool call_conv_wasm_c_api;
|
||||
bool wasm_c_api_with_env;
|
||||
} AOTImportFunc;
|
||||
|
||||
/**
|
||||
|
@ -98,60 +160,71 @@ typedef struct AOTFunc {
|
|||
uint32 func_type_index;
|
||||
uint32 local_count;
|
||||
uint8 *local_types;
|
||||
uint16 param_cell_num;
|
||||
uint16 local_cell_num;
|
||||
uint32 code_size;
|
||||
uint8 *code;
|
||||
} AOTFunc;
|
||||
|
||||
/**
|
||||
* Export function
|
||||
*/
|
||||
typedef struct AOTExportFunc {
|
||||
char *func_name;
|
||||
AOTFuncType *func_type;
|
||||
/* function pointer linked */
|
||||
void *func_ptr;
|
||||
uint32 func_index;
|
||||
} AOTExportFunc;
|
||||
|
||||
typedef struct AOTCompData {
|
||||
/* Memory and memory init data info */
|
||||
uint32 num_bytes_per_page;
|
||||
uint32 mem_init_page_count;
|
||||
uint32 mem_max_page_count;
|
||||
/* Import memories */
|
||||
uint32 import_memory_count;
|
||||
AOTImportMemory *import_memories;
|
||||
|
||||
/* Memories */
|
||||
uint32 memory_count;
|
||||
AOTMemory *memories;
|
||||
|
||||
/* Memory init data info */
|
||||
uint32 mem_init_data_count;
|
||||
AOTMemInitData **mem_init_data_list;
|
||||
|
||||
/* Table and table init data info */
|
||||
uint32 table_size;
|
||||
AOTTableInitData **table_init_data_list;
|
||||
/* Import tables */
|
||||
uint32 import_table_count;
|
||||
AOTImportTable *import_tables;
|
||||
|
||||
/* Tables */
|
||||
uint32 table_count;
|
||||
AOTTable *tables;
|
||||
|
||||
/* Table init data info */
|
||||
uint32 table_init_data_count;
|
||||
AOTTableInitData **table_init_data_list;
|
||||
|
||||
AOTImportGlobal *import_globals;
|
||||
/* Import globals */
|
||||
uint32 import_global_count;
|
||||
AOTImportGlobal *import_globals;
|
||||
|
||||
AOTGlobal *globals;
|
||||
/* Globals */
|
||||
uint32 global_count;
|
||||
AOTGlobal *globals;
|
||||
|
||||
AOTFuncType **func_types;
|
||||
/* Function types */
|
||||
uint32 func_type_count;
|
||||
AOTFuncType **func_types;
|
||||
|
||||
AOTImportFunc *import_funcs;
|
||||
/* Import functions */
|
||||
uint32 import_func_count;
|
||||
AOTImportFunc *import_funcs;
|
||||
|
||||
AOTFunc **funcs;
|
||||
/* Functions */
|
||||
uint32 func_count;
|
||||
AOTFunc **funcs;
|
||||
|
||||
AOTExportFunc *export_funcs;
|
||||
uint32 export_func_count;
|
||||
|
||||
uint32 start_func_index;
|
||||
uint32 addr_data_size;
|
||||
uint32 global_data_size;
|
||||
|
||||
uint32 llvm_aux_data_end;
|
||||
uint32 llvm_aux_stack_bottom;
|
||||
uint32 llvm_aux_stack_size;
|
||||
uint32 llvm_aux_stack_global_index;
|
||||
uint32 start_func_index;
|
||||
uint32 malloc_func_index;
|
||||
uint32 free_func_index;
|
||||
uint32 retain_func_index;
|
||||
|
||||
uint32 aux_data_end_global_index;
|
||||
uint32 aux_data_end;
|
||||
uint32 aux_heap_base_global_index;
|
||||
uint32 aux_heap_base;
|
||||
uint32 aux_stack_top_global_index;
|
||||
uint32 aux_stack_bottom;
|
||||
uint32 aux_stack_size;
|
||||
|
||||
WASMModule *wasm_module;
|
||||
} AOTCompData;
|
||||
|
@ -168,6 +241,32 @@ aot_get_last_error();
|
|||
void
|
||||
aot_set_last_error(const char *error);
|
||||
|
||||
void
|
||||
aot_set_last_error_v(const char *format, ...);
|
||||
|
||||
#if BH_DEBUG != 0
|
||||
#define HANDLE_FAILURE(callee) do { \
|
||||
aot_set_last_error_v("call %s failed in %s:%d", (callee),\
|
||||
__FUNCTION__, __LINE__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define HANDLE_FAILURE(callee) do { \
|
||||
aot_set_last_error_v("call %s failed", (callee)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
static inline uint32
|
||||
aot_get_tbl_data_slots(const AOTTable *tbl)
|
||||
{
|
||||
return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
|
||||
}
|
||||
|
||||
static inline uint32
|
||||
aot_get_imp_tbl_data_slots(const AOTImportTable *tbl)
|
||||
{
|
||||
return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -46,12 +46,35 @@ typedef enum IntArithmetic {
|
|||
INT_REM_U
|
||||
} IntArithmetic;
|
||||
|
||||
typedef enum V128Arithmetic {
|
||||
V128_ADD = 0,
|
||||
V128_ADD_SATURATE_S,
|
||||
V128_ADD_SATURATE_U,
|
||||
V128_SUB,
|
||||
V128_SUB_SATURATE_S,
|
||||
V128_SUB_SATURATE_U,
|
||||
V128_MUL,
|
||||
V128_DIV,
|
||||
V128_NEG,
|
||||
V128_MIN,
|
||||
V128_MAX,
|
||||
} V128Arithmetic;
|
||||
|
||||
typedef enum IntBitwise {
|
||||
INT_AND = 0,
|
||||
INT_OR,
|
||||
INT_XOR,
|
||||
} IntBitwise;
|
||||
|
||||
typedef enum V128Bitwise {
|
||||
V128_NOT,
|
||||
V128_AND,
|
||||
V128_ANDNOT,
|
||||
V128_OR,
|
||||
V128_XOR,
|
||||
V128_BITSELECT
|
||||
} V128Bitwise;
|
||||
|
||||
typedef enum IntShift {
|
||||
INT_SHL = 0,
|
||||
INT_SHR_S,
|
||||
|
@ -79,6 +102,34 @@ typedef enum FloatArithmetic {
|
|||
FLOAT_MAX
|
||||
} FloatArithmetic;
|
||||
|
||||
static inline bool
|
||||
check_type_compatible(uint8 src_type, uint8 dst_type)
|
||||
{
|
||||
if (src_type == dst_type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ext i1 to i32 */
|
||||
if (src_type == VALUE_TYPE_I1 && dst_type == VALUE_TYPE_I32) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* i32 <==> func.ref, i32 <==> extern.ref */
|
||||
if (src_type == VALUE_TYPE_I32
|
||||
&& (dst_type == VALUE_TYPE_EXTERNREF
|
||||
|| dst_type == VALUE_TYPE_FUNCREF)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dst_type == VALUE_TYPE_I32
|
||||
&& (src_type == VALUE_TYPE_FUNCREF
|
||||
|| src_type == VALUE_TYPE_EXTERNREF)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define CHECK_STACK() do { \
|
||||
if (!func_ctx->block_stack.block_list_end) { \
|
||||
aot_set_last_error("WASM block stack underflow."); \
|
||||
|
@ -96,11 +147,8 @@ typedef enum FloatArithmetic {
|
|||
CHECK_STACK(); \
|
||||
aot_value = aot_value_stack_pop \
|
||||
(&func_ctx->block_stack.block_list_end->value_stack); \
|
||||
if ((value_type != VALUE_TYPE_I32 \
|
||||
&& aot_value->type != value_type) \
|
||||
|| (value_type == VALUE_TYPE_I32 \
|
||||
&& (aot_value->type != VALUE_TYPE_I32 \
|
||||
&& aot_value->type != VALUE_TYPE_I1))) { \
|
||||
if (!check_type_compatible(aot_value->type, \
|
||||
value_type)) { \
|
||||
aot_set_last_error("invalid WASM stack data type."); \
|
||||
wasm_runtime_free(aot_value); \
|
||||
goto fail; \
|
||||
|
@ -108,12 +156,23 @@ typedef enum FloatArithmetic {
|
|||
if (aot_value->type == value_type) \
|
||||
llvm_value = aot_value->value; \
|
||||
else { \
|
||||
bh_assert(aot_value->type == VALUE_TYPE_I1); \
|
||||
if (!(llvm_value = LLVMBuildZExt(comp_ctx->builder, \
|
||||
aot_value->value, I32_TYPE, "i1toi32"))) { \
|
||||
aot_set_last_error("invalid WASM stack data type.");\
|
||||
wasm_runtime_free(aot_value); \
|
||||
goto fail; \
|
||||
if (aot_value->type == VALUE_TYPE_I1) { \
|
||||
if (!(llvm_value = LLVMBuildZExt(comp_ctx->builder, \
|
||||
aot_value->value, I32_TYPE, "i1toi32"))) { \
|
||||
aot_set_last_error("invalid WASM stack " \
|
||||
"data type."); \
|
||||
wasm_runtime_free(aot_value); \
|
||||
goto fail; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
bh_assert(aot_value->type == VALUE_TYPE_I32 \
|
||||
|| aot_value->type == VALUE_TYPE_FUNCREF \
|
||||
|| aot_value->type == VALUE_TYPE_EXTERNREF); \
|
||||
bh_assert(value_type == VALUE_TYPE_I32 \
|
||||
|| value_type == VALUE_TYPE_FUNCREF \
|
||||
|| value_type == VALUE_TYPE_EXTERNREF); \
|
||||
llvm_value = aot_value->value; \
|
||||
} \
|
||||
} \
|
||||
wasm_runtime_free(aot_value); \
|
||||
|
@ -123,6 +182,9 @@ typedef enum FloatArithmetic {
|
|||
#define POP_I64(v) POP(v, VALUE_TYPE_I64)
|
||||
#define POP_F32(v) POP(v, VALUE_TYPE_F32)
|
||||
#define POP_F64(v) POP(v, VALUE_TYPE_F64)
|
||||
#define POP_V128(v) POP(v, VALUE_TYPE_V128)
|
||||
#define POP_FUNCREF(v) POP(v, VALUE_TYPE_FUNCREF)
|
||||
#define POP_EXTERNREF(v) POP(v, VALUE_TYPE_EXTERNREF)
|
||||
|
||||
#define POP_COND(llvm_value) do { \
|
||||
AOTValue *aot_value; \
|
||||
|
@ -156,11 +218,11 @@ typedef enum FloatArithmetic {
|
|||
goto fail; \
|
||||
} \
|
||||
aot_value = wasm_runtime_malloc(sizeof(AOTValue)); \
|
||||
memset(aot_value, 0, sizeof(AOTValue)); \
|
||||
if (!aot_value) { \
|
||||
aot_set_last_error("allocate memory failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
memset(aot_value, 0, sizeof(AOTValue)); \
|
||||
aot_value->type = value_type; \
|
||||
aot_value->value = llvm_value; \
|
||||
aot_value_stack_push \
|
||||
|
@ -172,7 +234,10 @@ typedef enum FloatArithmetic {
|
|||
#define PUSH_I64(v) PUSH(v, VALUE_TYPE_I64)
|
||||
#define PUSH_F32(v) PUSH(v, VALUE_TYPE_F32)
|
||||
#define PUSH_F64(v) PUSH(v, VALUE_TYPE_F64)
|
||||
#define PUSH_V128(v) PUSH(v, VALUE_TYPE_V128)
|
||||
#define PUSH_COND(v) PUSH(v, VALUE_TYPE_I1)
|
||||
#define PUSH_FUNCREF(v) PUSH(v, VALUE_TYPE_FUNCREF)
|
||||
#define PUSH_EXTERNREF(v) PUSH(v, VALUE_TYPE_EXTERNREF)
|
||||
|
||||
#define TO_LLVM_TYPE(wasm_type) \
|
||||
wasm_type_to_llvm_type(&comp_ctx->basic_types, wasm_type)
|
||||
|
@ -192,7 +257,8 @@ typedef enum FloatArithmetic {
|
|||
#define INT64_PTR_TYPE comp_ctx->basic_types.int64_ptr_type
|
||||
#define F32_PTR_TYPE comp_ctx->basic_types.float32_ptr_type
|
||||
#define F64_PTR_TYPE comp_ctx->basic_types.float64_ptr_type
|
||||
#define VOID_PTR_TYPE comp_ctx->basic_types.void_ptr_type
|
||||
#define FUNC_REF_TYPE comp_ctx->basic_types.funcref_type
|
||||
#define EXTERN_REF_TYPE comp_ctx->basic_types.externref_type
|
||||
|
||||
#define I32_CONST(v) LLVMConstInt(I32_TYPE, v, true)
|
||||
#define I64_CONST(v) LLVMConstInt(I64_TYPE, v, true)
|
||||
|
@ -209,6 +275,9 @@ typedef enum FloatArithmetic {
|
|||
#define I32_TWO (comp_ctx->llvm_consts.i32_two)
|
||||
#define I32_THREE (comp_ctx->llvm_consts.i32_three)
|
||||
#define I32_FOUR (comp_ctx->llvm_consts.i32_four)
|
||||
#define I32_FIVE (comp_ctx->llvm_consts.i32_five)
|
||||
#define I32_SIX (comp_ctx->llvm_consts.i32_six)
|
||||
#define I32_SEVEN (comp_ctx->llvm_consts.i32_seven)
|
||||
#define I32_EIGHT (comp_ctx->llvm_consts.i32_eight)
|
||||
#define I32_NEG_ONE (comp_ctx->llvm_consts.i32_neg_one)
|
||||
#define I64_NEG_ONE (comp_ctx->llvm_consts.i64_neg_one)
|
||||
|
@ -219,6 +288,38 @@ typedef enum FloatArithmetic {
|
|||
#define I64_63 (comp_ctx->llvm_consts.i64_63)
|
||||
#define I64_64 (comp_ctx->llvm_consts.i64_64)
|
||||
|
||||
#define V128_TYPE comp_ctx->basic_types.v128_type
|
||||
#define V128_PTR_TYPE comp_ctx->basic_types.v128_ptr_type
|
||||
#define V128_i8x16_TYPE comp_ctx->basic_types.i8x16_vec_type
|
||||
#define V128_i16x8_TYPE comp_ctx->basic_types.i16x8_vec_type
|
||||
#define V128_i32x4_TYPE comp_ctx->basic_types.i32x4_vec_type
|
||||
#define V128_i64x2_TYPE comp_ctx->basic_types.i64x2_vec_type
|
||||
#define V128_f32x4_TYPE comp_ctx->basic_types.f32x4_vec_type
|
||||
#define V128_f64x2_TYPE comp_ctx->basic_types.f64x2_vec_type
|
||||
|
||||
#define V128_ZERO (comp_ctx->llvm_consts.v128_zero)
|
||||
#define V128_i8x16_ZERO (comp_ctx->llvm_consts.i8x16_vec_zero)
|
||||
#define V128_i16x8_ZERO (comp_ctx->llvm_consts.i16x8_vec_zero)
|
||||
#define V128_i32x4_ZERO (comp_ctx->llvm_consts.i32x4_vec_zero)
|
||||
#define V128_i64x2_ZERO (comp_ctx->llvm_consts.i64x2_vec_zero)
|
||||
#define V128_f32x4_ZERO (comp_ctx->llvm_consts.f32x4_vec_zero)
|
||||
#define V128_f64x2_ZERO (comp_ctx->llvm_consts.f64x2_vec_zero)
|
||||
|
||||
#define REF_NULL (comp_ctx->llvm_consts.i32_neg_one)
|
||||
|
||||
#define TO_V128_i8x16(v) LLVMBuildBitCast(comp_ctx->builder, v, \
|
||||
V128_i8x16_TYPE, "i8x16_val")
|
||||
#define TO_V128_i16x8(v) LLVMBuildBitCast(comp_ctx->builder, v, \
|
||||
V128_i16x8_TYPE, "i16x8_val")
|
||||
#define TO_V128_i32x4(v) LLVMBuildBitCast(comp_ctx->builder, v, \
|
||||
V128_i32x4_TYPE, "i32x4_val")
|
||||
#define TO_V128_i64x2(v) LLVMBuildBitCast(comp_ctx->builder, v, \
|
||||
V128_i64x2_TYPE, "i64x2_val")
|
||||
#define TO_V128_f32x4(v) LLVMBuildBitCast(comp_ctx->builder, v, \
|
||||
V128_f32x4_TYPE, "f32x4_val")
|
||||
#define TO_V128_f64x2(v) LLVMBuildBitCast(comp_ctx->builder, v, \
|
||||
V128_f64x2_TYPE, "f64x2_val")
|
||||
|
||||
#define CHECK_LLVM_CONST(v) do { \
|
||||
if (!v) { \
|
||||
aot_set_last_error("create llvm const failed."); \
|
||||
|
@ -226,6 +327,36 @@ typedef enum FloatArithmetic {
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#define GET_AOT_FUNCTION(name, argc) do { \
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types, \
|
||||
argc, false))) { \
|
||||
aot_set_last_error("llvm add function type failed."); \
|
||||
return false; \
|
||||
} \
|
||||
if (comp_ctx->is_jit_mode) { \
|
||||
/* JIT mode, call the function directly */ \
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { \
|
||||
aot_set_last_error("llvm add pointer type failed."); \
|
||||
return false; \
|
||||
} \
|
||||
if (!(value = I64_CONST((uint64)(uintptr_t)name)) \
|
||||
|| !(func = LLVMConstIntToPtr(value, func_ptr_type))) { \
|
||||
aot_set_last_error("create LLVM value failed."); \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
char *func_name = #name; \
|
||||
/* AOT mode, delcare the function */ \
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) \
|
||||
&& !(func = LLVMAddFunction(comp_ctx->module, \
|
||||
func_name, func_type))) { \
|
||||
aot_set_last_error("llvm add function failed."); \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
bool
|
||||
aot_compile_wasm(AOTCompContext *comp_ctx);
|
||||
|
||||
|
@ -237,9 +368,19 @@ aot_emit_aot_file(AOTCompContext *comp_ctx,
|
|||
AOTCompData *comp_data,
|
||||
const char *file_name);
|
||||
|
||||
uint8_t*
|
||||
aot_emit_aot_file_buf(AOTCompContext *comp_ctx,
|
||||
AOTCompData *comp_data,
|
||||
uint32_t *p_aot_file_size);
|
||||
|
||||
bool
|
||||
aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name);
|
||||
|
||||
uint8_t*
|
||||
aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size,
|
||||
uint32_t opt_level, uint32_t size_level,
|
||||
uint32_t *p_aot_file_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -124,8 +124,18 @@ get_mem_init_data_size(AOTMemInitData *mem_init_data)
|
|||
{
|
||||
/* init expr type (4 bytes) + init expr value (8 bytes)
|
||||
+ byte count (4 bytes) + bytes */
|
||||
return (uint32)(sizeof(uint32) + sizeof(uint64)
|
||||
+ sizeof(uint32) + mem_init_data->byte_count);
|
||||
uint32 total_size =
|
||||
(uint32)(sizeof(uint32) + sizeof(uint64)
|
||||
+ sizeof(uint32) + mem_init_data->byte_count);
|
||||
|
||||
/* bulk_memory enabled:
|
||||
is_passive (4 bytes) + memory_index (4 bytes)
|
||||
bulk memory disabled:
|
||||
placeholder (4 bytes) + placeholder (4 bytes)
|
||||
*/
|
||||
total_size += (sizeof(uint32) + sizeof(uint32));
|
||||
|
||||
return total_size;
|
||||
}
|
||||
|
||||
static uint32
|
||||
|
@ -142,12 +152,30 @@ get_mem_init_data_list_size(AOTMemInitData **mem_init_data_list,
|
|||
return size;
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_import_memory_size(AOTCompData *comp_data)
|
||||
{
|
||||
/* currently we only emit import_memory_count = 0 */
|
||||
return sizeof(uint32);
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_memory_size(AOTCompData *comp_data)
|
||||
{
|
||||
/* memory_count + count * (memory_flags + num_bytes_per_page +
|
||||
init_page_count + max_page_count) */
|
||||
return (uint32)(sizeof(uint32)
|
||||
+ comp_data->memory_count * sizeof(uint32) * 4);
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_mem_info_size(AOTCompData *comp_data)
|
||||
{
|
||||
/* num bytes per page + init page count + max page count
|
||||
+ init data count + init data list */
|
||||
return (uint32)sizeof(uint32) * 4
|
||||
/* import_memory_size + memory_size
|
||||
+ init_data_count + init_data_list */
|
||||
return get_import_memory_size(comp_data)
|
||||
+ get_memory_size(comp_data)
|
||||
+ (uint32)sizeof(uint32)
|
||||
+ get_mem_init_data_list_size(comp_data->mem_init_data_list,
|
||||
comp_data->mem_init_data_count);
|
||||
}
|
||||
|
@ -155,9 +183,14 @@ get_mem_info_size(AOTCompData *comp_data)
|
|||
static uint32
|
||||
get_table_init_data_size(AOTTableInitData *table_init_data)
|
||||
{
|
||||
/* init expr type (4 bytes) + init expr value (8 bytes)
|
||||
+ func index count (4 bytes) + func indexes */
|
||||
return (uint32)(sizeof(uint32) + sizeof(uint64) + sizeof(uint32)
|
||||
/*
|
||||
* mode (4 bytes), elem_type (4 bytes), do not need is_dropped field
|
||||
*
|
||||
* table_index(4 bytes) + init expr type (4 bytes) + init expr value (8 bytes)
|
||||
* + func index count (4 bytes) + func indexes
|
||||
*/
|
||||
return (uint32)(sizeof(uint32) * 2 + sizeof(uint32) + sizeof(uint32)
|
||||
+ sizeof(uint64) + sizeof(uint32)
|
||||
+ sizeof(uint32) * table_init_data->func_index_count);
|
||||
}
|
||||
|
||||
|
@ -165,9 +198,24 @@ static uint32
|
|||
get_table_init_data_list_size(AOTTableInitData **table_init_data_list,
|
||||
uint32 table_init_data_count)
|
||||
{
|
||||
/*
|
||||
* ------------------------------
|
||||
* | table_init_data_count
|
||||
* ------------------------------
|
||||
* | | U32 mode
|
||||
* | AOTTableInitData[N] | U32 elem_type
|
||||
* | | U32 table_index
|
||||
* | | U32 offset.init_expr_type
|
||||
* | | U64 offset.u.i64
|
||||
* | | U32 func_index_count
|
||||
* | | U32[func_index_count]
|
||||
* ------------------------------
|
||||
*/
|
||||
AOTTableInitData **table_init_data = table_init_data_list;
|
||||
uint32 size = 0, i;
|
||||
|
||||
size = (uint32)sizeof(uint32);
|
||||
|
||||
for (i = 0; i < table_init_data_count; i++, table_init_data++) {
|
||||
size = align_uint(size, 4);
|
||||
size += get_table_init_data_size(*table_init_data);
|
||||
|
@ -175,11 +223,69 @@ get_table_init_data_list_size(AOTTableInitData **table_init_data_list,
|
|||
return size;
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_import_table_size(AOTCompData *comp_data)
|
||||
{
|
||||
/*
|
||||
* ------------------------------
|
||||
* | import_table_count
|
||||
* ------------------------------
|
||||
* | | U32 table_init_size
|
||||
* | | ----------------------
|
||||
* | AOTImpotTable[N] | U32 table_init_size
|
||||
* | | ----------------------
|
||||
* | | U32 possible_grow (convenient than U8)
|
||||
* ------------------------------
|
||||
*/
|
||||
return (uint32)(sizeof(uint32)
|
||||
+ comp_data->import_table_count
|
||||
* (sizeof(uint32) * 3));
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_table_size(AOTCompData *comp_data)
|
||||
{
|
||||
/*
|
||||
* ------------------------------
|
||||
* | table_count
|
||||
* ------------------------------
|
||||
* | | U32 elem_type
|
||||
* | AOTTable[N] | U32 table_flags
|
||||
* | | U32 table_init_size
|
||||
* | | U32 table_max_size
|
||||
* | | U32 possible_grow (convenient than U8)
|
||||
* ------------------------------
|
||||
*/
|
||||
return (uint32)(sizeof(uint32)
|
||||
+ comp_data->table_count
|
||||
* (sizeof(uint32) * 5));
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_table_info_size(AOTCompData *comp_data)
|
||||
{
|
||||
/* table size + init data count + init data list */
|
||||
return (uint32)sizeof(uint32) * 2
|
||||
/*
|
||||
* ------------------------------
|
||||
* | import_table_count
|
||||
* ------------------------------
|
||||
* |
|
||||
* | AOTImportTable[import_table_count]
|
||||
* |
|
||||
* ------------------------------
|
||||
* | table_count
|
||||
* ------------------------------
|
||||
* |
|
||||
* | AOTTable[table_count]
|
||||
* |
|
||||
* ------------------------------
|
||||
* | table_init_data_count
|
||||
* ------------------------------
|
||||
* |
|
||||
* | AOTTableInitData*[table_init_data_count]
|
||||
* |
|
||||
* ------------------------------
|
||||
*/
|
||||
return get_import_table_size(comp_data) + get_table_size(comp_data)
|
||||
+ get_table_init_data_list_size(comp_data->table_init_data_list,
|
||||
comp_data->table_init_data_count);
|
||||
}
|
||||
|
@ -251,9 +357,14 @@ get_import_global_info_size(AOTCompData *comp_data)
|
|||
static uint32
|
||||
get_global_size(AOTGlobal *global)
|
||||
{
|
||||
/* type (1 byte) + is_mutable (1 byte)
|
||||
+ init expr type (2 byes) + init expr value (8 byes) */
|
||||
return sizeof(uint8) * 2 + sizeof(uint16) + sizeof(uint64);
|
||||
if (global->init_expr.init_expr_type != INIT_EXPR_TYPE_V128_CONST)
|
||||
/* type (1 byte) + is_mutable (1 byte)
|
||||
+ init expr type (2 byes) + init expr value (8 byes) */
|
||||
return sizeof(uint8) * 2 + sizeof(uint16) + sizeof(uint64);
|
||||
else
|
||||
/* type (1 byte) + is_mutable (1 byte)
|
||||
+ init expr type (2 byes) + v128 value (16 byes) */
|
||||
return sizeof(uint8) * 2 + sizeof(uint16) + sizeof(uint64) * 2;
|
||||
}
|
||||
|
||||
static uint32
|
||||
|
@ -372,9 +483,8 @@ get_init_data_section_size(AOTCompData *comp_data, AOTObjectData *obj_data)
|
|||
size = align_uint(size, 4);
|
||||
size += (uint32)sizeof(uint32) * 2;
|
||||
|
||||
/* llvm aux data end + llvm aux stack bottom
|
||||
+ llvm aux stack size + llvm stack global index */
|
||||
size += sizeof(uint32) * 4;
|
||||
/* aux data/heap/stack data */
|
||||
size += sizeof(uint32) * 7;
|
||||
|
||||
size += get_object_data_section_info_size(obj_data);
|
||||
return size;
|
||||
|
@ -402,23 +512,22 @@ get_func_section_size(AOTCompData *comp_data, AOTObjectData *obj_data)
|
|||
}
|
||||
|
||||
static uint32
|
||||
get_export_func_size(AOTExportFunc *export_func)
|
||||
get_export_size(AOTExport *export)
|
||||
{
|
||||
/* export func index + export func name */
|
||||
return (uint32)sizeof(uint32)
|
||||
+ get_string_size(export_func->func_name);
|
||||
/* export index + export kind + 1 byte padding + export name */
|
||||
return (uint32)sizeof(uint32) + sizeof(uint8) + 1
|
||||
+ get_string_size(export->name);
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_export_funcs_size(AOTExportFunc *export_funcs,
|
||||
uint32 export_func_count)
|
||||
get_exports_size(AOTExport *exports, uint32 export_count)
|
||||
{
|
||||
AOTExportFunc *export_func = export_funcs;
|
||||
AOTExport *export = exports;
|
||||
uint32 size = 0, i;
|
||||
|
||||
for (i = 0; i < export_func_count; i++, export_func++) {
|
||||
for (i = 0; i < export_count; i++, export++) {
|
||||
size = align_uint(size, 4);
|
||||
size += get_export_func_size(export_func);
|
||||
size += get_export_size(export);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
@ -426,10 +535,10 @@ get_export_funcs_size(AOTExportFunc *export_funcs,
|
|||
static uint32
|
||||
get_export_section_size(AOTCompData *comp_data)
|
||||
{
|
||||
/* export func count + export funcs */
|
||||
/* export count + exports */
|
||||
return (uint32)sizeof(uint32)
|
||||
+ get_export_funcs_size(comp_data->export_funcs,
|
||||
comp_data->export_func_count);
|
||||
+ get_exports_size(comp_data->wasm_module->exports,
|
||||
comp_data->wasm_module->export_count);
|
||||
}
|
||||
|
||||
static uint32
|
||||
|
@ -682,7 +791,8 @@ get_relocation_section_size(AOTObjectData *obj_data)
|
|||
}
|
||||
|
||||
static uint32
|
||||
get_aot_file_size(AOTCompData *comp_data, AOTObjectData *obj_data)
|
||||
get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
||||
AOTObjectData *obj_data)
|
||||
{
|
||||
uint32 size = 0;
|
||||
|
||||
|
@ -753,10 +863,28 @@ exchange_uint32(uint8 *p_data)
|
|||
static void
|
||||
exchange_uint64(uint8 *pData)
|
||||
{
|
||||
uint32 value;
|
||||
|
||||
value = *(uint32 *)pData;
|
||||
*(uint32 *)pData = *(uint32 *)(pData + 4);
|
||||
*(uint32 *)(pData + 4) = value;
|
||||
exchange_uint32(pData);
|
||||
exchange_uint32(pData + 4);
|
||||
}
|
||||
|
||||
static void
|
||||
exchange_uint128(uint8 *pData)
|
||||
{
|
||||
/* swap high 64bit and low 64bit */
|
||||
uint64 value = *(uint64*)pData;
|
||||
*(uint64*)pData = *(uint64*)(pData + 8);
|
||||
*(uint64*)(pData + 8) = value;
|
||||
/* exchange high 64bit */
|
||||
exchange_uint64(pData);
|
||||
/* exchange low 64bit */
|
||||
exchange_uint64(pData + 8);
|
||||
}
|
||||
|
||||
static union {
|
||||
int a;
|
||||
char b;
|
||||
|
@ -804,6 +932,17 @@ static union {
|
|||
offset += (uint32)sizeof(uint64); \
|
||||
} while (0)
|
||||
|
||||
#define EMIT_V128(v) do { \
|
||||
uint64 *t = (uint64*)v.i64x2; \
|
||||
CHECK_BUF(16); \
|
||||
if (!is_little_endian()) \
|
||||
exchange_uint128((uint8 *)t); \
|
||||
PUT_U64_TO_ADDR(buf + offset, t[0]); \
|
||||
offset += (uint32)sizeof(uint64); \
|
||||
PUT_U64_TO_ADDR(buf + offset, t[1]); \
|
||||
offset += (uint32)sizeof(uint64); \
|
||||
} while (0)
|
||||
|
||||
#define EMIT_BUF(v, len) do { \
|
||||
CHECK_BUF(len); \
|
||||
memcpy(buf + offset, v, len); \
|
||||
|
@ -868,20 +1007,46 @@ aot_emit_target_info_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
|
||||
static bool
|
||||
aot_emit_mem_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||
AOTCompData *comp_data, AOTObjectData *obj_data)
|
||||
AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
||||
AOTObjectData *obj_data)
|
||||
{
|
||||
uint32 offset = *p_offset, i;
|
||||
AOTMemInitData **init_datas = comp_data->mem_init_data_list;
|
||||
|
||||
*p_offset = offset = align_uint(offset, 4);
|
||||
|
||||
EMIT_U32(comp_data->num_bytes_per_page);
|
||||
EMIT_U32(comp_data->mem_init_page_count);
|
||||
EMIT_U32(comp_data->mem_max_page_count);
|
||||
EMIT_U32(comp_data->mem_init_data_count);
|
||||
/* Emit import memory count, only emit 0 currently.
|
||||
TODO: emit the actual import memory count and
|
||||
the full import memory info. */
|
||||
EMIT_U32(0);
|
||||
|
||||
/* Emit memory count */
|
||||
EMIT_U32(comp_data->memory_count);
|
||||
/* Emit memory items */
|
||||
for (i = 0; i < comp_data->memory_count; i++) {
|
||||
EMIT_U32(comp_data->memories[i].memory_flags);
|
||||
EMIT_U32(comp_data->memories[i].num_bytes_per_page);
|
||||
EMIT_U32(comp_data->memories[i].mem_init_page_count);
|
||||
EMIT_U32(comp_data->memories[i].mem_max_page_count);
|
||||
}
|
||||
|
||||
/* Emit mem init data count */
|
||||
EMIT_U32(comp_data->mem_init_data_count);
|
||||
/* Emit mem init data items */
|
||||
for (i = 0; i < comp_data->mem_init_data_count; i++) {
|
||||
offset = align_uint(offset, 4);
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
if (comp_ctx->enable_bulk_memory) {
|
||||
EMIT_U32(init_datas[i]->is_passive);
|
||||
EMIT_U32(init_datas[i]->memory_index);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* emit two placeholder to keep the same size */
|
||||
EMIT_U32(0);
|
||||
EMIT_U32(0);
|
||||
}
|
||||
EMIT_U32(init_datas[i]->offset.init_expr_type);
|
||||
EMIT_U64(init_datas[i]->offset.u.i64);
|
||||
EMIT_U32(init_datas[i]->byte_count);
|
||||
|
@ -907,11 +1072,38 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
|
||||
*p_offset = offset = align_uint(offset, 4);
|
||||
|
||||
EMIT_U32(comp_data->table_size);
|
||||
EMIT_U32(comp_data->table_init_data_count);
|
||||
/* Emit import table count */
|
||||
EMIT_U32(comp_data->import_table_count);
|
||||
/* Emit table items */
|
||||
for (i = 0; i < comp_data->import_table_count; i++) {
|
||||
/* TODO:
|
||||
* EMIT_STR(comp_data->import_tables[i].module_name );
|
||||
* EMIT_STR(comp_data->import_tables[i].table_name);
|
||||
*/
|
||||
EMIT_U32(comp_data->import_tables[i].table_init_size);
|
||||
EMIT_U32(comp_data->import_tables[i].table_max_size);
|
||||
EMIT_U32(comp_data->import_tables[i].possible_grow & 0x000000FF);
|
||||
}
|
||||
|
||||
/* Emit table count */
|
||||
EMIT_U32(comp_data->table_count);
|
||||
/* Emit table items */
|
||||
for (i = 0; i < comp_data->table_count; i++) {
|
||||
EMIT_U32(comp_data->tables[i].elem_type);
|
||||
EMIT_U32(comp_data->tables[i].table_flags);
|
||||
EMIT_U32(comp_data->tables[i].table_init_size);
|
||||
EMIT_U32(comp_data->tables[i].table_max_size);
|
||||
EMIT_U32(comp_data->tables[i].possible_grow & 0x000000FF);
|
||||
}
|
||||
|
||||
/* Emit table init data count */
|
||||
EMIT_U32(comp_data->table_init_data_count);
|
||||
/* Emit table init data items */
|
||||
for (i = 0; i < comp_data->table_init_data_count; i++) {
|
||||
offset = align_uint(offset, 4);
|
||||
EMIT_U32(init_datas[i]->mode);
|
||||
EMIT_U32(init_datas[i]->elem_type);
|
||||
EMIT_U32(init_datas[i]->table_index);
|
||||
EMIT_U32(init_datas[i]->offset.init_expr_type);
|
||||
EMIT_U64(init_datas[i]->offset.u.i64);
|
||||
EMIT_U32(init_datas[i]->func_index_count);
|
||||
|
@ -1004,7 +1196,10 @@ aot_emit_global_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
EMIT_U8(global->type);
|
||||
EMIT_U8(global->is_mutable);
|
||||
EMIT_U16(global->init_expr.init_expr_type);
|
||||
EMIT_U64(global->init_expr.u.i64);
|
||||
if (global->init_expr.init_expr_type != INIT_EXPR_TYPE_V128_CONST)
|
||||
EMIT_U64(global->init_expr.u.i64);
|
||||
else
|
||||
EMIT_V128(global->init_expr.u.v128);
|
||||
}
|
||||
|
||||
if (offset - *p_offset != get_global_info_size(comp_data)) {
|
||||
|
@ -1077,7 +1272,8 @@ aot_emit_object_data_section_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
|
||||
static bool
|
||||
aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||
AOTCompData *comp_data, AOTObjectData *obj_data)
|
||||
AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
||||
AOTObjectData *obj_data)
|
||||
{
|
||||
uint32 section_size = get_init_data_section_size(comp_data, obj_data);
|
||||
uint32 offset = *p_offset;
|
||||
|
@ -1087,7 +1283,7 @@ aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
EMIT_U32(AOT_SECTION_TYPE_INIT_DATA);
|
||||
EMIT_U32(section_size);
|
||||
|
||||
if (!aot_emit_mem_info(buf, buf_end, &offset, comp_data, obj_data)
|
||||
if (!aot_emit_mem_info(buf, buf_end, &offset, comp_ctx, comp_data, obj_data)
|
||||
|| !aot_emit_table_info(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_func_type_info(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_import_global_info(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|
@ -1099,10 +1295,13 @@ aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
EMIT_U32(comp_data->func_count);
|
||||
EMIT_U32(comp_data->start_func_index);
|
||||
|
||||
EMIT_U32(comp_data->llvm_aux_data_end);
|
||||
EMIT_U32(comp_data->llvm_aux_stack_bottom);
|
||||
EMIT_U32(comp_data->llvm_aux_stack_size);
|
||||
EMIT_U32(comp_data->llvm_aux_stack_global_index);
|
||||
EMIT_U32(comp_data->aux_data_end_global_index);
|
||||
EMIT_U32(comp_data->aux_data_end);
|
||||
EMIT_U32(comp_data->aux_heap_base_global_index);
|
||||
EMIT_U32(comp_data->aux_heap_base);
|
||||
EMIT_U32(comp_data->aux_stack_top_global_index);
|
||||
EMIT_U32(comp_data->aux_stack_bottom);
|
||||
EMIT_U32(comp_data->aux_stack_size);
|
||||
|
||||
if (!aot_emit_object_data_section_info(buf, buf_end, &offset, obj_data))
|
||||
return false;
|
||||
|
@ -1186,19 +1385,22 @@ aot_emit_export_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
AOTCompData *comp_data, AOTObjectData *obj_data)
|
||||
{
|
||||
uint32 section_size = get_export_section_size(comp_data);
|
||||
AOTExportFunc *func = comp_data->export_funcs;;
|
||||
uint32 i, offset = *p_offset, export_func_count = comp_data->export_func_count;
|
||||
AOTExport *export = comp_data->wasm_module->exports;
|
||||
uint32 export_count = comp_data->wasm_module->export_count;
|
||||
uint32 i, offset = *p_offset;
|
||||
|
||||
*p_offset = offset = align_uint(offset, 4);
|
||||
|
||||
EMIT_U32(AOT_SECTION_TYPE_EXPORT);
|
||||
EMIT_U32(section_size);
|
||||
EMIT_U32(export_func_count);
|
||||
EMIT_U32(export_count);
|
||||
|
||||
for (i = 0; i < export_func_count; i++, func++) {
|
||||
for (i = 0; i < export_count; i++, export++) {
|
||||
offset = align_uint(offset, 4);
|
||||
EMIT_U32(func->func_index);
|
||||
EMIT_STR(func->func_name);
|
||||
EMIT_U32(export->index);
|
||||
EMIT_U8(export->kind);
|
||||
EMIT_U8(0);
|
||||
EMIT_STR(export->name);
|
||||
}
|
||||
|
||||
if (offset - *p_offset != section_size + sizeof(uint32) * 2) {
|
||||
|
@ -1303,6 +1505,27 @@ aot_emit_relocation_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef uint32 U32;
|
||||
typedef int32 I32;
|
||||
typedef uint16 U16;
|
||||
typedef uint8 U8;
|
||||
|
||||
struct coff_hdr {
|
||||
U16 u16Machine;
|
||||
U16 u16NumSections;
|
||||
U32 u32DateTimeStamp;
|
||||
U32 u32SymTblPtr;
|
||||
U32 u32NumSymbols;
|
||||
U16 u16PeHdrSize;
|
||||
U16 u16Characs;
|
||||
};
|
||||
|
||||
#define IMAGE_FILE_MACHINE_AMD64 0x8664
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||
#define IMAGE_FILE_MACHINE_IA64 0x0200
|
||||
|
||||
#define AOT_COFF_BIN_TYPE 6
|
||||
|
||||
#define EI_NIDENT 16
|
||||
|
||||
typedef uint32 elf32_word;
|
||||
|
@ -1391,17 +1614,39 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
|
|||
const uint8 *elf_buf = (uint8 *)LLVMGetBufferStart(obj_data->mem_buf);
|
||||
uint32 elf_size = (uint32)LLVMGetBufferSize(obj_data->mem_buf);
|
||||
|
||||
if (bin_type != LLVMBinaryTypeELF32L
|
||||
if (bin_type != LLVMBinaryTypeCOFF
|
||||
&& bin_type != LLVMBinaryTypeELF32L
|
||||
&& bin_type != LLVMBinaryTypeELF32B
|
||||
&& bin_type != LLVMBinaryTypeELF64L
|
||||
&& bin_type != LLVMBinaryTypeELF64B) {
|
||||
&& bin_type != LLVMBinaryTypeELF64B
|
||||
&& bin_type != LLVMBinaryTypeMachO32L
|
||||
&& bin_type != LLVMBinaryTypeMachO32B
|
||||
&& bin_type != LLVMBinaryTypeMachO64L
|
||||
&& bin_type != LLVMBinaryTypeMachO64B) {
|
||||
aot_set_last_error("invaid llvm binary bin_type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
obj_data->target_info.bin_type = bin_type - LLVMBinaryTypeELF32L;
|
||||
|
||||
if (bin_type == LLVMBinaryTypeELF32L || bin_type == LLVMBinaryTypeELF32B) {
|
||||
if (bin_type == LLVMBinaryTypeCOFF) {
|
||||
struct coff_hdr * coff_header;
|
||||
|
||||
if (!elf_buf || elf_size < sizeof(struct coff_hdr)) {
|
||||
aot_set_last_error("invalid coff_hdr buffer.");
|
||||
return false;
|
||||
}
|
||||
coff_header = (struct coff_hdr *)elf_buf;
|
||||
obj_data->target_info.e_type = 1;
|
||||
obj_data->target_info.e_machine = coff_header->u16Machine;
|
||||
obj_data->target_info.e_version = 1;
|
||||
obj_data->target_info.e_flags = 0;
|
||||
|
||||
if (coff_header->u16Machine == IMAGE_FILE_MACHINE_AMD64)
|
||||
obj_data->target_info.bin_type = AOT_COFF_BIN_TYPE;
|
||||
}
|
||||
else if (bin_type == LLVMBinaryTypeELF32L
|
||||
|| bin_type == LLVMBinaryTypeELF32B) {
|
||||
struct elf32_ehdr *elf_header;
|
||||
bool is_little_bin = bin_type == LLVMBinaryTypeELF32L;
|
||||
|
||||
|
@ -1416,7 +1661,8 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
|
|||
SET_TARGET_INFO(e_version, e_version, uint32, is_little_bin);
|
||||
SET_TARGET_INFO(e_flags, e_flags, uint32, is_little_bin);
|
||||
}
|
||||
else {
|
||||
else if (bin_type == LLVMBinaryTypeELF64L
|
||||
|| bin_type == LLVMBinaryTypeELF64B) {
|
||||
struct elf64_ehdr *elf_header;
|
||||
bool is_little_bin = bin_type == LLVMBinaryTypeELF64L;
|
||||
|
||||
|
@ -1431,6 +1677,19 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
|
|||
SET_TARGET_INFO(e_version, e_version, uint32, is_little_bin);
|
||||
SET_TARGET_INFO(e_flags, e_flags, uint32, is_little_bin);
|
||||
}
|
||||
else if (bin_type == LLVMBinaryTypeMachO32L
|
||||
|| bin_type == LLVMBinaryTypeMachO32B) {
|
||||
/* TODO: parse file type of Mach-O 32 */
|
||||
aot_set_last_error("invaid llvm binary bin_type.");
|
||||
return false;
|
||||
}
|
||||
else if (bin_type == LLVMBinaryTypeMachO64L
|
||||
|| bin_type == LLVMBinaryTypeMachO64B) {
|
||||
/* TODO: parse file type of Mach-O 64 */
|
||||
aot_set_last_error("invaid llvm binary bin_type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
strncpy(obj_data->target_info.arch, comp_ctx->target_arch,
|
||||
sizeof(obj_data->target_info.arch));
|
||||
|
@ -1485,16 +1744,24 @@ aot_resolve_literal(AOTObjectData *obj_data)
|
|||
}
|
||||
|
||||
static bool
|
||||
is_data_section(char *section_name)
|
||||
get_relocations_count(LLVMSectionIteratorRef sec_itr, uint32 *p_count);
|
||||
|
||||
static bool
|
||||
is_data_section(LLVMSectionIteratorRef sec_itr, char *section_name)
|
||||
{
|
||||
uint32 relocation_count = 0;
|
||||
|
||||
return (!strcmp(section_name, ".data")
|
||||
|| !strcmp(section_name, ".rodata")
|
||||
/* ".rodata.cst4/8/16/.." */
|
||||
|| !strncmp(section_name, ".rodata.cst", strlen(".rodata.cst")));
|
||||
|| !strncmp(section_name, ".rodata.cst", strlen(".rodata.cst"))
|
||||
|| (!strcmp(section_name, ".rdata")
|
||||
&& get_relocations_count(sec_itr, &relocation_count)
|
||||
&& relocation_count > 0));
|
||||
}
|
||||
|
||||
static uint32
|
||||
get_object_data_sections_count(AOTObjectData *obj_data)
|
||||
static bool
|
||||
get_object_data_sections_count(AOTObjectData *obj_data, uint32 *p_count)
|
||||
{
|
||||
LLVMSectionIteratorRef sec_itr;
|
||||
char *name;
|
||||
|
@ -1502,18 +1769,19 @@ get_object_data_sections_count(AOTObjectData *obj_data)
|
|||
|
||||
if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
|
||||
aot_set_last_error("llvm get section iterator failed.");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
|
||||
if ((name = (char *)LLVMGetSectionName(sec_itr))
|
||||
&& (is_data_section(name))) {
|
||||
&& (is_data_section(sec_itr, name))) {
|
||||
count++;
|
||||
}
|
||||
LLVMMoveToNextSection(sec_itr);
|
||||
}
|
||||
LLVMDisposeSectionIterator(sec_itr);
|
||||
|
||||
return count;
|
||||
*p_count = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1522,9 +1790,13 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data)
|
|||
LLVMSectionIteratorRef sec_itr;
|
||||
char *name;
|
||||
AOTObjectDataSection *data_section;
|
||||
uint32 sections_count = get_object_data_sections_count(obj_data);
|
||||
uint32 sections_count;
|
||||
uint32 size;
|
||||
|
||||
if (!get_object_data_sections_count(obj_data, §ions_count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sections_count > 0) {
|
||||
size = (uint32)sizeof(AOTObjectDataSection) * sections_count;
|
||||
if (!(data_section = obj_data->data_sections = wasm_runtime_malloc(size))) {
|
||||
|
@ -1538,10 +1810,9 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data)
|
|||
aot_set_last_error("llvm get section iterator failed.");
|
||||
return false;
|
||||
}
|
||||
while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary,
|
||||
sec_itr)) {
|
||||
while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
|
||||
if ((name = (char *)LLVMGetSectionName(sec_itr))
|
||||
&& (is_data_section(name))) {
|
||||
&& (is_data_section(sec_itr, name))) {
|
||||
data_section->name = name;
|
||||
data_section->data = (uint8 *)LLVMGetSectionContents(sec_itr);
|
||||
data_section->size = (uint32)LLVMGetSectionSize(sec_itr);
|
||||
|
@ -1561,16 +1832,18 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
|
|||
AOTObjectFunc *func;
|
||||
LLVMSymbolIteratorRef sym_itr;
|
||||
char *name, *prefix = AOT_FUNC_PREFIX;
|
||||
uint32 func_index;
|
||||
uint32 func_index, total_size;
|
||||
|
||||
/* allocate memory for aot function */
|
||||
obj_data->func_count = comp_ctx->comp_data->func_count;
|
||||
if (!(obj_data->funcs
|
||||
= wasm_runtime_malloc((uint32)sizeof(AOTObjectFunc) * obj_data->func_count))) {
|
||||
aot_set_last_error("allocate memory for functions failed.");
|
||||
return false;
|
||||
if (obj_data->func_count) {
|
||||
total_size = (uint32)sizeof(AOTObjectFunc) * obj_data->func_count;
|
||||
if (!(obj_data->funcs = wasm_runtime_malloc(total_size))) {
|
||||
aot_set_last_error("allocate memory for functions failed.");
|
||||
return false;
|
||||
}
|
||||
memset(obj_data->funcs, 0, total_size);
|
||||
}
|
||||
memset(obj_data->funcs, 0, sizeof(AOTObjectFunc) * obj_data->func_count);
|
||||
|
||||
if (!(sym_itr = LLVMObjectFileCopySymbolIterator(obj_data->binary))) {
|
||||
aot_set_last_error("llvm get symbol iterator failed.");
|
||||
|
@ -1732,7 +2005,7 @@ fail:
|
|||
}
|
||||
|
||||
static bool
|
||||
is_relocation_section(char *section_name)
|
||||
is_relocation_section_name(char *section_name)
|
||||
{
|
||||
return (!strcmp(section_name, ".rela.text")
|
||||
|| !strcmp(section_name, ".rel.text")
|
||||
|
@ -1749,20 +2022,33 @@ is_relocation_section(char *section_name)
|
|||
strlen(".rel.rodata.cst")));
|
||||
}
|
||||
|
||||
static bool
|
||||
is_relocation_section(LLVMSectionIteratorRef sec_itr)
|
||||
{
|
||||
uint32 count = 0;
|
||||
char *name = (char *)LLVMGetSectionName(sec_itr);
|
||||
if (name) {
|
||||
if (is_relocation_section_name(name))
|
||||
return true;
|
||||
else if ((!strcmp(name, ".text") || !strcmp(name, ".rdata"))
|
||||
&& get_relocations_count(sec_itr, &count) && count > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
get_relocation_groups_count(AOTObjectData *obj_data, uint32 *p_count)
|
||||
{
|
||||
uint32 count = 0;
|
||||
LLVMSectionIteratorRef sec_itr;
|
||||
char *name;
|
||||
|
||||
if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
|
||||
aot_set_last_error("llvm get section iterator failed.");
|
||||
return false;
|
||||
}
|
||||
while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
|
||||
if ((name = (char *)LLVMGetSectionName(sec_itr))
|
||||
&& is_relocation_section(name)) {
|
||||
if (is_relocation_section(sec_itr)) {
|
||||
count++;
|
||||
}
|
||||
LLVMMoveToNextSection(sec_itr);
|
||||
|
@ -1803,8 +2089,8 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data)
|
|||
return false;
|
||||
}
|
||||
while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
|
||||
if ((name = (char *)LLVMGetSectionName(sec_itr))
|
||||
&& is_relocation_section(name)) {
|
||||
if (is_relocation_section(sec_itr)) {
|
||||
name = (char *)LLVMGetSectionName(sec_itr);
|
||||
relocation_group->section_name = name;
|
||||
if (!aot_resolve_object_relocation_group(
|
||||
obj_data,
|
||||
|
@ -1922,22 +2208,19 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
||||
const char *file_name)
|
||||
uint8*
|
||||
aot_emit_aot_file_buf(AOTCompContext *comp_ctx,
|
||||
AOTCompData *comp_data,
|
||||
uint32 *p_aot_file_size)
|
||||
{
|
||||
AOTObjectData *obj_data = aot_obj_data_create(comp_ctx);
|
||||
uint8 *aot_file_buf, *buf, *buf_end;
|
||||
uint32 aot_file_size, offset = 0;
|
||||
bool ret = false;
|
||||
FILE *file;
|
||||
|
||||
if (!obj_data)
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
bh_print_time("Begin to emit AOT file");
|
||||
|
||||
aot_file_size = get_aot_file_size(comp_data, obj_data);
|
||||
aot_file_size = get_aot_file_size(comp_ctx, comp_data, obj_data);
|
||||
|
||||
if (!(buf = aot_file_buf = wasm_runtime_malloc(aot_file_size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
|
@ -1949,7 +2232,7 @@ aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
|||
|
||||
if (!aot_emit_file_header(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_target_info_section(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_init_data_section(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_init_data_section(buf, buf_end, &offset, comp_ctx, comp_data, obj_data)
|
||||
|| !aot_emit_text_section(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_func_section(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|| !aot_emit_export_section(buf, buf_end, &offset, comp_data, obj_data)
|
||||
|
@ -1965,25 +2248,52 @@ aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
|||
goto fail2;
|
||||
}
|
||||
|
||||
/* write buffer to file */
|
||||
if (!(file = fopen(file_name, "wb"))) {
|
||||
aot_set_last_error("open or create aot file failed.");
|
||||
goto fail2;
|
||||
}
|
||||
if (!fwrite(aot_file_buf, aot_file_size, 1, file)) {
|
||||
aot_set_last_error("write to aot file failed.");
|
||||
goto fail3;
|
||||
}
|
||||
*p_aot_file_size = aot_file_size;
|
||||
|
||||
ret = true;
|
||||
|
||||
fail3:
|
||||
fclose(file);
|
||||
aot_obj_data_destroy(obj_data);
|
||||
return aot_file_buf;
|
||||
|
||||
fail2:
|
||||
wasm_runtime_free(aot_file_buf);
|
||||
|
||||
fail1:
|
||||
aot_obj_data_destroy(obj_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
||||
const char *file_name)
|
||||
{
|
||||
uint8 *aot_file_buf;
|
||||
uint32 aot_file_size;
|
||||
bool ret = false;
|
||||
FILE *file;
|
||||
|
||||
bh_print_time("Begin to emit AOT file");
|
||||
|
||||
if (!(aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data,
|
||||
&aot_file_size))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* write buffer to file */
|
||||
if (!(file = fopen(file_name, "wb"))) {
|
||||
aot_set_last_error("open or create aot file failed.");
|
||||
goto fail1;
|
||||
}
|
||||
if (!fwrite(aot_file_buf, aot_file_size, 1, file)) {
|
||||
aot_set_last_error("write to aot file failed.");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
fail2:
|
||||
fclose(file);
|
||||
|
||||
fail1:
|
||||
wasm_runtime_free(aot_file_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ aot_compile_op_f32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
int32 i32_const;
|
||||
memcpy(&i32_const, &f32_const, sizeof(int32));
|
||||
if (!(alloca = LLVMBuildAlloca(comp_ctx->builder,
|
||||
INT32_PTR_TYPE, "i32_ptr"))) {
|
||||
I32_TYPE, "i32_ptr"))) {
|
||||
aot_set_last_error("llvm build alloca failed.");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@ enum {
|
|||
|
||||
static void
|
||||
format_block_name(char *name, uint32 name_size,
|
||||
uint32 block_index, uint32 block_type,
|
||||
uint32 label_type)
|
||||
uint32 block_index, uint32 label_type,
|
||||
uint32 label_id)
|
||||
{
|
||||
if (block_type != BLOCK_TYPE_FUNCTION)
|
||||
if (label_type != LABEL_TYPE_FUNCTION)
|
||||
snprintf(name, name_size, "%s%d%s%s",
|
||||
block_name_prefix[block_type], block_index,
|
||||
"_", block_name_suffix[label_type]);
|
||||
block_name_prefix[label_type], block_index,
|
||||
"_", block_name_suffix[label_id]);
|
||||
else
|
||||
snprintf(name, name_size, "%s", "func_end");
|
||||
}
|
||||
|
@ -69,28 +69,58 @@ format_block_name(char *name, uint32 name_size,
|
|||
#define SET_BUILDER_POS(llvm_block) \
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, llvm_block)
|
||||
|
||||
#define CREATE_RETURN_VALUE_PHI(block) do { \
|
||||
if (block->return_type != VALUE_TYPE_VOID \
|
||||
&& !block->return_value_phi) { \
|
||||
LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
|
||||
SET_BUILDER_POS(block->llvm_end_block); \
|
||||
if (!(block->return_value_phi = \
|
||||
LLVMBuildPhi(comp_ctx->builder, \
|
||||
TO_LLVM_TYPE(block->return_type),\
|
||||
"phi"))) { \
|
||||
aot_set_last_error("llvm build phi failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
SET_BUILDER_POS(block_curr); \
|
||||
} \
|
||||
#define CREATE_RESULT_VALUE_PHIS(block) do { \
|
||||
if (block->result_count && !block->result_phis) { \
|
||||
uint32 i; \
|
||||
uint64 size; \
|
||||
LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
|
||||
/* Allocate memory */ \
|
||||
size = sizeof(LLVMValueRef) * (uint64)block->result_count; \
|
||||
if (size >= UINT32_MAX \
|
||||
|| !(block->result_phis = \
|
||||
wasm_runtime_malloc((uint32)size))) { \
|
||||
aot_set_last_error("allocate memory failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
SET_BUILDER_POS(block->llvm_end_block); \
|
||||
for (i = 0; i < block->result_count; i++) { \
|
||||
if (!(block->result_phis[i] = \
|
||||
LLVMBuildPhi(comp_ctx->builder, \
|
||||
TO_LLVM_TYPE(block->result_types[i]), \
|
||||
"phi"))) { \
|
||||
aot_set_last_error("llvm build phi failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} \
|
||||
SET_BUILDER_POS(block_curr); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ADD_TO_RETURN_PHI(block, value) do { \
|
||||
LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
|
||||
LLVMAddIncoming(block->return_value_phi, \
|
||||
&value, &block_curr, 1); \
|
||||
#define ADD_TO_RESULT_PHIS(block, value, idx) do { \
|
||||
LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
|
||||
LLVMTypeRef phi_ty = LLVMTypeOf(block->result_phis[idx]); \
|
||||
LLVMTypeRef value_ty = LLVMTypeOf(value); \
|
||||
bh_assert(LLVMGetTypeKind(phi_ty) == LLVMGetTypeKind(value_ty)); \
|
||||
bh_assert(LLVMGetTypeContext(phi_ty) \
|
||||
== LLVMGetTypeContext(value_ty)); \
|
||||
LLVMAddIncoming(block->result_phis[idx], &value, &block_curr, 1); \
|
||||
(void)phi_ty; \
|
||||
(void)value_ty; \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_ICMP(op, left, right, res, name) do { \
|
||||
if (!(res = LLVMBuildICmp(comp_ctx->builder, op, \
|
||||
left, right, name))) { \
|
||||
aot_set_last_error("llvm build icmp failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ADD_TO_PARAM_PHIS(block, value, idx) do { \
|
||||
LLVMBasicBlockRef block_curr = CURR_BLOCK(); \
|
||||
LLVMAddIncoming(block->param_phis[idx], \
|
||||
&value, &block_curr, 1); \
|
||||
} while (0)
|
||||
|
||||
static LLVMBasicBlockRef
|
||||
find_next_llvm_end_block(AOTBlock *block)
|
||||
|
@ -125,14 +155,23 @@ handle_next_reachable_block(AOTCompContext *comp_ctx,
|
|||
{
|
||||
AOTBlock *block = func_ctx->block_stack.block_list_end;
|
||||
AOTBlock *block_prev;
|
||||
uint8 *frame_ip;
|
||||
uint8 *frame_ip = NULL;
|
||||
uint32 i;
|
||||
AOTFuncType *func_type;
|
||||
|
||||
if (block->block_type == BLOCK_TYPE_IF
|
||||
aot_checked_addr_list_destroy(func_ctx);
|
||||
|
||||
bh_assert(block);
|
||||
|
||||
if (block->label_type == LABEL_TYPE_IF
|
||||
&& block->llvm_else_block
|
||||
&& !block->skip_wasm_code_else
|
||||
&& *p_frame_ip <= block->wasm_code_else) {
|
||||
/* Clear value stack and start to translate else branch */
|
||||
aot_value_stack_destroy(&block->value_stack);
|
||||
/* Recover parameters of else branch */
|
||||
for (i = 0; i < block->param_count; i++)
|
||||
PUSH(block->else_param_phis[i], block->param_types[i]);
|
||||
SET_BUILDER_POS(block->llvm_else_block);
|
||||
*p_frame_ip = block->wasm_code_else + 1;
|
||||
return true;
|
||||
|
@ -142,10 +181,23 @@ handle_next_reachable_block(AOTCompContext *comp_ctx,
|
|||
block_prev = block->prev;
|
||||
block = aot_block_stack_pop(&func_ctx->block_stack);
|
||||
|
||||
if (block->block_type == BLOCK_TYPE_IF
|
||||
&& block->llvm_end_block) {
|
||||
LLVMDeleteBasicBlock(block->llvm_end_block);
|
||||
block->llvm_end_block = NULL;
|
||||
if (block->label_type == LABEL_TYPE_IF) {
|
||||
if (block->llvm_else_block
|
||||
&& !block->skip_wasm_code_else
|
||||
&& *p_frame_ip <= block->wasm_code_else) {
|
||||
/* Clear value stack and start to translate else branch */
|
||||
aot_value_stack_destroy(&block->value_stack);
|
||||
SET_BUILDER_POS(block->llvm_else_block);
|
||||
*p_frame_ip = block->wasm_code_else + 1;
|
||||
/* Push back the block */
|
||||
aot_block_stack_push(&func_ctx->block_stack, block);
|
||||
return true;
|
||||
}
|
||||
else if (block->llvm_end_block) {
|
||||
/* Remove unreachable basic block */
|
||||
LLVMDeleteBasicBlock(block->llvm_end_block);
|
||||
block->llvm_end_block = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
frame_ip = block->wasm_code_end;
|
||||
|
@ -163,15 +215,39 @@ handle_next_reachable_block(AOTCompContext *comp_ctx,
|
|||
|
||||
/* Pop block, push its return value, and destroy the block */
|
||||
block = aot_block_stack_pop(&func_ctx->block_stack);
|
||||
if (block->return_type != VALUE_TYPE_VOID) {
|
||||
bh_assert(block->return_value_phi);
|
||||
if (block->block_type != BLOCK_TYPE_FUNCTION)
|
||||
PUSH(block->return_value_phi, block->return_type);
|
||||
else
|
||||
LLVMBuildRet(comp_ctx->builder, block->return_value_phi);
|
||||
func_type = func_ctx->aot_func->func_type;
|
||||
for (i = 0; i < block->result_count; i++) {
|
||||
bh_assert(block->result_phis[i]);
|
||||
if (block->label_type != LABEL_TYPE_FUNCTION) {
|
||||
PUSH(block->result_phis[i], block->result_types[i]);
|
||||
}
|
||||
else {
|
||||
/* Store extra return values to function parameters */
|
||||
if (i != 0) {
|
||||
uint32 param_index = func_type->param_count + i;
|
||||
if (!LLVMBuildStore(comp_ctx->builder,
|
||||
block->result_phis[i],
|
||||
LLVMGetParam(func_ctx->func, param_index))) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (block->block_type == BLOCK_TYPE_FUNCTION) {
|
||||
LLVMBuildRetVoid(comp_ctx->builder);
|
||||
if (block->label_type == LABEL_TYPE_FUNCTION) {
|
||||
if (block->result_count) {
|
||||
/* Return the first return value */
|
||||
if (!LLVMBuildRet(comp_ctx->builder, block->result_phis[0])) {
|
||||
aot_set_last_error("llvm build return failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!LLVMBuildRetVoid(comp_ctx->builder)) {
|
||||
aot_set_last_error("llvm build return void failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
aot_block_destroy(block);
|
||||
return true;
|
||||
|
@ -179,10 +255,116 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
AOTBlock *block)
|
||||
{
|
||||
uint32 i, param_index;
|
||||
LLVMValueRef value;
|
||||
uint64 size;
|
||||
char name[32];
|
||||
LLVMBasicBlockRef block_curr = CURR_BLOCK();
|
||||
|
||||
if (block->param_count) {
|
||||
size = sizeof(LLVMValueRef) * (uint64)block->param_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(block->param_phis = wasm_runtime_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (block->label_type == LABEL_TYPE_IF
|
||||
&& !block->skip_wasm_code_else
|
||||
&& !(block->else_param_phis = wasm_runtime_malloc((uint32)size))) {
|
||||
wasm_runtime_free(block->param_phis);
|
||||
block->param_phis = NULL;
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create param phis */
|
||||
for (i = 0; i < block->param_count; i++) {
|
||||
SET_BUILDER_POS(block->llvm_entry_block);
|
||||
snprintf(name, sizeof(name), "%s%d_phi%d",
|
||||
block_name_prefix[block->label_type],
|
||||
block->block_index, i);
|
||||
if (!(block->param_phis[i] =
|
||||
LLVMBuildPhi(comp_ctx->builder,
|
||||
TO_LLVM_TYPE(block->param_types[i]),
|
||||
name))) {
|
||||
aot_set_last_error("llvm build phi failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (block->label_type == LABEL_TYPE_IF
|
||||
&& !block->skip_wasm_code_else
|
||||
&& block->llvm_else_block) {
|
||||
/* Build else param phis */
|
||||
SET_BUILDER_POS(block->llvm_else_block);
|
||||
snprintf(name, sizeof(name), "else%d_phi%d",
|
||||
block->block_index, i);
|
||||
if (!(block->else_param_phis[i] =
|
||||
LLVMBuildPhi(comp_ctx->builder,
|
||||
TO_LLVM_TYPE(block->param_types[i]),
|
||||
name))) {
|
||||
aot_set_last_error("llvm build phi failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
SET_BUILDER_POS(block_curr);
|
||||
|
||||
/* Pop param values from current block's
|
||||
* value stack and add to param phis.
|
||||
*/
|
||||
for (i = 0; i < block->param_count; i++) {
|
||||
param_index = block->param_count - 1 - i;
|
||||
POP(value, block->param_types[param_index]);
|
||||
ADD_TO_PARAM_PHIS(block, value, param_index);
|
||||
if (block->label_type == LABEL_TYPE_IF
|
||||
&& !block->skip_wasm_code_else) {
|
||||
if (block->llvm_else_block) {
|
||||
/* has else branch, add to else param phis */
|
||||
LLVMAddIncoming(block->else_param_phis[param_index],
|
||||
&value, &block_curr, 1);
|
||||
}
|
||||
else {
|
||||
/* no else branch, add to result phis */
|
||||
CREATE_RESULT_VALUE_PHIS(block);
|
||||
ADD_TO_RESULT_PHIS(block, value, param_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Push the new block to block stack */
|
||||
aot_block_stack_push(&func_ctx->block_stack, block);
|
||||
|
||||
/* Push param phis to the new block */
|
||||
for (i = 0; i < block->param_count; i++) {
|
||||
PUSH(block->param_phis[i], block->param_types[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
if (block->param_phis) {
|
||||
wasm_runtime_free(block->param_phis);
|
||||
block->param_phis = NULL;
|
||||
}
|
||||
if (block->else_param_phis) {
|
||||
wasm_runtime_free(block->else_param_phis);
|
||||
block->else_param_phis = NULL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip, uint8 *frame_ip_end,
|
||||
uint32 block_type, uint32 block_ret_type)
|
||||
uint32 label_type, uint32 param_count, uint8 *param_types,
|
||||
uint32 result_count, uint8 *result_types)
|
||||
{
|
||||
BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
|
||||
AOTBlock *block;
|
||||
|
@ -200,8 +382,8 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* Get block info */
|
||||
if (!(wasm_loader_find_block_addr((BlockAddr*)block_addr_cache,
|
||||
*p_frame_ip, frame_ip_end, (uint8)block_type,
|
||||
&else_addr, &end_addr, NULL, 0))) {
|
||||
*p_frame_ip, frame_ip_end, (uint8)label_type,
|
||||
&else_addr, &end_addr))) {
|
||||
aot_set_last_error("find block end addr failed.");
|
||||
return false;
|
||||
}
|
||||
|
@ -211,49 +393,66 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
aot_set_last_error("allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
memset(block, 0, sizeof(AOTBlock));
|
||||
if (param_count
|
||||
&& !(block->param_types = wasm_runtime_malloc(param_count))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
if (result_count) {
|
||||
if (!(block->result_types = wasm_runtime_malloc(result_count))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init aot block data */
|
||||
memset(block, 0, sizeof(AOTBlock));
|
||||
block->block_type = block_type;
|
||||
block->return_type = (uint8)block_ret_type;
|
||||
block->label_type = label_type;
|
||||
block->param_count = param_count;
|
||||
memcpy(block->param_types, param_types, param_count);
|
||||
block->result_count = result_count;
|
||||
memcpy(block->result_types, result_types, result_count);
|
||||
block->wasm_code_else = else_addr;
|
||||
block->wasm_code_end = end_addr;
|
||||
block->block_index = func_ctx->block_stack.block_index[block_type];
|
||||
func_ctx->block_stack.block_index[block_type]++;
|
||||
block->block_index = func_ctx->block_stack.block_index[label_type];
|
||||
func_ctx->block_stack.block_index[label_type]++;
|
||||
|
||||
if (block_type == BLOCK_TYPE_BLOCK
|
||||
|| block_type == BLOCK_TYPE_LOOP) {
|
||||
if (label_type == LABEL_TYPE_BLOCK
|
||||
|| label_type == LABEL_TYPE_LOOP) {
|
||||
/* Create block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_BEGIN);
|
||||
block->block_index, label_type, LABEL_BEGIN);
|
||||
CREATE_BLOCK(block->llvm_entry_block, name);
|
||||
MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
|
||||
/* Jump to the entry block */
|
||||
BUILD_BR(block->llvm_entry_block);
|
||||
if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
|
||||
goto fail;
|
||||
/* Start to translate the block */
|
||||
SET_BUILDER_POS(block->llvm_entry_block);
|
||||
aot_block_stack_push(&func_ctx->block_stack, block);
|
||||
if (label_type == LABEL_TYPE_LOOP)
|
||||
aot_checked_addr_list_destroy(func_ctx);
|
||||
}
|
||||
else if (block_type == BLOCK_TYPE_IF) {
|
||||
else if (label_type == LABEL_TYPE_IF) {
|
||||
POP_COND(value);
|
||||
if (!LLVMIsConstant(value)) {
|
||||
/* Compare value is not constant, create condition br IR */
|
||||
/* Create entry block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_BEGIN);
|
||||
block->block_index, label_type, LABEL_BEGIN);
|
||||
CREATE_BLOCK(block->llvm_entry_block, name);
|
||||
MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
|
||||
|
||||
/* Create end block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_END);
|
||||
block->block_index, label_type, LABEL_END);
|
||||
CREATE_BLOCK(block->llvm_end_block, name);
|
||||
MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_entry_block);
|
||||
|
||||
if (else_addr) {
|
||||
/* Create else block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_ELSE);
|
||||
block->block_index, label_type, LABEL_ELSE);
|
||||
CREATE_BLOCK(block->llvm_else_block, name);
|
||||
MOVE_BLOCK_AFTER(block->llvm_else_block, block->llvm_entry_block);
|
||||
/* Create condition br IR */
|
||||
|
@ -266,49 +465,48 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
block->llvm_end_block);
|
||||
block->is_reachable = true;
|
||||
}
|
||||
if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
|
||||
goto fail;
|
||||
/* Start to translate if branch of BLOCK if */
|
||||
SET_BUILDER_POS(block->llvm_entry_block);
|
||||
aot_block_stack_push(&func_ctx->block_stack, block);
|
||||
}
|
||||
else {
|
||||
if ((int32)LLVMConstIntGetZExtValue(value) != 0) {
|
||||
/* Compare value is not 0, condtion is true, else branch of
|
||||
/* Compare value is not 0, condition is true, else branch of
|
||||
BLOCK if cannot be reached */
|
||||
block->skip_wasm_code_else = true;
|
||||
/* Create entry block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_BEGIN);
|
||||
block->block_index, label_type, LABEL_BEGIN);
|
||||
CREATE_BLOCK(block->llvm_entry_block, name);
|
||||
MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
|
||||
/* Jump to the entry block */
|
||||
BUILD_BR(block->llvm_entry_block);
|
||||
if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
|
||||
goto fail;
|
||||
/* Start to translate the if branch */
|
||||
SET_BUILDER_POS(block->llvm_entry_block);
|
||||
aot_block_stack_push(&func_ctx->block_stack, block);
|
||||
}
|
||||
else {
|
||||
/* Compare value is not 0, condtion is false, if branch of
|
||||
/* Compare value is not 0, condition is false, if branch of
|
||||
BLOCK if cannot be reached */
|
||||
if (else_addr) {
|
||||
/* Create else block */
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block_type, LABEL_ELSE);
|
||||
block->block_index, label_type, LABEL_ELSE);
|
||||
CREATE_BLOCK(block->llvm_else_block, name);
|
||||
MOVE_BLOCK_AFTER_CURR(block->llvm_else_block);
|
||||
/* Jump to the else block */
|
||||
BUILD_BR(block->llvm_else_block);
|
||||
if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
|
||||
goto fail;
|
||||
/* Start to translate the else branch */
|
||||
SET_BUILDER_POS(block->llvm_else_block);
|
||||
*p_frame_ip = else_addr + 1;
|
||||
aot_block_stack_push(&func_ctx->block_stack, block);
|
||||
}
|
||||
else {
|
||||
if (block->return_type != VALUE_TYPE_VOID) {
|
||||
aot_set_last_error("WASM value stack underflow.");
|
||||
goto fail;
|
||||
}
|
||||
/* skip the block */
|
||||
wasm_runtime_free(block);
|
||||
aot_block_destroy(block);
|
||||
*p_frame_ip = end_addr + 1;
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +519,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
return true;
|
||||
fail:
|
||||
wasm_runtime_free(block);
|
||||
aot_block_destroy(block);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -332,13 +530,14 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
AOTBlock *block = func_ctx->block_stack.block_list_end;
|
||||
LLVMValueRef value;
|
||||
char name[32];
|
||||
uint32 i, result_index;
|
||||
|
||||
/* Check block */
|
||||
if (!block) {
|
||||
aot_set_last_error("WASM block stack underflow.");
|
||||
return false;
|
||||
}
|
||||
if (block->block_type != BLOCK_TYPE_IF
|
||||
if (block->label_type != LABEL_TYPE_IF
|
||||
|| (!block->skip_wasm_code_else
|
||||
&& !block->llvm_else_block)) {
|
||||
aot_set_last_error("Invalid WASM block type.");
|
||||
|
@ -348,7 +547,7 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
/* Create end block if needed */
|
||||
if (!block->llvm_end_block) {
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block->block_type, LABEL_END);
|
||||
block->block_index, block->label_type, LABEL_END);
|
||||
CREATE_BLOCK(block->llvm_end_block, name);
|
||||
if (block->llvm_else_block)
|
||||
MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_else_block);
|
||||
|
@ -359,10 +558,11 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
block->is_reachable = true;
|
||||
|
||||
/* Comes from the if branch of BLOCK if */
|
||||
if (block->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value, block->return_type);
|
||||
CREATE_RETURN_VALUE_PHI(block);
|
||||
ADD_TO_RETURN_PHI(block, value);
|
||||
CREATE_RESULT_VALUE_PHIS(block);
|
||||
for (i = 0; i < block->result_count; i++) {
|
||||
result_index = block->result_count - 1 - i;
|
||||
POP(value, block->result_types[result_index]);
|
||||
ADD_TO_RESULT_PHIS(block, value, result_index);
|
||||
}
|
||||
|
||||
/* Jump to end block */
|
||||
|
@ -370,9 +570,14 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
if (!block->skip_wasm_code_else
|
||||
&& block->llvm_else_block) {
|
||||
/* Clear value stack and start to translate else branch */
|
||||
/* Clear value stack, recover param values
|
||||
* and start to translate else branch.
|
||||
*/
|
||||
aot_value_stack_destroy(&block->value_stack);
|
||||
for (i = 0; i < block->param_count; i++)
|
||||
PUSH(block->else_param_phis[i], block->param_types[i]);
|
||||
SET_BUILDER_POS(block->llvm_else_block);
|
||||
aot_checked_addr_list_destroy(func_ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -391,6 +596,7 @@ aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
LLVMValueRef value;
|
||||
LLVMBasicBlockRef next_llvm_end_block;
|
||||
char name[32];
|
||||
uint32 i, result_index;
|
||||
|
||||
/* Check block stack */
|
||||
if (!(block = func_ctx->block_stack.block_list_end)) {
|
||||
|
@ -401,17 +607,20 @@ aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
/* Create the end block */
|
||||
if (!block->llvm_end_block) {
|
||||
format_block_name(name, sizeof(name),
|
||||
block->block_index, block->block_type, LABEL_END);
|
||||
block->block_index, block->label_type, LABEL_END);
|
||||
CREATE_BLOCK(block->llvm_end_block, name);
|
||||
if ((next_llvm_end_block = find_next_llvm_end_block(block)))
|
||||
MOVE_BLOCK_BEFORE(block->llvm_end_block, next_llvm_end_block);
|
||||
}
|
||||
|
||||
/* Handle block return value */
|
||||
if (block->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value, block->return_type);
|
||||
CREATE_RETURN_VALUE_PHI(block);
|
||||
ADD_TO_RETURN_PHI(block, value);
|
||||
/* Handle block result values */
|
||||
CREATE_RESULT_VALUE_PHIS(block);
|
||||
for (i = 0; i < block->result_count; i++) {
|
||||
value = NULL;
|
||||
result_index = block->result_count - 1 - i;
|
||||
POP(value, block->result_types[result_index]);
|
||||
bh_assert(value);
|
||||
ADD_TO_RESULT_PHIS(block, value, result_index);
|
||||
}
|
||||
|
||||
/* Jump to the end block */
|
||||
|
@ -423,21 +632,112 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
bool
|
||||
check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef terminate_addr, terminate_flags, flag, offset, res;
|
||||
LLVMBasicBlockRef terminate_check_block, non_terminate_block;
|
||||
AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
|
||||
LLVMBasicBlockRef terminate_block;
|
||||
|
||||
/* Offset of suspend_flags */
|
||||
offset = I32_FIVE;
|
||||
|
||||
if (!(terminate_addr =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
|
||||
&offset, 1, "terminate_addr"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
if (!(terminate_addr =
|
||||
LLVMBuildBitCast(comp_ctx->builder,
|
||||
terminate_addr,
|
||||
INT32_PTR_TYPE, "terminate_addr_ptr"))) {
|
||||
aot_set_last_error("llvm build bit cast failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(terminate_flags =
|
||||
LLVMBuildLoad(comp_ctx->builder,
|
||||
terminate_addr, "terminate_flags"))) {
|
||||
aot_set_last_error("llvm build bit cast failed");
|
||||
return false;
|
||||
}
|
||||
/* Set terminate_flags memory accecc to volatile, so that the value
|
||||
will always be loaded from memory rather than register */
|
||||
LLVMSetVolatile(terminate_flags, true);
|
||||
|
||||
CREATE_BLOCK(terminate_check_block, "terminate_check");
|
||||
MOVE_BLOCK_AFTER_CURR(terminate_check_block);
|
||||
|
||||
CREATE_BLOCK(non_terminate_block, "non_terminate");
|
||||
MOVE_BLOCK_AFTER_CURR(non_terminate_block);
|
||||
|
||||
BUILD_ICMP(LLVMIntSGT, terminate_flags, I32_ZERO, res, "need_terminate");
|
||||
BUILD_COND_BR(res, terminate_check_block, non_terminate_block);
|
||||
|
||||
/* Move builder to terminate check block */
|
||||
SET_BUILDER_POS(terminate_check_block);
|
||||
|
||||
CREATE_BLOCK(terminate_block, "terminate");
|
||||
MOVE_BLOCK_AFTER_CURR(terminate_block);
|
||||
|
||||
if (!(flag =
|
||||
LLVMBuildAnd(comp_ctx->builder, terminate_flags,
|
||||
I32_ONE, "termination_flag"))) {
|
||||
aot_set_last_error("llvm build AND failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
BUILD_ICMP(LLVMIntSGT, flag, I32_ZERO, res, "need_terminate");
|
||||
BUILD_COND_BR(res, terminate_block, non_terminate_block);
|
||||
|
||||
/* Move builder to terminate block */
|
||||
SET_BUILDER_POS(terminate_block);
|
||||
if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Move builder to terminate block */
|
||||
SET_BUILDER_POS(non_terminate_block);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
#endif /* End of WASM_ENABLE_THREAD_MGR */
|
||||
|
||||
bool
|
||||
aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 br_depth, uint8 **p_frame_ip)
|
||||
{
|
||||
AOTBlock *block_dst;
|
||||
LLVMValueRef value_ret;
|
||||
LLVMValueRef value_ret, value_param;
|
||||
LLVMBasicBlockRef next_llvm_end_block;
|
||||
char name[32];
|
||||
uint32 i, param_index, result_index;
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
/* Insert suspend check point */
|
||||
if (comp_ctx->enable_thread_mgr) {
|
||||
if (!check_suspend_flags(comp_ctx, func_ctx))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(block_dst = get_target_block(func_ctx, br_depth))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (block_dst->block_type == BLOCK_TYPE_LOOP) {
|
||||
if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
||||
/* Dest block is Loop block */
|
||||
/* Handle Loop parameters */
|
||||
for (i = 0; i < block_dst->param_count; i++) {
|
||||
param_index = block_dst->param_count - 1 - i;
|
||||
POP(value_param, block_dst->param_types[param_index]);
|
||||
ADD_TO_PARAM_PHIS(block_dst, value_param, param_index);
|
||||
}
|
||||
BUILD_BR(block_dst->llvm_entry_block);
|
||||
}
|
||||
else {
|
||||
|
@ -445,7 +745,7 @@ aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
/* Create the end block */
|
||||
if (!block_dst->llvm_end_block) {
|
||||
format_block_name(name, sizeof(name),
|
||||
block_dst->block_index, block_dst->block_type,
|
||||
block_dst->block_index, block_dst->label_type,
|
||||
LABEL_END);
|
||||
CREATE_BLOCK(block_dst->llvm_end_block, name);
|
||||
if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
|
||||
|
@ -455,13 +755,13 @@ aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
block_dst->is_reachable = true;
|
||||
|
||||
/* Handle return value */
|
||||
if (block_dst->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value_ret, block_dst->return_type);
|
||||
CREATE_RETURN_VALUE_PHI(block_dst);
|
||||
ADD_TO_RETURN_PHI(block_dst, value_ret);
|
||||
/* Handle result values */
|
||||
CREATE_RESULT_VALUE_PHIS(block_dst);
|
||||
for (i = 0; i < block_dst->result_count; i++) {
|
||||
result_index = block_dst->result_count - 1 - i;
|
||||
POP(value_ret, block_dst->result_types[result_index]);
|
||||
ADD_TO_RESULT_PHIS(block_dst, value_ret, result_index);
|
||||
}
|
||||
|
||||
/* Jump to the end block */
|
||||
BUILD_BR(block_dst->llvm_end_block);
|
||||
}
|
||||
|
@ -476,9 +776,19 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
uint32 br_depth, uint8 **p_frame_ip)
|
||||
{
|
||||
AOTBlock *block_dst;
|
||||
LLVMValueRef value_cmp, value_ret;
|
||||
LLVMValueRef value_cmp, value, *values = NULL;
|
||||
LLVMBasicBlockRef llvm_else_block, next_llvm_end_block;
|
||||
char name[32];
|
||||
uint32 i, param_index, result_index;
|
||||
uint64 size;
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
/* Insert suspend check point */
|
||||
if (comp_ctx->enable_thread_mgr) {
|
||||
if (!check_suspend_flags(comp_ctx, func_ctx))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
POP_COND(value_cmp);
|
||||
if (!LLVMIsConstant(value_cmp)) {
|
||||
|
@ -491,8 +801,29 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
CREATE_BLOCK(llvm_else_block, "br_if_else");
|
||||
MOVE_BLOCK_AFTER_CURR(llvm_else_block);
|
||||
|
||||
if (block_dst->block_type == BLOCK_TYPE_LOOP) {
|
||||
if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
||||
/* Dest block is Loop block */
|
||||
/* Handle Loop parameters */
|
||||
if (block_dst->param_count) {
|
||||
size = sizeof(LLVMValueRef) * (uint64)block_dst->param_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(values = wasm_runtime_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < block_dst->param_count; i++) {
|
||||
param_index = block_dst->param_count - 1 - i;
|
||||
POP(value, block_dst->param_types[param_index]);
|
||||
ADD_TO_PARAM_PHIS(block_dst, value, param_index);
|
||||
values[param_index] = value;
|
||||
}
|
||||
for (i = 0; i < block_dst->param_count; i++) {
|
||||
PUSH(values[i], block_dst->param_types[i]);
|
||||
}
|
||||
wasm_runtime_free(values);
|
||||
values = NULL;
|
||||
}
|
||||
|
||||
BUILD_COND_BR(value_cmp, block_dst->llvm_entry_block,
|
||||
llvm_else_block);
|
||||
|
||||
|
@ -504,7 +835,7 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
/* Create the end block */
|
||||
if (!block_dst->llvm_end_block) {
|
||||
format_block_name(name, sizeof(name),
|
||||
block_dst->block_index, block_dst->block_type,
|
||||
block_dst->block_index, block_dst->label_type,
|
||||
LABEL_END);
|
||||
CREATE_BLOCK(block_dst->llvm_end_block, name);
|
||||
if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
|
||||
|
@ -512,15 +843,29 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
next_llvm_end_block);
|
||||
}
|
||||
|
||||
/* Set reachable flag and create condtion br IR */
|
||||
/* Set reachable flag and create condition br IR */
|
||||
block_dst->is_reachable = true;
|
||||
|
||||
/* Handle return value */
|
||||
if (block_dst->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value_ret, block_dst->return_type);
|
||||
CREATE_RETURN_VALUE_PHI(block_dst);
|
||||
ADD_TO_RETURN_PHI(block_dst, value_ret);
|
||||
PUSH(value_ret, block_dst->return_type);
|
||||
/* Handle result values */
|
||||
if (block_dst->result_count) {
|
||||
size = sizeof(LLVMValueRef) * (uint64)block_dst->result_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(values = wasm_runtime_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
CREATE_RESULT_VALUE_PHIS(block_dst);
|
||||
for (i = 0; i < block_dst->result_count; i++) {
|
||||
result_index = block_dst->result_count - 1 - i;
|
||||
POP(value, block_dst->result_types[result_index]);
|
||||
values[result_index] = value;
|
||||
ADD_TO_RESULT_PHIS(block_dst, value, result_index);
|
||||
}
|
||||
for (i = 0; i < block_dst->result_count; i++) {
|
||||
PUSH(values[i], block_dst->result_types[i]);
|
||||
}
|
||||
wasm_runtime_free(values);
|
||||
values = NULL;
|
||||
}
|
||||
|
||||
/* Condition jump to end block */
|
||||
|
@ -533,16 +878,18 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
else {
|
||||
if ((int32)LLVMConstIntGetZExtValue(value_cmp) != 0) {
|
||||
/* Compare value is not 0, condtion is true, same as op_br */
|
||||
/* Compare value is not 0, condition is true, same as op_br */
|
||||
return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
|
||||
}
|
||||
else {
|
||||
/* Compare value is not 0, condtion is false, skip br_if */
|
||||
/* Compare value is not 0, condition is false, skip br_if */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
if (values)
|
||||
wasm_runtime_free(values);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -551,14 +898,24 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
uint32 *br_depths, uint32 br_count,
|
||||
uint8 **p_frame_ip)
|
||||
{
|
||||
uint32 i;
|
||||
LLVMValueRef value_switch, value_cmp, value_case, value_ret = NULL;
|
||||
uint32 i, j;
|
||||
LLVMValueRef value_switch, value_cmp, value_case, value, *values = NULL;
|
||||
LLVMBasicBlockRef default_llvm_block = NULL, target_llvm_block;
|
||||
LLVMBasicBlockRef next_llvm_end_block;
|
||||
AOTBlock *target_block;
|
||||
uint32 br_depth, depth_idx;
|
||||
uint32 param_index, result_index;
|
||||
uint64 size;
|
||||
char name[32];
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
/* Insert suspend check point */
|
||||
if (comp_ctx->enable_thread_mgr) {
|
||||
if (!check_suspend_flags(comp_ctx, func_ctx))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
POP_I32(value_cmp);
|
||||
if (!LLVMIsConstant(value_cmp)) {
|
||||
/* Compare value is not constant, create switch IR */
|
||||
|
@ -567,13 +924,13 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
if (!target_block)
|
||||
return false;
|
||||
|
||||
if (target_block->block_type != BLOCK_TYPE_LOOP) {
|
||||
if (target_block->label_type != LABEL_TYPE_LOOP) {
|
||||
/* Dest block is Block/If/Function block */
|
||||
/* Create the end block */
|
||||
if (!target_block->llvm_end_block) {
|
||||
format_block_name(name, sizeof(name),
|
||||
target_block->block_index,
|
||||
target_block->block_type,
|
||||
target_block->label_type,
|
||||
LABEL_END);
|
||||
CREATE_BLOCK(target_block->llvm_end_block, name);
|
||||
if ((next_llvm_end_block =
|
||||
|
@ -581,18 +938,50 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
MOVE_BLOCK_BEFORE(target_block->llvm_end_block,
|
||||
next_llvm_end_block);
|
||||
}
|
||||
/* Handle return value */
|
||||
if (target_block->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value_ret, target_block->return_type);
|
||||
CREATE_RETURN_VALUE_PHI(target_block);
|
||||
ADD_TO_RETURN_PHI(target_block, value_ret);
|
||||
PUSH(value_ret, target_block->return_type);
|
||||
/* Handle result values */
|
||||
if (target_block->result_count) {
|
||||
size = sizeof(LLVMValueRef) * (uint64)target_block->result_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(values = wasm_runtime_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
CREATE_RESULT_VALUE_PHIS(target_block);
|
||||
for (j = 0; j < target_block->result_count; j++) {
|
||||
result_index = target_block->result_count - 1 - j;
|
||||
POP(value, target_block->result_types[result_index]);
|
||||
values[result_index] = value;
|
||||
ADD_TO_RESULT_PHIS(target_block, value, result_index);
|
||||
}
|
||||
for (j = 0; j < target_block->result_count; j++) {
|
||||
PUSH(values[j], target_block->result_types[j]);
|
||||
}
|
||||
wasm_runtime_free(values);
|
||||
}
|
||||
target_block->is_reachable = true;
|
||||
if (i == br_count)
|
||||
default_llvm_block = target_block->llvm_end_block;
|
||||
}
|
||||
else {
|
||||
/* Handle Loop parameters */
|
||||
if (target_block->param_count) {
|
||||
size = sizeof(LLVMValueRef) * (uint64)target_block->param_count;
|
||||
if (size >= UINT32_MAX
|
||||
|| !(values = wasm_runtime_malloc((uint32)size))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
for (j = 0; j < target_block->param_count; j++) {
|
||||
param_index = target_block->param_count - 1 - j;
|
||||
POP(value, target_block->param_types[param_index]);
|
||||
values[param_index] = value;
|
||||
ADD_TO_PARAM_PHIS(target_block, value, param_index);
|
||||
}
|
||||
for (j = 0; j < target_block->param_count; j++) {
|
||||
PUSH(values[j], target_block->param_types[j]);
|
||||
}
|
||||
wasm_runtime_free(values);
|
||||
}
|
||||
if (i == br_count)
|
||||
default_llvm_block = target_block->llvm_entry_block;
|
||||
}
|
||||
|
@ -612,7 +1001,7 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
target_block = get_target_block(func_ctx, br_depths[i]);
|
||||
if (!target_block)
|
||||
return false;
|
||||
target_llvm_block = target_block->block_type != BLOCK_TYPE_LOOP
|
||||
target_llvm_block = target_block->label_type != LABEL_TYPE_LOOP
|
||||
? target_block->llvm_end_block
|
||||
: target_block->llvm_entry_block;
|
||||
LLVMAddCase(value_switch, value_case, target_llvm_block);
|
||||
|
@ -630,6 +1019,8 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
|
||||
}
|
||||
fail:
|
||||
if (values)
|
||||
wasm_runtime_free(values);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -639,14 +1030,38 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
{
|
||||
AOTBlock *block_func = func_ctx->block_stack.block_list_head;
|
||||
LLVMValueRef value;
|
||||
AOTFuncType *func_type;
|
||||
uint32 i, param_index, result_index;
|
||||
|
||||
bh_assert(block_func);
|
||||
if (block_func->return_type != VALUE_TYPE_VOID) {
|
||||
POP(value, block_func->return_type);
|
||||
LLVMBuildRet(comp_ctx->builder, value);
|
||||
func_type = func_ctx->aot_func->func_type;
|
||||
|
||||
if (block_func->result_count) {
|
||||
/* Store extra result values to function parameters */
|
||||
for (i = 0; i < block_func->result_count - 1; i++) {
|
||||
result_index = block_func->result_count - 1 - i;
|
||||
POP(value, block_func->result_types[result_index]);
|
||||
param_index = func_type->param_count + result_index;
|
||||
if (!LLVMBuildStore(comp_ctx->builder,
|
||||
value,
|
||||
LLVMGetParam(func_ctx->func, param_index))) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
/* Return the first result value */
|
||||
POP(value, block_func->result_types[0]);
|
||||
if (!LLVMBuildRet(comp_ctx->builder, value)) {
|
||||
aot_set_last_error("llvm build return failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!LLVMBuildRetVoid(comp_ctx->builder)) {
|
||||
aot_set_last_error("llvm build return void failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
LLVMBuildRetVoid(comp_ctx->builder);
|
||||
|
||||
return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
|
||||
fail:
|
||||
|
|
|
@ -15,7 +15,8 @@ extern "C" {
|
|||
bool
|
||||
aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip, uint8 *frame_ip_end,
|
||||
uint32 block_type, uint32 block_ret_type);
|
||||
uint32 label_type, uint32 param_count, uint8 *param_types,
|
||||
uint32 result_count, uint8 *result_types);
|
||||
|
||||
bool
|
||||
aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
|
@ -52,6 +53,11 @@ aot_handle_next_reachable_block(AOTCompContext *comp_ctx,
|
|||
AOTFuncContext *func_ctx,
|
||||
uint8 **p_frame_ip);
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
bool
|
||||
check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -89,6 +89,156 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
#define ADD_BASIC_BLOCK(block, name) do { \
|
||||
if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \
|
||||
func_ctx->func, \
|
||||
name))) { \
|
||||
aot_set_last_error("llvm add basic block failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
\
|
||||
LLVMMoveBasicBlockAfter(block, LLVMGetInsertBlock(comp_ctx->builder)); \
|
||||
} while (0)
|
||||
|
||||
static bool
|
||||
trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMValueRef operand, LLVMTypeRef dest_type,
|
||||
LLVMValueRef min_value, LLVMValueRef max_value,
|
||||
char *name, bool sign)
|
||||
{
|
||||
LLVMBasicBlockRef check_nan_succ, check_less_succ, check_greater_succ;
|
||||
LLVMBasicBlockRef is_nan_block, is_less_block, is_greater_block, res_block;
|
||||
LLVMValueRef is_less, is_greater, res, phi;
|
||||
LLVMValueRef zero = (dest_type == I32_TYPE) ? I32_ZERO : I64_ZERO;
|
||||
LLVMValueRef vmin, vmax;
|
||||
|
||||
if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO,
|
||||
operand, operand, "fcmp_is_nan"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ADD_BASIC_BLOCK(check_nan_succ, "check_nan_succ");
|
||||
ADD_BASIC_BLOCK(is_nan_block, "is_nan_block");
|
||||
ADD_BASIC_BLOCK(check_less_succ, "check_less_succ");
|
||||
ADD_BASIC_BLOCK(is_less_block, "is_less_block");
|
||||
ADD_BASIC_BLOCK(check_greater_succ, "check_greater_succ");
|
||||
ADD_BASIC_BLOCK(is_greater_block, "is_greater_block");
|
||||
ADD_BASIC_BLOCK(res_block, "res_block");
|
||||
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, res,
|
||||
is_nan_block, check_nan_succ)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate is_nan block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, is_nan_block);
|
||||
if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate check_nan_succ block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_nan_succ);
|
||||
if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand,
|
||||
min_value, "fcmp_min_value"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, is_less,
|
||||
is_less_block, check_less_succ)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate is_less block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, is_less_block);
|
||||
if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate check_less_succ block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_less_succ);
|
||||
if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand,
|
||||
max_value, "fcmp_max_value"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, is_greater,
|
||||
is_greater_block, check_greater_succ)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate is_greater block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, is_greater_block);
|
||||
if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate check_greater_succ block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_greater_succ);
|
||||
if (sign)
|
||||
res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name);
|
||||
else
|
||||
res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name);
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start to translate res_block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, res_block);
|
||||
/* Create result phi */
|
||||
if (!(phi = LLVMBuildPhi(comp_ctx->builder,
|
||||
dest_type,
|
||||
"trunc_sat_result_phi"))) {
|
||||
aot_set_last_error("llvm build phi failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add phi incoming values */
|
||||
if (dest_type == I32_TYPE) {
|
||||
if (sign) {
|
||||
vmin = I32_CONST(INT32_MIN);
|
||||
vmax = I32_CONST(INT32_MAX);
|
||||
}
|
||||
else {
|
||||
vmin = I32_CONST(0);
|
||||
vmax = I32_CONST(UINT32_MAX);
|
||||
}
|
||||
}
|
||||
else if (dest_type == I64_TYPE) {
|
||||
if (sign) {
|
||||
vmin = I64_CONST(INT64_MIN);
|
||||
vmax = I64_CONST(INT64_MAX);
|
||||
}
|
||||
else {
|
||||
vmin = I64_CONST(0);
|
||||
vmax = I64_CONST(UINT64_MAX);
|
||||
}
|
||||
}
|
||||
LLVMAddIncoming(phi, &zero, &is_nan_block, 1);
|
||||
LLVMAddIncoming(phi, &vmin, &is_less_block, 1);
|
||||
LLVMAddIncoming(phi, &vmax, &is_greater_block, 1);
|
||||
LLVMAddIncoming(phi, &res, &check_greater_succ, 1);
|
||||
|
||||
if (dest_type == I32_TYPE)
|
||||
PUSH_I32(phi);
|
||||
else if (dest_type == I64_TYPE)
|
||||
PUSH_I64(phi);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
|
@ -109,7 +259,7 @@ fail:
|
|||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
bool sign, bool saturating)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
@ -125,16 +275,22 @@ aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
max_value = F32_CONST(4294967296.0f);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
|
||||
if (!saturating)
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
|
||||
else
|
||||
return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_sat_f32_s" :
|
||||
"i32_trunc_sat_f32_u", sign);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
bool sign, bool saturating)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
@ -150,9 +306,15 @@ aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
max_value = F64_CONST(4294967296.0);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
|
||||
if (!saturating)
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
|
||||
else
|
||||
return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
|
||||
I32_TYPE, min_value, max_value,
|
||||
sign ? "i32_trunc_sat_f64_s" :
|
||||
"i32_trunc_sat_f64_u", sign);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
@ -180,9 +342,83 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int8 bitwidth)
|
||||
{
|
||||
LLVMValueRef value, res, cast_value = NULL;
|
||||
|
||||
POP_I64(value);
|
||||
|
||||
if (bitwidth == 8) {
|
||||
cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
|
||||
INT8_TYPE, true, "i8_intcast_i64");
|
||||
}
|
||||
else if (bitwidth == 16) {
|
||||
cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
|
||||
INT16_TYPE, true, "i16_intcast_i64");
|
||||
}
|
||||
else if (bitwidth == 32) {
|
||||
cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
|
||||
I32_TYPE, true, "i32_intcast_i64");
|
||||
}
|
||||
|
||||
if (!cast_value) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
res = LLVMBuildSExt(comp_ctx->builder, cast_value, I64_TYPE, "i64_extend_i64_s");
|
||||
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_I64(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int8 bitwidth)
|
||||
{
|
||||
LLVMValueRef value, res, cast_value = NULL;
|
||||
|
||||
POP_I32(value);
|
||||
|
||||
if (bitwidth == 8) {
|
||||
cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
|
||||
INT8_TYPE, true, "i8_intcast_i32");
|
||||
}
|
||||
else if (bitwidth == 16) {
|
||||
cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
|
||||
INT16_TYPE, true, "i16_intcast_i32");
|
||||
}
|
||||
|
||||
if (!cast_value) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
res = LLVMBuildSExt(comp_ctx->builder, cast_value, I32_TYPE, "i32_extend_i32_s");
|
||||
|
||||
if (!res) {
|
||||
aot_set_last_error("llvm build conversion failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PUSH_I32(res);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
bool sign, bool saturating)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
@ -198,16 +434,22 @@ aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
max_value = F32_CONST(18446744073709551616.0f);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
|
||||
if (!saturating)
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
|
||||
else
|
||||
return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_sat_f32_s" :
|
||||
"i64_trunc_sat_f32_u", sign);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign)
|
||||
bool sign, bool saturating)
|
||||
{
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef min_value, max_value;
|
||||
|
@ -223,9 +465,16 @@ aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
max_value = F64_CONST(18446744073709551616.0);
|
||||
}
|
||||
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
|
||||
if (!saturating)
|
||||
return trunc_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
|
||||
else
|
||||
return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
|
||||
I64_TYPE, min_value, max_value,
|
||||
sign ? "i64_trunc_sat_f64_s" :
|
||||
"i64_trunc_sat_f64_u", sign);
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -17,23 +17,31 @@ aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
|||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
bool sign, bool saturating);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
bool sign, bool saturating);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int8 bitwidth);
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int8 bitwidth);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
bool sign, bool saturating);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
bool sign);
|
||||
bool sign, bool saturating);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
|
|
|
@ -6,20 +6,6 @@
|
|||
#include "aot_emit_exception.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
static char *exce_block_names[] = {
|
||||
"exce_unreachable", /* EXCE_UNREACHABLE */
|
||||
"exce_out_of_memory", /* EXCE_OUT_OF_MEMORY */
|
||||
"exce_out_of_bounds_mem_access",/* EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS */
|
||||
"exce_integer_overflow", /* EXCE_INTEGER_OVERFLOW */
|
||||
"exce_divide_by_zero", /* EXCE_INTEGER_DIVIDE_BY_ZERO */
|
||||
"exce_invalid_convert_to_int", /* EXCE_INVALID_CONVERSION_TO_INTEGER */
|
||||
"exce_invalid_func_type_idx", /* EXCE_INVALID_FUNCTION_TYPE_INDEX */
|
||||
"exce_invalid_func_idx", /* EXCE_INVALID_FUNCTION_INDEX */
|
||||
"exce_undefined_element", /* EXCE_UNDEFINED_ELEMENT */
|
||||
"exce_uninit_element", /* EXCE_UNINITIALIZED_ELEMENT */
|
||||
"exce_call_unlinked" /* EXCE_CALL_UNLINKED_IMPORT_FUNC */
|
||||
};
|
||||
|
||||
bool
|
||||
aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
int32 exception_id,
|
||||
|
@ -27,7 +13,6 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
LLVMValueRef cond_br_if,
|
||||
LLVMBasicBlockRef cond_br_else_block)
|
||||
{
|
||||
LLVMBasicBlockRef exce_block;
|
||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMValueRef exce_id = I32_CONST((uint32)exception_id), func_const, func;
|
||||
LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
|
||||
|
@ -51,10 +36,8 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
func_ctx->got_exception_block);
|
||||
|
||||
/* Create exection id phi */
|
||||
if (!(func_ctx->exception_id_phi =
|
||||
LLVMBuildPhi(comp_ctx->builder,
|
||||
comp_ctx->basic_types.int32_type,
|
||||
"exception_id_phi"))) {
|
||||
if (!(func_ctx->exception_id_phi = LLVMBuildPhi(
|
||||
comp_ctx->builder, I32_TYPE, "exception_id_phi"))) {
|
||||
aot_set_last_error("llvm build phi failed.");
|
||||
return false;
|
||||
}
|
||||
|
@ -108,60 +91,20 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* Create return IR */
|
||||
AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
|
||||
if (aot_func_type->result_count) {
|
||||
switch (aot_func_type->types[aot_func_type->param_count]) {
|
||||
case VALUE_TYPE_I32:
|
||||
LLVMBuildRet(comp_ctx->builder, I32_ZERO);
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
LLVMBuildRet(comp_ctx->builder, I64_ZERO);
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
LLVMBuildRet(comp_ctx->builder, F32_ZERO);
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
LLVMBuildRet(comp_ctx->builder, F64_ZERO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LLVMBuildRetVoid(comp_ctx->builder);
|
||||
if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Resume the builder position */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
|
||||
}
|
||||
|
||||
/* Create exception block if needed */
|
||||
if (!(exce_block = func_ctx->exception_blocks[exception_id])) {
|
||||
if (!(func_ctx->exception_blocks[exception_id] = exce_block =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
exce_block_names[exception_id]))) {
|
||||
aot_set_last_error("add LLVM basic block failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Move before got_exception block */
|
||||
LLVMMoveBasicBlockBefore(exce_block, func_ctx->got_exception_block);
|
||||
|
||||
/* Add phi incoming value to got_exception block */
|
||||
LLVMAddIncoming(func_ctx->exception_id_phi, &exce_id, &exce_block, 1);
|
||||
|
||||
/* Jump to got exception block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, exce_block);
|
||||
if (!LLVMBuildBr(comp_ctx->builder, func_ctx->got_exception_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Resume builder position */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
|
||||
/* Add phi incoming value to got_exception block */
|
||||
LLVMAddIncoming(func_ctx->exception_id_phi, &exce_id, &block_curr, 1);
|
||||
|
||||
if (!is_cond_br) {
|
||||
/* not condition br, create br IR */
|
||||
if (!LLVMBuildBr(comp_ctx->builder, exce_block)) {
|
||||
if (!LLVMBuildBr(comp_ctx->builder, func_ctx->got_exception_block)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
return false;
|
||||
}
|
||||
|
@ -169,7 +112,7 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
else {
|
||||
/* Create condition br */
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, cond_br_if,
|
||||
exce_block, cond_br_else_block)) {
|
||||
func_ctx->got_exception_block, cond_br_else_block)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
return false;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,12 +14,24 @@ extern "C" {
|
|||
|
||||
bool
|
||||
aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 func_idx, uint8 **p_frame_ip);
|
||||
uint32 func_idx, bool tail_call);
|
||||
|
||||
bool
|
||||
aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 type_idx);
|
||||
aot_compile_op_call_indirect(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 type_idx,
|
||||
uint32 tbl_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_ref_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_ref_is_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_ref_func(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 func_idx);
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,6 +7,9 @@
|
|||
#define _AOT_EMIT_MEMORY_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
#include "wasm_shared_memory.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -14,11 +17,13 @@ extern "C" {
|
|||
|
||||
bool
|
||||
aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes, bool sign);
|
||||
uint32 align, uint32 offset, uint32 bytes,
|
||||
bool sign, bool atomic);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes, bool sign);
|
||||
uint32 align, uint32 offset, uint32 bytes,
|
||||
bool sign, bool atomic);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
|
@ -30,11 +35,11 @@ aot_compile_op_f64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
bool
|
||||
aot_compile_op_i32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes);
|
||||
uint32 align, uint32 offset, uint32 bytes, bool atomic);
|
||||
|
||||
bool
|
||||
aot_compile_op_i64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes);
|
||||
uint32 align, uint32 offset, uint32 bytes, bool atomic);
|
||||
|
||||
bool
|
||||
aot_compile_op_f32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
|
@ -44,12 +49,57 @@ bool
|
|||
aot_compile_op_f64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset);
|
||||
|
||||
LLVMValueRef
|
||||
aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 offset, uint32 bytes);
|
||||
|
||||
bool
|
||||
aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
bool
|
||||
aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 seg_index);
|
||||
|
||||
bool
|
||||
aot_compile_op_data_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 seg_index);
|
||||
|
||||
bool
|
||||
aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
bool
|
||||
aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 atomic_op, uint8 op_type,
|
||||
uint32 align, uint32 offset,
|
||||
uint32 bytes);
|
||||
|
||||
bool
|
||||
aot_compile_op_atomic_cmpxchg(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 op_type, uint32 align,
|
||||
uint32 offset, uint32 bytes);
|
||||
|
||||
bool
|
||||
aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint8 op_type, uint32 align,
|
||||
uint32 offset, uint32 bytes);
|
||||
|
||||
bool
|
||||
aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 align, uint32 offset, uint32 bytes);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2020 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
|||
#define ADD_BASIC_BLOCK(block, name) do { \
|
||||
if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \
|
||||
func_ctx->func, \
|
||||
name))) { \
|
||||
name))) { \
|
||||
aot_set_last_error("llvm add basic block failed."); \
|
||||
goto fail; \
|
||||
} \
|
||||
|
@ -135,116 +135,12 @@
|
|||
} while (0)
|
||||
|
||||
|
||||
static LLVMValueRef
|
||||
__call_llvm_intrinsic(AOTCompContext *comp_ctx,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMTypeRef *param_types,
|
||||
int param_count,
|
||||
LLVMValueRef *param_values)
|
||||
{
|
||||
LLVMValueRef func, ret;
|
||||
LLVMTypeRef func_type;
|
||||
|
||||
/* Declare llvm intrinsic function if necessary */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, name))) {
|
||||
if (!(func_type =
|
||||
LLVMFunctionType(ret_type, param_types, (uint32)param_count, false))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(func = LLVMAddFunction(comp_ctx->module, name, func_type))) {
|
||||
aot_set_last_error("add LLVM function failed.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the LLVM intrinsic function */
|
||||
if (!(ret = LLVMBuildCall(comp_ctx->builder, func, param_values,
|
||||
(uint32)param_count, "call"))) {
|
||||
aot_set_last_error("llvm build call failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static LLVMValueRef
|
||||
call_llvm_intrinsic(AOTCompContext *comp_ctx,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMTypeRef *param_types,
|
||||
int param_count,
|
||||
...)
|
||||
{
|
||||
LLVMValueRef *param_values, ret;
|
||||
va_list argptr;
|
||||
uint64 total_size;
|
||||
int i = 0;
|
||||
|
||||
/* Create param values */
|
||||
total_size = sizeof(LLVMValueRef) * (uint64)param_count;
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(param_values = wasm_runtime_malloc((uint32)total_size))) {
|
||||
aot_set_last_error("allocate memory for param values failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Load each param value */
|
||||
va_start(argptr, param_count);
|
||||
while (i < param_count)
|
||||
param_values[i++] = va_arg(argptr, LLVMValueRef);
|
||||
va_end(argptr);
|
||||
|
||||
ret = __call_llvm_intrinsic(comp_ctx, name, ret_type,
|
||||
param_types, param_count,
|
||||
param_values);
|
||||
|
||||
wasm_runtime_free(param_values);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static LLVMValueRef
|
||||
call_llvm_intrinsic_v(AOTCompContext *comp_ctx,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMTypeRef *param_types,
|
||||
int param_count,
|
||||
va_list param_value_list)
|
||||
{
|
||||
LLVMValueRef *param_values, ret;
|
||||
uint64 total_size;
|
||||
int i = 0;
|
||||
|
||||
/* Create param values */
|
||||
total_size = sizeof(LLVMValueRef) * (uint64)param_count;
|
||||
if (total_size >= UINT32_MAX
|
||||
|| !(param_values = wasm_runtime_malloc((uint32)total_size))) {
|
||||
aot_set_last_error("allocate memory for param values failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Load each param value */
|
||||
while (i < param_count)
|
||||
param_values[i++] = va_arg(param_value_list, LLVMValueRef);
|
||||
|
||||
ret = __call_llvm_intrinsic(comp_ctx, name, ret_type,
|
||||
param_types, param_count,
|
||||
param_values);
|
||||
|
||||
wasm_runtime_free(param_values);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Call llvm constrained floating-point intrinsic */
|
||||
static LLVMValueRef
|
||||
call_llvm_float_expermental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
||||
const char *intrinsic,
|
||||
bool is_f32,
|
||||
...)
|
||||
call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
||||
bool is_f32,
|
||||
const char *intrinsic,
|
||||
...)
|
||||
{
|
||||
va_list param_value_list;
|
||||
LLVMValueRef ret;
|
||||
|
@ -253,14 +149,10 @@ call_llvm_float_expermental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
|||
param_types[0] = param_types[1] = ret_type;
|
||||
param_types[2] = param_types[3] = MD_TYPE;
|
||||
|
||||
va_start(param_value_list, is_f32);
|
||||
va_start(param_value_list, intrinsic);
|
||||
|
||||
ret = call_llvm_intrinsic_v(comp_ctx,
|
||||
intrinsic,
|
||||
ret_type,
|
||||
param_types,
|
||||
4,
|
||||
param_value_list);
|
||||
ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, param_types,
|
||||
4, param_value_list);
|
||||
|
||||
va_end(param_value_list);
|
||||
|
||||
|
@ -269,10 +161,10 @@ call_llvm_float_expermental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
|||
|
||||
/* Call llvm constrained libm-equivalent intrinsic */
|
||||
static LLVMValueRef
|
||||
call_llvm_libm_expermental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
||||
const char *intrinsic,
|
||||
bool is_f32,
|
||||
...)
|
||||
call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
||||
bool is_f32,
|
||||
const char *intrinsic,
|
||||
...)
|
||||
{
|
||||
va_list param_value_list;
|
||||
LLVMValueRef ret;
|
||||
|
@ -281,14 +173,10 @@ call_llvm_libm_expermental_constrained_intrinsic(AOTCompContext *comp_ctx,
|
|||
param_types[0] = ret_type;
|
||||
param_types[1] = param_types[2] = MD_TYPE;
|
||||
|
||||
va_start(param_value_list, is_f32);
|
||||
va_start(param_value_list, intrinsic);
|
||||
|
||||
ret = call_llvm_intrinsic_v(comp_ctx,
|
||||
intrinsic,
|
||||
ret_type,
|
||||
param_types,
|
||||
3,
|
||||
param_value_list);
|
||||
ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, param_types,
|
||||
3, param_value_list);
|
||||
|
||||
va_end(param_value_list);
|
||||
|
||||
|
@ -342,13 +230,8 @@ compile_op_float_min_max(AOTCompContext *comp_ctx,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!(cmp = call_llvm_intrinsic(comp_ctx,
|
||||
intrinsic,
|
||||
ret_type,
|
||||
param_types,
|
||||
2,
|
||||
left,
|
||||
right)))
|
||||
if (!(cmp = aot_call_llvm_intrinsic(comp_ctx, intrinsic, ret_type,
|
||||
param_types, 2, left, right)))
|
||||
return NULL;
|
||||
|
||||
if (!(cmp = LLVMBuildSelect(comp_ctx->builder,
|
||||
|
@ -406,21 +289,21 @@ aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* Call the LLVM intrinsic function */
|
||||
if (type < POP_CNT32)
|
||||
DEF_INT_UNARY_OP(call_llvm_intrinsic(comp_ctx,
|
||||
bit_cnt_llvm_intrinsic[type],
|
||||
ret_type,
|
||||
param_types,
|
||||
2,
|
||||
operand,
|
||||
zero_undef),
|
||||
DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(comp_ctx,
|
||||
bit_cnt_llvm_intrinsic[type],
|
||||
ret_type,
|
||||
param_types,
|
||||
2,
|
||||
operand,
|
||||
zero_undef),
|
||||
NULL);
|
||||
else
|
||||
DEF_INT_UNARY_OP(call_llvm_intrinsic(comp_ctx,
|
||||
bit_cnt_llvm_intrinsic[type],
|
||||
ret_type,
|
||||
param_types,
|
||||
1,
|
||||
operand),
|
||||
DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(comp_ctx,
|
||||
bit_cnt_llvm_intrinsic[type],
|
||||
ret_type,
|
||||
param_types,
|
||||
1,
|
||||
operand),
|
||||
NULL);
|
||||
|
||||
return true;
|
||||
|
@ -861,6 +744,7 @@ static bool
|
|||
is_target_arm(AOTCompContext *comp_ctx)
|
||||
{
|
||||
return !strncmp(comp_ctx->target_arch, "arm", 3) ||
|
||||
!strncmp(comp_ctx->target_arch, "aarch64", 7) ||
|
||||
!strncmp(comp_ctx->target_arch, "thumb", 5);
|
||||
}
|
||||
|
||||
|
@ -929,12 +813,12 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
DEF_FP_BINARY_OP(LLVMBuildFAdd(comp_ctx->builder, left, right, "fadd"),
|
||||
"llvm build fadd fail.");
|
||||
else
|
||||
DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic(
|
||||
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
|
||||
comp_ctx,
|
||||
is_f32,
|
||||
(is_f32
|
||||
? "llvm.experimental.constrained.fadd.f32"
|
||||
: "llvm.experimental.constrained.fadd.f64"),
|
||||
is_f32,
|
||||
left,
|
||||
right,
|
||||
comp_ctx->fp_rounding_mode,
|
||||
|
@ -946,12 +830,12 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
DEF_FP_BINARY_OP(LLVMBuildFSub(comp_ctx->builder, left, right, "fsub"),
|
||||
"llvm build fsub fail.");
|
||||
else
|
||||
DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic(
|
||||
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
|
||||
comp_ctx,
|
||||
is_f32,
|
||||
(is_f32
|
||||
? "llvm.experimental.constrained.fsub.f32"
|
||||
: "llvm.experimental.constrained.fsub.f64"),
|
||||
is_f32,
|
||||
left,
|
||||
right,
|
||||
comp_ctx->fp_rounding_mode,
|
||||
|
@ -963,12 +847,12 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
DEF_FP_BINARY_OP(LLVMBuildFMul(comp_ctx->builder, left, right, "fmul"),
|
||||
"llvm build fmul fail.");
|
||||
else
|
||||
DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic(
|
||||
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
|
||||
comp_ctx,
|
||||
is_f32,
|
||||
(is_f32
|
||||
? "llvm.experimental.constrained.fmul.f32"
|
||||
: "llvm.experimental.constrained.fmul.f64"),
|
||||
is_f32,
|
||||
left,
|
||||
right,
|
||||
comp_ctx->fp_rounding_mode,
|
||||
|
@ -980,12 +864,12 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
DEF_FP_BINARY_OP(LLVMBuildFDiv(comp_ctx->builder, left, right, "fdiv"),
|
||||
"llvm build fdiv fail.");
|
||||
else
|
||||
DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic(
|
||||
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
|
||||
comp_ctx,
|
||||
is_f32,
|
||||
(is_f32
|
||||
? "llvm.experimental.constrained.fdiv.f32"
|
||||
: "llvm.experimental.constrained.fdiv.f64"),
|
||||
is_f32,
|
||||
left,
|
||||
right,
|
||||
comp_ctx->fp_rounding_mode,
|
||||
|
@ -1020,9 +904,9 @@ fail:
|
|||
|
||||
static LLVMValueRef
|
||||
call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx,
|
||||
const char *intrinsic,
|
||||
bool is_f32,
|
||||
...)
|
||||
bool is_f32,
|
||||
const char *intrinsic,
|
||||
...)
|
||||
{
|
||||
va_list param_value_list;
|
||||
LLVMValueRef ret;
|
||||
|
@ -1030,14 +914,10 @@ call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx,
|
|||
|
||||
param_type = ret_type;
|
||||
|
||||
va_start(param_value_list, is_f32);
|
||||
va_start(param_value_list, intrinsic);
|
||||
|
||||
ret = call_llvm_intrinsic_v(comp_ctx,
|
||||
intrinsic,
|
||||
ret_type,
|
||||
¶m_type,
|
||||
1,
|
||||
param_value_list);
|
||||
ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, ¶m_type,
|
||||
1, param_value_list);
|
||||
|
||||
va_end(param_value_list);
|
||||
|
||||
|
@ -1051,9 +931,9 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
switch (math_op) {
|
||||
case FLOAT_ABS:
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.fabs.f32" :
|
||||
"llvm.fabs.f64",
|
||||
is_f32,
|
||||
operand),
|
||||
NULL);
|
||||
return true;
|
||||
|
@ -1064,51 +944,51 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
case FLOAT_CEIL:
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.ceil.f32" :
|
||||
"llvm.ceil.f64",
|
||||
is_f32,
|
||||
operand),
|
||||
NULL);
|
||||
return true;
|
||||
case FLOAT_FLOOR:
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
is_f32 ? "llvm.floor.f32" :
|
||||
"llvm.floor.f64",
|
||||
is_f32,
|
||||
is_f32 ? "llvm.floor.f32":
|
||||
"llvm.floor.f64",
|
||||
operand),
|
||||
NULL);
|
||||
return true;
|
||||
case FLOAT_TRUNC:
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.trunc.f32" :
|
||||
"llvm.trunc.f64",
|
||||
is_f32,
|
||||
operand),
|
||||
NULL);
|
||||
return true;
|
||||
case FLOAT_NEAREST:
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.rint.f32" :
|
||||
"llvm.rint.f64",
|
||||
is_f32,
|
||||
operand),
|
||||
NULL);
|
||||
return true;
|
||||
case FLOAT_SQRT:
|
||||
if (is_targeting_soft_float(comp_ctx, is_f32))
|
||||
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
|
||||
is_f32,
|
||||
is_f32 ? "llvm.sqrt.f32" :
|
||||
"llvm.sqrt.f64",
|
||||
is_f32,
|
||||
operand),
|
||||
NULL);
|
||||
else
|
||||
DEF_FP_UNARY_OP(call_llvm_libm_expermental_constrained_intrinsic(
|
||||
DEF_FP_UNARY_OP(call_llvm_libm_experimental_constrained_intrinsic(
|
||||
comp_ctx,
|
||||
is_f32,
|
||||
(is_f32
|
||||
? "llvm.experimental.constrained.sqrt.f32"
|
||||
: "llvm.experimental.constrained.sqrt.f64"),
|
||||
is_f32,
|
||||
operand,
|
||||
comp_ctx->fp_rounding_mode,
|
||||
comp_ctx->fp_exception_behavior),
|
||||
|
@ -1133,14 +1013,14 @@ compile_float_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
param_types[0] = param_types[1] = ret_type = is_f32 ? F32_TYPE : F64_TYPE;
|
||||
|
||||
DEF_FP_BINARY_OP(call_llvm_intrinsic(comp_ctx,
|
||||
is_f32 ? "llvm.copysign.f32" :
|
||||
"llvm.copysign.f64",
|
||||
ret_type,
|
||||
param_types,
|
||||
2,
|
||||
left,
|
||||
right),
|
||||
DEF_FP_BINARY_OP(aot_call_llvm_intrinsic(comp_ctx,
|
||||
is_f32 ? "llvm.copysign.f32" :
|
||||
"llvm.copysign.f64",
|
||||
ret_type,
|
||||
param_types,
|
||||
2,
|
||||
left,
|
||||
right),
|
||||
NULL);
|
||||
return true;
|
||||
|
||||
|
|
|
@ -45,10 +45,18 @@ pop_value_from_wasm_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
wasm_runtime_free(aot_value);
|
||||
|
||||
if ((is_32
|
||||
&& (type != VALUE_TYPE_I32 && type != VALUE_TYPE_F32))
|
||||
|| (!is_32
|
||||
&& (type != VALUE_TYPE_I64 && type != VALUE_TYPE_F64))) {
|
||||
/* is_32: i32, f32, ref.func, ref.extern, v128 */
|
||||
if (is_32
|
||||
&& !(type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32
|
||||
|| type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF
|
||||
|| type == VALUE_TYPE_V128)) {
|
||||
aot_set_last_error("invalid WASM stack data type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* !is_32: i64, f64 */
|
||||
if (!is_32
|
||||
&& !(type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)) {
|
||||
aot_set_last_error("invalid WASM stack data type.");
|
||||
return false;
|
||||
}
|
||||
|
|
487
core/iwasm/compilation/aot_emit_table.c
Normal file
487
core/iwasm/compilation/aot_emit_table.c
Normal file
|
@ -0,0 +1,487 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_emit_table.h"
|
||||
#include "aot_emit_exception.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
|
||||
uint64
|
||||
get_tbl_inst_offset(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx)
|
||||
{
|
||||
uint64 offset = 0, i = 0;
|
||||
AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
|
||||
AOTTable *tbls = comp_ctx->comp_data->tables;
|
||||
|
||||
/* from the head of AOTModuleInstance */
|
||||
offset =
|
||||
offsetof(AOTModuleInstance, global_table_data.bytes)
|
||||
+ (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance)
|
||||
+ comp_ctx->comp_data->global_data_size;
|
||||
|
||||
while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
|
||||
offset += offsetof(AOTTableInstance, data);
|
||||
offset += sizeof(uint32) * aot_get_imp_tbl_data_slots(imp_tbls + i);
|
||||
++i;
|
||||
}
|
||||
|
||||
if (i == tbl_idx) {
|
||||
return offset;
|
||||
}
|
||||
|
||||
tbl_idx -= comp_ctx->comp_data->import_table_count;
|
||||
i -= comp_ctx->comp_data->import_table_count;
|
||||
while (i < tbl_idx && i < comp_ctx->comp_data->table_count) {
|
||||
offset += offsetof(AOTTableInstance, data);
|
||||
offset += sizeof(uint32) * aot_get_tbl_data_slots(tbls + i);
|
||||
++i;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
|
||||
LLVMValueRef
|
||||
aot_compile_get_tbl_inst(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx)
|
||||
{
|
||||
LLVMValueRef offset, tbl_inst;
|
||||
|
||||
if (!(offset =
|
||||
I64_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(tbl_inst = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
|
||||
&offset, 1, "tbl_inst"))) {
|
||||
HANDLE_FAILURE("LLVMBuildGEP");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return tbl_inst;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_elem_drop(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_seg_idx)
|
||||
{
|
||||
LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
|
||||
LLVMValueRef param_values[2], ret_value, func, value;
|
||||
|
||||
/* void aot_drop_table_seg(AOTModuleInstance *, uint32 ) */
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = I32_TYPE;
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_drop_table_seg, 2);
|
||||
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
if (!(param_values[1] = I32_CONST(tbl_seg_idx))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* "" means return void */
|
||||
if (!(ret_value =
|
||||
LLVMBuildCall(comp_ctx->builder, func, param_values, 2, ""))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
aot_check_table_access(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx,
|
||||
LLVMValueRef elem_idx)
|
||||
{
|
||||
LLVMValueRef offset, tbl_sz, cmp_elem_idx;
|
||||
LLVMBasicBlockRef check_elem_idx_succ;
|
||||
|
||||
/* get the cur size of the table instance */
|
||||
if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
|
||||
+ offsetof(AOTTableInstance, cur_size)))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(tbl_sz = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst, &offset,
|
||||
1, "cur_size_i8p"))) {
|
||||
HANDLE_FAILURE("LLVMBuildGEP");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
|
||||
"cur_siuze_i32p"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(tbl_sz = LLVMBuildLoad(comp_ctx->builder, tbl_sz, "cur_size"))) {
|
||||
HANDLE_FAILURE("LLVMBuildLoad");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check if (uint32)elem index >= table size */
|
||||
if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
|
||||
tbl_sz, "cmp_elem_idx"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Throw exception if elem index >= table size */
|
||||
if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext(
|
||||
comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMMoveBasicBlockAfter(check_elem_idx_succ,
|
||||
LLVMGetInsertBlock(comp_ctx->builder));
|
||||
|
||||
if (!(aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, true,
|
||||
cmp_elem_idx, check_elem_idx_succ)))
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_table_get(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx)
|
||||
{
|
||||
LLVMValueRef elem_idx, offset, table_elem, func_idx;
|
||||
|
||||
POP_I32(elem_idx);
|
||||
|
||||
if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* load data as i32* */
|
||||
if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
|
||||
+ offsetof(AOTTableInstance, data)))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
|
||||
&offset, 1, "table_elem_i8p"))) {
|
||||
aot_set_last_error("llvm build add failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
|
||||
INT32_PTR_TYPE, "table_elem_i32p"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Load function index */
|
||||
if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx,
|
||||
1, "table_elem"))) {
|
||||
HANDLE_FAILURE("LLVMBuildNUWAdd");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func_idx =
|
||||
LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) {
|
||||
HANDLE_FAILURE("LLVMBuildLoad");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_I32(func_idx);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_table_set(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx)
|
||||
{
|
||||
LLVMValueRef val, elem_idx, offset, table_elem;
|
||||
|
||||
POP_I32(val);
|
||||
POP_I32(elem_idx);
|
||||
|
||||
if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* load data as i32* */
|
||||
if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
|
||||
+ offsetof(AOTTableInstance, data)))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
|
||||
&offset, 1, "table_elem_i8p"))) {
|
||||
HANDLE_FAILURE("LLVMBuildGEP");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
|
||||
INT32_PTR_TYPE, "table_elem_i32p"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Load function index */
|
||||
if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx,
|
||||
1, "table_elem"))) {
|
||||
HANDLE_FAILURE("LLVMBuildGEP");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(LLVMBuildStore(comp_ctx->builder, val, table_elem))) {
|
||||
HANDLE_FAILURE("LLVMBuildStore");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_table_init(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx,
|
||||
uint32 tbl_seg_idx)
|
||||
|
||||
{
|
||||
LLVMValueRef func, param_values[6], value;
|
||||
LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
|
||||
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = I32_TYPE;
|
||||
param_types[2] = I32_TYPE;
|
||||
param_types[3] = I32_TYPE;
|
||||
param_types[4] = I32_TYPE;
|
||||
param_types[5] = I32_TYPE;
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_table_init, 6);
|
||||
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
|
||||
if (!(param_values[1] = I32_CONST(tbl_idx))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(param_values[2] = I32_CONST(tbl_seg_idx))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* n */
|
||||
POP_I32(param_values[3]);
|
||||
/* s */
|
||||
POP_I32(param_values[4]);
|
||||
/* d */
|
||||
POP_I32(param_values[5]);
|
||||
|
||||
/* "" means return void */
|
||||
if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 6, ""))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_table_copy(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 src_tbl_idx,
|
||||
uint32 dst_tbl_idx)
|
||||
{
|
||||
LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
|
||||
LLVMValueRef func, param_values[6], value;
|
||||
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = I32_TYPE;
|
||||
param_types[2] = I32_TYPE;
|
||||
param_types[3] = I32_TYPE;
|
||||
param_types[4] = I32_TYPE;
|
||||
param_types[5] = I32_TYPE;
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_table_copy, 6);
|
||||
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
|
||||
if (!(param_values[1] = I32_CONST(src_tbl_idx))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(param_values[2] = I32_CONST(dst_tbl_idx))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* n */
|
||||
POP_I32(param_values[3]);
|
||||
/* s */
|
||||
POP_I32(param_values[4]);
|
||||
/* d */
|
||||
POP_I32(param_values[5]);
|
||||
|
||||
/* "" means return void */
|
||||
if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 6, ""))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_table_size(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx)
|
||||
{
|
||||
LLVMValueRef offset, tbl_sz;
|
||||
|
||||
if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
|
||||
+ offsetof(AOTTableInstance, cur_size)))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(tbl_sz = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst, &offset,
|
||||
1, "tbl_sz_ptr_i8"))) {
|
||||
HANDLE_FAILURE("LLVMBuildGEP");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
|
||||
"tbl_sz_ptr"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(tbl_sz = LLVMBuildLoad(comp_ctx->builder, tbl_sz, "tbl_sz"))) {
|
||||
HANDLE_FAILURE("LLVMBuildLoad");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_I32(tbl_sz);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_table_grow(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx)
|
||||
{
|
||||
LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type;
|
||||
LLVMValueRef func, param_values[4], ret, value;
|
||||
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = I32_TYPE;
|
||||
param_types[2] = I32_TYPE;
|
||||
param_types[3] = I32_TYPE;
|
||||
ret_type = I32_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_table_grow, 4);
|
||||
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
|
||||
if (!(param_values[1] = I32_CONST(tbl_idx))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* n */
|
||||
POP_I32(param_values[2]);
|
||||
/* v */
|
||||
POP_I32(param_values[3]);
|
||||
|
||||
if (!(ret = LLVMBuildCall(comp_ctx->builder, func, param_values, 4,
|
||||
"table_grow"))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_I32(ret);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_table_fill(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx)
|
||||
{
|
||||
LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
|
||||
LLVMValueRef func, param_values[5], value;
|
||||
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = I32_TYPE;
|
||||
param_types[2] = I32_TYPE;
|
||||
param_types[3] = I32_TYPE;
|
||||
param_types[4] = I32_TYPE;
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_table_fill, 5);
|
||||
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
|
||||
if (!(param_values[1] = I32_CONST(tbl_idx))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* n */
|
||||
POP_I32(param_values[2]);
|
||||
/* v */
|
||||
POP_I32(param_values[3]);
|
||||
/* i */
|
||||
POP_I32(param_values[4]);
|
||||
|
||||
/* "" means return void */
|
||||
if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 5, ""))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* WASM_ENABLE_REF_TYPES != 0 */
|
71
core/iwasm/compilation/aot_emit_table.h
Normal file
71
core/iwasm/compilation/aot_emit_table.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _AOT_EMIT_TABLE_H_
|
||||
#define _AOT_EMIT_TABLE_H_
|
||||
|
||||
#include "aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_elem_drop(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_seg_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_table_get(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_table_set(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_table_init(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx,
|
||||
uint32 tbl_seg_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_table_copy(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 src_tbl_idx,
|
||||
uint32 dst_tbl_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_table_size(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_table_grow(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx);
|
||||
|
||||
bool
|
||||
aot_compile_op_table_fill(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx);
|
||||
|
||||
uint64
|
||||
get_tbl_inst_offset(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx);
|
||||
|
||||
LLVMValueRef
|
||||
aot_compile_get_tbl_inst(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 tbl_idx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
#endif
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include "aot_emit_variable.h"
|
||||
#include "aot_emit_exception.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
#define CHECK_LOCAL(idx) do { \
|
||||
|
@ -30,6 +31,7 @@ aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
{
|
||||
char name[32];
|
||||
LLVMValueRef value;
|
||||
AOTValue *aot_value;
|
||||
|
||||
CHECK_LOCAL(local_idx);
|
||||
|
||||
|
@ -42,6 +44,10 @@ aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
|
||||
PUSH(value, get_local_type(func_ctx, local_idx));
|
||||
|
||||
aot_value = func_ctx->block_stack.block_list_end->value_stack.value_list_end;
|
||||
aot_value->is_local = true;
|
||||
aot_value->local_idx = local_idx;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
|
@ -65,6 +71,7 @@ aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
return false;
|
||||
}
|
||||
|
||||
aot_checked_addr_list_del(func_ctx, local_idx);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
|
@ -92,6 +99,7 @@ aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
|
||||
PUSH(value, type);
|
||||
aot_checked_addr_list_del(func_ctx, local_idx);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
|
@ -100,15 +108,16 @@ fail:
|
|||
|
||||
static bool
|
||||
compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 global_idx, bool is_set)
|
||||
uint32 global_idx, bool is_set, bool is_aux_stack)
|
||||
{
|
||||
AOTCompData *comp_data = comp_ctx->comp_data;
|
||||
uint32 import_global_count = comp_data->import_global_count;
|
||||
uint32 global_base_offset = offsetof(AOTModuleInstance,
|
||||
global_table_data.bytes);
|
||||
uint32 global_base_offset =
|
||||
offsetof(AOTModuleInstance, global_table_data.bytes)
|
||||
+ sizeof(AOTMemoryInstance) * comp_ctx->comp_data->memory_count;
|
||||
uint32 global_offset;
|
||||
uint8 global_type;
|
||||
LLVMValueRef offset, global_ptr, global;
|
||||
LLVMValueRef offset, global_ptr, global, res;
|
||||
LLVMTypeRef ptr_type = NULL;
|
||||
|
||||
bh_assert(global_idx < import_global_count + comp_data->global_count);
|
||||
|
@ -134,6 +143,8 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
switch (global_type) {
|
||||
case VALUE_TYPE_I32:
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
ptr_type = comp_ctx->basic_types.int32_ptr_type;
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
|
@ -145,8 +156,11 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
case VALUE_TYPE_F64:
|
||||
ptr_type = comp_ctx->basic_types.float64_ptr_type;
|
||||
break;
|
||||
case VALUE_TYPE_V128:
|
||||
ptr_type = comp_ctx->basic_types.v128_ptr_type;
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
bh_assert("unknown type");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -162,14 +176,74 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
aot_set_last_error("llvm build load failed.");
|
||||
return false;
|
||||
}
|
||||
/* All globals' data is 4-byte aligned */
|
||||
LLVMSetAlignment(global, 4);
|
||||
PUSH(global, global_type);
|
||||
}
|
||||
else {
|
||||
POP(global, global_type);
|
||||
if (!LLVMBuildStore(comp_ctx->builder, global, global_ptr)) {
|
||||
|
||||
if (is_aux_stack && comp_ctx->enable_aux_stack_check) {
|
||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMBasicBlockRef check_overflow_succ, check_underflow_succ;
|
||||
LLVMValueRef cmp;
|
||||
|
||||
/* Add basic blocks */
|
||||
if (!(check_overflow_succ =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_overflow_succ"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
return false;
|
||||
}
|
||||
LLVMMoveBasicBlockAfter(check_overflow_succ, block_curr);
|
||||
|
||||
if (!(check_underflow_succ =
|
||||
LLVMAppendBasicBlockInContext(comp_ctx->context,
|
||||
func_ctx->func,
|
||||
"check_underflow_succ"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
return false;
|
||||
}
|
||||
LLVMMoveBasicBlockAfter(check_underflow_succ, check_overflow_succ);
|
||||
|
||||
/* Check aux stack overflow */
|
||||
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE,
|
||||
global, func_ctx->aux_stack_bound,
|
||||
"cmp"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
return false;
|
||||
}
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_AUX_STACK_OVERFLOW,
|
||||
true, cmp, check_overflow_succ)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check aux stack underflow */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_overflow_succ);
|
||||
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT,
|
||||
global, func_ctx->aux_stack_bottom,
|
||||
"cmp"))) {
|
||||
aot_set_last_error("llvm build icmp failed.");
|
||||
return false;
|
||||
}
|
||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||
EXCE_AUX_STACK_UNDERFLOW,
|
||||
true, cmp, check_underflow_succ)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_underflow_succ);
|
||||
}
|
||||
|
||||
if (!(res = LLVMBuildStore(comp_ctx->builder,
|
||||
global, global_ptr))) {
|
||||
aot_set_last_error("llvm build store failed.");
|
||||
return false;
|
||||
}
|
||||
/* All globals' data is 4-byte aligned */
|
||||
LLVMSetAlignment(res, 4);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -181,13 +255,13 @@ bool
|
|||
aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 global_idx)
|
||||
{
|
||||
return compile_global(comp_ctx, func_ctx, global_idx, false);
|
||||
return compile_global(comp_ctx, func_ctx, global_idx, false, false);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 global_idx)
|
||||
uint32 global_idx, bool is_aux_stack)
|
||||
{
|
||||
return compile_global(comp_ctx, func_ctx, global_idx, true);
|
||||
return compile_global(comp_ctx, func_ctx, global_idx, true, is_aux_stack);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
bool
|
||||
aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 global_idx);
|
||||
uint32 global_idx, bool is_aux_stack);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,13 +7,16 @@
|
|||
#define _AOT_LLVM_H_
|
||||
|
||||
#include "aot.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm-c/Types.h"
|
||||
#include "llvm-c/Target.h"
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm-c/Object.h"
|
||||
#include "llvm-c/ExecutionEngine.h"
|
||||
#include "llvm-c/Analysis.h"
|
||||
#include "llvm-c/Transforms/Utils.h"
|
||||
#include "llvm-c/Transforms/Scalar.h"
|
||||
#include "llvm-c/Transforms/Vectorize.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -30,6 +33,8 @@ typedef struct AOTValue {
|
|||
LLVMValueRef value;
|
||||
/* VALUE_TYPE_I32/I64/F32/F64/VOID */
|
||||
uint8 type;
|
||||
bool is_local;
|
||||
uint32 local_idx;
|
||||
} AOTValue;
|
||||
|
||||
/**
|
||||
|
@ -46,10 +51,8 @@ typedef struct AOTBlock {
|
|||
|
||||
/* Block index */
|
||||
uint32 block_index;
|
||||
/* BLOCK_TYPE_BLOCK/LOOP/IF/FUNCTION */
|
||||
uint32 block_type;
|
||||
/* VALUE_TYPE_I32/I64/F32/F64/VOID */
|
||||
uint8 return_type;
|
||||
/* LABEL_TYPE_BLOCK/LOOP/IF/FUNCTION */
|
||||
uint32 label_type;
|
||||
/* Whether it is reachable */
|
||||
bool is_reachable;
|
||||
/* Whether skip translation of wasm else branch */
|
||||
|
@ -70,8 +73,16 @@ typedef struct AOTBlock {
|
|||
/* WASM operation stack */
|
||||
AOTValueStack value_stack;
|
||||
|
||||
/* Return value of this block, a PHI node */
|
||||
LLVMValueRef return_value_phi;
|
||||
/* Param count/types/PHIs of this block */
|
||||
uint32 param_count;
|
||||
uint8 *param_types;
|
||||
LLVMValueRef *param_phis;
|
||||
LLVMValueRef *else_param_phis;
|
||||
|
||||
/* Result count/types/PHIs of this block */
|
||||
uint32 result_count;
|
||||
uint8 *result_types;
|
||||
LLVMValueRef *result_phis;
|
||||
} AOTBlock;
|
||||
|
||||
/**
|
||||
|
@ -84,6 +95,24 @@ typedef struct AOTBlockStack {
|
|||
uint32 block_index[3];
|
||||
} AOTBlockStack;
|
||||
|
||||
typedef struct AOTCheckedAddr {
|
||||
struct AOTCheckedAddr *next;
|
||||
uint32 local_idx;
|
||||
uint32 offset;
|
||||
uint32 bytes;
|
||||
} AOTCheckedAddr, *AOTCheckedAddrList;
|
||||
|
||||
typedef struct AOTMemInfo {
|
||||
LLVMValueRef mem_base_addr;
|
||||
LLVMValueRef mem_data_size_addr;
|
||||
LLVMValueRef mem_cur_page_count_addr;
|
||||
LLVMValueRef mem_bound_check_1byte;
|
||||
LLVMValueRef mem_bound_check_2bytes;
|
||||
LLVMValueRef mem_bound_check_4bytes;
|
||||
LLVMValueRef mem_bound_check_8bytes;
|
||||
LLVMValueRef mem_bound_check_16bytes;
|
||||
} AOTMemInfo;
|
||||
|
||||
typedef struct AOTFuncContext {
|
||||
AOTFunc *aot_func;
|
||||
LLVMValueRef func;
|
||||
|
@ -91,26 +120,23 @@ typedef struct AOTFuncContext {
|
|||
|
||||
LLVMValueRef exec_env;
|
||||
LLVMValueRef aot_inst;
|
||||
LLVMValueRef table_base;
|
||||
LLVMValueRef argv_buf;
|
||||
LLVMValueRef native_stack_bound;
|
||||
LLVMValueRef aux_stack_bound;
|
||||
LLVMValueRef aux_stack_bottom;
|
||||
LLVMValueRef last_alloca;
|
||||
LLVMValueRef func_ptrs;
|
||||
|
||||
LLVMValueRef heap_base_offset;
|
||||
LLVMValueRef mem_base_addr;
|
||||
LLVMValueRef total_mem_size;
|
||||
LLVMValueRef mem_bound_check_1byte;
|
||||
LLVMValueRef mem_bound_check_2bytes;
|
||||
LLVMValueRef mem_bound_check_4bytes;
|
||||
LLVMValueRef mem_bound_check_8bytes;
|
||||
AOTMemInfo *mem_info;
|
||||
|
||||
LLVMValueRef cur_exception;
|
||||
|
||||
bool mem_space_unchanged;
|
||||
AOTCheckedAddrList checked_addr_list;
|
||||
|
||||
LLVMBasicBlockRef *exception_blocks;
|
||||
LLVMBasicBlockRef got_exception_block;
|
||||
LLVMBasicBlockRef func_return_block;
|
||||
LLVMValueRef exception_id_phi;
|
||||
LLVMValueRef func_ptrs;
|
||||
LLVMValueRef func_type_indexes;
|
||||
LLVMValueRef locals[1];
|
||||
} AOTFuncContext;
|
||||
|
@ -126,14 +152,26 @@ typedef struct AOTLLVMTypes {
|
|||
LLVMTypeRef void_type;
|
||||
|
||||
LLVMTypeRef int8_ptr_type;
|
||||
LLVMTypeRef int8_pptr_type;
|
||||
LLVMTypeRef int16_ptr_type;
|
||||
LLVMTypeRef int32_ptr_type;
|
||||
LLVMTypeRef int64_ptr_type;
|
||||
LLVMTypeRef float32_ptr_type;
|
||||
LLVMTypeRef float64_ptr_type;
|
||||
LLVMTypeRef void_ptr_type;
|
||||
|
||||
LLVMTypeRef v128_type;
|
||||
LLVMTypeRef v128_ptr_type;
|
||||
LLVMTypeRef i8x16_vec_type;
|
||||
LLVMTypeRef i16x8_vec_type;
|
||||
LLVMTypeRef i32x4_vec_type;
|
||||
LLVMTypeRef i64x2_vec_type;
|
||||
LLVMTypeRef f32x4_vec_type;
|
||||
LLVMTypeRef f64x2_vec_type;
|
||||
|
||||
LLVMTypeRef meta_data_type;
|
||||
|
||||
LLVMTypeRef funcref_type;
|
||||
LLVMTypeRef externref_type;
|
||||
} AOTLLVMTypes;
|
||||
|
||||
typedef struct AOTLLVMConsts {
|
||||
|
@ -142,10 +180,20 @@ typedef struct AOTLLVMConsts {
|
|||
LLVMValueRef i64_zero;
|
||||
LLVMValueRef f32_zero;
|
||||
LLVMValueRef f64_zero;
|
||||
LLVMValueRef v128_zero;
|
||||
LLVMValueRef i8x16_vec_zero;
|
||||
LLVMValueRef i16x8_vec_zero;
|
||||
LLVMValueRef i32x4_vec_zero;
|
||||
LLVMValueRef i64x2_vec_zero;
|
||||
LLVMValueRef f32x4_vec_zero;
|
||||
LLVMValueRef f64x2_vec_zero;
|
||||
LLVMValueRef i32_one;
|
||||
LLVMValueRef i32_two;
|
||||
LLVMValueRef i32_three;
|
||||
LLVMValueRef i32_four;
|
||||
LLVMValueRef i32_five;
|
||||
LLVMValueRef i32_six;
|
||||
LLVMValueRef i32_seven;
|
||||
LLVMValueRef i32_eight;
|
||||
LLVMValueRef i32_neg_one;
|
||||
LLVMValueRef i64_neg_one;
|
||||
|
@ -155,6 +203,7 @@ typedef struct AOTLLVMConsts {
|
|||
LLVMValueRef i32_32;
|
||||
LLVMValueRef i64_63;
|
||||
LLVMValueRef i64_64;
|
||||
LLVMValueRef ref_null;
|
||||
} AOTLLVMConsts;
|
||||
|
||||
/**
|
||||
|
@ -170,11 +219,36 @@ typedef struct AOTCompContext {
|
|||
LLVMTargetMachineRef target_machine;
|
||||
char *target_cpu;
|
||||
char target_arch[16];
|
||||
unsigned pointer_size;
|
||||
|
||||
/* LLVM execution engine required by JIT */
|
||||
LLVMExecutionEngineRef exec_engine;
|
||||
bool is_jit_mode;
|
||||
|
||||
/* Bulk memory feature */
|
||||
bool enable_bulk_memory;
|
||||
|
||||
/* Bounday Check */
|
||||
bool enable_bound_check;
|
||||
|
||||
/* 128-bit SIMD */
|
||||
bool enable_simd;
|
||||
|
||||
/* Auxiliary stack overflow/underflow check */
|
||||
bool enable_aux_stack_check;
|
||||
|
||||
/* Generate auxiliary stack frame */
|
||||
bool enable_aux_stack_frame;
|
||||
|
||||
/* Thread Manager */
|
||||
bool enable_thread_mgr;
|
||||
|
||||
/* Tail Call */
|
||||
bool enable_tail_call;
|
||||
|
||||
/* Reference Types */
|
||||
bool enable_ref_types;
|
||||
|
||||
/* Whether optimize the JITed code */
|
||||
bool optimize;
|
||||
|
||||
|
@ -213,9 +287,18 @@ typedef struct AOTCompOption{
|
|||
char *target_abi;
|
||||
char *target_cpu;
|
||||
char *cpu_features;
|
||||
bool enable_bulk_memory;
|
||||
bool enable_thread_mgr;
|
||||
bool enable_tail_call;
|
||||
bool enable_simd;
|
||||
bool enable_ref_types;
|
||||
bool enable_aux_stack_check;
|
||||
bool enable_aux_stack_frame;
|
||||
bool is_sgx_platform;
|
||||
uint32 opt_level;
|
||||
uint32 size_level;
|
||||
uint32 output_format;
|
||||
uint32 bounds_checks;
|
||||
} AOTCompOption, *aot_comp_option_t;
|
||||
|
||||
AOTCompContext *
|
||||
|
@ -258,6 +341,43 @@ aot_block_destroy(AOTBlock *block);
|
|||
LLVMTypeRef
|
||||
wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type);
|
||||
|
||||
bool
|
||||
aot_checked_addr_list_add(AOTFuncContext *func_ctx,
|
||||
uint32 local_idx, uint32 offset, uint32 bytes);
|
||||
|
||||
void
|
||||
aot_checked_addr_list_del(AOTFuncContext *func_ctx, uint32 local_idx);
|
||||
|
||||
bool
|
||||
aot_checked_addr_list_find(AOTFuncContext *func_ctx,
|
||||
uint32 local_idx, uint32 offset, uint32 bytes);
|
||||
|
||||
void
|
||||
aot_checked_addr_list_destroy(AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_build_zero_function_ret(AOTCompContext *comp_ctx,
|
||||
AOTFuncType *func_type);
|
||||
|
||||
LLVMValueRef
|
||||
aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMTypeRef *param_types,
|
||||
int param_count,
|
||||
...);
|
||||
|
||||
LLVMValueRef
|
||||
aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
|
||||
const char *name,
|
||||
LLVMTypeRef ret_type,
|
||||
LLVMTypeRef *param_types,
|
||||
int param_count,
|
||||
va_list param_value_list);
|
||||
|
||||
bool
|
||||
aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
|
148
core/iwasm/compilation/aot_llvm_extra.cpp
Normal file
148
core/iwasm/compilation/aot_llvm_extra.cpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <llvm/ADT/SmallVector.h>
|
||||
#include <llvm/ADT/Twine.h>
|
||||
#include <llvm/ADT/Triple.h>
|
||||
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
||||
#include <llvm/MC/MCSubtargetInfo.h>
|
||||
#include <llvm/Support/TargetSelect.h>
|
||||
#include <llvm/Target/TargetMachine.h>
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm-c/ExecutionEngine.h>
|
||||
#include <llvm/ExecutionEngine/GenericValue.h>
|
||||
#include <llvm/ExecutionEngine/JITEventListener.h>
|
||||
#include <llvm/ExecutionEngine/RTDyldMemoryManager.h>
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/Support/ErrorHandling.h>
|
||||
#include <llvm/Target/CodeGenCWrappers.h>
|
||||
#include <llvm/Target/TargetOptions.h>
|
||||
#include <cstring>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
extern "C" LLVMBool
|
||||
WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
|
||||
LLVMModuleRef M,
|
||||
LLVMMCJITCompilerOptions *PassedOptions,
|
||||
size_t SizeOfPassedOptions,
|
||||
char **OutError);
|
||||
|
||||
extern "C" bool
|
||||
aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
|
||||
|
||||
LLVMBool
|
||||
WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
|
||||
LLVMModuleRef M,
|
||||
LLVMMCJITCompilerOptions *PassedOptions,
|
||||
size_t SizeOfPassedOptions,
|
||||
char **OutError)
|
||||
{
|
||||
LLVMMCJITCompilerOptions options;
|
||||
// If the user passed a larger sized options struct, then they were compiled
|
||||
// against a newer LLVM. Tell them that something is wrong.
|
||||
if (SizeOfPassedOptions > sizeof(options)) {
|
||||
*OutError = strdup(
|
||||
"Refusing to use options struct that is larger than my own; assuming "
|
||||
"LLVM library mismatch.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Defend against the user having an old version of the API by ensuring that
|
||||
// any fields they didn't see are cleared. We must defend against fields being
|
||||
// set to the bitwise equivalent of zero, and assume that this means "do the
|
||||
// default" as if that option hadn't been available.
|
||||
LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
|
||||
memcpy(&options, PassedOptions, SizeOfPassedOptions);
|
||||
|
||||
TargetOptions targetOptions;
|
||||
targetOptions.EnableFastISel = options.EnableFastISel;
|
||||
std::unique_ptr<Module> Mod(unwrap(M));
|
||||
|
||||
if (Mod) {
|
||||
// Set function attribute "frame-pointer" based on
|
||||
// NoFramePointerElim.
|
||||
for (auto &F : *Mod) {
|
||||
auto Attrs = F.getAttributes();
|
||||
StringRef Value = options.NoFramePointerElim ? "all" : "none";
|
||||
Attrs = Attrs.addAttribute(F.getContext(), AttributeList::FunctionIndex,
|
||||
"frame-pointer", Value);
|
||||
F.setAttributes(Attrs);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Error;
|
||||
bool JIT;
|
||||
char *host_cpu = LLVMGetHostCPUName();
|
||||
|
||||
if (!host_cpu) {
|
||||
*OutError = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string mcpu(host_cpu);
|
||||
LLVMDisposeMessage(host_cpu);
|
||||
|
||||
EngineBuilder builder(std::move(Mod));
|
||||
builder.setEngineKind(EngineKind::JIT)
|
||||
.setErrorStr(&Error)
|
||||
.setMCPU(mcpu)
|
||||
.setOptLevel((CodeGenOpt::Level)options.OptLevel)
|
||||
.setTargetOptions(targetOptions);
|
||||
if (Optional<CodeModel::Model> CM = unwrap(options.CodeModel, JIT))
|
||||
builder.setCodeModel(*CM);
|
||||
if (options.MCJMM)
|
||||
builder.setMCJITMemoryManager(
|
||||
std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM)));
|
||||
if (ExecutionEngine *JIT = builder.create()) {
|
||||
*OutJIT = wrap(JIT);
|
||||
return 0;
|
||||
}
|
||||
*OutError = strdup(Error.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str)
|
||||
{
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
if (!arch_c_str || !cpu_c_str) {
|
||||
return false;
|
||||
}
|
||||
|
||||
llvm::SmallVector<std::string, 1> targetAttributes;
|
||||
llvm::Triple targetTriple(arch_c_str, "", "");
|
||||
auto targetMachine =
|
||||
std::unique_ptr<llvm::TargetMachine>(llvm::EngineBuilder().selectTarget(
|
||||
targetTriple, "", std::string(cpu_c_str), targetAttributes));
|
||||
if (!targetMachine) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const llvm::Triple::ArchType targetArch =
|
||||
targetMachine->getTargetTriple().getArch();
|
||||
const llvm::MCSubtargetInfo *subTargetInfo =
|
||||
targetMachine->getMCSubtargetInfo();
|
||||
if (subTargetInfo == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targetArch == llvm::Triple::x86_64) {
|
||||
return subTargetInfo->checkFeatures("+sse4.1");
|
||||
}
|
||||
else if (targetArch == llvm::Triple::aarch64) {
|
||||
return subTargetInfo->checkFeatures("+neon");
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
(void)arch_c_str;
|
||||
(void)cpu_c_str;
|
||||
return true;
|
||||
#endif /* WASM_ENABLE_SIMD */
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user