Merge branch 'bytecodealliance:main' into master

This commit is contained in:
Wang Xin 2021-07-04 03:26:31 -04:00 committed by GitHub
commit 85c0bc2d9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
453 changed files with 70382 additions and 8883 deletions

View File

@ -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
View 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
View 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
View 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
View 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
View File

@ -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

View File

@ -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
View 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)

View File

@ -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

View File

@ -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
View 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')

View File

@ -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
View 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 projects 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
projects 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
View File

@ -0,0 +1 @@
/node_modules

View File

@ -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
}

View File

@ -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
View 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')

View 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')

View File

@ -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 ()

View File

@ -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
View 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
View 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"

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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)
{

View File

@ -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
};
};

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -31,6 +31,9 @@ app_manager_get_watchdog_timer(void *timer);
bool
watchdog_startup();
void
watchdog_destroy();
#ifdef __cplusplus
} /* end of extern "C" */
#endif

View File

@ -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" */

View File

@ -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_ */

View File

@ -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
View 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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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()

View File

@ -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()

View File

@ -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),

View File

@ -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;
}

View File

@ -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

View 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')

View File

@ -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 */

View 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

View File

@ -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

View File

@ -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 */

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 ()

View 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;
}

File diff suppressed because it is too large Load Diff

View 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 */

View File

@ -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

View File

@ -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

View File

@ -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*/

View File

@ -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

View File

@ -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

View 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;
}

View 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 */

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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, &sections_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;
}

View File

@ -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;
}

View File

@ -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:

View File

@ -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

View File

@ -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;
}

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,
&param_type,
1,
param_value_list);
ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, &param_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;

View File

@ -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;
}

View 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 */

View 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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View 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